目录
一、SPI接口简介
1.SPI的简介
SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议。
2. SPI 接口4条线通信:
MISO 主设备数据输入,从设备数据输出。
MOSI 主设备数据输出,从设备数据输入。
SCLK 时钟信号,由主设备产生。
CS 从设备片选信号,由主设备控制。
3.SPI的特征
● 3线全双工同步传输
● 带或不带第三根双向数据线的双线单工同步传输
● 8或16位传输帧格式选择
● 主或从操作
● 支持多主模式
● 8个主模式波特率预分频系数(最大为fPCLK/2)
● 从模式频率 (最大为fPCLK/2)
● 主模式和从模式的快速通信
● 主模式和从模式下均可以由软件或硬件进行NSS管理:主/从操作模式的动态改变
● 可编程的时钟极性和相位
● 可编程的数据顺序,MSB在前或LSB在前
● 可触发中断的专用发送和接收标志
● SPI总线忙状态标志
● 支持可靠通信的硬件CRC
4.接口框图
5.SPI整体的通讯过程
整体的传输大概可以分为以下几个过程:
主机先将NSS信号拉低,这样保证开始接收数据;
当接收端检测到时钟的边沿信号时,它将立即读取数据线上的信号,这样就得到了一位数据(1bit);
由于时钟是随数据一起发送的,因此指定数据的传输速度并不重要,尽管设备将具有可以运行的最高速度(稍后我们将讨论选择合适的时钟边沿和速度)。
主机发送到从机时:主机产生相应的时钟信号,然后数据一位一位地将从MOSI信号线上进行发送到从机;
主机接收从机数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过MISO信号线发送;
注:SPI是“全双工”(具有单独的发送和接收线路),因此可以在同一时间发送和接收数据,另外SPI的接收硬件可以是一个简单的移位寄存器
二、OLED的原理
1.OLED模块参数
ALINETEK 0.96寸OLED模块参数:
1)双色:1/4黄色 + 3/4蓝色
2)尺寸:0.96存.模块尺寸:27mm26mm
3)分辨率:12864
4)支持接口方式4种(通信方式)
1:6800,8080并行接口
2:4线串行SPI
3:2线IIC
5)模块工作电压3.3V
2.该模块的特点:
该模块有以下特点:
1)模块有单色和双色两种可选,单色为纯蓝色,而双色则为黄蓝双色。
2)尺寸小,显示尺寸为 0.96 寸,而模块的尺寸仅为 27mmx26mm 大小。
3)高分辨率,该模块的分辨率为128x64。
4)多种接口方式,该模块提供了总共 5 种接口包括:6800、8080 两种并行接口方式、3线或 4 线的穿行 SPI 接口方式、IIC 接口方式(只需要 2 根线就可以控制 OLED 了)。
5)不需要高压,直接接 3.3V 就可以工作了。
注意该模块不和 5.0V 接口兼容,所以在使用的时候一定要小心,勿直接接到 5V 的系统上去,否则可能烧坏模块。
3.OLED工作模式选择
通过模块BS1/BS2设置OLED工作模式
由OLED模块图片背部焊点可以看到,默认TP引脚与VCC焊接
即BS1=1,BS2=1,为8080并口通信方式
4.引脚说明
0.96寸OLED显示屏相关介绍,可参考0.96寸OLED显示屏相关说明
三、字模的生成
下载取字模软件
链接:https://pan.baidu.com/s/19Z1WDAuuWEu_sUGjQ-sheQ
提取码:qdo0
安装完成取字模软件后设置初始参数
在文字输入区输入目标文字,并ctrl+enter,得到显示图
选择C51格式,即可生成点阵
四、STM32+OLED显示自己的学号和姓名
1.初始程序
进入官网下载相关程序0.96inch SPI OLED Module --demo进行更改便可以达到我们需要的目标。
2.代码的编写
在test.c文件中的TEST_MainPage
的函数修改显示内容
void TEST_MainPage(void)
{
GUI_ShowCHinese(28,12,16,"李",1);
GUI_ShowString(40,32,"632007030xxxx",16,1);
delay_ms(1500);
delay_ms(1500);
}
提取字模
文字存储,在oledfront.h
文件中,在typFNT_GB16 cfont16[]
函数中储存文字
将main.c函数文件中的除TEST_MainPage
函数外全部注释掉
进行编译,编译无误
3.结果展示
五、STM32+OLED显示AHT20的温度及湿度
1.温湿度显示代码
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