本文将会使用STM32F103的SPI或IIC接口实现以下功能:1) 显示自己的学号和姓名;
2) 显示AHT20的温度和湿度;3) 上下或左右的滑动显示长字符或者一段歌词或诗词(最好使用硬件刷屏模式)。
目录
一、SPI的介绍
1.什么是SPI
SPI是一个同步的数据总线,也就是说它是用单独的数据线和一个单独的时钟信号来保证发送端和接收端的完美同步。
时钟是一个振荡信号,它告诉接收端在确切的时机对数据线上的信号进行采样。产生时钟的一侧称为主机,另一侧称为从机。总是只有一个主机(一般来说可以是微控制器/MCU),但是可以有多个从机;数据的采集时机可能是时钟信号的上升沿(从低到高)或下降沿(从高到低)。
2.SPI的传输过程
整体的传输大概可以分为以下几个过程:
- 主机先将NSS信号拉低,这样保证开始接收数据;
- 当接收端检测到时钟的边沿信号时,它将立即读取数据线上的信号,这样就得到了一位数据(1bit);
由于时钟是随数据一起发送的,因此指定数据的传输速度并不重要,尽管设备将具有可以运行的最高速度(稍后我们将讨论选择合适的时钟边沿和速度)。 - 主机发送到从机时:主机产生相应的时钟信号,然后数据一位一位地将从MOSI信号线上进行发送到从机;
- 主机接收从机数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过MISO信号线发送;
具体如下图所示;
注意,SPI是“全双工”(具有单独的发送和接收线路),因此可以在同一时间发送和接收数据,另外SPI的接收硬件可以是一个简单的移位寄存器。这比异步串行通信所需的完整UART要简单得多,并且更加便宜;
3.SPI四条逻辑线
SPI总线包括4条逻辑线,定义如下:
MISO
:Master input slave output 主机输入,从机输出(数据来自从机);
MOSI
:Master output slave input 主机输出,从机输入(数据来自主机);
SCLK
:Serial Clock 串行时钟信号,由主机产生发送给从机;
SS
:Slave Select 片选信号,由主机发送,以控制与哪个从机通信,通常是低电平有效信号。
4.SPI特点
可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。
二、OLED的介绍
1.什么是OLED
OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。OLED显示技术具有自发光的特性,采用非常薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光,而且OLED显示屏幕可视角度大,并且能够节省电能。
2.ALINETEK 的 OLED 显示模块
我们使用的是 ALINETEK 的 OLED 显示模块,该模块有以下特点:
1)模块有单色和双色两种可选,单色为纯蓝色,而双色则为黄蓝双色。
2)尺寸小,显示尺寸为 0.96 寸,而模块的尺寸仅为 27mmx26mm 大小。
3)高分辨率,该模块的分辨率为128x64。
4)多种接口方式,该模块提供了总共 5 种接口包括:6800、8080 两种并行接口方式、3线或 4 线的穿行 SPI 接口方式、IIC 接口方式(只需要 2 根线就可以控制 OLED 了)。
5)不需要高压,直接接 3.3V 就可以工作了。
注意该模块不和 5.0V 接口兼容,所以在使用的时候一定要小心,勿直接接到 5V 的系统上去,否则可能烧坏模块。以上4种模式通过模块的BS02设置,BS02的设置与模块接口模式的关系如表所示:
3.OLED模块实物图与原理图
该模块采用 8*2 的 2.54 排针与外部连接,总共有 16 个管脚,在 16 条线中,我们只用了 15条,有一个是悬空的。15 条线中,电源和地线占了 2 条,还剩下 13 条信号线。在不同模式下,我们需要的信号线数量是不同的,在 8080 模式下,需要全部 13 条,而在 IIC 模式下,仅需要2条线就够了!这其中有一条是共同的,那就是复位线 RST(RES),RST 上的低电平,将导致 OLED 复位,在每次初始化之前,都应该复位一下 OLED 模块。下面是OLED模块的具体实物图:
下面是OLED模块的具体原理图:
参考文章OLED显示模块原理
0.96寸OLED显示屏相关介绍可参考链接:
http://www.lcdwiki.com/zh/0.96inch_SPI_OLED_Module
三、STM32+OLED显示个人学号姓名
1.文字取模
利用取模软件将需要显示的文字用十六进制表示出来,取模软件会放在文章最后资料链接中。
软件初始设置,自定义取模方式
在文字输入区输入目标文字,并ctrl+enter
,得到显示图
点击C51格式,即可生成点阵
2.编写代码
内容显示 TEST_MainPage函数->test.c文件
void TEST_MainPage(void)
{
// GUI_ShowString(28,0,"abc",16,1);//英文姓名
GUI_ShowCHinese(28,20,16,"南南南",1);//中文姓名
GUI_ShowString(4,48,"12345678910",16,1);//数字详细
delay_ms(1500);
delay_ms(1500);
}
文字存储(举例)->oledfont.h文件
const typFNT_GB16 cfont16[] =
{
"南",0x20,0x27,0x24,0x24,0x26,0x25,0x24,0xFC,0x24,0x25,0x26,0x24,0x24,0x27,0x20,0x00,
0x00,0xFF,0x00,0x10,0x90,0x90,0x90,0xFE,0x90,0x90,0x90,0x12,0x01,0xFE,0x00,0x00,
"南",0x20,0x27,0x24,0x24,0x26,0x25,0x24,0xFC,0x24,0x25,0x26,0x24,0x24,0x27,0x20,0x00,
0x00,0xFF,0x00,0x10,0x90,0x90,0x90,0xFE,0x90,0x90,0x90,0x12,0x01,0xFE,0x00,0x00,
"南",0x20,0x27,0x24,0x24,0x26,0x25,0x24,0xFC,0x24,0x25,0x26,0x24,0x24,0x27,0x20,0x00,
0x00,0xFF,0x00,0x10,0x90,0x90,0x90,0xFE,0x90,0x90,0x90,0x12,0x01,0xFE,0x00,0x00,
};
主函数->main.c文件
int main(void)
{
delay_init(); //延时函数初始化
OLED_Init(); //初始化OLED
OLED_Clear(0); //清屏(全黑)
while(1)
{
TEST_MainPage(); //界面显示
}
}
编译后无误
3.电路连接
使用的是七线OLED
接线如图所示
实物连接:
4.运行效果
四、STM32+OLED显示AHT20的温度和湿度
1.文字取模
取模步骤与上相同
2.编写代码
温湿度显示read_AHT20函数->bsp_i2c.c文件
void read_AHT20(void)
{
uint8_t i;
for(i=0; i<6; i++)
{
readByte[i]=0;
}
//-------------
I2C_Start();
I2C_WriteByte(0x71);
ack_status = Receive_ACK();
readByte[0]= I2C_ReadByte();
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();
SendNot_Ack();
//Send_ACK();
I2C_Stop();
//--------------
if( (readByte[0] & 0x68) == 0x08 )
{
H1 = readByte[1];
H1 = (H1<<8) | readByte[2];
H1 = (H1<<8) | readByte[3];
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("lyy");
}
/*通过串口显示采集得到的温湿度
printf("\r\n");
printf("温度:%d%d.%d",T1/100,(T1/10)%10,T1%10);
printf("湿度:%d%d.%d",H1/100,(H1/10)%10,H1%10);
printf("\r\n");*/
t=T1/10;
t1=T1%10;
a=(float)(t+t1*0.1);
h=H1/10;
h1=H1%10;
b=(float)(h+h1*0.1);
sprintf(strTemp,"%.1f",a); //调用Sprintf函数把DHT11的温度数据格式化到字符串数组变量strTemp中
sprintf(strHumi,"%.1f",b); //调用Sprintf函数把DHT11的湿度数据格式化到字符串数组变量strHumi中
GUI_ShowCHinese(16,00,16,"温湿度显示",1);
GUI_ShowCHinese(16,20,16,"温度",1);
GUI_ShowString(53,20,strTemp,16,1);
GUI_ShowCHinese(16,38,16,"湿度",1);
GUI_ShowString(53,38,strHumi,16,1);
delay_ms(1500);
delay_ms(1500);
}
点阵显示文字
"温",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,0x1F,0xF0,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,0x10,0x10,0x1F,0xF0,
0x04,0x40,0x44,0x44,0x24,0x44,0x14,0x48,0x14,0x50,0x04,0x40,0xFF,0xFE,0x00,0x00,/*"显",0*/
"示",0x00,0x00,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x01,0x00,
0x01,0x00,0x11,0x10,0x11,0x08,0x21,0x04,0x41,0x02,0x81,0x02,0x05,0x00,0x02,0x00,/*"示",0*/
主函数main.c文件
#include "delay.h"
#include "usart.h"
#include "bsp_i2c.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
int main(void)
{
delay_init(); //延时函数初始化
uart_init(115200);
IIC_Init();
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
OLED_Init(); //初始化OLED
OLED_Clear(0);
while(1)
{
//printf("温度湿度显示");
read_AHT20_once();
OLED_Clear(0);
delay_ms(1500);
}
}
编译后无误
3.电路连接
OLED屏连接方法与上面相同,温度传感器连接方法:
GPIO引脚PB6,PB7。
SCL连接PB6,SDA连接PB7
如果采用硬件I2C进行实现,可以查看关于STM32的原理图,可以看到硬件I2C接口,野火stm32mini开发板的I2C接口是PA2,PA3,要实现硬件I2C读取数据,就根据上面介绍的方式进行配置,即可完成通讯。
4.运行效果
wd
五、STM32+OLED上下或左右的滑动显示长字符
1.文字取模
取模步骤与上相同
2.编写代码
(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); //开启滚动
(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); //开启滚动
}
编译后无误
3.电路连接
OLED屏连接方法与上面相同
4.运行效果
六、总结
通过三个实验基本熟练了STM32+OLED的操作显示,代码和管脚配置没有问题的情况下,完成三个应用并不困难。注意OLED显示时要对字长进行设置,否则无法完全显示出来。字模取模时,注意横向取模、纵向取模、倒序的差别,否则会得到一片模糊的点点,而不是正常清晰的汉字。本过程也进行了对应字库的一个了解,以及怎么实现将点阵格式转换成十六进制格式。出来了给出的几个中文的点阵之外,其他的显示也都是依据点阵进行的存储。其实,整个显示屏也是一个点阵,显示过程就是将显示屏整个点阵中的每个小点进行改变,从而实现显示。并且OLED是一个比较有意思的外设,在之后完成更多硬件项目时,可以利用OLED进行调试显示,帮助会很大,所以要好好掌握OLED的使用,多加练习,很有收获。
七、参考资料
OLED显示模块原理
https://blog.csdn.net/qq_46467126/article/details/121439142?spm=1001.2014.3001.5501
https://blog.csdn.net/qq_43279579/article/details/111414037
资料链接(含全部代码)
链接:https://pan.baidu.com/s/1gD4f5UOWS4tslH8N5MTBsw
提取码:v5ti