STM32单片机学习(23) —— OLED的使用
文章目录
概述
在讲完I2C相关所有概念、I2C通信协议、时序要求等问题后,我们再了解一下支持I2C通信的硬件从机设备——OLED。
这可以为后续我们做实验打下基础。
使用I2C协议驱动OLED显示屏
若想使用I2C协议驱动OLED显示屏,你需要知道以下内容:
- OLED显示屏的硬件从机地址。
- OLED显示屏I2C通信的数据帧格式。
- 常见OLED显示屏控制指令。
下面逐一讲解这些内容。
OLED显示屏的硬件从机地址
通过查阅手册,我们知道OLED显示器的硬件从机地址是下面这样的:
0 1 1 1 1 0 SA0
其中的SA0是什么呢?
手册中的原话是:
D/C# pin acts as SA0 for slave address selection.
D/C#引脚作为SA0用于从地址选择。
也就是说,D/C 引脚作为SA0用于从地址选择。那么D/C引脚在哪里呢?
我们可以直接查看OLED的硬件电路图,如下图所示:

其中D/C引脚部分的电路图如下所示:

所以D/C引脚的电平值,可以是高电平的1,也可以是低电平的0,具体使用哪一个要看引脚被焊接到哪一个电阻上。
那这怎么看呢?把OLED屏幕反着放置在桌上,就能看到如下内容:

那么这张图表示SA0是低电平0还是高电平1呢?
首先这里的两个值Ox78和Ox7A,都不是它的从机地址,因为两位十六进制数表示8位二进制数,而从机地址是7位的。
这两个数是寻址字节的取值,也就是**“从机地址的7位二进制,再添上一个0(写标志)”**得到的8位数值。
0x78的二进制表示是:
0 1 1 1 1 0 0 0
和上面的:
0 1 1 1 1 0 SA0
这说明SA0的取值是0,我们使用的OLED屏幕D/C引脚实际是接地的。
除此之外,我们还需要注意这个电路图的这个部分:

OLED屏幕的SDA和SCL引脚都各自内置了一个4.7KΩ的上拉电阻,这就意味着OLED屏幕接入电路后,完全不需要再手动添加上拉电阻了。
OLED内部电路中的上拉电阻就可以帮助我们实现,I2C通信中"逻辑线与"的功能。
想一想,我们早就使用过OLED屏幕了,使用的工具函数就是基于I2C通信协议实现的,但我们并没有在电路中接入上拉电阻,原因就在于此。
OLED显示屏I2C通信的数据帧格式
I2C通信可以实现单片机和外部其它芯片/集成电路的数据通信,在上面我们讲解是通用的数据帧格式。
即先发起始位,再发寻址字节表示读/写某个从机,随后就是正常的数据交互过程。
但不同的外设,它们的数据帧,往往在第二个字节的数据发送处会有所不同。
比如像EEPROM(以字节为单位读写的非易失性存储器,类似一个小Falsh闪存),以及各类支持I2C通信的传感器。
主机与它们通信时,就需要通过发送的第二个字节的数据,指出读/写的寄存器的地址,从而实现数据存储,获取数据等功能。
所以这类设备的数据帧格式如下所示(以写数据为例):
[S] [寻址字节] [ACK] [寄存器地址] [ACK] …[数据字节] [ACK] [P]
更详细的一个数据帧的格式就如下所示:
[起始位] [从机地址][读写标志] 从机应答 [需要写的从机寄存器地址]从机应答[写到从机寄存器的1个字节数据]从机应答…从机应答[停止位]
所以在使用这些设备时,你还需要通过查阅手册,获取你想要实现功能所需的寄存器的地址,操作还是比较繁琐的。
但OLED屏幕使用时的数据帧格式相对比较简单,因为它本身不是用于存储数据的外设,所以寄存器设计简单。
总之OLED显示屏I2C通信的数据帧格式,如下所示:
[起始位] OLED设备从机地址[读写标志] 从机应答 [控制字节]从机应答[后续指令/需要写的字节数据]从机应答…从机应答[停止位]
当然,使用OLED时你也需要查一查控制字节有哪些,控制指令有哪些,写字节数据时具体的写法。
其中第二个控制字节的选项只有两个:
| 控制字节 | 作用 |
|---|---|
0x00 |
发送 命令(如清屏、设置光标位置) |
0x40 |
发送 待显示数据(写入 OLED 显存) |
在向 OLED 发送数据时,必须在寻址字节后面 再发送一个控制字节,告诉 OLED 如何处理后续的字节数据。
常见OLED显示屏控制指令
由于我们本章节只用于I2C通信入门,所以我们只需要了解简单的控制指令用于实现I2C通信即可。
慢慢查阅手册比较麻烦,我这里就列出两个我们做实验会用到的指令字节序列。
假如我想实现一个简单功能:开启OLED,并点亮全部像素。
此时只需要控制主机向从机屏幕发送以下指令序列就可以了:
uint8_t Commands[] = {
0x00, // 下面的指令是命令流
0x8D, 0x14, // 开启电荷泵
0xAF, // 打开屏幕
0xA5 // 让屏幕全亮,点亮所有像素点
};
组指令可以用于初始化 OLED 并让屏幕全亮。以下是解释:
0x00: 表示发送的是命令流。0x8D, 0x14: 打开 OLED 的内部电荷泵,为 OLED 提供驱动电压。0xAF: 打开 OLED 显示。0xA5: 让屏幕所有像素点亮。
假如我想实现一个简单功能:完全关闭OLED。
也就是上面操作的逆向操作,你只需要操作主机向OLED从机发送以下指令序列即可:
uint8_t Commands[] = {
0x00, // 下面的指令是命令流
0xA4, // 普通显示模式
0xAE, // 关闭 OLED 显示
0x8D, 0x10 // 关闭电荷泵
};
说明:
0x00: 表示发送的是命令流。0xA4: 将 OLED 从 “全屏像素点亮” 模式(0xA5)切换到全部像素熄灭状态。0xAE: 关闭 OLED 显示。0x8D, 0x10:关闭电荷泵,停止为 OLED 提供驱动电压,彻底关闭OLED。
主机读OLED。
上面是实现了写OLED屏幕的功能,实际上OLED在I2C通信中几乎只需要主机写功能,OLED作为从机几乎没必要向主机发送数据。
毕竟OLED既不是存储器也不是传感器,但OLED仍然具有唯一一个向主机发送数据的功能:返回状态字节。
如下图所示:

