当前位置:   article > 正文

STM32开发基于SPI接口的OLED数据显示_stm32 oled spi

stm32 oled spi

摘要:进行对SPI串口的通信的学习,进而用STM32建立工程实现OLED的数据显示

一、 SPI简介

SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。

具体内容参考
SPI详细解释
串行通信_SPI通讯协议

二、 前期准备

  • 软件准备:Keil 5.28,FlyMcu v0.188(烧录软件),XCOM v2.6(串口通信软件)、PCtoLCD2002(汉字取模软件)

  • 硬件准备:stm32F103C8,AHT21B(温湿度采集模块),USB转TTL模块,0.96inch 7线S OLED

  • 代码工程准备:0.96inch SPI OLED Module

请大家在进行以下实验时对相关例程代码进行了学习,并可以在OLED上显示出汉字。

三、 0.96 inch 7线 OLED简介

  • 产品图片

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

  • 产品参数
名称参数
显示颜色白色、蓝色、黄蓝双色
SKUMSP096B 、MSP096W、 MSP096Y
尺寸0.96(inch)
类型OLED
驱动芯片SSD1306
分辨率128*64 (Pixel)
模块接口3-line、4-line SPI、IIC interface
有效显示区域(AA区)21.744x10.864 (mm)
触摸屏类型无触摸屏
触摸IC无触摸IC
模块PCB底板尺寸27.3x27.8 (mm)
视角>160°
工作电压3.3V~5V
工作温度-20℃~60℃
存储温度-30℃~70℃
功耗待定
产品重量(含包装)8(g)
  • 接口定义

在这里插入图片描述

1、本模块支持IIC、3线制SPI以及4线制SPI接口总线模式切换(如图2红框内所示),具体说明如下:
A、使用4.7K电阻只焊接R3、R4,则选择4线制SPI总线接口(默认);
B、使用4.7K电阻只焊接R2、R3,则选择3线制SPI总线接口;
C、使用4.7K电阻只焊接R1、R4、R6、R7、R8,则选择IIC总线接口
2、接口总线模式切换后,需要选择相应配套的软件和相应的接线引脚(如图1所示),模块才能正常运行。相应的接线引脚说明如下:
A、选择4线制SPI总线接口,所有的引脚都需要使用;
B、选择3线制SPI总线接口,只有DC引脚不需要使用(可以不接),其他引脚都需要使用;
C、选择IIC总线接口,只需要使用GND、VCC、D0、D1这四个引脚,同时将RES接高电平(可以接VCC),DC和CS接电源地;

序号模块引脚引脚说明
1GNDOLED电源地
2VCCOLED电源正(3.3V~5V)
3D0OLED SPI和IIC总线时钟信号
4D1OLED SPI和IIC总线数据信号
5RESOLED复位信号,低电平复位(选择IIC总线时,该引脚需要接高电平(可以接VCC))
6DCOLED命令/数据输入选择信号,高电平:数据,低电平:命令选择(3线制SPI总线时,该引脚不需要使用(可以不接);选择IIC总线时,该引脚需要接电源地)
7CSOLED片选信号,低电平使能(选择IIC总线时,该引脚需要接电源地)

以上0.96 inch OLED信息皆来自0.96inch SPI OLED Module,如有侵权,立即删除。

由于此次实验是使用默认4线SPI,无需进行电阻焊接。

四、 工程编译以及实验结果

平滑滚动参考0.96oled屏,驱动ssd1306 一些不常用的命令用法和效果

4.1 任务要求

  1. 显示自己的学号和姓名;
  2. 显示AHT21B的温度和湿度;
  3. 上下或左右的滑动显示长字符,比如“Hello,欢迎来到重庆交通大学物联网205实训室!”

4.2 实验代码

  • main.c
#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
#include "AHT20tem.h"

