一、简介
OLED(Organic Light-Emitting Diode),又称为有机电激光显示、有机发光半导体(Organic Electroluminescence Display,OLED)。OLED属于一种电流型的有机发光器件,是通过载流子的注入和复合而致发光的现象,发光强度与注入的电流成正比。OLED在电场的作用下,阳极产生的空穴和阴极产生的电子就会发生移动,分别向空穴传输层和电子传输层注入,迁移到发光层。当二者在发光层相遇时,产生能量激子,从而激发发光分子最终产生可见光。
OLED显示威廉希尔官方网站
与传统的LCD显示方式不同,无需背光灯,采用非常薄的有机材料涂层和玻璃基板(或柔性有机基板),当有电流通过时,这些有机材料就会发光。而且OLED显示屏幕可以做得更轻更薄,可视角度更大,并且能够显著的节省耗电量。
因此,在商业领域当中,POS机、复印机、ATM机中都可以安装小尺寸的OLED屏幕,由于OLED屏幕可弯曲、轻薄、抗衰性能强等特性,既美观又实用。大屏幕可以用作商务宣传屏,也可以用作车站、机场等广告投放屏幕,这是因为OLED屏幕广视角、亮度高、色彩鲜艳,视觉效果比LCD屏好很多。
本文基于瑞芯微RK2206芯片 + 鸿蒙LiteOS操作系统,通过i2c总线控制OLED,实现控制OLED显示功能。
二、硬件电路设计
模块整体硬件电路如下图所示:
图1 硬件电路图
由上图可以看出引脚连接情况:
引脚名称 | 功能描述 |
SCL | I2C时钟信号线 |
SDA | I2C数据信号线 |
GND | 电源地引脚 |
VCC | 电源输入引脚 |
OLED和小凌派-RK2206开发板硬件连接如下所示:
图2 OLED和小凌派-RK2206开发板实物连接图
三、OLED简介
我们选择的OLED为0.96寸OLED显示屏,型号为SSD1306,像素为128 * 64。
OLED液晶屏采用i2c通信方式,根据芯片手册说明,从设备地址为 `0x3C`。如下图所示:
四、程序设计1、初始化I2C
以下源代码为i2c初始化的代码。首先用 I2cIoInit()`函数将GPIO0_PC1复用为I2C1_SDA_M1,GPIO0_PC2复用为I2C1_SCL_M1。最后调用 `LzI2cInit()`函数初始化I2C1端口。
- 1.if (I2cIoInit(m_i2cBus) != LZ_HARDWARE_SUCCESS)
- 2.{
- 3. printf("%s, %d: I2cIoInit failed!", __FILE__, __LINE__);
- 4. return __FILE__;
- 5.}
- 6.if (LzI2cInit(OLED_I2C_BUS, m_i2c_freq) != LZ_HARDWARE_SUCCESS)
- 7.{
- 8. printf("%s, %d: I2cIoInit failed!", __FILE__, __LINE__);
- 9. return __FILE__;
- 10.}
复制代码 2、OLED命令函数实现
OLED液晶屏通过i2c与RK2206芯片进行通信。其中,通信数据部分第1字节为0x00,表示该数据下一个字节是命令(注意:在i2c通信中,该通信部分之前还有一个字节,即从设备地址+R/W)。
- 1.static inline void Write_IIC_Command(unsigned char IIC_Command)
- 2.{
- 3. unsigned char buffer[2];
- 4. unsigned int ret;
- 5.
- 6. /* 填充数据,第一个字节是通知OLED芯片,下一个字节是命令 */
- 7. buffer[0] = 0x00;
- 8. buffer[1] = IIC_Command;
- 9. ret = LzI2cWrite(OLED_I2C_BUS, OLED_I2C_ADDRESS, buffer, 2);
- 10. if (ret != 0)
- 11. {
- 12. printf("%s, %s, %d: LzI2cWrite failed(%d)!", __FILE__, __func__, __LINE__, ret);
- 13. }
- 14.}
复制代码 3、OLED数据函数实现OLED液晶屏通过i2c与RK2206芯片进行通信。其中,通信数据部分第1字节为0x40,表示该数据下一个字节是数据(注意:在i2c通信中,该通信部分之前还有一个字节,即从设备地址+R/W)。
- 1.static inline void Write_IIC_Data(unsigned char IIC_Data)
- 2.{
- 3. unsigned char buffer[2];
- 4. unsigned int ret;
- 5.
- 6. /* 填充数据,第一个字节是通知OLED芯片,下一个字节是数据 */
- 7. buffer[0] = 0x40;
- 8. buffer[1] = IIC_Data;
- 9. ret = LzI2cWrite(OLED_I2C_BUS, OLED_I2C_ADDRESS, buffer, 2);
- 10. if (ret != 0)
- 11. {
- 12. printf("%s, %s, %d: LzI2cWrite failed(%d)!", __FILE__, __func__, __LINE__, ret);
- 13. }
- 14.}
复制代码 4、OLED配置实现OELD液晶屏需要配置才能正常工作,具体配置内容如下所示:
- 1.LOS_Msleep(200);
- 2.
- 3.Oled_WR_Byte(0xAE, OLED_CMD); //--display off
- 4.Oled_WR_Byte(0x00, OLED_CMD); //---set low column address
- 5.Oled_WR_Byte(0x10, OLED_CMD); //---set high column address
- 6.Oled_WR_Byte(0x40, OLED_CMD); //--set start line address
- 7.Oled_WR_Byte(0xB0, OLED_CMD); //--set page address
- 8.Oled_WR_Byte(0x81, OLED_CMD); // contract control
- 9.Oled_WR_Byte(0xFF, OLED_CMD); //--128
- 10.Oled_WR_Byte(0xA1, OLED_CMD); //set segment remap
- 11.Oled_WR_Byte(0xA6, OLED_CMD); //--normal / reverse
- 12.Oled_WR_Byte(0xA8, OLED_CMD); //--set multiplex ratio(1 to 64)
- 13.Oled_WR_Byte(0x3F, OLED_CMD); //--1/32 duty
- 14.Oled_WR_Byte(0xC8, OLED_CMD); //Com scan direction
- 15.Oled_WR_Byte(0xD3, OLED_CMD); //-set display offset
- 16.Oled_WR_Byte(0x00, OLED_CMD); //
- 17.
- 18.Oled_WR_Byte(0xD5, OLED_CMD); //set osc division
- 19.Oled_WR_Byte(0x80, OLED_CMD); //
- 20.
- 21.Oled_WR_Byte(0xD8, OLED_CMD); //set area color mode off
- 22.Oled_WR_Byte(0x05, OLED_CMD); //
- 23.
- 24.Oled_WR_Byte(0xD9, OLED_CMD); //Set Pre-Charge Period
- 25.Oled_WR_Byte(0xF1, OLED_CMD); //
- 26.
- 27.Oled_WR_Byte(0xDA, OLED_CMD); //set com pin configuartion
- 28.Oled_WR_Byte(0x12, OLED_CMD); //
- 29.
- 30.Oled_WR_Byte(0xDB, OLED_CMD); //set Vcomh
- 31.Oled_WR_Byte(0x30, OLED_CMD); //
- 32.
- 33.Oled_WR_Byte(0x8D, OLED_CMD); //set charge pump enable
- 34.Oled_WR_Byte(0x14, OLED_CMD); //
- 35.
- 36.Oled_WR_Byte(0xAF, OLED_CMD); //--turn on oled panel
复制代码 5、OLED英文字符显示OLED显示英文字符的本质是:首先将OLED英文显示的点阵数据存放到一个变量中(即const unsigned char F6x8[][6],为6*8点阵大小的英文字符);其次在oled_show_char函数中,根据字符字体大小(目前只有6*8,有兴趣的读者可以自己去研究),选择合适的字符点阵。最后将对应的点阵数据通过命令+数据函数实现OLED液晶屏显示。
(1)英文字符显示函数
- 1./***************************************************************
- 2. * 函数名称: oled_show_char
- 3. * 说 明: oled显示字符
- 4. * 参 数:
- 5. * @x:字符的X轴坐标
- 6. * @y:字符的Y轴坐标
- 7. * @chr:字符
- 8. * @chr_size:字符的字体,包括12/16两种字体
- 9. * 返 回 值: 无
- 10. ***************************************************************/
- 11.void oled_show_char(uint8_t x, uint8_t y, uint8_t chr, uint8_t chr_size)
- 12.{
- 13. unsigned char c = 0, i = 0;
- 14.
- 15. c = chr - ' '; //得到偏移后的值
- 16.
- 17. if (x > (OLED_COLUMN_MAX - 1))
- 18. {
- 19. x = 0;
- 20. y = y + 2;
- 21. }
- 22.
- 23. if (chr_size == 16)
- 24. {
- 25. oled_set_pos(x, y);
- 26. for (i = 0; i < 8; i++)
- 27. {
- 28. oled_wr_byte(F8X16[c * 16 + i], OLED_DATA);
- 29. }
- 30. oled_set_pos(x, y + 1);
- 31. for (i = 0; i < 8; i++)
- 32. {
- 33. oled_wr_byte(F8X16[c * 16 + i + 8], OLED_DATA);
- 34. }
- 35. }
- 36. else
- 37. {
- 38. oled_set_pos(x, y);
- 39. for (i = 0; i < 6; i++)
- 40. {
- 41. oled_wr_byte(F6x8[c][i], OLED_DATA);
- 42. }
- 43.
- 44. }
- 45.}
复制代码(2)英文字符点阵
- 1.//常用ASCII表
- 2.//偏移量32
- 3.//ASCII字符集
- 4.//偏移量32
- 5.//大小:12*6
- 6./************************************6*8的点阵************************************/
- 7.const unsigned char F6x8[][6] =
- 8.{
- 9.0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
- 10.0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
- 11.0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
- 12.0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// #
- 13.0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $
- 14.0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// %
- 15.0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// &
- 16.0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// '
- 17.0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// (
- 18.0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// )
- 19.0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// *
- 20.0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// +
- 21.0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// ,
- 22.0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// -
- 23.0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// .
- 24.0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// /
- 25.0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
- 26.0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
- 27.0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
- 28.0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
- 29.0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
- 30.0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5
- 31.0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
- 32.0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7
- 33.0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8
- 34.0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
- 35.0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// :
- 36.0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ;
- 37.0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// <
- 38.0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// =
- 39.0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// >
- 40.0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ?
- 41.0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @
- 42.0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A
- 43.0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B
- 44.0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C
- 45.0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
- 46.0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E
- 47.0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F
- 48.0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G
- 49.0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
- 50.0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I
- 51.0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J
- 52.0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K
- 53.0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L
- 54.0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M
- 55.0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
- 56.0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
- 57.0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P
- 58.0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
- 59.0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R
- 60.0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S
- 61.0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T
- 62.0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
- 63.0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
- 64.0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W
- 65.0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X
- 66.0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y
- 67.0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z
- 68.0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [
- 69.0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55
- 70.0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ]
- 71.0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^
- 72.0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _
- 73.0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// '
- 74.0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a
- 75.0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b
- 76.0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c
- 77.0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d
- 78.0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e
- 79.0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f
- 80.0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g
- 81.0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h
- 82.0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i
- 83.0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j
- 84.0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k
- 85.0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l
- 86.0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m
- 87.0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n
- 88.0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o
- 89.0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p
- 90.0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q
- 91.0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r
- 92.0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s
- 93.0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t
- 94.0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
- 95.0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
- 96.0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
- 97.0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x
- 98.0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y
- 99.0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z
- 100.0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines
- 101.};
复制代码
四、编译过程1、搭建和下载源代码
我已将OpenHarmony源代码上传到Gitee社区中,大家可以根据以下网址下载。
https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk2206-openharmony3.0lts
2、打开sdk下面路径的文件
/vendor/lockzhiner/rk2206/samples/b5_oled/oled_example.c
注意:Gitee上的OLED控制案例为通用案例,请大家根据上述的需求修改相关源代码。
3、修改编译脚本
修改 vendor/lockzhiner/rk2206/sample 路径下 BUILD.gn 文件,指定 oled_example 参与编译。
"./b5_oled:oled_example",
修改 device/lockzhiner/rk2206/sdk_liteos 路径下 Makefile 文件,添加 -loled_example 参与编译。
hardware_LIBS = -lhal_iothardware -lhardware -loled_example
4、编译固件
hb set -root .
hb set
hb build -f
5、烧写固件
五、实验结果程序编译烧写到开发板后,按下开发板的RESET按键,实验结果如下所示: