stm32基于SPI协议的OLED屏显

一、SPI

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

SPI 通讯设备之间的常用连接方式,如下图:
在这里插入图片描述
SPI 通讯的通讯时序,如下图所示:
在这里插入图片描述

二、使用SPI串口实现功能

一、显示自己的学号和姓名

先在取字模的软件,把自己名字的字模给生成
这里使用的是野火光盘里自带的PCtoLCD2002
在这里插入图片描述

在OLED官网下载例程:http://www.lcdwiki.com/zh/0.96inch_SPI_OLED_Module

在这里插入图片描述
在这里插入图片描述

连接方式:
在这里插入图片描述
main.c

#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
 
int main(void)
{
    
    	
	delay_init();	    	       //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级	
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0);             //清屏(全黑)
	while(1) 
	{
    
    	
		TEST_MainPage();         //主界面显示测试
		OLED_Clear(0); 
	}
}

test.c中改一下

void TEST_MainPage(void)
{
    
    	
	GUI_ShowString(20,0,"631807060113",8,1);
	GUI_ShowCHinese(16,20,16,"金孝文",1);
	delay_ms(1500);		
}

oledfont.h中改一下

const typFNT_GB16 cfont16[] = 
{
    
    
"金",0x01,0x00,0x01,0x00,0x02,0x80,0x04,0x40,0x08,0x20,0x10,0x10,0x2F,0xE8,0xC1,0x06,0x01,0x00,0x3F,0xF8,0x01,0x00,0x11,0x10,
0x09,0x10,0x09,0x20,0xFF,0xFE,0x00,0x00,/*"金",0*/
"孝",0x02,0x00,0x02,0x08,0x3F,0xD0,0x02,0x20,0x02,0x40,0xFF,0xFE,0x01,0x00,0x02,0x00,0x3F,0xE0,0x10,0x40,0x20,0x80,0x5F,0xFC,
0x80,0x80,0x00,0x80,0x02,0x80,0x01,0x00,/*"孝",1*/
"文",0x02,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x10,0x10,0x10,0x10,0x08,0x20,0x08,0x20,0x04,0x40,0x02,0x80,0x01,0x00,0x02,0x80,
0x04,0x40,0x08,0x20,0x30,0x18,0xC0,0x06,/*"文",2*/
};

显示效果:
在这里插入图片描述

二、显示AHT20的温度和湿度

这里显示AHT20的温度和湿度的代码使用之前的代码:stm32指南者基于I2C硬件协议的AHT20温湿度传感器的数据采集

将显示温湿度代码移植到oled显示的代码中
在这里插入图片描述
main.c


#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
#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();                  //读取温度并显示	
		delay_ms(1500);
	}
}

bsp_i2c.c中修改一下

