最近项目里有用到1.3寸的OLED显示屏,它用的驱动芯片是SH1106。

而我们初学者入门的时候应该用的是0.96寸的OLED显示屏,它用的驱动芯片是SSD1306.

其实二者的差异不大,可以说在使用上是没有什么区别的。

图片

如果是买现成的模块,不用自己画OLED屏幕的话,在手册的首页里,我们只需要注意两个点,上图用红框框出来了。

第一个是显示屏幕的大小是132*64个点。

现在某宝买普通的OLED模块,小一点(0.96寸)的一般用的驱动是SSD1306,大一点(其实也没多大,1.3寸的128*64)用SH1106

二者的驱动程序基本是兼容的,一点都不用改,唯一要注意的就是尺寸问题。SSD1306的范围是128*64,而SH1106132*64,多出4列像素点。

第二个是支持400KHzI2C(高速)。

手册里接下来是个介绍各个引脚的功能的表格,这边就不看了,因为主要是要了解怎么驱动,OLED是直接买现成的模块所以不用自己画外围电路。

图片

就是有一点要说一下,可以通过引脚的配置来决定SH1106用的什么接口,我这边主要看I2C的。

不过只要知道寄存器怎么配置是做什么的,那么用别的接口,其实问题也不大。

图片

上面是使用I2C的时候的引脚配置。

图片

从机地址可以有两个,通过引脚去配置,一般我们买模块就是0111100这个地址,所以写的时候地址就是0111 10000x78),读的时候地址就是0111 10010x79)。

接下来看看SH1106是如何驱动OLED显示的。

图片

图片

我们知道它支持132*64OLED显示,所以它可以显示64行和132列数据。

其中它规定每8行为一页,所以一页的分辨率是132*8

我们要显示东西的话,首先需要设置光标,这个命令后面会说,可以先暂时忽略。

我们能设置光标在哪一页以及哪一列。

也就是说把显示屏套在坐标系里,我们可以很精确的控制光标在x轴上的数值(0~131),但是y轴就很粗糙了(0~7)。

设置完光标时候,我们直接发送数据就可以往显示屏里填充内容了,具体怎么发送,后面会说。

假设我将光标设置为了2页65列,接着发送数据0xFF,那么就会出现下面这种图像。

图片

上图中蓝色边框只是为了更容易看出具体是哪一页,实际上不会有边框显示出来的。

在第二页的中间出现了一条竖线。

因为0xFF换成二进制是 1111 1111,是8个数字,而每一页有8行,所以每个数字对应当前列的每一行的这个像素点是否显示。

这样子,这一页的这一列的画面就已经填充完毕了,然后光标会自动移动到当前页的下一列,也就是光标此刻的位置是第二页的第66列,我们可以接着发送数据接着填充画面。

假设我接着发送了0x55和0xAA,那么第二页的画面就会是下面这样的。

图片

因为0x55是0101 0101,0xAA是1010 1010,我们发送数据是高位在下的,也就是下面这样。

图片

知道怎么显示之后,我们就可以在OLED上显示自己想要显示的字符或是图像了。

比如下面这样

图片

我把我写好的驱动打包好了,虽然你不一定用的到里面封装好的东西(我用的芯片是STC32G),但是可以结合着文章内容去学习如何驱动SH1106。

到我同名公众号私信回复“OLED”即可免费获取。

图片

I2C的读写流程如上图,反正我是没看很明白。

主要看右下角的control byte

图片

D/C0的时候表示发送命令,D/C1的时候表示发送数据。

接下来直接看它的命令有哪些。

图片

前两个是设置列地址。

不过是分为了两个部分,低位是0x00~0x0F,高位是0x10~0x1F

乍一看可能有点迷糊,我们需要把这俩命令的高位去掉,也就是低位0x00~0x0F把前面的0去掉,看做是0x0~0xF,高位也是一样,把高位的1去掉,也看做是0x0~0xF

所以如果是要设置列地址为1000x64),那么我们要发送的命令就是0x160x04

图片

