目录
一、SPI协议
1、简介
2、SPI物理层
3、协议层
4、STM32的SPI特性及架构
二、oled显示
1、文字取模
?2、代码改写
3、接线方式
?4、将生成的hex文件烧录后运行结果
三、OLED 滑动显示字符
1、添加字模
2、修改显示函数
3、修改主函数
4、连线方式
5、效果展示?
四、OLED 显示温湿度数据
1、添加字模
2、修改代码
3、运行结果?
五、总结
六、参考文献
一、SPI协议
1、简介
SPI协议是由摩托罗拉公司提出的通讯协议(SerialPeripheralInterface),即串行外围设备接口,是 一种高速全双工的通信总线。它被广泛地使用在 ADC、LCD 等设备与 MCU 间,要求通讯速率 较高的场合。?
2、SPI物理层
?SPI通讯使用3条总线及片选线,3条总线分别为SCK、MOSI、MISO,片选线为SS,它们的作 用介绍如下:
(1) SS*(*SlaveSelect):从设备选择信号线,常称为片选信号线,也称为NSS、CS,以下用NSS 表示。当有多个 SPI 从设备与 SPI 主机相连时,设备的其它信号线 SCK、MOSI 及 MISO 同时并联到相同的SPI总线上,即无论有多少个从设备,都共同只使用这3条总线;而每 个从设备都有独立的这一条NSS信号线,本信号线独占主机的一个引脚,即有多少个从设 备,就有多少条片选信号线。I2C协议中通过设备地址来寻址、选中总线上的某个设备并与?其进行通讯;而SPI协议中没有设备地址,它使用NSS信号线来寻址,当主机要选择从设 备时,把该从设备的NSS信号线设置为低电平,该从设备即被选中,即片选有效,接着主 机开始与被选中的从设备进行SPI通讯。所以SPI通讯以NSS线置低电平为开始信号,以 NSS线被拉高作为结束信号。
(2) SCK(SerialClock):时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了通讯的速 率,不同的设备支持的最高时钟频率不一样,如STM32的SPI时钟频率最大为fpclk/2,两 个设备之间通讯时,通讯速率受限于低速设备。
(3) MOSI(MasterOutput,SlaveInput):主设备输出/从设备输入引脚。主机的数据从这条信号线 输出,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。
(4) MISO(MasterInput,,SlaveOutput):主设备输入/从设备输出引脚。主机从这条信线读入数据, 从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。
3、协议层
与I2C的类似,SPI协议定义了通讯的起始和停止信号、数据有效性、时钟同步等环节。
这是一个主机的通讯时序。NSS、SCK、MOSI 信号都由主机控制产生,而 MISO 的信号由从机 产生,主机通过该信号线读取从机的数据。MOSI与MISO的信号只在NSS为低电平的时候才有 效,在SCK的每个时钟周期MOSI和MISO传输一位数据。?
4、STM32的SPI特性及架构
STM32的SPI外设可用作通讯的主机及从机,支持最高的SCK时钟频率为fpclk/2(STM32F103型 号的芯片默认f:sub:pclk1为72MHz,fpclk2 为36MHz),完全支持SPI协议的4种模式,数据帧长 度可设置为8位或16位,可设置数据MSB先行或LSB先行。它还支持双线全双工(前面小节说 明的都是这种模式)、双线单向以及单线模式。其中双线单向模式可以同时使用MOSI及MISO数 据线向一个方向传输数据,可以加快一倍的传输速度。而单线模式则可以减少硬件接线,当然这 样速率会受到影响。
二、oled显示
1、文字取模
利用取模软件将需要显示的文字用十六进制表示出来
需要用到的取模软件
PCtoLCD2002
软件初始设置
?在文字输入区输入目标文字,点击生成字模,得到结果如下图
?2、代码改写
修改test.c文件下的内容显示函数TEST_MainPage(void)
void TEST_MainPage(void)
{
GUI_ShowCHinese(28,20,16,"黄三金",1);
GUI_ShowString(4,48,"6319xxxxxxx8",16,1);
//GUI_ShowString(4,48,"www.lcdwiki.com",16,1);
delay_ms(1500);
delay_ms(1500);
}
?函数说明: ① GUI_ShowString() 函数各参数分别对应: X 坐标、Y 坐标、字符串(ASCLL码中的)、bit (表示字符显示格式,这里我用的 16 ,和汉字一样高)、显示样式(1:白字黑底;0:黑字白底)。 ② GUI_ShowChinese() 函数各参数分别对应: X 坐标、Y 坐标、汉字点阵大小(这里使用的是 16×16 的,参数应该是 16)、要显示的汉字、显示样式(1:白字黑底;0:黑字白底)。
修改oledfont.h 文件下的文字存储typFNT_GB16 cfont16[]函数,将上述文字取模中的16进制按下述形式复制进去。
const typFNT_GB16 cfont16[] =
{
"黄",0x04,0x40,0x3F,0xF8,0x04,0x40,0x04,0x40,0xFF,0xFE,0x01,0x00,0x1F,0xF0,0x11,0x10,
0x11,0x10,0x1F,0xF0,0x11,0x10,0x11,0x10,0x1F,0xF0,0x04,0x40,0x08,0x20,0x10,0x10,/*"黄",0*/
"三",0x00,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,/*"三",1*/
"金",0x01,0x00,0x01,0x00,0x02,0x80,0x04,0x40,0x08,0x20,0x10,0x10,0x2F,0xE8,0xC1,0x06,
0x01,0x00,0x3F,0xF8,0x01,0x00,0x11,0x10,0x09,0x10,0x09,0x20,0xFF,0xFE,0x00,0x00,/*"金",2*/
};
修改main.c文件中的while循环如下
int main(void)
{
delay_init(); //延时函数初始化
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
OLED_Init(); //初始化OLED
OLED_Clear(0); //清屏(全黑)
while(1)
{
TEST_MainPage(); //主界面显示测试
}
}
3、接线方式
?4、将生成的hex文件烧录后运行结果
三、OLED 滑动显示字符
1、添加字模
跟上述方法一样,获取字模后,向?gui.c ?下的?oledfont.h ?头文件里的?cfont16[] 数组 内的添加中文文字点阵即可。
这里我添加的是莫说相公痴,更有痴似相公者
2、修改显示函数
同上,在?test.c ?里?void TEST_MainPage(void) ?函数中不添加自己的想要显示的字符,如下:
void TEST_MainPage(void)
{
GUI_ShowCHinese(28,20,16,"莫说相公痴,更有痴似相公者",1);
//GUI_ShowCHinese(28,20,16,"黄三金",1);
//GUI_ShowString(4,48,"6319xxxxxxx8",16,1);
//GUI_ShowString(4,48,"www.lcdwiki.com",16,1);
delay_ms(1500);
delay_ms(1500);
}
3、修改主函数
将?main.c ?代码中的?while ?函数删除,再添加如下代码:
我设置的是左右移动
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(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); //开启滚动
TEST_MainPage();
OLED_WR_Byte(0x2F,OLED_CMD);
}
注:水平左右移动
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); //开启滚动
4、连线方式
这一步如上面一样
5、效果展示?
四、OLED 显示温湿度数据
1、添加字模
跟上述方法一样,获取需要显示的字的字模后,向?gui.c ?下的?oledfont.h ?头文件里的?cfont16[] 数组 内的添加中文文字点阵即可。 我这里添加了“当、前、温、湿、度”这 5 个字的点阵。
2、修改代码
然后我们从这篇博客中移植部分代码(以下四个文件)。
基于 I2C 协议使用 AHT20 温湿度传感器采集数据_ssj925319的博客-CSDN博客
bsp_i2c.h
bsp_i2c.c
sys.h(移植后更改了名称为 AHT20_sys.h,不然会重名)
sys.c(移植后更改了名称为 AHT20_sys.c,不然会重名)
具体移植过程和修改可以参考这篇博客:基于 SPI 协议在 0.96 寸 OLED上【平滑显示汉字】及【温湿度数据采集显示】_ssj925319的博客-CSDN博客
将bsp_i2c.c 文件中的串口发送改为 OLED 显示?void Show_OLED(void) ?即可
void Show_OLED(void)
{
/*---
------
---*/
GUI_ShowCHinese(28,10,16,"当前温湿度",1);
GUI_ShowCHinese(20,32,16,"温度:",1);
GUI_ShowString(60,32,strTemp1,16,1);
GUI_ShowString(68,32,strTemp2,16,1);
GUI_ShowString(76,32,".",16,1);
GUI_ShowString(84,32,strTemp3,16,1);
GUI_ShowCHinese(92,32,16,"℃",1);
GUI_ShowCHinese(20,48,16,"湿度:",1);
GUI_ShowString(60,48,strHumi1,16,1);
GUI_ShowString(68,48,strHumi2,16,1);
GUI_ShowString(76,48,".",16,1);
GUI_ShowString(84,48,strHumi3,16,1);
GUI_ShowCHinese(92,48,16,"%",1);
}
将?main.c ?代码中不用的函数注释掉,再修改代码,之后的结果如下
#include "bsp_i2c.h" //注意添加头文件
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
OLED_Init(); //初始化OLED
IIC_Init(); //初始化IIC
OLED_Clear(0); //清屏(全黑)
while(1)
{
read_AHT20_once(); //读取温度并显示
OLED_Clear(0); //清屏(全黑)
delay_ms(1500);
}
具体的工程文件如下
链接:https://pan.baidu.com/s/1YGvasonWqI_ss0XTAoRulA? 提取码:4vvf
3、运行结果?
?
五、总结
其实说实话,这个实验从头到尾,对于这个 SPI 协议并没有了解多少,入门小白,出门还是小白,整个文章的过程就是调用函数,修改变量而已,就好比学会了怎么吃饭,却不知道怎么做饭,对于嵌入式开发的同志们,这是极大的弊端,要深入分析,由于我还是大学生,时间不太多,就不花费时间写文章分析代码了,注释都很全,慢慢学,只要头发没掉光,你就还没学到头! ?
六、参考文献
基于 SPI 协议在 0.96 寸 OLED上【平滑显示汉字】及【温湿度数据采集显示】_ssj925319的博客-CSDN博客
基于STM32的温湿度采集——OLED显示_Harriet的博客-CSDN博客_基于stm32温湿度传感器采集
基于 I2C 协议使用 AHT20 温湿度传感器采集数据_ssj925319的博客-CSDN博客
|