本节课将讲解如何基于CC2530来使用OLED显示屏来显示字符和图片。

视频讲解

https://www.bilibili.com/video/BV1k34y1D7Vz?p=18

OLED显示技术简介

(1)OLED的全称是Organic Light-Emitting Diode,也就是有机发光二尽管,具有自发光、广视角、高对比度和较低功耗等优点。

(2)开发套件里面配套的0.96寸OLED显示器的实物图如下图所示,它的分辨率是64×128像素,也就是纵向有64个像素点、横向有128个像素点。
第6章:OLED 显示器实验 - 图1

(3)显示器的技术参数如下:

  • 型号:0.96OLED12864
  • 尺寸:0.96寸
  • 像素:128×64
  • 接口:SPI
  • 针脚:GND、VCC、D0、D1、RES、DC和CS

    SPI通信协议简介

    SPI是一种跟UART类似的通信协议,它的全称是Serial Peripheral Interface,也就是串行外设接口,具有传输速度快、能够同时收发数据、发射端和接收端通信同步的特点。配套的OLED显示器用的就是SPI通信协议。

    字库与图库

    为了使OLED屏幕能够正确地显示各种字符或图片,还需要先准备好一套字库和图库,例如标准ASCII字库、汉字字库和自主制作的图库等。

    OLED 驱动 API

    为驱动OLED屏幕,笔者设计了相应驱动API供读者学习和使用。

OLED的驱动API可分为两个层次,分别是上层的OLED显示API下层的SPI驱动API,驱动API还需要字库和图库文件配合工作。这3者在本实验代码中的如图所示位置。
第6章:OLED 显示器实验 - 图2

OLED显示API简介
在配置好显示屏引脚和字库/图库文件后,调用OLED显示API即可在屏幕上显示指定的内容。打开OLED122864文件夹中的hal_oled12864.h文件,可以找到OLED显示API的定义代码:

  1. //2. 51单片机入门/6. 显示器实验/Workspace/code/HW_LCD/HAL_OLED/hal_oled12864.h
  2. /**
  3. * @fn halOLED12864Init
  4. *
  5. * @brief 初始化OLED12864显示器,在使用屏幕前必须先调用
  6. */
  7. void halOLED12864Init(void);
  8. /**
  9. * @fn halOLED12864ClearScreen
  10. *
  11. * @brief 清除屏幕上显示内容
  12. */
  13. void halOLED12864ClearScreen(void);
  14. /**
  15. * @fn halOLED12864Show
  16. *
  17. * @brief 在屏幕上显示字符串,支持的字符格式:1. 8×16 ASCII码;2. 16×16 汉字
  18. *
  19. * @param line - 参数值范围:0 ~ 3
  20. * @param column - 参数值范围:0 ~ 127
  21. * @param str - 待显示的字符串
  22. *
  23. * @warning 16×16汉字
  24. 的字库需要先在此文件中定义FONT_TABLE_CHINESE_16×16
  25. */
  26. void halOLED12864ShowX16(unsigned char line, unsigned char column, const unsigned char *str);
  27. /**
  28. * @fn halOLED12864ShowPicture
  29. *
  30. * @brief 在屏幕上显示图片
  31. *
  32. * @param x - 指定在横向从左边数起第x个像素开始显示图像,参数值范围:0 ~ 127
  33. * @param y - 指定在纵向从上边数起的第y个像素开始显示图像,参数值范围:0 ~ 64
  34. * @param picWidth - 图片的宽度,参数值范围:1~128
  35. * @param picHeight - 图片的高度,参数值范围:1~64
  36. * @param pic - 待显示的图片
  37. */
  38. void halOLED12864ShowPicture(unsigned char x, unsigned char y, unsigned char picWidth, unsigned char picHeight, const unsigned char *pic);

halOLED12864ShowX16 使用详解
OLED12864显示屏的分辨率为64x128像素,可以把其理解为64行和128列的二维表格。halOLED12864ShowX16函数支持显示8×16的标准ASCII字符和16×16的汉字,其中的8×16是指占据屏幕8行、16列的字体,16×16是指占据屏幕16行和16列的字体。因此可以理解为halOLED12864ShowX16函数支持在屏幕中显示4行ASCII字符或汉字,于是参数line的取值范围便是0~3,但是参数column仍是使用像素点来表示在横向第几个像素的位置开始显示字符,因此其取值范围为0~127。

