【STM32】基于SPI总线的OLED显示屏与DHT20温湿度采集显示数据
一、SPI通讯协议
SPI是一个同步的数据总线,也就是说它是用单独的数据线
和一个单独的时钟信号
来保证发送端和接收端的完美同步
。
时钟是一个振荡信号,它告诉接收端在确切的时机对数据线上的信号进行采样。
产生时钟的一侧称为主机
,另一侧称为从机
。总是只有一个主机(一般来说可以是微控制器/MCU),但是可以有多个从机(后面详细介绍);
数据的采集时机可能是时钟信号的上升沿(从低到高)或下降沿(从高到低)。
具体要看对SPI的配置;
整体的传输大概可以分为以下几个过程:
- 主机先将NSS信号拉低,这样保证开始接收数据;
- 当接收端检测到时钟的边沿信号时,它将立即读取数据线上的信号,这样就得到了一位数据(1bit);
由于时钟是随数据一起发送的,因此指定数据的传输速度并不重要,尽管设备将具有可以运行的最高速度(稍后我们将讨论选择合适的时钟边沿和速度)。
- 主机发送到从机时:主机产生相应的时钟信号,然后数据一位一位地将从MOSI信号线上进行发送到从机;
- 主机接收从机数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过MISO信号线发送;
具体如下图所示;
注意,SPI是“全双工”(具有单独的发送和接收线路),因此可以在同一时间发送和接收数据,另外SPI的接收硬件可以是一个简单的移位寄存器。这比异步串行通信所需的完整UART要简单得多,并且更加便宜;
扫描二维码关注公众号,回复: 14838616 查看本文章
SPI特性
SPI总线包括4条逻辑线
,定义如下:
MISO:
Master input slave output
主机输入,从机输出(数据来自从机);
MOSI:Master output slave input
主机输出,从机输入(数据来自主机);
SCLK :Serial Clock
串行时钟信号,由主机产生发送给从机;
SS:Slave Select
片选信号,由主机发送,以控制与哪个从机通信,通常是低电平有效信号。
其他制造商可能会遵循其他命名规则,但是最终他们指的相同的含义。以下是一些常用术语
;
MISO也可以是SIMO,DOUT,DO,SDO或SO(在主机端);
MOSI也可以是SOMI,DIN,DI,SDI或SI(在主机端);
NSS也可以是CE,CS或SSEL;
SCLK也可以是SCK;
详细SPI协议介绍请点击SPI协议详解(图文并茂+超详细)
二、关于0.96英寸OLED模块
1.厂家资料 0.96inch SPI OLED Module 厂家资料
宽电压供电(3V~5V),兼容3.3V和5V逻辑电平,无需电平转换芯片
默认为4线制SPI总线,可以选择3线制SPI总线或者IIC总线
引脚说明
注意:
1、本模块支持IIC、3线制SPI以及4线制SPI接口总线模式切换(如图2红框内所示),具体说明如下:
A、使用4.7K电阻只焊接R3、R4,则选择4线制SPI总线接口(默认);
本实验采用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接电源地;
三、硬件连接
四、示例代码
下载厂家提供资料百度网盘资料下载
提取码:8520
打开0.96inch_OLED_Demo_STM32F103RCT6_Hardware_4-wire_SPI
编译烧录能够成功演示
五、代码修改与撰写
我们使用16*16点阵,采用C51格式
使用取模软件取模取模软件点击下载提取码:8520
在文字输入区中输入字符,按Ctrl+Enter
后,在取模方式中选择C51格式
即生成点阵序列
并将其写入oledfont.h
文件中
const typFNT_GB16 cfont16[] = {
"你",0x08,0x80,0x08,0x80,0x08,0x80,0x11,0xFE,0x11,0x02,0x32,0x04,0x34,0x20,0x50,0x20,
0x91,0x28,0x11,0x24,0x12,0x24,0x12,0x22,0x14,0x22,0x10,0x20,0x10,0xA0,0x10,0x40,
"好",0x10,0x00,0x10,0xFC,0x10,0x04,0x10,0x08,0xFC,0x10,0x24,0x20,0x24,0x20,0x25,0xFE,
0x24,0x20,0x48,0x20,0x28,0x20,0x10,0x20,0x28,0x20,0x44,0x20,0x84,0xA0,0x00,0x40,
",",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x10,0x00,0x20,0x00,0x00,0x00,
"未",0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,
0x03,0x80,0x05,0x40,0x09,0x20,0x11,0x10,0x21,0x08,0xC1,0x06,0x01,0x00,0x01,0x00,
"曾",0x08,0x20,0x04,0x40,0x3F,0xF8,0x21,0x08,0x29,0x28,0x25,0x48,0x3F,0xF8,0x00,0x00,
0x1F,0xF0,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,
"见",0x00,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,0x11,0x10,0x11,0x10,0x11,0x10,0x11,0x10,
0x11,0x10,0x12,0x90,0x12,0x90,0x04,0x80,0x04,0x80,0x08,0x82,0x30,0x82,0xC0,0x7E,
"面",0x00,0x00,0xFF,0xFE,0x02,0x00,0x02,0x00,0x04,0x00,0x3F,0xF8,0x24,0x48,0x24,0x48,
0x27,0xC8,0x24,0x48,0x24,0x48,0x27,0xC8,0x24,0x48,0x24,0x48,0x3F,0xF8,0x20,0x08,
"的",0x10,0x40,0x10,0x40,0x20,0x40,0x7E,0x7C,0x42,0x84,0x42,0x84,0x43,0x04,0x42,0x44,
0x7E,0x24,0x42,0x24,0x42,0x04,0x42,0x04,0x42,0x04,0x7E,0x04,0x42,0x28,0x00,0x10,
"你",0x08,0x80,0x08,0x80,0x08,0x80,0x11,0xFE,0x11,0x02,0x32,0x04,0x34,0x20,0x50,0x20,
0x91,0x28,0x11,0x24,0x12,0x24,0x12,0x22,0x14,0x22,0x10,0x20,0x10,0xA0,0x10,0x40,
}
实现代码
void TEST_MainPage(void)
{
GUI_ShowCHinese(5,20,16,"你好,未曾见面的你",1);//中文姓名
delay_ms(1500);
delay_ms(1500);
}
main.c文件
int main(void)
{
delay_init(); //延时函数初始化
OLED_Init(); //初始化OLED
OLED_Clear(0); //清屏(全黑)
while(1)
{
TEST_MainPage(); //界面显示
}
}
学号加姓名展示
六、屏幕歌词滚动
1、滚屏设置
水平左右移动
OLED_WR_Byte(0x2E,OLED_CMD); //关闭滚动
OLED_WR_Byte(0x26,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(0x07,OLED_CMD); //终止页 7
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
OLED_WR_Byte(0xFF,OLED_CMD); //虚拟字节
OLED_WR_Byte(0x2F,OLED_CMD); //开启滚动
垂直和水平滚动
OLED_WR_Byte(0x2e,OLED_CMD); //关闭滚动
OLED_WR_Byte(0x29,OLED_CMD); //水平垂直和水平滚动左右 29/2a
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
OLED_WR_Byte(0x00,OLED_CMD); //起始页 0
OLED_WR_Byte(0x07,OLED_CMD); //滚动时间间隔
OLED_WR_Byte(0x07,OLED_CMD); //终止页 1
OLED_WR_Byte(0x01,OLED_CMD); //垂直滚动偏移量
OLED_WR_Byte(0x2F,OLED_CMD); //开启滚动
在发送开始滚屏前要先传输好显示数据,如果在滚屏的时候传输显示数据RAM中的内容可能被损坏,无法正常显示。
2、代码撰写
在添加文字字模代码->oledfont.h文件
OLED显示函数test.c
void TEST_MainPage(void)
{
GUI_ShowCHinese(10,20,16,"我们有光明未来",1);
delay_ms(1500);
delay_ms(1500);
}
主函数main.c文件
#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
int main(void)
{
delay_init(); //延时函数初始化
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
OLED_Init(); //初始化OLED
OLED_Clear(0); //清屏(全黑)
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(0x07,OLED_CMD); //终止页 7
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
OLED_WR_Byte(0xFF,OLED_CMD); //虚拟字节
TEST_MainPage();
OLED_WR_Byte(0x2F,OLED_CMD); //开启滚动
}
七、展示
544c24c1c3889
八、DHT20温湿度采集显示数据
请参考博客STM32基于I2C温湿度采集
九、总结
此次实验是基于SPI的OLED显示屏与DHT20温湿度采集显示数据,既学习了SPI的知识,点亮了OLED屏幕,并且实现了滚动与刷屏,还将DHT20运用上,将两者结合运用。
十、参考资料
0.96inch SPI OLED Module 厂家资料
SPI协议详解(图文并茂+超详细)
【嵌入式16】STM32+OLED屏显应用实例
STM32实现OLED屏显示字符串