欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SPI接口下的OLED显示

程序员文章站 2022-06-27 22:59:12
之前介绍了STM32数据传输的一种方式IIC,这次我将进行另外一种数据传输方式SPI。...

一、SPI简介:

1、spi:

SPI是一种同步、全双工、主从式接口。来自主机或从机的数据在时钟上升沿或下降沿同步。主机和从机可以同时传输数据。SPI接口可以是3线式或4线式。本文重点介绍常用的4线SPI接口。
接口:
SPI接口下的OLED显示

四线接口包括四个信号

  • 时钟(SPI CLK, SCLK)
  • 片选(CS)
  • 主机输出、从机输入(MOSI)
  • 主机输入、从机输出(MISO)

产生时钟信号的器件称为主机。主机和从机之间传输的数据与主机产生的时钟同步。同I2C接口相比,SPI器件支持更高的时钟频率。用户应查阅产品数据手册以了解SPI接口的时钟频率规格。

SPI接口只能有一个主机,但可以有一个或多个从机。图1显示了主机和从机之间的SPI连接。

来自主机的片选信号用于选择从机。这通常是一个低电平有效信号,拉高时从机与SPI总线断开连接。当使用多个从机时,主机需要为每个从机提供单独的片选信号。本文中的片选信号始终是低电平有效信号。

MOSIMISO数据线。MOSI将数据从主机发送到从机,MISO将数据从从机发送到主机。

2、IIC与SPI的区别:

相对优势:
IIC:

  • 总线拓扑结构:
    IIC只需两根信号线,而标准SPI至少四根信号,如果有多个从设备,信号需要更多。一些SPI变种虽然只使用三根线——SCLK、SS和双向的MISO/MOSI,但SS线还是要和从设备一对一根。另外,如果SPI要实现多主设备结构,总线系统需额外的逻辑和线路。用IIC构建系统总线唯一的问题是有限的7位地址空间,但这个问题新标准已经解决——使用10位地址。从第一点上看,IIC是明显的大赢家。
  • 优雅性:
    IIC常被称更优雅于SPI。IIC的优雅在于它的特色——用很轻盈的架构实现了多主设备仲裁和设备路由。但是对使用的工程师来讲,理解总线结构更费劲,而且总线的性能不高。

SPI:

  • 传输速率:
    如果应用中必须使用高速数据传输,那么SPI是必然的选择。因为SPI是全双工,IIC的不是。SPI没有定义速度限制,一般的实现通常能达到甚至超过10Mbps。IIC最高的速度也就快速+模式(1Mbps)和高速模式(3.4Mbps),后面的模式还需要额外的I/O缓冲区,还并不是总是容易实现的。
  • 易掌握性:
    SPI的优点在于它的结构相当的直观简单,容易实现,并且有很好扩展性。SPI的简单性不足称其优雅,因为要用SPI搭建一个有用的通信平台,还需要在SPI之上构建特定的通信协议软件。也就是说要想获得SPI特有而IIC没有的特性——高速性能,工程师们需要付出更多的劳动。另外,这种自定的工作是完全*的,这也说明为什么SPI没有官方标准。IIC和SPI都对低速设备通信提供了很好的支持,不过,SPI适合数据流应用,而IIC更适合“字节设备”的多主设备应用。

二、程序实现

1、下载文件

相应商家会附送文件,一般找他们要都可,我们使用的是0.96寸SPI 7针和0.96寸SPI4针。店铺地址在此
我在这单独再推荐一家店铺优信电子

2、查看文件以及文件解析

SPI接口下的OLED显示
文件主要包括这些
其中:
gui.c是商家编写好的一些OLED屏幕应用的函数。
OLED.c是OLED的一些基本定义函数。
spi.c是SPI数据传输的基础

gui.c
主要定义了一些显示数字,显示字符串,显示点,显示圆圈等一些函数,由商家定义,其实质上是对像素点的亮灭处理,用物理地址来表示该像素亮灭,然后由像素点的亮灭构成图像(由于OLED屏幕没有RGB显示的功能,所以数据传输量比较小)
SPI接口下的OLED显示
OLED.c
SPI接口下的OLED显示
这里写了一些OLED的控制函数,主要包括像素点状态控制的函数OLED_WR_Byte等,在.c文件里还定义了OLED屏幕的数组,如图:
SPI接口下的OLED显示
这里相当于一个初始化,将OLED屏幕初始化为灭的状态,所以里面幅值只有0和1,函数的对屏幕像素的控制也是对这个数组进行控制,0为灭,1为亮。