uint8_t  t;
u8 *strTemp1;
u8 *strTemp2;
u8 *strTemp3;
u8 *strHumi1;
u8 *strHumi2;
u8 *strHumi3;
void read_AHT20(void)
{
    
    
	uint8_t i;

	//初始化 readByte 数组
	for(i=0; i<6; i++)
	{
    
    
		readByte[i]=0;
	}

	I2C_Start();

	//通过发送 0x71 可以获取一个字节的状态字
	I2C_WriteByte(0x71);
	ack_status = Receive_ACK();
	
	//接收 6 个 8 bit的数据
	readByte[0]= I2C_ReadByte();
	//发送 ACK 信号
	Send_ACK();

	readByte[1]= I2C_ReadByte();
	Send_ACK();

	readByte[2]= I2C_ReadByte();
	Send_ACK();

	readByte[3]= I2C_ReadByte();
	Send_ACK();

	readByte[4]= I2C_ReadByte();
	Send_ACK();

	readByte[5]= I2C_ReadByte();
	//发送 NACK 信号
	SendNot_Ack();

	I2C_Stop();

	//温湿度的二进制数据处理
	//0x68 = 0110 1000
  //0x08 = 0000 1000	
	if( (readByte[0] & 0x68) == 0x08 )
	{
    
    
		H1 = readByte[1];
		//H1 左移 8 位并与 readByte[2] 相或 
		H1 = (H1<<8) | readByte[2];
		H1 = (H1<<8) | readByte[3];
		//H1 右移 4 位
		H1 = H1>>4;

		H1 = (H1*1000)/1024/1024;

		T1 = readByte[3];
		//与运算
		T1 = T1 & 0x0000000F;
		T1 = (T1<<8) | readByte[4];
		T1 = (T1<<8) | readByte[5];

		T1 = (T1*2000)/1024/1024 - 500;

		AHT20_OutData[0] = (H1>>8) & 0x000000FF;
		AHT20_OutData[1] = H1 & 0x000000FF;

		AHT20_OutData[2] = (T1>>8) & 0x000000FF;
		AHT20_OutData[3] = T1 & 0x000000FF;
	}
	else
	{
    
    
		AHT20_OutData[0] = 0xFF;
		AHT20_OutData[1] = 0xFF;

		AHT20_OutData[2] = 0xFF;
		AHT20_OutData[3] = 0xFF;

	}
	/*
	printf("完成!\n");
	printf("----温度:%d%d.%d °C\n",T1/100,(T1/10)%10,T1%10);
	printf("----湿度:%d%d.%d %%",H1/100,(H1/10)%10,H1%10);
	printf("\n\n");
	*/
		t = T1/100;
	switch(t)
	{
    
    
		case 0:break;
		case 1:strTemp1 = "1";break;
		case 2:strTemp1 = "2";break;
		case 3:strTemp1 = "3";break;
		case 4:strTemp1 = "4";break;
		case 5:strTemp1 = "5";break;
		case 6:strTemp1 = "6";break;
		case 7:strTemp1 = "7";break;
		case 8:strTemp1 = "8";break;
		case 9:strTemp1 = "9";break;
	}
	t = (T1/10)%10;
	switch(t)
	{
    
    
		case 0:strTemp2 = "0";break;
		case 1:strTemp2 = "1";break;
		case 2:strTemp2 = "2";break;
		case 3:strTemp2 = "3";break;
		case 4:strTemp2 = "4";break;
		case 5:strTemp2 = "5";break;
		case 6:strTemp2 = "6";break;
		case 7:strTemp2 = "7";break;
		case 8:strTemp2 = "8";break;
		case 9:strTemp2 = "9";break;
	}
	t = T1%10;
	switch(t)
	{
    
    
		case 0:strTemp3 = "0";break;
		case 1:strTemp3 = "1";break;
		case 2:strTemp3 = "2";break;
		case 3:strTemp3 = "3";break;
		case 4:strTemp3 = "4";break;
		case 5:strTemp3 = "5";break;
		case 6:strTemp3 = "6";break;
		case 7:strTemp3 = "7";break;
		case 8:strTemp3 = "8";break;
		case 9:strTemp3 = "9";break;
	}
	t = H1/100;
	switch(t)
	{
    
    
		case 0:break;
		case 1:strHumi1 = "1";break;
		case 2:strHumi1 = "2";break;
		case 3:strHumi1 = "3";break;
		case 4:strHumi1 = "4";break;
		case 5:strHumi1 = "5";break;
		case 6:strHumi1 = "6";break;
		case 7:strHumi1 = "7";break;
		case 8:strHumi1 = "8";break;
		case 9:strHumi1 = "9";break;
	}
	t = H1/100;
	switch(t)
	{
    
    
		case 0:strHumi2 = "0";break;
		case 1:strHumi2 = "1";break;
		case 2:strHumi2 = "2";break;
		case 3:strHumi2 = "3";break;
		case 4:strHumi2 = "4";break;
		case 5:strHumi2 = "5";break;
		case 6:strHumi2 = "6";break;
		case 7:strHumi2 = "7";break;
		case 8:strHumi2 = "8";break;
		case 9:strHumi2 = "9";break;
	}
	t = H1/100;
	switch(t)
	{
    
    
		case 0:strHumi3 = "0";break;
		case 1:strHumi3 = "1";break;
		case 2:strHumi3 = "2";break;
		case 3:strHumi3 = "3";break;
		case 4:strHumi3 = "4";break;
		case 5:strHumi3 = "5";break;
		case 6:strHumi3 = "6";break;
		case 7:strHumi3 = "7";break;
		case 8:strHumi3 = "8";break;
		case 9:strHumi3 = "9";break;
	}
	GUI_ShowString(40,32,"    ",16,1);
	GUI_ShowString(40,48,"    ",16,1);
  GUI_ShowCHinese(0,32,16,"温度:",1);
	GUI_ShowString(40,32,strTemp1,16,1);
	GUI_ShowString(48,32,strTemp2,16,1);
	GUI_ShowString(56,32,".",16,1);
	GUI_ShowString(64,32,strTemp3,16,1);
	GUI_ShowCHinese(72,32,16,"℃",1);
  GUI_ShowCHinese(0,48,16,"湿度:",1);
	GUI_ShowString(40,48,strHumi1,16,1);
	GUI_ShowString(48,48,strHumi2,16,1);
	GUI_ShowString(56,48,".",16,1);
	GUI_ShowString(64,48,strHumi3,16,1);
	GUI_ShowCHinese(72,48,16,"%",1);
}