SSD1306控制芯片的OLED屏幕没有提供明确的可读寄存器地址,主机读OLED从机时,会直接出现以下情况:
- 主机发送起始信号。
- 主机发送从机地址 + 读模式(
0x78 | 0x01)。 - 从机OLED直接返回状态字节给主机。
状态字节中只有bit6是有效的,它用于指示当前OLED是否开启,比如刚刚执行完0xAE指令,OLED就处于关闭状态,bit6的值就是1。
所以我们在演示I2C主机读OLED时,可以使用这个操作,读一下OLED屏幕的当前亮灭状态。
读写操作时序图举例
OLED屏幕写模式下的时序图
在寻址成功后,发送两个字节数据给OLED
待发送的两个字节数据是:0x66,0x88
I2C通信的比特序是MSB,从最高位发送到最低位
I2C写的过程,从主机发送写模式寻址字节0x78开始
由于我们需要用指令控制OLED屏幕,所以第二个字节需要发送0x00,让OLED屏幕进入指令控制模式
0x78: 0111 1000
SCL与SDA输出高电平 ——> 空闲时间
SDA在SCL高电平期间拉低,开始传输起始信号
SCL的第一个下降沿,起始信号传输完成,准备通信
传输开始
第一个字节为寻址字节(7 + 1), 7位地址位和1位读写标志
- 读写标志位为0, 表示主机向从机写数据
- 读写标志位为1,表示从机发送数据到主机,也就是主机读数据
传输过程中
SCL一个高低电平代表一个时钟周期,并且只有在SCL处于高电平期间为工作时间,所以SDA需要在休息时间,准备号数据,完成电平的转换。
应答
从机拉低SDA——表示ACK应答成功
I2C通信,每一个数据帧,不限制发送的字节数量,但是每发一个字节都要应答1个时钟周期
传输停止
SCL 高点平工作时间内,SDA产生一个上升沿
在发送停止信号的前一个休息时间内,需要拉低SDA电平,以便产生上升沿
OLED屏幕读模式时序图
读模式下,OLED屏幕的寻址字节是:0x79 0111 1001
假如说,OLED屏幕现在是关闭状态,OLED发送的状态字节的bit6位就是1‘
假设OLED发送的状态字节是:0100 0000

读模式下主机应答NACK(无应答),代表不再接收数据
更多推荐




所有评论(0)