|
|
|
@ -309,7 +309,7 @@ main函数的 USER CODE BEGIN 2 区域添加内容
|
|
|
|
|
|
|
|
|
|
HAL_I2C_Master_Transmit和HAL_I2C_Master_Receive 的地址都使用0x70,HAL_I2C_Master_Transmit会自动设置最后一位是0(仍然是0x70);HAL_I2C_Master_Receive会自动设置最后一位是1(就是0x71)
|
|
|
|
|
|
|
|
|
|
### 温湿度数据的重组
|
|
|
|
|
### 2.3.2. 温湿度数据的重组
|
|
|
|
|
|
|
|
|
|
按照AHT20的说明(p8),返回六个字节的顺序:
|
|
|
|
|
|
|
|
|
@ -317,4 +317,88 @@ HAL_I2C_Master_Transmit和HAL_I2C_Master_Receive 的地址都使用0x70,HAL_I2
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
## 2.4. I2C的中断和DMA
|
|
|
|
|
|
|
|
|
|
[中断模式和DMA](https://www.bilibili.com/video/BV1AN41127VL?spm_id_from=333.788.videopod.sections&vd_source=3c8e333d6657680a469ddf0238f01d6a)
|
|
|
|
|
|
|
|
|
|
# 3. OLED显示
|
|
|
|
|
|
|
|
|
|
[视频演示](https://www.bilibili.com/video/BV19u4y197df?spm_id_from=333.788.videopod.sections&vd_source=3c8e333d6657680a469ddf0238f01d6a)
|
|
|
|
|
|
|
|
|
|
开发板上的OLED显示器是单色的显示,分辨率为 128 * 64。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
相当于有128 * 64个小灯,只需要点亮相应的小灯就可以组成图案。如果使用IO进行操作,需要 128 * 64 个IO口(8192个),显然是不合适的。如何解决?
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
其实显示器的矩阵可以看作是一段连续的内存,每一个灯就是一个bit(单色模式,如果是彩色显示器,每个灯可能是一个byte或者是多个byte)。和内存一样,显示器内部也有一个存储区域(寄存器),和点阵是对应的,我们只需要对显示器的控制芯片寄存器的相应位置写入相应的数据,显示器对应点就会点亮或者熄灭。这种方式就如同写寄存器一样。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
因此,显示驱动芯片其实有很多IO与显示器进行连接,然后驱动芯片与外部有个通信接口(这里是I2C);通过接口,MCU告诉显示器需要如何显示就好了。这样避免了MCU使用很多IO直接控制显示器。另外这里的通信是I2C,但是还有其他的方式,例如串口、SPI、VGA、HDMI等。
|
|
|
|
|
|
|
|
|
|
## 3.1. 显示原理
|
|
|
|
|
|
|
|
|
|
开发板使用SSD1306作为驱动,[显示器资料](../../配套模块资料/OLED显示屏/1.3-ZJY130-2864KSWLG01.pdf),[CH1116芯片资料](<../../配套模块资料/OLED显示屏/CH1116 V0.2.pdf>)
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
分成了8个Page(大行),每个Page中有8个小行,一共就是64行,刚好是纵向的分辨率;然后,每行有128个寄存器,表示列,这样就得到128*64的一组寄存器。这个和内存中的分页技术是一致的。
|
|
|
|
|
|
|
|
|
|
### 3.1.1. 通信方式
|
|
|
|
|
|
|
|
|
|
通信分为两种,指令和数据,指令包含两个字节,数据没有限制。指令表示要从哪个位置开始写数据;数据代表写入什么数据。指令包含页的设置和列的设置两个部分。
|
|
|
|
|
|
|
|
|
|
每个指令都包含两个字节,第一个字节0x00;第二个字节表示页/列的设置。指令选择页和选择列,但后续只有一个字节了,这个后续的一个字节需要携带页还是列?具体是哪个页和列;因此第二字节可以拆分成为高4位和低4位进行表示,其中高4位表示是什么(页、列),低4位表示具体的参数(哪个页、哪个列)。
|
|
|
|
|
|
|
|
|
|
#### 3.1.1.1. 指令
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
1. 页地址:B0~B7;其实这里的B就代表设置页,地4位的0~7表示哪个页,一共只有8页;
|
|
|
|
|
2. 列地址,把列分为两个字节发送,分为高4位和低四位。低位先发,高位后发(有点像小端模式);高4为分别为0和1,表示表示列的低4位和高4位;因为一共128列,因此设置列需要发送两次指令;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
例如选择页,使用Bx的方式,高4位B表示设置页的命令,低四位X可以是0~7表示具体是哪一页。这样一个完整的设置页的命令就是0x00,0xb0:选择第0页;0x00,0xb1:选择第1页;因为一共只有8页,4位的取值范围是0~15,完全覆盖8页的取值范围,这样是没有问题的。但是如果选择列,列的取值是0~127,这样使用一条命令是不够的。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
在设置列的时候,参数字节的高4位是0表示设置列的低四位;参数字节的高四位是1表示设置列的高四位;00-00:设置低四位00-10:设置高四位这样列就是00列。注意:驱动的第0页其实是从02开始的,因此需要发送(0x0002,0x0010)来选择第0列。
|
|
|
|
|
|
|
|
|
|
#### 3.1.1.2. 数据
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
数据是 0x40 后携带N个字节,表示从指令设置的页和列开始连续的设置相应的列。
|
|
|
|
|
|
|
|
|
|
## 3.2. 显示驱动
|
|
|
|
|
|
|
|
|
|
在内存中建立一个数组(存储空间)与显存的空间进行对应。当要画图的时候,先在内存中写数据,然后把内存中的数据全部写入到显示器(显存)。这样做有很多好处方便,操作内存比操作显存更方便。但是这样做也有缺陷:
|
|
|
|
|
|
|
|
|
|
问题:什么缺陷?
|
|
|
|
|
|
|
|
|
|
OLED_NewFrame 函数用于把内存中一个虚拟屏幕清空,这样很快。OLED_ShowFram用于将内存中的一个虚拟屏幕的内容发送到显示器的显存当中,这样就可以显示了。
|
|
|
|
|
|
|
|
|
|
视频演示有个地方错了,关于画点的函数(仔细看看)。
|
|
|
|
|
|
|
|
|
|
### 3.2.1. 如何显示文字和图片
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
显示器和图片都是以点来存放图片或者文字的。如果把上面的文字转换成点阵就可以在点阵的显示器上显示了。如何做到?
|
|
|
|
|
|
|
|
|
|
任何文字或者图片都可以使用点阵进行描述:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
### 3.2.2. 如何快速的进行显示
|
|
|
|
|
|
|
|
|
|
1. 抽象基本的功能:画点,划线、画圆。。。
|
|
|
|
|
2. 字库:通过ASCII码(其实是一个整数)对应到一个数组(点阵),然后使用画点的方式画出文字。英文处理相对简单,中文处理需要更大的存储空间。
|
|
|
|
|
|
|
|
|
|
[取模工具](https://led.baud-dance.com/)
|
|
|
|
|