显示屏引脚配置
在调用上述显示API前,需要先进行显示屏引脚配置,即将显示屏的引脚与CC2530的GPIO配置上。配套的0.96英寸OLED显示屏包含如下7个引脚:
(1)GND - 地线
(2)VCC - 电源(2.8~5.5v)
(3)SCL(D0) - SPI时钟
(4)SDA(D1) - SPI数据
(5)CS - SPI片选
(6)RES - 屏幕复位引脚
(7)DC - 数据或命令选择

打开hal_lcd_spi.h文件,可以看到如下引脚配置代码。

  1. //2.51单片机入门/6.显示器实验/Workspace/code/HW_LCD/HAL_LCD_SPI/hal_lcd_spi.h
  2. #ifdef HAL_LCD_SPI_SW
  3. /* SCL -> CC2530 P1_5 引脚*/
  4. #define HAL_LCD_SPI_SCK_PORT 1
  5. #define HAL_LCD_SPI_SCK_PIN 5
  6. /* SDA -> CC2530 P1_6 引脚*/
  7. #define HAL_LCD_SPI_SDA_PORT 1
  8. #define HAL_LCD_SPI_SDA_PIN 6
  9. #endif
  10. /* CS -> CC2530 P2_0 引脚*/
  11. #define HAL_LCD_SPI_CS_PORT 2
  12. #define HAL_LCD_SPI_CS_PIN 0
  13. /* DC -> CC2530 P1_4 引脚*/
  14. #define HAL_LCD_SPI_DC_PORT 1
  15. #define HAL_LCD_SPI_DC_PIN 4
  16. /* RES -> CC2530 P1_0 引脚*/
  17. #define HAL_LCD_SPI_RST_PORT 1
  18. #define HAL_LCD_SPI_RST_PIN 0

上述代码完成了5个引脚的配置,其中的VCC和GND引脚不用配置。如果需要修改引脚配置,那么直接修改上述代码右边的数字即可。

配置字库
在配置好引脚后,还需配置字库和图库,其中字库包括两种,分别是8×16标准ASCII字库、16×16中文字库,字库文件在本实验代码如图所示位置。
第6章:OLED 显示器实验 - 图3

在本课程配套的软件工具中,可以找到“字模软件2.2.zip”这个软件,它就是用来生成字库的。运行字模软件,如图所示。
第6章:OLED 显示器实验 - 图4
如您还没有下载本课程配套的软件工具,可以前往下载页下载:前往

8×16标准ASCII字库取模取模步骤如下:
(1)单击“参数设置”→“其他选项”,依次选择“纵向取模”、“字节倒序”和“保留”,如图所示。
第6章:OLED 显示器实验 - 图5
不同屏幕显示对字库的要求有所不同,配套的OLED显示屏要求“纵向取模”和“字节倒序”。

(2)在文字输入区输入想要取模的文字,输入后按一下Ctrl+Enter,如图所示。
第6章:OLED 显示器实验 - 图6

(3)单击“取模方式”→“C51 格式”,选择“点阵生成区”,即可看到成功生成的字模,如图所示。
第6章:OLED 显示器实验 - 图7

就这样,8×16字体对应的字库做好了。16×16汉字的取模方式与8×16字体基本一致,只需要依照相同的方式并且在输入区输入汉字即可。

配置图库
与自字体取模类似地,在基本操作处导入图片,然后参照字体取模流程操作即可完成图片的取模,如图所示。
第6章:OLED 显示器实验 - 图8

使用OLED显示API