3、显示自己想要的字符

3.1 看看别人如何实现的

在之前我讲了OLED屏幕如何实现显示的大概原理,这一讲将从更加细致的地方来分析原理并实现自己想要的字符。
我们首先看看原程序,字符是怎么定义的
在gui.c包含的库文件里找到oledfont.h
SPI接口下的OLED显示
找到
SPI接口下的OLED显示
SPI接口下的OLED显示
发现它只是定义了一些十六进制数,细想一下2的4次方为16,4+4=8,832=1616=256,正好对应一个字符256个像素点,也就是我们只需要把一个十六进制数化成二进制,通过移位幅值就能实现对对像素点的控制了,比如0x03,二进制为00000011,那么只需要前面2个灯灭,后面6个灯亮就好了。
移位的话应该从右往左看
后面注释了一下表示哪些字符,于是
提出问题?
那是如何实现字符对应的呢(就是计算机如何知道这个字对应的就是哪些十六进制数的呢?)

3.2 定义自己的字符

这里介绍一个软件
SPI接口下的OLED显示

店铺会提供文件,店铺地址
设置方法里面有详解,这里直接看生成后的图:
SPI接口下的OLED显示
只需要把生成后的下面这些文件按照之前的格式复制过去就好了。
但是问题又来了,单片机是如何知道秒对应的这32个数为什么是,而不是另外定义的32个数呢?

3.3 添加属于自己的字符

通过查询程序可以知道,原函数是通过数组来定义的,就是通过他自己的定义,数组第一行就表示,但是这样极其不优雅,别人使用这个程序的时候又如何知道这个字符应该处于第几个呢。于是我们定义了一个新的结构体:
SPI接口下的OLED显示
再修改一下程序
SPI接口下的OLED显示
源代码

void GUI_ShowCHinese(u8 x,u8 y,u8 hsize,u8 *str,u8 mode)
{ 
	while(*str!='\0')
	{
		if(hsize == 16)
		{
			GUI_ShowFont16(x,y,str,mode);
		}
		else if(hsize == 24)
		{
			GUI_ShowFont24(x,y,str,mode);
		}
		else if(hsize == 32)
		{
			GUI_ShowFont32(x,y,str,mode);
		}
		else
		{
			return;
		}
		x+=hsize;
		if(x>WIDTH-hsize)
		{
			x=0;
			y+=hsize;
		}
		str+=2;
	}			
}

这样我们只需要对第一个字符进行搜索,然后就能找到对应的字符啦!!!
再从新顶一下数(格式如下:)
SPI接口下的OLED显示

3.4 最后实现效果:

主函数:

#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
#include "24cxx.h"	 
#include "AHT20.h"
struct m_AHT20 AHT20;
int main(void)
{	
	int c1,t1;
	delay_init();	    	       //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	IIC_Init();							//IIC初始化
	AHT20.alive=!AHT20_Init();	        //AHT20初始化
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0);             //清屏(全黑)
	while(1) 
	{	
		show_my_num(); //显示学号
		
		show_my_name();//显示姓名
		
		/*读取测量温湿度数据*/
		if(AHT20.alive)//是否存活
		{
			//读取其原始数据
			AHT20.flag = AHT20_ReadHT(AHT20.HT);
			c1 = AHT20.HT[0]*100*10/1024/1024/10;  //湿度
			t1 = (AHT20.HT[1]*200*10/1024/1024-500)/10;//温度计算公式
		}
		
		show_tem(c1,t1);//显示温湿度
		
		delay_ms(6000);
	}
}

次要函数:
SPI接口下的OLED显示
效果图:
SPI接口下的OLED显示
SPI接口下的OLED显示

四、总结

本次尝试非常成功,我也收获满满,期待下一次的探索!!!

本文地址:https://blog.csdn.net/qq_47343729/article/details/111999190

相关标签: 嵌入式 stm32