在电子设备的显示领域,O 凭借其出色的显示效果和低功耗等优势,得到了广泛应用。本文将聚焦于两种不同尺寸的 OLED 显示屏 ——0.96 寸和 0.91 寸,它们均采用 4 引脚 I2C 接口,这种接口在数据传输和控制方面具有独特的优势。

值得一提的是,经过项目测试发现,本文所介绍的驱动方式和代码也完全适用于 1.54 寸 SSD1309 主控的 1.54 寸 OLED 和 1.29 寸 CH1115 主控的 OLED 屏。如果需要更大的屏幕可以选用这两款,但是他们的分辨率仍然是 126*64,只是显示的字体和图案可以更大。
0.96 英寸 OLED 显示屏工作电压范围为 3.3 - 5V,内置 3.3V LDO,其 I2C 通信接口电平为 3.3V。像素点阵规模达到 128x64,意味着共有 8192 颗 LED 参与显示,驱动 IC 采用 SSD1306。而 0.91 英寸 OLED 显示屏同样工作在 3.3 - 5V 电压下,内置 3.3V LDO,I2C 通信接口电平也是 3.3V,不过其像素点阵规模为 128x32,仅有 4096 颗 LED,驱动 IC 同样为 SSD1306。由此可见,0.91 英寸的像素点规模只有 0.96 英寸的一半,除此之外其余参数基本相同。接下来将主要介绍 0.96 英寸显示屏的使用方法。
该 OLED 显示屏的接口定义清晰明确。VCC 为模块电源正,可接入 3.3 - 5V 电源;GND 是模块电源地;SCL 为模块 I2C 总线时钟信号;SDA 则是模块 I2C 总线数据信号。在硬件设计方面,模块内置了型号为 662K 的 3.3V LDO,因此支持 3.3 - 5V 供电。同时,模块已经板载了 SCL 和 SDA 线的上拉电阻,且上拉到了 3.3V。如果是 5V 的,只要将 IO 配置为开漏输出,就可以直接接入到模块,不过需要注意的是,3.3V 能否被 5V 单片机识别为高电平,这需要查看单片机的数据手册,一般情况下是没有问题的。此外,当其他 I2C 从机挂接到同一个 I2C 总线时,无需再外接 I2C 总线的上拉电阻。模块的 I2C 从机地址为:0111 10 [SA0] [RW],其中 SA0 是硬件地址选择位,当 SA0 接高电平时,地址中的 SA0 就是 1,当 SA0 接低电平时,地址中的 SA0 就是 0。模块出厂的时候,一般 SA0 是接的低电平,用户可以自己动手修改模块后面的电阻来改变 SA0 为高电平,这也意味着,同一个 I2C 总线多支持挂接 2 个 OLED 模块。

