目标:用OLED显示屏实时显示前面制作的SHTx温湿度传感器的测量数据。
从网上买的,带底板的0.91吋白色OLED。外观如图1所示。
图1. OLED显示屏外观示意图
主要参数如下:
从图1可以看出,显示屏共有4个引脚。GND接地;VCC接3.3V电源;SCL接单片机I2C接口的时钟引脚(PB6);SDA接数据引脚(PB7)。用杜邦线连一下就可以了。
据说单片机的一个I2C模块可以挂多个I2C从机,但一直没弄成功,留待以后学习吧。好在单片机有2个I2C接口,温湿度传感器占了一个,显示屏就用了另一个I2C接口(I2C1 of STM32F103ZET6)。
OLED是自发光的,每个像素可以单独点亮。OLED屏可以看出是一个LED的点阵,在控制器中有一个等大的缓存(显存),每个bit控制OLED的一个像素。正常模式下,0表示灭,1表示亮;反显模式则反之。显示过程实际上就是控制器根据用户设置,把显存中的每个bit映射到屏幕上对应像素的过程。用户需要做的,主要是把要显示的信息文字点阵化,并存入缓存中的合适位置。
图2. OLED显示原理
现在用的这款OLED的控制器是SSD1306。根据手册,显示器的像素被划分成了多个PAGE(页)来管理,每页8行。比如:128×32的屏幕会被分为了4页,128×64的会被分成8页,以此类推。这样,每页上每列正好对应一个字节(8个bit)。控制器在往显存中写入数据时,就是按字节写入的,低位优先(参考图2的第123列)。控制器基于显存控制屏幕上的像素亮/灭时,是按照用户设定的扫描顺序,逐个字节依次扫描。比如默认的Page mode,就是从第一页的左侧第一列开始,向右逐列填充。扫描完一页,程序中需要定位到下一页,然后控制器继续从左到右进行扫描。
在对字符进行取模时,要按照上述显示时的扫描原理进行,才能正确显示。如图3所示。
图3. 点阵字取模方向和顺序
比如“温”字,取模结果如下:
{0x10,0x60,0x02,0x8C,0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00},{0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00},
换算成二进制,恰好是图1中所示的情况,1的位置亮,0的位置不亮。注意:低位优先,0x10=0b0001 0000,要从下向上排列(见图2中P1的第一列)。
用户程序控制显示的过程,实际上就是往显存中的对应位置,写入点阵化字符的过程。这项工作可以利用I2C外设的HAL_I2C_Mem_Write函数来完成。函数接口如下:
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
需要指定MCU的I2C句柄、OLED的通讯地址(写:0x78;读:079)、显存地址(命令:0x00;数据:0x40)、数据长度(I2C_MEMADD_SIZE_8BIT)、数据数量和超时时长。这个函数一次可以发送任意数量的指令/数据。
SSD1036控制器根据写入时指向的显存地址不同,来区分发送过来的是指令还是数据。指令直接送入控制单元,数据则存入显存。发送数据前要先发送指令,来定位数据的写入位置。
需要特别说明的是,OLED商家提供的例程和目前网上找到的例程,几乎无一例外都是基于模拟I2C来操作的,指令和数据都是一个字节一个字节发送的。这种思路如果照搬到HAL库中会导致程序执行效率降低,因为HAL库函数为了增强安全性,增加了许多验证操作。解决这个问题的办法,就是把尽可能多的数据或指令存到一个缓存数组中,然后调用HAL_I2C_Mem_Write,一次性发送过去。这样可以有效减少冗余验证,提高程序效率。具体实现方法,详见后面的代码部分。
留言与评论(共有 0 条评论) “” |