赞
踩
摘要:进行对SPI串口的通信的学习,进而用STM32建立工程实现OLED的数据显示
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上显示出汉字。
名称 | 参数 |
---|---|
显示颜色 | 白色、蓝色、黄蓝双色 |
SKU | MSP096B 、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接电源地;
序号 | 模块引脚 | 引脚说明 |
---|---|---|
1 | GND | OLED电源地 |
2 | VCC | OLED电源正(3.3V~5V) |
3 | D0 | OLED SPI和IIC总线时钟信号 |
4 | D1 | OLED SPI和IIC总线数据信号 |
5 | RES | OLED复位信号,低电平复位(选择IIC总线时,该引脚需要接高电平(可以接VCC)) |
6 | DC | OLED命令/数据输入选择信号,高电平:数据,低电平:命令选择(3线制SPI总线时,该引脚不需要使用(可以不接);选择IIC总线时,该引脚需要接电源地) |
7 | CS | OLED片选信号,低电平使能(选择IIC总线时,该引脚需要接电源地) |
以上0.96 inch OLED信息皆来自0.96inch SPI OLED Module,如有侵权,立即删除。
由于此次实验是使用默认4线SPI,无需进行电阻焊接。
#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); //清屏 } }
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);
}
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);
}
#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(); }
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);//开滚动
}
其中汉字取模可以直接通过工具进行生成,所以不在此进行列出。
OLED模块 | stm32 | 说明 |
---|---|---|
VCC | DC 5V/3.3V | OLED屏电源 |
GND | GND | OLED屏电源地 |
D1 | PB15 | OLED屏SPI写信号 |
CS | PB11 | OLED屏片选控制信号 |
RES | PB12 | OLED屏复位控制信号 |
DC | PB10 | OLED屏数据/命令选择控制信号 |
D0 | PB13 | OLED屏SPI时钟信号 |
上图的时间以及星期,是直接显示的并没有接入互联网进行自动同步时间。
通过对SPI和OLED显示的学习,了解SPI高速串口的基本知识,也通过对OLED的显示学习了解到单片机在日常生活中使用的多样性。但实验其中也遇到了不少问题,特别感谢老师以及Bazinga223333博主的硬件支持以及软件工程编写上的帮助。同时通过视觉展示的效果也大大的激发了我对嵌入式学习的兴趣。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。