在配置好显示屏引脚和字库文件后,调用OLED显示API即可在屏幕上显示内容。打开配套的实验代码,打开OLED12864文件夹中的main.c,可以看到使用OLED显示API的示例代码:

  1. //2. 51单片机入门/6. 显示器实验/Workspace/code/OLED12864/main.c
  2. void main(void)
  3. {
  4. setSystemClk32MHZ();//把系统频率设置为32MHz
  5. halOLED12864Init();//初始化
  6. while(1)
  7. {
  8. /* Test1 - 显示 8×16 的字符 */
  9. halOLED12864ShowX16(0, 0, "0123456789");//在第1行显示
  10. halOLED12864ShowX16(1, 0, "abcdefghiABCDE");//在第2行显示
  11. halOLED12864ShowX16(2, 0, "{}[]()!@#$%");//在第3行显示
  12. halOLED12864ShowX16(3, 0, "==========>");//在第3行显示
  13. delayMs(SYSCLK_32MHZ, 4000);//延迟
  14. halOLED12864ClearScreen();//清空
  15. /* Test2 - 显示 8×16 字符 和 16×16 汉字 */
  16. halOLED12864ShowX16(0, 0, "今天气温:");
  17. halOLED12864ShowX16(1, 30, "温度:22 ℃");
  18. halOLED12864ShowX16(2, 30, "湿度:30 %");
  19. /* 注意:对于汉字,必须先取字模后存放到汉字字库文件font_chinese_v_16x16.h中*/
  20. delayMs(SYSCLK_32MHZ, 4000);//延迟
  21. halOLED12864ClearScreen();//清空
  22. /* Test3 - 在坐标(30像素, 30像素)处显示分辨率为 32x32 像素的图片*/
  23. halOLED12864ShowPicture(30, 30, 32, 32, Picture_32x32_AppleIco);
  24. /*注意:对于图片,系需要先取模后存放在图库文件font_v_picture.h中*/
  25. delayMs(SYSCLK_32MHZ, 4000);//延迟
  26. halOLED12864ClearScreen();//清空
  27. /* Test4 - 全屏显示 128x64 图片,即在坐标(30像素, 30像素)处显示一张分辨率为128x64像素的图片 */
  28. halOLED12864ShowPicture(0, 0, 128, 64, Picture_128x128_SuccessPic);
  29. delayMs(SYSCLK_32MHZ, 4000);//延迟
  30. halOLED12864ClearScreen();//清空
  31. }
  32. }

在实际的开发过程中,开发者一般只要套用上述代码即可使用OLED屏幕,非常方便。

SPI 驱动 API 的设计原理

SPI 驱动 API 的设计原理较为复杂,读者简单了解其原理即可。
上文讲到,笔者设计的OLED屏幕的驱动API可分为两个层次,分别是上层的OLED显示API下层的SPI驱动API。这里简单地讲解一下本SPI驱动API的设计原理。

设计思想
笔者把SPI驱动API分为两个部分,分别是通用SPI驱动API专用SPI驱动API
(1)通用SPI驱动API适用于使用SPI通信的多种设备,图中的SPI_Driver文件夹存放的便是此部分API。
(2)专用SPI驱动API通用SPI驱动API的基础上,专门去适配特定的设备,例如配套的这个OLED显示屏。图中的hal_lcd_spi.h和hal_lcd_spi.c便是此部分API
第6章:OLED 显示器实验 - 图9
这样做的好处还是比较明显的,通用SPI驱动API可以在各种SPI设备中使用,只需要为这些设备增加对应的适配代码即可。

硬件和软件SPI模式的支持
在通用的SPI驱动API中,支持硬件SPI和软件SPI模式。硬件模式SPI是指利用利用硬件处理单元实现SPI协议,软件SPI模式是指通过编写程序代码的方式实现SPI。如图所示,hw_spi.h/c是基于硬件实现的SPI驱动API,sw_spi.h/c是软件模拟实现的SPI驱动API,如图所示。
第6章:OLED 显示器实验 - 图10

可以在适配程序hal_lcd_spi.h和hal_lcd_spi.c中通过配置的方式来选择使用哪种方式,如图所示。
第6章:OLED 显示器实验 - 图11

调试仿真

可以运行本实验代码以观察运行结果,操作步骤如下:
(1)把OLED屏幕插入到标准板或者Mini板中,如图所示。
第6章:OLED 显示器实验 - 图12
第6章:OLED 显示器实验 - 图13

(2)由于本实验需要用到SPI通信,因此如果使用ZigBee标准板测试,需要把拨码开关的第8、9和10位分别打到CLK、SDI和SDO端,如图所示。
第6章:OLED 显示器实验 - 图14

(3)编译链接本实验代码后,把程序烧录到配套的ZigBee开发板中,即可看到屏幕循环地显示相应的内容。