OLED屏显和汉字点阵编码

目录

一、SPI协议

(1)SPI协议简介

(2)SPI物理层

(3)协议层

(4)SPI 基本通讯过程

(5)CPOL/CPHA 及通讯模式

(6)通讯引脚

(7)SPI优缺点

 二、OLED

(1)OLED简介

(2)点阵编码原理与显示

(3)OLED 显示汉字

1、添加字模

2、修改显示函数

3、修改主函数

4、烧录

(4)OLED滑动显示字符

(5)oled显示温湿度

三、总结

四、参考


一、SPI协议

(1)SPI协议简介

SPI 协议是由摩托罗拉公司提出的通讯协议 (Serial Peripheral Interface),即串行外围设备接口,是 一种高速全双工的通信总线。它被广泛地使用在 ADC、LCD 等设备与 MCU 间,要求通讯速率 较高的场合。

(2)SPI物理层

SPI 通讯设备之间的常用连接方式如下

OLED屏显和汉字点阵编码_第1张图片

 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通讯的通讯时序如下

OLED屏显和汉字点阵编码_第2张图片

 这是一个主机的通讯时序。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 的“偶数边沿”采样。如下图

OLED屏显和汉字点阵编码_第3张图片

 我们来分析这个 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 的偶数边沿被采样,如下图

OLED屏显和汉字点阵编码_第4张图片

 由 CPOL 及 CPHA 的不同状态,SPI 分成了四种模式,见表 24‑1,主机与从机需要工作在相同的 模式下才可以正常通讯,实际中采用较多的是“模式 0”与“模式 3”。如下图

OLED屏显和汉字点阵编码_第5张图片

(6)通讯引脚

 SPI 的所有硬件架构都是从 MOSI、MISO、SCK 及 NSS 线展开的。STM32 芯片有多个 SPI 外设,它们的 SPI 通讯信号引出到不同的 GPIO 引脚上,使用时必须配置到这些指定的引脚,如下图。关于 GPIO 引脚的复用功能,可查阅《STM32F4xx规格书》,以它为准。

OLED屏显和汉字点阵编码_第6张图片

 注:其中 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屏

OLED屏显和汉字点阵编码_第7张图片

 (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生成字模

OLED屏显和汉字点阵编码_第8张图片

下载0.96寸OLED屏Demo程序,然后选择STM32F103RCT6,在模板上进行修改,下载链接如下

http://www.lcdwiki.com/res/Program/OLED/0.96inch/SPI_SSD1306_MSP096X_V1.0/0.96inch_SPI_OLED_Module_SSD1306_MSP096X_V1.0.zip

1、添加字模


打开上面下载的工程文件“0.96inch_OLED_Demo_STM32F103RCT6_Software_4-wire_SPI\PROJECT\OLED.uvprojx”,打开 gui.c 下的 oledfont.h 头文件,将 cfont16[] 数组内的内容修改成自己的中文文字点阵即可。

OLED屏显和汉字点阵编码_第9张图片

2、修改显示函数


将 test.c 里 void TEST_MainPage(void) 函数中的语句修改为自己的执行语句,如下:

OLED屏显和汉字点阵编码_第10张图片

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

3、修改主函数


将 main.c 代码中的 while 函数里除 TEST_MainPage(); 语句以外的语句删除,如下:

  OLED屏显和汉字点阵编码_第11张图片

4、烧录

编译后,将hex文件烧录进stm32中,效果如下

OLED屏显和汉字点阵编码_第12张图片

 完成

(4)OLED滑动显示字符

添加字模方式跟上面一样,如下

OLED屏显和汉字点阵编码_第13张图片

修改代码时,在 test.c 里 void TEST_MainPage(void) 函数中不用的语句删掉,添加自己的想要显示的字符

OLED屏显和汉字点阵编码_第14张图片

 将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显示时间

你可能感兴趣的:(stm32,arm,嵌入式硬件)