然后我们先看看后面的一个命令,就是这个设置页地址的,也可以看成是设置行,只不过能设置的行只能是8nn = 0~7)。

命令是0xB0~0xB7,一样的,我们需要把命令的高位忽略,也就是忽略这个B,那么命令就变成了0x0~0x7

通过这两个命令,我们就可以设置页地址和列地址,设置完之后,直接发送数据,也就是control byte设置为0x40然后发数据,这样就可以把我们要输出的字符或者图像打印到OLED上了。

    // 设置光标位置 (Y = 0 ~ 7 ; X = 0 ~ 127)
    void Z_OLED_SetCursor(u8 Y, u8 X){
        Z_OLED_WriteCommand(0xB0 | Y);                  //设置Y位置
        Z_OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));  //设置X位置高4位
        Z_OLED_WriteCommand(0x00 | (X & 0x0F));         //设置X位置低4位
    }

    理论上来说,我们要显示一些东西,就靠这设置页和设置列的命令就行。

    因为其他的配置命令,一般来说OLED的卖家都会提供。

    不过我们这边还是来看看其他命令,因为卖家提供的初始化代码基本上都是祖传的包浆代码,很多地方我觉得都是多此一举,如果我们能知道每个命令是做什么的,那么我们也可以根据自己的实际需求去修改(虽然大多数情况不用改)。

    图片

    下一个设置电荷泵的电压,命令是0x30~0x33,可以设置的电压范围是6.4~9.0,我们可以简单理解为电压越高,越清晰,但一般不要设置为9V,普通使用的话6.4就行(0x30)。

    图片

    0x40~0x7F,用来设置起始行地址,一般默认是0,通过这个命令可以用来设置哪一行作为屏幕的第一行。

    听起来有点抽象,下面举个例子就明白了。

    图片

    正常情况下我们就是像上图这样,第一行就是0页,那么0就是起始行地址。

    图片

    所以一般情况下我们不会去修改,就是以0页为起始页。

    图片

    0x81,然后发送0x00~0xFF来设置比例因子,具体要设置为多少,大家可以自行去尝试对比。

    图片

    我英语不好,拿翻译直译下来我看不懂。

    反正这个命令就是用来设置左右方向的,0xA1是设置为从左往右(正常也是用这种),0xA0是设置为从右往左。

    图片

    0xA4打开显示,0xA5关闭显示。

    图片

    0xA7开启反显,0xA6正常显示,一般是黑底白字(也有蓝色的),开反显之后就变成了黑字白底(或者是蓝底)。

    图片

    设置多路复用率,先固定发送0xA8,再发送0x00~0x3F来设置,我们的显示屏有几行,我们就设置为几(要减个1,因为是从0开始算的),比如说我们的OLED64行,那就设置为0x3F63)。

    图片

    这个命令用来控制内部的DCDC开关,一般来说这个命令我们用不到。

    图片

    0xAE关闭显示,0xAF开启显示。

    区别于上面的0xA40xA5,上面是强制开关。

    而这边的关闭显示则是进入到睡眠模式。

    一般来说还是0xAE和0xAF用得比较多。

    图片

    设置扫描方式,一般来说是用页面0到页面7的。

    如果设置为了0xC8,那么是从页面7扫描到页面0,也就是上下颠倒的。

    图片

    显示偏移,这个我没看很懂,因为上面已经有了偏移指令了。

    懒得去试验对比区别了。

    图片

    上面一堆是讲设置时钟分频比,振荡器频率的,我的卖家给我提供的初始化代码在这一块是0xD5(固定)和0x80

    我用着也没感觉有什么不适。

    图片

    这是设置放电/预充电周期的,我这里是0xD9 0xF1

    图片

    用来设置引脚焊盘顺序的,一般来说我们买现成的模块,那么这个是固定死的,都是需要设置为0xDA 0x12的。

    图片

    最后一个是设置VCOM取消选择时电平的,什么意思不太清楚,我这是设置为0xDB 0x30

    差不多内容就这些,相信大家认真看完之后就知道如何配置以及显示画面了。

    Logo

    智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

    更多推荐