基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据

文章内容
理解 OLED 屏显和汉字点阵编码原理,使用 STM32F103 的 SPI 或 IIC 接口实现以下功能:

  1. 显示自己的学号和姓名;
  2. 显示 AHT20 的温度和湿度;
  3. 上下或左右的滑动显示长字符,或者一段歌词或诗词(最好使用硬件刷屏模式)。

目录

  • 1 SPI 协议
    • 1.1 SPI 协议简介
    • 2.2 SPI 物理层与协议层
    • 2.3 STM32 的 SPI 特性及架构
  • 2 OLED 显示实验
    • 2.1 具体要求
    • 2.2 准备工具
    • 2.3 硬件连接及说明
    • 2.4 代码实现
      • 2.4.1 Demo 程序
      • 2.4.2 OLED 显示汉字(姓名与学号)
      • 2.4.3 OLED 滑动显示字符
      • 2.4.4 OLED 显示温湿度数据
  • 3 总结
  • 4 参考链接

1 SPI 协议

1.1 SPI 协议简介

SPI 协议是由摩托罗拉公司提出的通讯协议,即串行外设接口(Serial Peripheral Interface),是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便。它被广泛地使用在 ADC、LCD 等设备与 MCU 间,要求通讯速率较高的场合。

SPI 和 I2C 的通信 2 种总线的异同点可以参看这篇博客:I2C和SPI总线对比。

2.2 SPI 物理层与协议层

  • SPI 物理层
    基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据_第1张图片
    SPI 通讯使用 3 条总线及片选线,3 条总线分别为 SCK、MOSI、MISO,片选线为 SS。

  • SPI 协议层
    基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据_第2张图片
    这是一个主机的通讯时序。NSS、SCK、MOSI 信号都由主机控制产生,而 MISO 的信号由从机产生,主机通过该信号线读取从机的数据。MOSI 与 MISO 的信号只在 NSS 为低电平的时候才有效,在 SCK 的每个时钟周期 MOSI 和 MISO 传输一位数据。

2.3 STM32 的 SPI 特性及架构

  • 与 I2C 外设一样,STM32 芯片也集成了专门用于 SPI 协议通讯的外设。
  • STM32 的 SPI 外设可用作通讯的主机及从机,支持最高的 SCK 时钟频率为 fpclk/2 (STM32F103 型号的芯片默认 fpclk1 为 72MHz,fpclk2 为 36MHz),完全支持 SPI 协议的 4 种模式,数据帧长度可设置为 8 位或 16 位,可设置数据 MSB 先行或 LSB 先行。它还支持双线全双工(前面小节说明的都是这种模式)、双线单向以及单线模式。其中双线单向模式可以同时使用 MOSI 及 MISO 数据线向一个方向传输数据,可以加快一倍的传输速度。而单线模式则可以减少硬件接线,当然这样速率会受到影响。我们只讲解双线全双工模式。

更多的 SPI 协议内容可以查看资料:《零死角玩转STM32—F103指南者.pdf》。

2 OLED 显示实验

2.1 具体要求

  • 显示自己的学号和姓名
  • 显示 AHT20 的温度和湿度
  • 上下或左右的滑动显示长字符,或者一段歌词或诗词(最好使用硬件刷屏模式)

2.2 准备工具

硬件工具:

  • STM32F103 开发板
  • AHT20 芯片(温湿度数据采集)
    AHT20 芯片的具体信息及参考代码参考官网介绍,链接:
    http://www.aosong.com/class-36.html
  • USB 转 TTL 模块
  • 杜邦线若干
  • PC 机(Win10)
  • 0.96寸OLED显示屏模块

软件工具:

  • keil 5 MDK
  • 烧录软件 mcuisp (提取码均为:luha)

2.3 硬件连接及说明

  • STM32F103 开发板与 OLED 模块连接
    基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据_第3张图片
  • 其他模块的具体连接参考上篇博客的第 2.4.1 部分:
    STM32 基于 I2C 通信协议的温湿度采集并串口显示
  • 使用硬件 SPI 通信

2.4 代码实现

2.4.1 Demo 程序

需要下载 0.96 寸 OLED 显示屏厂家给出的 Demo 程序。
程序下载链接:
0.96 寸 SPI_OLED 模块配套资料包。

  • 下载资料包之后打开其中的“0.96inch_SPI_OLED_Module_SSD1306_MSP096X_V1.0\1-Demo\Demo_STM32\0.96inch_OLED_Demo_STM32F103RCT6_Software_4-wire_SPI”。
    注意:我用的开发板是 STM32F103C8T6 芯片,所以这里我用的是这个文件里的代码,如果不一样,请选择与自己平台相同的实例文件。
  • 接下来只需要对 Demo 程序进行修改,就可以实现以下功能。