void gunon1()//水平滚动  SSD1306电机驱动可以实现平滑滚动,但是必须要先对显示屏内容进行书写缓存才可以实现平滑滚动的效果
{
	  OLED_WR_Byte(0x2e,OLED_CMD);//关滚动
    OLED_WR_Byte(0x2A,OLED_CMD);//29向右,2a向左
    OLED_WR_Byte(0x00,OLED_CMD);//A:空字节
    OLED_WR_Byte(0x00,OLED_CMD);//B:水平起始页
    OLED_WR_Byte(0x00,OLED_CMD);//C:水平滚动速度
    OLED_WR_Byte(0x07,OLED_CMD);//D:水平结束页
    OLED_WR_Byte(0x00,OLED_CMD);//E:每次垂直滚动位移
	  OLED_WR_Byte(0x2f,OLED_CMD);//开滚动

}

void gunon2(void)//垂直滚动
{
	  OLED_WR_Byte(0x2e,OLED_CMD);//关滚动
		OLED_WR_Byte(0x2A,OLED_CMD);//29向右,2a向左
    OLED_WR_Byte(0x00,OLED_CMD);//A:空字节
    OLED_WR_Byte(0x00,OLED_CMD);//B:水平起始页
    OLED_WR_Byte(0x00,OLED_CMD);//C:水平滚动速度
    OLED_WR_Byte(0x00,OLED_CMD);//D:水平结束页
    OLED_WR_Byte(0x01,OLED_CMD);//E:每次垂直滚动位移
	  OLED_WR_Byte(0x2f,OLED_CMD);//开滚动

}

void gunoff()//关滚动
{
		  OLED_WR_Byte(0x2e,OLED_CMD);//关滚动
}

int main(void)//主函数
{			  
	u8 i;
	delay_init();	    	       //延时函数初始化	  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  AHT20tem_init(); //AHT20初始化   
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0);             //清屏(全黑)   
	
	
	
	
	TEST_Chinese();//姓名+学号
	gunon1();//垂直滚动
	delay_ms(1000);
	delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);//延时
	gunoff();//关闭滚动
	OLED_Clear(0);//清屏
	
	
	
	TEST_English();          //欢迎来到**大学205实训室
	gunon1();
	delay_ms(1000);
	delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);//延时
	gunoff();//关闭滚动
	OLED_Clear(0);//清屏
	
	while(1) //进行温度显示
	{	


	for(i=0;i<5;i++)
	{
		TEST_Menu2();            //AHT20温湿度显示
		delay_ms(1000);
	}
		OLED_Clear(0); //清屏
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 显示姓名+学号
void TEST_Chinese(void)
{	

	GUI_ShowString(35,0,"63*******",8,1);
	GUI_ShowCHinese(20,10,24,"******",1);	
	GUI_ShowCHinese(45,35,24,"******",1);	
    delay_ms(1000);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 显示欢迎来到**大学205实训室
void TEST_English(void)
{

  GUI_ShowString(0,0,"Hello,",16,1);
	GUI_ShowCHinese(30,15,16,"欢迎来到**大学",1);	
	GUI_ShowString(0,46,"205",16,1);
	GUI_ShowCHinese(24,46,16,"实训室!",1);
  delay_ms(100);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • AHT21B温度采集代码
#include "AHT20tem.h"

//读取AHT20的状态寄存器
u8 AHT20_Read_Status(void)
{

	u8 Byte_first,flag;	
	IIC_Start();
    IIC_Send_Byte(0x71);
	flag=IIC_Wait_Ack();
	Byte_first = IIC_Read_Byte(flag);
		
	IIC_NAck();
	IIC_Stop();

	return Byte_first;
}

void AHT20_SendAC(void) //向AHT20发送AC命令
{

	IIC_Start();
	IIC_Send_Byte(0x70);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xac);//0xAC采集命令
	IIC_Wait_Ack();
	IIC_Send_Byte(0x33);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Stop();

}

void AHT20_Init(void)   //初始化AHT20
{	
	IIC_Init();
	IIC_Start();
	IIC_Send_Byte(0x70);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xa8);//0xA8进入NOR工作模式
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Stop();

	delay_ms(10);//延时10ms左右

	IIC_Start();
	IIC_Send_Byte(0x70);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xbe);//0xBE初始化命令,AHT20的初始化命令是0xBE,   AHT10的初始化命令是0xE1
	IIC_Wait_Ack();
	IIC_Send_Byte(0x08);//相关寄存器bit[3]置1,为校准输出
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Stop();
	delay_ms(10);//延时10ms左右
}

