stm32基于SPI通信实现OLED显示

一. SPI协议

1. 简介

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

SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是MISO(数据输入),MOSI(数据输出),SCLK(时钟),CS(片选)。

2. 连接方式

image-20211124094604845

  • SS( Slave Select):从设备选择信号线,常称为片选信号线。
  • SCK (Serial Clock):时钟信号线,用于通讯数据同步。
  • MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚。
  • MISO(Master Input,,Slave Output):主设备输入/从设备输出引脚。

3. 通讯过程

这是一个主机的通讯时序。NSS、SCK、MOSI 信号都由主机控制产生,而 MISO 的信 号由从机产生,主机通过该信号线读取从机的数据。MOSI 与 MISO 的信号只在 NSS 为低 电平的时候才有效,在 SCK 的每个时钟周期 MOSI 和 MISO 传输一位数据。

image-20211124094838607

  1. 标号 1 处,NSS 信号线由高变低,是 SPI 通讯的起始信号。NSS 是每个从机各自独占的信号线,当从机在自己的 NSS 线检测到起始信号后,就知道自己被主机选 中了,开始准备与主机通讯。

  2. 标号 6 处,NSS 信号由低变高,是 SPI 通讯的停止信号,表示本次通讯结束,从机的选中状态被取消。

  3. 标号 2 3 4 5 处,MOSI 及 MISO 的数据在 SCK 的上升沿期间变化输出,在 SCK 的下降沿时被采样。即在 SCK 的下降沿时刻,MOSI 及 MISO 的数据有效,高电平时 表示数据“1”,为低电平时表示数据“0”。在其它时刻,数据无效,MOSI及 MISO 为下 一次表示数据做准备。

4. 工作模式

为方便说明,在此引入时钟极性 CPOL时钟相位 CPHA 的概念。

  • 时钟极性 CPOL 是指 SPI 通讯设备处于空闲状态时,SCK 信号线的电平信号(即 SPI 通讯开始前、 NSS 线为高电平时 SCK 的状态)。CPOL=0 时, SCK 在空闲状态时为低电平,CPOL=1 时,则相反。
  • 时钟相位 CPHA 是指数据的采样的时刻,当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的“奇数边沿”被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边沿”采样。

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

image-20211124095424287

5. 优缺点

  • SPI 优点

支持全双工通信
通信简单
数据传输速率块

  • SPI 缺点

没有指定的流控制,没有应答机制确认是否接收到数据,所以跟IIC总线协议比较在数据
可靠性上有一定的缺陷。

二. OLED

OLED显示屏介绍:0.96inch SPI OLED Module - LCD wiki

你可以在该链接中下载相关手册及配套程序

我使用的是 0.96寸 7针OLED显示屏,此次实验都是在OLED配套程序上进行添加修改。

三. OLED显示

7针OLED显示屏接线。我使用的是 stmf103c8t6芯片 ,也是按这个接线。

其它芯片查看文档:0.96inch_OLED_SPI_Module_MSP096X_User_Manual_CN.pdf (lcdwiki.com)

image-20211124225349231

也可以查看自己下载的配套程序的主文件 main.c 中 有接线方法

image-20211124225847303

1. 显示姓名学号

调用函数即可。

//显示姓名学号
void showNameID()
{
    
    
	GUI_ShowString(28,10,"631900022222",8,1);
	GUI_ShowCHinese(28,30,16,"缔宇",1);    //这里使用 16*16 的矩阵
}

由于我们要显示汉字,所以先要进行汉字取模。

软件也是可以在前面OLED显示屏链接中下载 。

汉字取模软件 PCtoLCD2002 :
http://www.lcdwiki.com/res/software/PCtoLCD2002.zip

打开软件,点击 选项

image-20211124230813554

image-20211124231033215


将生成的字模放入配套程序中的 oledfont.h 文件相关函数中

我汉字取得是 16*16 ,所以放入图中的函数

image-20211124231259026

image-20211124231417265

最后效果

image-20211124231800182

2. 显示AHT20的温度和湿度

这里更改配套相关示例函数。

这里通过 I2C协议读取 AHT20 的温度湿度。

AHT20以及I2C协议的代码,OLED配套代码是没有的,需要自己编写或引入。

这一块的代码可以参考:基于I2C通信协议的温湿度采集_不#曾&轻听的博客-CSDN博客

