OLED屏显和汉字点阵编码
作者:互联网
目录
一、SPI协议
(1)SPI协议简介
SPI 协议是由摩托罗拉公司提出的通讯协议 (Serial Peripheral Interface),即串行外围设备接口,是 一种高速全双工的通信总线。它被广泛地使用在 ADC、LCD 等设备与 MCU 间,要求通讯速率 较高的场合。
(2)SPI物理层
SPI 通讯设备之间的常用连接方式如下
SPI 通讯使用 3 条总线及片选线,3 条总线分别为 SCK、MOSI、MISO,片选线为 SS ,它们的作 用介绍如下:
① SS*(* Slave Select):从设备选择信号线,常称为片选信号线,也称为 NSS、CS,以下用 NSS 表示。当有多个 SPI 从设备与 SPI 主机相连时,设备的其它信号线 SCK、MOSI 及 MISO 同时并联到相同的 SPI 总线上,即无论有多少个从设备,都共同只使用这 3 条总线;而每个从设备都有独立的这一条 NSS 信号线,本信号线独占主机的一个引脚,即有多少个从设 备,就有多少条片选信号线。I2C 协议中通过设备地址来寻址、选中总线上的某个设备并与其进行通讯;而 SPI 协议中没有设备地址,它使用 NSS 信号线来寻址,当主机要选择从设 备时,把该从设备的 NSS 信号线设置为低电平,该从设备即被选中,即片选有效,接着主机开始与被选中的从设备进行 SPI 通讯。所以 SPI 通讯以 NSS 线置低电平为开始信号,以 NSS 线被拉高作为结束信号。
② SCK (Serial Clock):时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了通讯的速 率,不同的设备支持的最高时钟频率不一样,如 STM32 的 SPI 时钟频率最大为 fpclk/2,两个设备之间通讯时,通讯速率受限于低速设备。
③ MOSI (Master Output,Slave Input):主设备输出/从设备输入引脚。主机的数据从这条信号线 输出,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。
④ MISO(Master Input,,Slave Output):主设备输入/从设备输出引脚。主机从这条信线读入数据, 从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。
(3)协议层
与 I2C 的类似,SPI 协议定义了通讯的起始和停止信号、数据有效性、时钟同步等环节。
(4)SPI 基本通讯过程
SPI通讯的通讯时序如下
这是一个主机的通讯时序。NSS、SCK、MOSI 信号都由主机控制产生,而 MISO 的信号由从机 产生,主机通过该信号线读取从机的数据。MOSI 与 MISO 的信号只在 NSS 为低电平的时候才有 效,在 SCK 的每个时钟周期 MOSI 和 MISO 传输一位数据。
(5)CPOL/CPHA 及通讯模式
上面讲述的图 24‑2 中的时序只是 SPI 中的其中一种通讯模式,SPI 一共有四种通讯模式,它们的 主要区别是总线空闲时 SCK 的时钟状态以及数据采样时刻。为方便说明,在此引入“时钟极性 CPOL”和“时钟相位 CPHA”的概念。 时钟极性 CPOL 是指 SPI 通讯设备处于空闲状态时,SCK 信号线的电平信号 (即 SPI 通讯开始前、 NSS 线为高电平时 SCK 的状态)。CPOL=0 时,SCK 在空闲状态时为低电平,CPOL=1 时,则相反。 时钟相位 CPHA 是指数据的采样的时刻,当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的“奇数边沿”被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边沿”采样。如下图
我们来分析这个 CPHA=0 的时序图。首先,根据 SCK 在空闲状态时的电平,分为两种情况。SCK 信号线在空闲状态为低电平时,CPOL=0;空闲状态为高电平时,CPOL=1。 无论 CPOL=0 还是 =1,因为我们配置的时钟相位 CPHA=0,在图中可以看到,采样时刻都是在 SCK 的奇数边沿。注意当 CPOL=0 的时候,时钟的奇数边沿是上升沿,而 CPOL=1 的时候,时钟的奇数边沿是下降沿。所以 SPI 的采样时刻不是由上升/下降沿决定的。MOSI 和 MISO 数据线的有效信号在 SCK 的奇数边沿保持不变,数据信号将在 SCK 奇数边沿时被采样,在非采样时刻, MOSI 和 MISO 的有效信号才发生切换。 类似地,当 CPHA=1 时,不受 CPOL 的影响,数据信号在 SCK 的偶数边沿被采样,如下图
由 CPOL 及 CPHA 的不同状态,SPI 分成了四种模式,见表 24‑1,主机与从机需要工作在相同的 模式下才可以正常通讯,实际中采用较多的是“模式 0”与“模式 3”。如下图
(6)通讯引脚
SPI 的所有硬件架构都是从 MOSI、MISO、SCK 及 NSS 线展开的。STM32 芯片有多个 SPI 外设,它们的 SPI 通讯信号引出到不同的 GPIO 引脚上,使用时必须配置到这些指定的引脚,如下图。关于 GPIO 引脚的复用功能,可查阅《STM32F4xx规格书》,以它为准。
注:其中 PF、PH 端口在 176 引脚型号的芯片才有。 其中 SPI1、SPI4、SPI5、SPI6 是 APB2 上的设备,最高通信速率达 42Mbtis/s,SPI2、SPI3 是 APB1 上的设备,最高通信速率为 21Mbits/s。其它功能上没有差异。
(7)SPI优缺点
优点
支持全双工通信
通信简单
数据传输速率块
缺点
没有指定的流控制,没有应答机制确认是否接收到数据,所以跟IIC总线协议比较在数据
可靠性上有一定的缺陷。
二、OLED
(1)OLED简介
OLED(Organic Light-Emitting Diode),又称为有机电激光显示、有机发光半导体(Organic Electroluminescence Display,OLED)。OLED属于一种电流型的有机发光器件,是通过载流子的注入和复合而致发光的现象,发光强度与注入的电流成正比。OLED在电场的作用下,阳极产生的空穴和阴极产生的电子就会发生移动,分别向空穴传输层和电子传输层注入,迁移到发光层。当二者在发光层相遇时,产生能量激子,从而激发发光分子最终产生可见光。
0.96寸七针OLED屏
(2)点阵编码原理与显示
汉字点阵编码
在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0 代表没有点,1 代表有点,将 0 和 1 分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有 1212, 1414, 16*16 三 种字库。
字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期 UCDOS 字库),纵向矩阵一 般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字库 矩阵做成纵向,省得在显示时还要做矩阵转换。
OLED点阵显示
点阵屏像素按128列X64行组织,每一行128个像素单元的阴极是连接在一起,作为公共极(COM),每一列64个像素单元的阳极也连接在一起,作为一段(SEG)。行列交叉点上的LED就是一个显示单元,即一个像素。要点亮一个像素,只要在该像素所在列电极上加上正电压、行电极接地。同样,要驱动一整行图像,就需要同时把128列信号加载到列电极上,把该行行电极接地。该行显示时,其他63行均不能显示,其行电极应为高电平或悬空。
可见,整屏的显示,只能分时扫描进行,一行一行的显示,每次显示一行。行驱依次产生低电平扫描各行,列驱动读取显示数据依次加载到列电极上。扫描一行的时间称为行周期,完成一次全屏扫描,就叫做一帧。一般帧频大于60,人眼观察不到逐行显示。每行扫描显示用时叫占空比,占空比小,为达到相同的显示亮度,驱动电流就大。SSD1306段驱动最大电流为100uA,当整行128个像素全部点亮时,行电极就要流过12.8mA的电流。
(3)OLED 显示汉字
为了在 OLED 上显示想要的汉字,需要对汉字进行点阵编码得到汉字的字模,然后存入代码中。
使用PCtoLCD生成字模
下载0.96寸OLED屏Demo程序,然后选择STM32F103RCT6,在模板上进行修改,下载链接如下
1、添加字模
打开上面下载的工程文件“0.96inch_OLED_Demo_STM32F103RCT6_Software_4-wire_SPI\PROJECT\OLED.uvprojx”,打开 gui.c 下的 oledfont.h 头文件,将 cfont16[] 数组内的内容修改成自己的中文文字点阵即可。
2、修改显示函数
将 test.c
里 void TEST_MainPage(void)
函数中的语句修改为自己的执行语句,如下:
函数说明:
① GUI_ShowString() 函数各参数分别对应:
X 坐标、Y 坐标、字符串(ASCLL码中的)、bit (表示字符显示格式,这里我用的 16 ,和汉字一样高)、显示样式(1:白字黑底;0:黑字白底)。
② GUI_ShowChinese() 函数各参数分别对应:
X 坐标、Y 坐标、汉字点阵大小(这里使用的是 16×16 的,参数应该是 16)、要显示的汉字、显示样式(1:白字黑底;0:黑字白底)。
3、修改主函数
将 main.c
代码中的 while
函数里除 TEST_MainPage();
语句以外的语句删除,如下:
4、烧录
编译后,将hex文件烧录进stm32中,效果如下
完成
(4)OLED滑动显示字符
添加字模方式跟上面一样,如下
修改代码时,在 test.c
里 void TEST_MainPage(void)
函数中不用的语句删掉,添加自己的想要显示的字符
将main.c中的main函数改为下列所示
int main(void)
{
delay_init(); //延时函数初始化
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
OLED_Init(); //初始化OLED
OLED_Clear(0); //清屏(全黑)
//从左到右滑动( 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); //开启滚动
}
编译烧录,成功
(5)oled显示温湿度
移植 AHT20 温湿度采集代码
查看上篇博客里的使用的工程文件,从里面移植下面 4 个文件:
bsp_i2c.h、bsp_i2c.c、
sys.h(移植后更改了名称为 AHT20_sys.h,不然会重名)、
sys.c(移植后更改了名称为 AHT20_sys.c,不然会重名);
并将bsp_i2c.c文件中的串口发送改为 OLED 显示 void Show_OLED(void) 即可。
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);
}
修改主函数
将 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);
}
要注意添加头文件,调用温湿度读取并显示函数。
编译烧录,成功
三、总结
学习了SPI协议,并且通过SPI协议对汉字和温湿度进行了显示,中途遇到了部分问题,例如汉字可能不显示的问题,也没有找到什么解决办法,如果有知道问题所在的大佬可以教教我
四、参考
(9条消息) 基于 SPI 协议用 0.96 寸 OLED 显示汉字及温湿度数据_L-GRAZY的博客-CSDN博客
(9条消息) 基于SPI通信方式的OLED显示_不#曾&轻听的博客-CSDN博客_oled spi通讯
(9条消息) 基于STM32的0.96寸OLED显示屏显示数据_Harriet的博客-CSDN博客_基于stm32的oled显示时间
标签:信号线,通讯,SPI,SCK,16,屏显,OLED,点阵 来源: https://blog.csdn.net/pink_lemon/article/details/121544199