void AHT20tem_init()
{
	delay_ms(40);//刚上电,延时40ms才可以读取状态
	
    //首先发0x71读取状态字bit[3],如果=1,为校准输出,无须初始化!!!正常情况下读回来的状态是0x1C或者是0x18,读回来是0x80表示忙状态;
	if(!((AHT20_Read_Status()&0x08)==0x08))
	{
        AHT20_Init(); //初始化AHT20 
	}
}
    
void AHT20_Read_CTdata(u32 *ct) //没有CRC校验,直接读取AHT20的温度和湿度数据
{
	volatile u8  Byte_1th=0;
	volatile u8  Byte_2th=0;
	volatile u8  Byte_3th=0;
	volatile u8  Byte_4th=0;
	volatile u8  Byte_5th=0;
	volatile u8  Byte_6th=0;
	u32 RetuData = 0;
	u16 cnt = 0,flag;
	AHT20_SendAC();//向AHT20发送AC命令
	delay_ms(80);	//大约延时80ms
    cnt = 0;
	while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表示为空闲状态,若为1,表示忙状态
	{
		delay_ms(1);
		if(cnt++>=100) break;
	}
	IIC_Start();

	IIC_Send_Byte(0x71);
	
	flag=IIC_Wait_Ack();
	Byte_1th = IIC_Read_Byte(flag);//状态字
	Byte_2th = IIC_Read_Byte(flag);//湿度
	Byte_3th = IIC_Read_Byte(flag);//湿度
	Byte_4th = IIC_Read_Byte(flag);//湿度/温度
	Byte_5th = IIC_Read_Byte(flag);//温度
	Byte_6th = IIC_Read_Byte(!flag);//温度	
	IIC_Stop();

	RetuData = (RetuData|Byte_2th)<<8;
	RetuData = (RetuData|Byte_3th)<<8;
	RetuData = (RetuData|Byte_4th);
	RetuData =RetuData >>4;
	
	ct[0] = RetuData;//湿度
	
	
	RetuData = 0;
	RetuData = (RetuData|Byte_4th)<<8;
	RetuData = (RetuData|Byte_5th)<<8;
	RetuData = (RetuData|Byte_6th);
	RetuData = RetuData&0xfffff;
	ct[1] =RetuData; //温度
	
	//temphum_init();
	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 平滑水平滚动
void gunon1()//水平滚动  SSD1306电机驱动可以实现平滑滚动,但是必须要先对显示屏内容进行书写缓存才可以实现平滑滚动的效果
{
	  OLED_WR_Byte(0x2e,OLED_CMD);//关滚动
    OLED_WR_Byte(0x2A,OLED_CMD);//29向右,2a向左
    OLED_WR_Byte(0x00,OLED_CMD);//A:空字节
    OLED_WR_Byte(0x00,OLED_CMD);//B:水平起始页
    OLED_WR_Byte(0x00,OLED_CMD);//C:水平滚动速度
    OLED_WR_Byte(0x07,OLED_CMD);//D:水平结束页
    OLED_WR_Byte(0x00,OLED_CMD);//E:每次垂直滚动位移
	  OLED_WR_Byte(0x2f,OLED_CMD);//开滚动

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

其中汉字取模可以直接通过工具进行生成,所以不在此进行列出。

4.3 OLED与STM32连线

OLED模块stm32说明
VCCDC 5V/3.3VOLED屏电源
GNDGNDOLED屏电源地
D1PB15OLED屏SPI写信号
CSPB11OLED屏片选控制信号
RESPB12OLED屏复位控制信号
DCPB10OLED屏数据/命令选择控制信号
D0PB13OLED屏SPI时钟信号

4.4 实验效果展示

在这里插入图片描述

在这里插入图片描述

上图的时间以及星期,是直接显示的并没有接入互联网进行自动同步时间。

五、 总结

通过对SPI和OLED显示的学习,了解SPI高速串口的基本知识,也通过对OLED的显示学习了解到单片机在日常生活中使用的多样性。但实验其中也遇到了不少问题,特别感谢老师以及Bazinga223333博主的硬件支持以及软件工程编写上的帮助。同时通过视觉展示的效果也大大的激发了我对嵌入式学习的兴趣。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/713624
推荐阅读
相关标签
  

闽ICP备14008679号