2.4.2 OLED 显示汉字(姓名与学号)

  • 2.4.2.1 获取汉字字模
    OLED 上可以直接显示数字和英文,但是为了在 OLED 上显示想要的汉字,就得自己对汉字进行编码成点阵,得到汉字的字模,存入代码中。
  1. 取字模软件下载链接:https://pan.baidu.com/s/1LJdX5ldRJghzivdjb4T3ig
    提取码:luha
  2. 打开程序,获取想要的汉字点阵
    基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据_第4张图片
    这里需要注意,我将文字进行了“左旋90度”、“垂直翻转”,这样在 OLED 屏上显示的文字才是正向的,这是因为 OLED 竖屏显示的原因。
  • 2.4.2.2 修改代码
  1. 添加字模
    打开上面下载的工程文件“0.96inch_OLED_Demo_STM32F103RCT6_Software_4-wire_SPI\PROJECT\OLED.uvprojx”,打开 gui.c 下的 oledfont.h 头文件,将 cfont16[] 数组内的内容修改成自己的中文文字点阵即可。
    基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据_第5张图片
    这里面是我存入的一些需要的字模,代码设计的只会从cfont16[] 数组内读取数据,所以需要将字模数据存取其中。

  2. 修改显示函数
    test.cvoid TEST_MainPage(void) 函数中的语句注释掉,添加自己的执行语句,如下:
    基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据_第6张图片

//主界面显示测试
void TEST_MainPage(void)
{	
	//GUI_ShowString(28,0,"OLED TEST",16,1);
	//GUI_ShowString(12,16,"0.96\" SSD1306",16,1);
	//GUI_ShowString(40,32,"64X128",16,1);
	//GUI_ShowString(4,48,"www.lcdwiki.com",16,1);
	GUI_ShowCHinese(40,16,16,"刘同学",1);
	GUI_ShowString(16,32,"631907030513",16,1);
	delay_ms(1500);		
	delay_ms(1500);
}

函数说明
① GUI_ShowString() 函数各参数分别对应:
X 坐标Y 坐标字符串(ASCLL码中的)、bit (表示字符显示格式,这里我用的 16 ,和汉字一样高)、显示样式(1:白字黑底;0:黑字白底)。
② GUI_ShowChinese() 函数各参数分别对应:
X 坐标Y 坐标汉字点阵大小(这里使用的是 16×16 的,参数应该是 16)、要显示的汉字显示样式(1:白字黑底;0:黑字白底)。

  1. 修改主函数
    main.c 代码中的 while 函数里除 TEST_MainPage(); 语句以外的语句全注释掉,如下:
    基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据_第7张图片
  • 2.4.2.3 编译烧录
    注意按照上面 2.3 部分的硬件连接说明将电路连接正确,并将编译的 hex 文件成功烧录到开发板上。
  • 2.4.2.4 汉字显示效果
    基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据_第8张图片
    可以看到,成功显示了名字和学号。

2.4.3 OLED 滑动显示字符

  • 2.4.3.1 添加字模
    跟上述方法一样,获取字模后,向 gui.c 下的 oledfont.h 头文件里的 cfont16[] 数组内的添加中文文字点阵即可。
    我这里添加了“欢、迎、阅、读、此、文、章”这 7 个字的点阵。
  • 2.4.3.2 修改代码
  1. 修改显示函数
    同上,在 test.cvoid TEST_MainPage(void) 函数中不用的语句注释掉,添加自己的想要显示的字符,如下:
void TEST_MainPage(void)
{	
	//GUI_ShowString(28,0,"OLED TEST",16,1);
	//GUI_ShowString(12,16,"0.96\" SSD1306",16,1);
	//GUI_ShowString(40,32,"64X128",16,1);
	//GUI_ShowString(4,48,"www.lcdwiki.com",16,1);
	GUI_ShowCHinese(10,16,16,"欢迎阅读此文章",1);
	//GUI_ShowCHinese(40,16,16,"刘同学",1);
	//GUI_ShowString(16,32,"631907030513",16,1);
	delay_ms(1500);		
	delay_ms(1500);
}
  1. 修改主函数
    main.c 代码中的 while 函数注释掉,再添加如下代码:
//从左到右滑动( OLED 屏的滚屏命令)
	OLED_WR_Byte(0x2E,OLED_CMD);        //关闭滚动
    OLED_WR_Byte(0x27,OLED_CMD);        //水平向左或者右滚动 26/27
    OLED_WR_Byte(0x00,OLED_CMD);        //虚拟字节
	OLED_WR_Byte(0x00,OLED_CMD);        //起始页 0
	OLED_WR_Byte(0x07,OLED_CMD);        //滚动时间间隔
	OLED_WR_Byte(0x07,OLED_CMD);        //终止页 7
	OLED_WR_Byte(0x00,OLED_CMD);        //虚拟字节
	OLED_WR_Byte(0xFF,OLED_CMD);        //虚拟字节
	TEST_MainPage();
	OLED_WR_Byte(0x2F,OLED_CMD);        //开启滚动

