STM32之基于I2C的温湿度采集(AHT20)

本文内容:本文主要介绍I2C协议,以及用I2C口连接温湿度传感器AHT20,并通过串口显示温湿度数据到上位机。

一、何为I2C协议

(一)定义

I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要USART、CAN 等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC)间的通讯。

(二)I2C物理层

在这里插入图片描述
(1) 它是一个支持设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。
(2) 一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。

(三)I2C协议层

I2C 的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。
下图为起始信号和停止信号
在这里插入图片描述
下图为数据有效性,只有在SCL处于高电平时,SDA的数据传输才是有效的。
在这里插入图片描述
下图为响应与非响应信号
在这里插入图片描述

(四)硬件I2C与软件I2C

1.硬件I2C

只要配置好对应的寄存器,外设就会产生标准串口协议的时序。在初始化好 I2C 外设后,只需要把某寄存器位置 1,此时外设就会控制对应的 SCL 及 SDA 线自动产生 I2C 起始信号,不需要内核直接控制引脚的电平。

2.软件I2C

需要在控制产生 I2C 的起始信号时,控制作为 SCL 线的 GPIO 引脚输出高电平,然后控制作为 SDA 线的 GPIO 引脚在此期间完成由高电平至低电平的切换,最后再控制SCL 线切换为低电平,这样就输出了一个标准的 I2C 起始信号。

当硬件I2C管脚不够用时,可以采用软件I2C

二、AHT20温湿度采集程序

想了解AHT20的相关资料,可以访问官网:
AHT20
主函数代码

#include "delay.h"
#include "usart.h"
#include "bsp_i2c.h"


int main(void)
{
    
    	
	delay_init();     
	uart_init(115200);	//串口通信波特率115200
	IIC_Init();
		while(1)
	{
    
    
		printf("温度湿度显示");
		read_AHT20_once();
		delay_ms(1500);
  }
}

模块读取函数

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();//读取AHT20采集的到的数据
	delay_ms(5);
}

I2C读取及输出温湿度的函数

void read_AHT20(void)
{
    
    
	uint8_t   i;

	for(i=0; i<6; i++)
	{
    
    
		readByte[i]=0;
	}
	I2C_Start();//I2C启动

	I2C_WriteByte(0x71);//I2C写数据
	ack_status = Receive_ACK();//收到的应答信息
	readByte[0]= I2C_ReadByte();//I2C读取数据
	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();//I2C停止函数
	//如果读取过程没有问题,就对读到的数据进行相应的处理
	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("读取失败");

	}
	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");
}

三、运行效果

连接如下,PA9连到USB模块的RX,PA10连到USB模块的TX,SCL连接PB6,SDA连接PB7。
在这里插入图片描述
运行效果如下图
在这里插入图片描述
可以看到室内温度在20度左右,湿度在60左右,当把手放到模块上后,可以发现温度逐渐升高,达到23度,湿度也提高到70

四、总结

实验代码主要是参考其它大佬的,自己只是小做改动,大概了解到了AHT20是如何通过I2C协议一步步读取数据的。温湿度传感器感觉测得还算准,改变环境温度也会发生改变。

五、参考文章

stm32通过I2C接口实现温湿度(AHT20)的采集

完整代码

猜你喜欢

转载自blog.csdn.net/m0_58414679/article/details/121410352