文末我会给出完整代码。

//显示AHT20的温度湿度
void showAHT20()
{
    
    
	u32 CT_data[2];
    volatile int  c1=0,t1=0;    
	srand(123456);
	delay_ms(40);
	AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
	c1 = CT_data[0]*100*10/1024/1024;    //湿度
    t1 = CT_data[1]*200*10/1024/1024-500; //温度
	
	GUI_DrawLine(0, 10, WIDTH-1, 10,1);
	GUI_DrawLine(WIDTH/2-1,11,WIDTH/2-1,HEIGHT-1,1);
	GUI_DrawLine(WIDTH/2-1,10+(HEIGHT-10)/2-1,WIDTH-1,10+(HEIGHT-10)/2-1,1);
	
	GUI_ShowString(0,1,"2021-11-23",8,1);
	GUI_ShowString(74,1,"Tuesday",8,1);
	GUI_ShowString(14,HEIGHT-1-10,"Cloudy",8,1);
	GUI_ShowString(WIDTH/2+1,13,"TEMP",8,1);	//显示温度
	GUI_DrawCircle(WIDTH-20, 25, 1,2);
	GUI_ShowString(WIDTH-15,20,"C",16,1);
	GUI_ShowNum(WIDTH/2+8,20,t1/10,2,16,1);
	GUI_ShowString(WIDTH-41,26,".",8,1);
	GUI_ShowNum(WIDTH-35,20,t1%10,1,16,1);
	
	GUI_ShowString(WIDTH/2+1,39,"HUM",8,1);		//显示湿度
	GUI_ShowNum(WIDTH/2+8,46,c1/10,2,16,1);
	GUI_ShowString(WIDTH-41,52,".",8,1);
	GUI_ShowNum(WIDTH-35,46,c1%10,1,16,1);
	GUI_ShowString(WIDTH-21,46,"%",16,1);
	GUI_DrawBMP(6,16,51,32, BMP5, 1);
	delay_ms(1000);
}

最后效果:

有一点黑屏效果是使用摄像头录制导致的,实际是看不出的。
aht20

3. 上下或左右的滑动显示长字符

如果将你在 main函数的while循环中调用此函数,你需要添加代码中的延时。在while循环外调用,可以去掉延时。

要显示汉字,所以需要进行汉字取模,前面显示姓名学号部分已经有示例了,就不再示范。

//水平向左滚动显示数据
void showScroll()
{
    
    
	GUI_ShowCHinese(10,30,16,"欢迎来到信息科学与工程学院",1);
	OLED_horizontal_scroll();   //这个需要根据OLED内置芯片手册自己写
	delay_ms(1000);
	delay_ms(1000);
	delay_ms(1000);
	delay_ms(1000);
	delay_ms(1000);
	delay_ms(1000);
}

滚动函数:

可以查看我的另一篇博客进行编写:OLED显示屏滚动函数编写_diyu-CSDN博客

也可以自己根据手册写:SSD1780 (lcdwiki.com)

//OLED水平滚动
void OLED_horizontal_scroll()
{
    
    
	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);        //滚动间隔 2帧
	OLED_WR_Byte(0x07,OLED_CMD);        //终止页 7
	OLED_WR_Byte(0x00,OLED_CMD);        //虚拟字节
	OLED_WR_Byte(0xFF,OLED_CMD);        //虚拟字节
	OLED_WR_Byte(0x2F,OLED_CMD);        //开启滚动
}

最后效果:

有一点黑屏效果是使用摄像头录制导致的,实际是看不出的。
请添加图片描述

四.逻辑分析仪分析协议波形

打开逻辑分析仪。选择协议

image-20211125104854949

  • I2C协议波形

image-20211125105111044

  • SPI协议波形

image-20211125105457911

  • 串口波形

image-20211125110714466

五. 总结

总体而言,还是不难的,基本就是查看手册以及调用现有函数。


六. 全部代码

资源免费下载: 0.96_OLED_SPI.zip-嵌入式文档类资源-CSDN文库

不过我后来才发现,只有会员才可以下载

因此,我补上gitee链接
https://gitee.com/diyugreat/stm32.git
下载后 文件夹名为 0.96_OLED_SPI 的则为此次工程代码。


参考资料:

猜你喜欢

转载自blog.csdn.net/qq_45945548/article/details/121531521