OLED 屏的滚屏命令:
本 OLED 屏的芯片类型是 SSD1306,其详细命令的介绍,可以参考下面链接去了解
https://wlink.blog.csdn.net/article/details/81329770

  • 2.4.3.3 编译烧录
    注意按照上面 2.3 部分的硬件连接说明将电路连接正确,并将编译的 hex 文件成功烧录到开发板上。

  • 2.4.3.4 滑动显示效果

    可以看到,文字内容已经在 OLED 上滑动显示。

2.4.4 OLED 显示温湿度数据

  • 2.4.4.1 添加字模
    跟上述方法一样,获取需要显示的字的字模后,向 gui.c 下的 oledfont.h 头文件里的 cfont16[] 数组内的添加中文文字点阵即可。
    我这里添加了“当、前、温、湿、度”这 5 个字的点阵。
  • 2.4.4.2 修改代码
  1. 移植 AHT20 温湿度采集代码
    查看上篇博客里的使用的工程文件,从里面移植下面 4 个文件:
    bsp_i2c.hbsp_i2c.c
    sys.h(移植后更改了名称为 AHT20_sys.h,不然会重名)、
    sys.c(移植后更改了名称为 AHT20_sys.c,不然会重名);
    并将bsp_i2c.c文件中的串口发送改为 OLED 显示 void Show_OLED(void) 即可。
    具体移植过程和修改可以参考这篇博客:基于 SPI 协议在 0.96 寸 OLED上【平滑显示汉字】及【温湿度数据采集显示】。
void Show_OLED(void)
{
	/*---
	------
	---*/
	GUI_ShowCHinese(28,10,16,"当前温湿度",1);
    GUI_ShowCHinese(20,32,16,"温度:",1);
	GUI_ShowString(60,32,strTemp1,16,1);
	GUI_ShowString(68,32,strTemp2,16,1);
	GUI_ShowString(76,32,".",16,1);
	GUI_ShowString(84,32,strTemp3,16,1);
	GUI_ShowCHinese(92,32,16,"℃",1);
    GUI_ShowCHinese(20,48,16,"湿度:",1);
	GUI_ShowString(60,48,strHumi1,16,1);
	GUI_ShowString(68,48,strHumi2,16,1);
	GUI_ShowString(76,48,".",16,1);
	GUI_ShowString(84,48,strHumi3,16,1);
	GUI_ShowCHinese(92,48,16,"%",1);
}

  1. 修改主函数
    main.c 代码中不用的函数注释掉,再修改代码,之后的结果如下:
#include "bsp_i2c.h"  //注意添加头文件
int main(void)
{	
	delay_init();	    	       //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	OLED_Init();			         //初始化OLED
	IIC_Init();                //初始化IIC
	OLED_Clear(0);             //清屏(全黑)
	while(1) 
	{
		read_AHT20_once();         //读取温度并显示
		OLED_Clear(0);             //清屏(全黑)		
		delay_ms(1500);
	}	

要注意添加头文件,调用温湿度读取并显示函数。

这里为大家提供一下我修改完的温湿度 OLED 显示工程文件:
链接:https://pan.baidu.com/s/1Dbg6Z-TkixAvsvip0SA9NQ
提取码:luha

  • 2.4.4.3 编译烧录
    注意按照上面 2.3 部分的硬件连接说明将电路连接正确,并将编译的 hex 文件成功烧录到开发板上。

  • 2.4.4.4 温湿度显示效果

可以看到,成功采集了温湿度数据并显示了温湿度信息,当用手捂住 AHT20 芯片,温湿度都升高了。

3 总结

文篇文章对 SPI 协议进行了简单介绍,并通过使用 SPI 通信方式对汉字和温湿度进行了显示,和上篇博客(利用 I2C 协议通信串口显示温湿度)比较,可见利用 SPI 总线传输速度明显更快。上面实现任务的代码,只是对已有代码的修改而已,没有更深入的理解 SPI 协议,如果需要了解详细的 SPI 协议应用,还需要继续学习。我也是 SPI 初学者,文章如有疑问,敬请读者指正。

4 参考链接

  1. 《零死角玩转STM32—F103指南者.pdf》
    提取码:luha
  2. SPI —百度百科
  3. 基于 SPI 协议在 0.96 寸 OLED上【平滑显示汉字】及【温湿度数据采集显示】
  4. 基于STM32的温湿度采集——OLED显示

你可能感兴趣的:(嵌入式,stm32,stm32,嵌入式硬件,spi,串口通信,传感器)