一、温湿度采集
1.学习I2C总线通信协议,使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出。具体任务:
(1)解释什么是“软件I2C”和“硬件I2C”? (阅读野火配套教材的第23章“I2C–读写EEPROM”原理章节)
(2)阅读AHT20数据手册,编程实现:每隔2秒钟采集一次温湿度数据,并通过串口发送到上位机(win10)。
1、I2C总线协议
I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC)间的通讯。
I2C 协议的物理层和协议层
①物理层
I2C是一个支持设备的总线。可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。对于I2C 总线,只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。
I2C 通讯设备常用连接方式(引用野火资料中的图)
②协议层
主要是定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等。
I2C的两种方式——硬件I2C和软件I2C
①硬件I2C
直接利用 STM32 芯片中的硬件 I2C 外设。
硬件I2C的使用
只要配置好对应的寄存器,外设就会产生标准串口协议的时序。在初始化好 I2C 外设后,只需要把某寄存器位置 1,此时外设就会控制对应的 SCL 及 SDA 线自动产生 I2C 起始信号,不需要内核直接控制引脚的电平。
②软件I2C
直接使用 CPU 内核按照 I2C 协议的要求控制 GPIO 输出高低电平,从而模拟I2C。
软件I2C的使用
需要在控制产生 I2C 的起始信号时,控制作为 SCL 线的 GPIO 引脚输出高电平,然后控制作为 SDA 线的 GPIO 引脚在此期间完成由高电平至低电平的切换,最后再控制SCL 线切换为低电平,这样就输出了一个标准的 I2C 起始信号。
③两者的差别
硬件 I2C 直接使用外设来控制引脚,可以减轻 CPU 的负担。不过使用硬件I2C 时必须使用某些固定的引脚作为 SCL 和 SDA,软件模拟 I2C 则可以使用任意 GPIO 引脚,相对比较灵活。对于硬件I2C用法比较复杂,软件I2C的流程更清楚一些。如果要详细了解I2C的协议,使用软件I2C可能更好的理解这个过程。在使用I2C过程,硬件I2C可能通信更加快,更加稳定。
IIC协议数据传输过程
主设备和从设备进行数据传输时遵循以下协议格式。数据通过一条SDA数据线在主设备和从设备之间传输0和1的串行数据。串行数据序列的结构可以分为,开始条件,地址位,读写位,应答位,数据位,停止条件。
开始条件:当主设备决定开始通讯时,需要发送开始信号,需要执行以下动作:先将SDA线从高压电平切换到低压电平;然后将SCL从高电平切换到低电平;在主设备发送开始条件信号之后,所有从机即使处于睡眠模式也将变为活动状态,并等待接收地址位。
从机应答/非应答:主机每次发送完数据之后会等待从设备的应答信号ACK; 在第9个时钟信号,如果从设备发送应答信号ACK,则SDA会被拉低若没有应答信NACK,则SDA会输出为高电平,这过程会引起主设备发生重启或者停止.
结束条件 :当主设备决定结束通讯时,需要发送停止信号,需要执行以下动作;先将SDA线从低电压电平切换到高电压电平; 再将SCL线从高电平拉到低电平.
2、电路连接
了解AHT20芯片的相关信息
具体信息请到官方下载对应产品介绍文档,资料链接如下:
http://www.aosong.com/class-36.html
DHT20采用I2C通讯协议,响应迅速,配有一个全新设计的ASIC专用芯片、一个经过改进的MEMS半导体电容式湿度传感元件和一个标准的片上温度传感元件,是一款全新升级的智能温湿度传感器模块,在测量精度、供电电压、测量范围等方面的性能参数都有大幅提升,超出了前一代传感器的可靠性水平,即使在恶劣环境下也能保持性能稳定。每一款产品出厂时都经过严格的校准和测试。由于对传感器做了改良和微型化改进,因此它的性价比更高。
AHT20的SCL,GND,SDA,VCC分别对应接stm32f103指南者i2c模块的B6,GND,B7,5V。(GND和5V任意模块都可以)
3、代码编写
read_AHT20_once(); //I2C读取传感器温度
void read_AHT20_once(void)
{
delay_ms(10);
reset_AHT20(); //复位AHT20
delay_ms(10);
init_AHT20(); //初始化AHT20
delay_ms(10);
startMeasure_AHT20(); //准备开始测量AHT20温湿度
delay_ms(80);
read_AHT20(); //通过IIC读取AHT20采集的温湿度
delay_ms(5);
main() ; 函数
int main(void)
{
delay_init(); //延时函数初始化
uart_init(115200); //串口初始化
IIC_Init(); //IIC协议初始化
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
OLED_Init(); //初始化OLED
OLED_Clear(0);
while(1)
{
printf("温度湿度显示");
read_AHT20_once(); //I2C读取传感器温度
OLED_Clear(0);
delay_ms(1500);
}
}
4、烧录输出
二、OLED显示
理解OLED屏显和汉字点阵编码原理,使用STM32F103的SPI或IIC接口实现以下功能:
(1) 显示自己的学号和姓名;
(2) 显示AHT20的温度和湿度;
(3) 上下或左右的滑动显示长字符,比如“Hello,欢迎来到重庆交通大学物联网205实训室!”或者一段歌词或诗词(最好使用硬件刷屏模式)。
1、SPI和OLED介绍
SPI
SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议。
SPI内部结构框图如下
通常SPI通过4个引脚与外部器件相连:
MISO:主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。MOSI:主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。SCK:串口时钟,作为主设备的输出,从设备的输入。
NSS:从设备选择。这是一个可选的引脚,用来选择主/从设备。它的功能是用来作为“片选引脚”,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。从设备的NSS引脚可以由主设备的一个标准I/O引脚来驱动。一旦被使能(SSOE位),NSS引脚也可以作为输出引脚,并在SPI处于主模式时拉低;此时,所有的SPI设备,如果它们的NSS引脚连接到主设备的NSS引脚,则会检测到低电平,如果它们被设置为NSS硬件模式,就会自动进入从设备状态。当配置为主设备、NSS配置为输入引脚(MSTR=1,SSOE=0)时,如果NSS被拉低,则这个SPI设备进入主模式失败状态:即MSTR位被自动清除,此设备进入从模式。
SPI总线传输过程
主机先将NSS信号拉低,这样保证开始接收数据; 当接收端检测到时钟的边沿信号时,它将立即读取数据线上的信号,这样就得到了一位数据(1bit);主机发送到从机时:主机产生相应的时钟信号,然后数据一位一位地将从MOSI信号线上进行发送到从机;主机接收从机数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过MISO信号线发送;
具体框图如下
OLED
OLED(Organic Light-Emitting Diode),又称为有机电激光显示、有机发光半导体(Organic Electroluminescence Display,OLED)。OLED属于一种电流型的有机发光器件,是通过载流子的注入和复合而致发光的现象,发光强度与注入的电流成正比。OLED在电场的作用下,阳极产生的空穴和阴极产生的电子就会发生移动,分别向空穴传输层和电子传输层注入,迁移到发光层。当二者在发光层相遇时,产生能量激子,从而激发发光分子最终产生可见光。
接口定义
1、本模块支持IIC、3线制SPI以及4线制SPI接口总线模式切换(如图红框内所示),具体说明如下:
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接电源地;
2、电路连接
3、汉字取模
通过取模软件将需要OLED显示的汉字或图片转化为16进制
取模软件链接如下:0.96inch SPI OLED Module
软件初始设置
在文字输入区输入目标文字,并Ctr+enter,得到显示图
点击C51格式,即可生成点阵
4、代码编写
(1)OLED姓名学号
TEST_MainPage(); //学号姓名字符串显示函数
GUI_ShowCHinese(28,20,16,"冉冉",1);
GUI_ShowString(4,48,"632007030206",16,1);
void TEST_MainPage(void)
{
// GUI_ShowString(28,0,"Harriet",16,1);
GUI_ShowCHinese(28,20,16,"冉冉",1);
//GUI_ShowString(40,32,"64X128",16,1);
GUI_ShowString(4,48,"632007030206",16,1);
//GUI_ShowString(4,48,"www.lcdwiki.com",16,1);
delay_ms(1500);
delay_ms(1500);
}
汉字字模存储数组
(2)OLED温湿度
bsp_i2c.c文件
char strTemp[30]; //声明字符数组strTemp,初始化元素30
char strHumi[30]; //声明字符数组strHumi,初始化元素30
int t;
int h;
float a;
float b;
点阵显示文字,加入至oledfont.h文件
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);
}
}
我们将之前OLED代码里面的.h和.c文件都加入如今的温湿度传感器文件中。
(3)OLED诗句
水平左右移动
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); //开启滚动
test.c文件
void TEST_MainPage(void)
{
GUI_ShowCHinese(20,30,16,"鲜衣怒马少年时不负韶华行且知",1);
//GUI_ShowString(40,32,"64X128",16,1);
//GUI_ShowString(4,48,"www.lcdwiki.com",16,1);*/
delay_ms(500);
delay_ms(500);
}
点阵显示文字,加入至oledfont.h文件
5、烧录输出
(1)OLED姓名学号
OLED名字学号
(2)OLED温湿度
(3)OLED诗句
OLED诗句
三、总结
了解学习了I2C协议进行通信,需要对这个协议有比较清晰的了解。对AHT20芯片读取数据的过程也要有一个比较清晰的认识,才能看懂代码中是如何进行读取的。这次试验既是对I2C有了清晰的认识,也对C8T6有了更多的学习。通过OLED三个实验基本熟练了STM32+OLED的操作显示,代码和管脚配置没有问题的情况下,完成三个应用并不困难。注意OLED显示时要对字长进行设置,否则无法完全显示出来。字模取模时,注意横向取模、纵向取模、倒序的差别,否则会得到一片模糊的点点,而不是正常清晰的汉字。OLED是一个比较有意思的外设,在之后完成更多硬件项目时,可以利用OLED进行调试显示,帮助会很大,所以要好好掌握OLED的使用,多加练习,受益匪浅。