oledfont.h中修改一下

const typFNT_GB16 cfont16[] = 
{
    
    
	"温",0x00,0x00,0x23,0xF8,0x12,0x08,0x12,0x08,0x83,0xF8,0x42,0x08,0x42,0x08,0x13,0xF8,
  0x10,0x00,0x27,0xFC,0xE4,0xA4,0x24,0xA4,0x24,0xA4,0x24,0xA4,0x2F,0xFE,0x00,0x00,/*"温",0*/
	"度",0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x3F,0xFC,0x22,0x20,0x22,0x20,
  0x23,0xE0,0x20,0x00,0x2F,0xF0,0x24,0x10,0x42,0x20,0x41,0xC0,0x86,0x30,0x38,0x0E,/*"度",0*/
	"湿",0x00,0x00,0x27,0xF8,0x14,0x08,0x14,0x08,0x87,0xF8,0x44,0x08,0x44,0x08,0x17,0xF8,
  0x11,0x20,0x21,0x20,0xE9,0x24,0x25,0x28,0x23,0x30,0x21,0x20,0x2F,0xFE,0x00,0x00,/*"湿",0*/
	":",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,/*":",0*/
	"℃",0x60,0x00,0x91,0xF4,0x96,0x0C,0x6C,0x04,0x08,0x04,0x18,0x00,0x18,0x00,0x18,0x00,
  0x18,0x00,0x18,0x00,0x18,0x00,0x08,0x00,0x0C,0x04,0x06,0x08,0x01,0xF0,0x00,0x00,/*"℃",0*/
	"%",0x00,0x00,0x18,0x04,0x24,0x08,0x24,0x10,0x24,0x20,0x24,0x40,0x24,0x80,0x19,0x00,
  0x02,0x60,0x04,0x90,0x08,0x90,0x10,0x90,0x20,0x90,0x40,0x90,0x00,0x60,0x00,0x00,/*"%",0*/
};

显示效果:
在这里插入图片描述

三、上下或左右的滑动显示长字符

main.c

#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
#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) 
	{
    
    
		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(0x01,OLED_CMD);        //终止页 1
		OLED_WR_Byte(0x00,OLED_CMD);        //虚拟字节
		OLED_WR_Byte(0xFF,OLED_CMD);        //虚拟字节
		TEST_MainPage();                //显示文本
		OLED_WR_Byte(0x2F,OLED_CMD);        //开启滚动		
		delay_ms(1500);
		delay_ms(1500);

	}
}

test.c中修改一下

void TEST_MainPage(void)
{
    
    	
	  GUI_ShowCHinese(0,0,16,"欢迎来到重庆交通大学物联网205实训室",1);
	  delay_ms(1500);
	  delay_ms(1500);
}

oledfont.h中修改一下