在 SSD1306 的 I2C 协议中,控制字节起着关键作用,其控制位的格式为:[Co][D/C#][000000]。在发送指令字节或者数据字节前,需要先发送一个控制字节,通过控制字节中的 D/C# 位,来告诉 SSD1306,接下来发送的一个字节是指令还是数据。这里我们先不考虑控制字节中 Co 位的作用,这样就可以编写出发送单个字节的指令和单个字节的数据的函数。发送单个字节指令的流程为:起始信号【从机地址,ACK】【控制字节,ACK】【单字节的指令,ACK】结束信号;发送单个字节显存数据的流程为:起始信号【从机地址,ACK】【控制字节,ACK】【单字节的数据,ACK】结束信号。然而,每次发送一个指令或者数据字节,都要开启完整的 I2C 通信时序流程,会造成大量的通信时间浪费,特别是在快速刷屏的时候。为了提高效率,当控制字节中 Co = 0,且 D/C# = 1 时,则接下来可以连续发送任意多个显存数据字节,直到产生停止信号。通过在 0.91 英寸 OLED 屏幕上测试发现,使用 150KHz I2C 总线,刷完一帧屏幕,使用单个发送字节显存数据函数需要大约 100ms,而使用性发送多个显存数据的函数则只需要大约 33ms,速度提升非常明显。

理解 SSD1306 数据手册中的指令集对于正确驱动 OLED 显示屏至关重要。以截取的 3 条指令为例,指令 A 用于设置页地址,它由连续的 3 个字节组成,个字节 0x22 代表指令码,用于标识指令功能本身,后面的两个字节 A [2:0] 和 B [2:0] 则是两个指令参数,指令参数是指令运行时所需的参数数据。指令 B 比较特殊,它将指令码和指令参数融合为了一个字节,高位部分固定为 [10110],低位部分 [X2,X1,X0] 则用于编码指令参数。指令 C 只有一个固定的指令码,没有指令参数,类似于 C 语言中的无参数函数。表格的列 D/C#,用于告诉我们,发送对应的字节时,需要将 D/C# 位设置为 0 还是 1。D/C# = 0 代表发送的是指令性相关的数据,这些字节数据被 SSD1306 接收并解析,主要用于改变屏幕的工作参数;D/C# = 1 代表发送的是显示数据字节,这些字节将被写入到 SSD1306 的显存 GDDRAM 中作为显示数据使用。

驱动芯片 SSD1306 带有一个 128x64 bit 大小的 GDDRAM,用于存放显示数据,也就是所谓的显存。显存中的数据与显示内容是息息相关的,具体来说,显存中的每一个 bit 对应一颗像素点,如果显存中的某个 bit 为 1,则它对应的那颗像素 LED 被点亮,否则是熄灭的。GDDRAM 支持 3 种内存寻址模式,分别为页寻址模式、水平寻址模式和垂直寻址模式,其中页寻址模式为常用。当使用页寻址模式时,GDDRAM 被划分为 8 个页:PAGE0 - PAGE7,每个页由 128 个字节组成。通过单片机向 GDDRAM 中写入数据时,需要指定 2 个地址:页地址和列地址,这样才能定位到 GDDRAM 中的一个的字节存储单元。在页寻址模式下,每次写入一个字节的显示数据,列地址自动增 1。当列地址超过 127 时,会自动回归到 0,但页指针不会改变,除非使用指令重新设置指向其他的页。设置页地址和列地址需要通过查看 SSD1306 的指令表,其中列地址需要拆成 2 部分写入,用条指令发送列地址值的低 4bit 部分,用第二条指令发送列地址值的高 4bit 部分。配置寻址模式为页寻址模式时,先发送指令码 0x20,来告诉屏幕要现在要设置内存寻址模式,然后发送指令参数:0x00 水平地址模式,0x01 垂直模式,0x02 页地址模式。芯片复位后默认就是页寻址模式。

在 OLED 显示屏上显示图片和汉字,需要借助 Pctolcd2002 这款取模软件。以显示图片为例,首先要准备一张尺寸与 OLED 屏显示需求同等比例的图片,例如要在 0.96 英寸 OLED 上显示一张 128 宽,64 高的图片,则准备一张 378x189 的意法半导体 logo 图片。用 Windows 自带的画图软件打开它,调整大小为想要的像素规模,然后保存为 BMP 格式。接着打开 Pctolcd2002 软件,将菜单栏【模式】修改为图形模式,通过【文件】【打开】选中上一步生成的 BMP 图像。点击工具栏的【齿轮】按钮,在弹出的界面中按照特定要求进行配置,配置完成后点击【确定】返回主界面。在主界面中,若生成的点阵预览图有细节瑕疵,可以使用鼠标进行修补,左键增加一个像素,右键取消一个像素。点击主界面右下角的【生成子模】按钮,即可输出子模字节数据。将这个子模数据以一维字节数组的形式定义在 C 程序中,就可以使用了。由于【取模方式】用的是【列行式】,对于页寻址模式非常方便。显示汉字时,打开 Pctolcd2002 软件,将菜单栏【模式】修改为字符模式,【选择字体】,设置【字宽和字高】。在下方输入需要取模的汉字,然后点击【生成字模】。实际使用过程中,为了达到比较好的显示效果,汉字一般使用 16x16 宽和高。Pctolcd2002 软件把每一个汉字当做一个基本的图像来进行取模,且按照输入的文字依次进行取模。在显示汉字的时候,要先按顺序显示每个字的上半部分,然后换到下一个 page,再按顺序显示每个字的下半部分。
不同尺寸的 OLED 显示屏在初始化序列上略有差异。对于 0.96 寸 IIC 接口 OLED,初始化时首先要初始化驱动 I2C 总线的引脚,延时 200ms 等待 OLED 稳定。然后依次发送一系列指令,如关闭显示、设置列地址、页地址、对比度控制、扫描方向等参数,开启电荷泵并打开 OLED 面板,同时清除屏幕显示。而 0.91 寸 IIC 接口 OLED 的初始化过程类似,但部分指令参数有所不同,同样需要初始化 I2C 总线引脚,延时等待稳定后,发送相应的指令来配置屏幕的工作参数,打开显示并清除屏幕。
通过以上对 OLED 显示屏 I2C 接口的详细介绍,我们可以全面了解其从硬件设计到软件编程,再到图片和汉字显示的整个过程,为在实际项目中应用 OLED 显示屏提供了坚实的理论基础和实践指导。
关键词:I2C 接口