【嵌入式08】基于IIC和SPI协议的温湿度采集与OLED显示

一、温湿度采集

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的使用,多加练习,受益匪浅。

四、参考网址

STM32+OLED屏显应用实例
OLED显示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值