const typFNT_GB16 cfont16[] = 
{
    
    
	"欢",0x00,0x80,0x00,0x80,0xFC,0x80,0x04,0xFC,0x05,0x04,0x49,0x08,0x2A,0x40,0x14,0x40,
	0x10,0x40,0x28,0xA0,0x24,0xA0,0x45,0x10,0x81,0x10,0x02,0x08,0x04,0x04,0x08,0x02,/*"欢",0*/
  "迎",0x00,0x00,0x20,0x80,0x13,0x3C,0x12,0x24,0x02,0x24,0x02,0x24,0xF2,0x24,0x12,0x24,
	0x12,0x24,0x12,0xB4,0x13,0x28,0x12,0x20,0x10,0x20,0x28,0x20,0x47,0xFE,0x00,0x00,/*"迎",1*/
	"来",0x01,0x00,0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x11,0x10,0x09,0x10,0x09,0x20,
	0xFF,0xFE,0x03,0x80,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00,0x01,0x00,/*"来",2*/
	"到",0x00,0x04,0xFF,0x84,0x08,0x04,0x10,0x24,0x22,0x24,0x41,0x24,0xFF,0xA4,0x08,0xA4,
	0x08,0x24,0x08,0x24,0x7F,0x24,0x08,0x24,0x08,0x04,0x0F,0x84,0xF8,0x14,0x40,0x08,/*"到",3*/
	"重",0x00,0x10,0x00,0xF8,0x3F,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00,0x1F,0xF0,0x11,0x10,
	0x1F,0xF0,0x11,0x10,0x1F,0xF0,0x01,0x00,0x3F,0xF8,0x01,0x00,0xFF,0xFE,0x00,0x00,/*"重",4*/
	"庆",0x01,0x00,0x00,0x80,0x3F,0xFE,0x20,0x00,0x20,0x80,0x20,0x80,0x20,0x80,0x2F,0xFC,
	0x20,0x80,0x21,0x40,0x21,0x40,0x22,0x20,0x42,0x20,0x44,0x10,0x88,0x08,0x10,0x06,/*"庆",5*/
	"交",0x02,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00,0x10,0x10,0x10,0x08,0x20,0x24,
	0x48,0x24,0x04,0x40,0x02,0x80,0x01,0x00,0x02,0x80,0x0C,0x40,0x30,0x30,0xC0,0x0E,/*"交",6*/
	"通",0x00,0x00,0x47,0xF8,0x20,0x10,0x21,0xA0,0x00,0x40,0x07,0xFC,0xE4,0x44,0x24,0x44,
	0x27,0xFC,0x24,0x44,0x24,0x44,0x27,0xFC,0x24,0x44,0x24,0x54,0x54,0x08,0x8F,0xFE,/*"通",7*/
	"大",0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,
	0x02,0x80,0x02,0x80,0x04,0x40,0x04,0x40,0x08,0x20,0x10,0x10,0x20,0x08,0xC0,0x06,/*"大",8*/
	"学",0x22,0x08,0x11,0x08,0x11,0x10,0x00,0x20,0x7F,0xFE,0x40,0x02,0x80,0x04,0x1F,0xE0,
	0x00,0x40,0x01,0x80,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00,/*"学",9*/
	"物",0x10,0x80,0x10,0x80,0x50,0x80,0x50,0xFC,0x7D,0x54,0x52,0x54,0x90,0x54,0x10,0x94,
	0x1C,0x94,0xF1,0x24,0x52,0x24,0x10,0x44,0x10,0x44,0x10,0x84,0x11,0x28,0x10,0x10,/*"物",10*/
	"联",0x00,0x88,0xFC,0x48,0x48,0x50,0x48,0x00,0x79,0xFC,0x48,0x20,0x48,0x20,0x78,0x20,
	0x4B,0xFE,0x48,0x20,0x4C,0x50,0x78,0x50,0xC8,0x88,0x08,0x88,0x09,0x04,0x0A,0x02,/*"联",11*/
	"网",0x00,0x00,0x7F,0xFC,0x40,0x04,0x40,0x04,0x42,0x14,0x52,0x94,0x4A,0x54,0x44,0x24,
	0x44,0x24,0x4A,0x54,0x4A,0x54,0x52,0x94,0x61,0x04,0x40,0x04,0x40,0x14,0x40,0x08,/*"网",12*/
	"实",0x02,0x00,0x01,0x00,0x7F,0xFE,0x40,0x02,0x88,0x84,0x04,0x80,0x04,0x80,0x10,0x80,
	0x08,0x80,0x08,0x80,0xFF,0xFE,0x01,0x40,0x02,0x20,0x04,0x10,0x18,0x08,0x60,0x04,/*"实",13*/
	"训",0x01,0x04,0x21,0x24,0x11,0x24,0x11,0x24,0x01,0x24,0x01,0x24,0xF1,0x24,0x11,0x24,
	0x11,0x24,0x11,0x24,0x11,0x24,0x15,0x24,0x19,0x24,0x12,0x24,0x02,0x04,0x04,0x04,/*"训",14*/
	"室",0x02,0x00,0x01,0x00,0x7F,0xFE,0x40,0x02,0x80,0x04,0x3F,0xF8,0x04,0x00,0x08,0x20,
	0x1F,0xF0,0x01,0x10,0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00,/*"室",15*/

};

显示效果:
在这里插入图片描述

三、总结

四、参考文献

通过SPI总线实现OLED屏幕显示
0.96inch SPI OLED Module
基于STM32的0.96寸OLED显示屏显示数据
STM32 SPI协议接口下的OLED屏显示
基于 SPI 协议在 0.96 寸 OLED上【平滑显示汉字】及【温湿度数据采集显示】

猜你喜欢

转载自blog.csdn.net/weixin_45888898/article/details/111593706