基于I2C硬件协议的AHT20温湿度传感器的数据采集

本文详细介绍了I2C协议的物理层和协议层特性,对比了软件I2C和硬件I2C的实现方式,并通过STM32单片机实现了对AHT20温湿度传感器的数据采集。实验结果显示,对着传感器呼气能观察到温湿度变化,验证了通信的正确性。

一、I2C协议简介

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

1、I2C物理层

I2C 通讯设备之间的常用连接方式见图

在这里插入图片描述

它的物理层有如下特点:

(1) 它是一个支持设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线 中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。

(2) 一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线 (SCL)。数据线即用来表示数据,时钟线用于数据收发同步。

(3) 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之 间的访问。

(4) 总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而当所有设备都空 闲,都输出高阻态时,由上拉电阻把总线拉成高电平。

(5) 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用 总线。

(6) 具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式 下可达 3.4Mbit/s,但目前大多 I 2C 设备尚不支持高速模式。

(7) 连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制 。

2、I2C协议层

I2C 的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地 址广播等环节。

I2C 通讯过程的基本结构

在这里插入图片描述

二、软件I2C和硬件I2C

(1)软件I2C

所谓软件模拟,即直接使用 CPU 内核按照 I2C 协议的要求控制 GPIO 输出高低电平。 如控制产生 I2C 的起始信号时,见图 24-5,先控制作为 SCL 线的 GPIO 引脚输出高电平, 然后控制作为 SDA 线的 GPIO 引脚在此期间完成由高电平至低电平的切换,最后再控制 SCL 线切换为低电平,这样就输出了一个标准的 I2C 起始信号。

(2)硬件I2C

硬件 I2C 是指直接利用 STM32 芯片中的硬件 I2C 外设,该硬件 I2C 外设跟 USART 串口外设类似,只要配置好对应的寄存器,外设就会产生标准串口协议的时序。使用它的 I2C 外设则可以方便地通过外设寄存器产生 I2C 协议方式的通讯,如初始化好 I2C 外设后, 只需要把某寄存器位置 1,那么外设就会控制对应的 SCL 及 SDA 线自动产生 I2C 起始信号, 而不需要内核直接控制引脚的电平。

三、AHT20温湿度传感器的数据采集

(1)实验工具

——温湿度传感器AHT20

——单片机:STM32F103系列单片机(野火mini)

(2)主要代码

main.c

#include "led.h"
#include "delay.h"
#include "temhum.h"
#include "sys.h"
#include "usart.h"

 int main(void)
 {	 	
    u32 CT_data[2]={0};
    volatile float  hum=0,tem=0;     
     
    delay_init();	    	 //延时函数初始化	  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    uart_init(115200);	 //串口初始化为115200
    LED_Init();			     //LED端口初始化
    temphum_init();     //ATH20初始化    
	
	while(1)
	{
        AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据 

        hum = CT_data[0]*100*10/1024/1024;  //计算得到湿度值(放大了10倍)
        tem = CT_data[1]*200*10/1024/1024-500;//计算得到温度值(放大了10倍)

        printf("湿度:%.1f%%\r\n",(hum/10));
        printf("温度:%.1f度\r\n",(tem/10));
        printf("\r\n");
        
        //延时2s,LED闪烁提示串口发送状态
        LED=0;
        delay_ms(1000);
        LED=1;
        delay_ms(1000);
	 }
}

代码参考:

AHT20的DEMO板的例程资料

(3)实验结果在这里插入图片描述

对着传感器呼气有明显的温湿度变化,说明实验成功

在这里插入图片描述

四、参考资料

《零死角玩转STM32——MINI》

基于I2C通信协议的温湿度采集

<think>好的,我需要帮助用户解决STM32F103C8T6通过模拟I2CAHT20通信的问题。用户想要示例代码,所以我得先确保代码正确,并符合他们的需求。 首先,用户提到使用模拟I2C协议,所以不能依赖硬件I2C,需要软件实现GPIO控制。我需要定义SDA和SCL的引脚,并初始化它们为输出模式。通常,这两个引脚需要上拉电阻,但用户可能已经接好,所以在代码中可能需要配置为开漏模式,但STM32的GPIO模式设置可能需要特别注意。不过,模拟I2C通常会将引脚设置为推挽输出,并在适当的时候切换为输入读取数据。因此,初始化部分应该设置GPIO为输出,并初始化为高电平。 接下来是I2C的起始和停止信号。起始信号是SCL高时,SDA从高到低;停止信号是SCL高时,SDA从低到高。这部分需要正确实现时序,可能需要微秒级的延时,这里用HAL_Delay不太合适,应该用更精确的延时函数,比如HAL_Delay(1)可能太长,但作为示例代码可能简化处理,用户实际使用时可能需要调整。 发送字节的函数需要逐位发送,从高位开始。每个时钟周期,设置SDA的电平,然后拉高SCL,保持一段时间,再拉低SCL。接收字节时,需要释放SDA(设置为输入模式),读取每一位,并在SCL高时采样。 AHT20的初始化步骤需要发送初始化命令,比如0xE1后跟两个参数0x08和0x00。然后需要等待传感器校准完成,通过读取状态字,判断最高位是否为0。如果校准未完成,可能需要延时等待。 读取数据时,发送触发测量命令0xAC,然后等待数据就绪,同样通过状态字判断。之后读取6个字节的数据,组合成温湿度值。注意数据需要转换,比如湿度值SRH是20位的,温度是20位的,需要按位操作提取,并进行公式计算。 示例代码中需要包含这些步骤,并添加必要的注释,让用户理解每个部分的作用。同时,需要提醒用户检查引脚配置、延时函数是否合适,以及可能的硬件连接问题。 可能的问题包括:I2C地址是否正确(AHT20地址是0x38),GPIO是否正确配置,延时是否足够,是否处理了传感器的响应信号(ACK/NACK)。此外,用户可能需要根据实际情况调整计算公式中的参数,确保温湿度值的准确性。 最后,生成相关问题,帮助用户深入理解,比如如何提高采集精度,处理通信失败的情况,或者优化代码结构。这些问题应该与用户的应用场景相关,帮助他们进一步开发和调试。</think>### 解答步骤 #### 步骤1:配置GPIO模拟I2C协议 STM32F103C8T6需通过GPIO模拟I2C时序,定义`SDA`和`SCL`引脚: ```c // 定义I2C引脚(示例使用GPIOB_Pin6和GPIOB_Pin7) #define I2C_SCL_PIN GPIO_PIN_6 #define I2C_SDA_PIN GPIO_PIN_7 #define I2C_PORT GPIOB // 初始化GPIO void I2C_Init() { GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出模式 GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Pin = I2C_SCL_PIN | I2C_SDA_PIN; HAL_GPIO_Init(I2C_PORT, &GPIO_InitStruct); HAL_GPIO_WritePin(I2C_PORT, I2C_SCL_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(I2C_PORT, I2C_SDA_PIN, GPIO_PIN_SET); } ``` #### 步骤2:实现I2C基础函数 包括起始信号、停止信号、发送字节、接收应答等: ```c // I2C起始信号 void I2C_Start() { HAL_GPIO_WritePin(I2C_PORT, I2C_SDA_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(I2C_PORT, I2C_SCL_PIN, GPIO_PIN_SET); Delay_us(5); HAL_GPIO_WritePin(I2C_PORT, I2C_SDA_PIN, GPIO_PIN_RESET); Delay_us(5); HAL_GPIO_WritePin(I2C_PORT, I2C_SCL_PIN, GPIO_PIN_RESET); } // 发送一个字节 void I2C_WriteByte(uint8_t data) { for (int i = 0; i < 8; i++) { HAL_GPIO_WritePin(I2C_PORT, I2C_SDA_PIN, (data & 0x80) ? GPIO_PIN_SET : GPIO_PIN_RESET); data <<= 1; HAL_GPIO_WritePin(I2C_PORT, I2C_SCL_PIN, GPIO_PIN_SET); Delay_us(5); HAL_GPIO_WritePin(I2C_PORT, I2C_SCL_PIN, GPIO_PIN_RESET); Delay_us(5); } // 等待ACK HAL_GPIO_WritePin(I2C_PORT, I2C_SDA_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(I2C_PORT, I2C_SCL_PIN, GPIO_PIN_SET); Delay_us(5); HAL_GPIO_WritePin(I2C_PORT, I2C_SCL_PIN, GPIO_PIN_RESET); } ``` #### 步骤3:AHT20初始化与数据读取 AHT20需发送校准命令并等待就绪: ```c #define AHT20_ADDRESS 0x38 // I2C地址 void AHT20_Init() { I2C_Start(); I2C_WriteByte(AHT20_ADDRESS << 1); // 写模式 I2C_WriteByte(0xE1); // 初始化命令 I2C_WriteByte(0x08); // 参数1 I2C_WriteByte(0x00); // 参数2 I2C_Stop(); HAL_Delay(40); // 等待校准完成 } // 读取温湿度数据 void AHT20_ReadData(float *temp, float *humi) { uint8_t data[6] = {0}; I2C_Start(); I2C_WriteByte(AHT20_ADDRESS << 1); I2C_WriteByte(0xAC); // 触发测量命令 I2C_WriteByte(0x33); I2C_WriteByte(0x00); I2C_Stop(); HAL_Delay(80); // 等待测量完成 // 读取6字节数据 I2C_Start(); I2C_WriteByte((AHT20_ADDRESS << 1) | 0x01); // 读模式 for (int i = 0; i < 5; i++) { data[i] = I2C_ReadByte(); I2C_SendAck(0); // 发送ACK } I2C_SendAck(1); // 发送NACK I2C_Stop(); // 数据解析(公式见AHT20手册) uint32_t raw_humi = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; uint32_t raw_temp = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; *humi = (raw_humi * 100.0) / (1 << 20); *temp = (raw_temp * 200.0) / (1 << 20) - 50; } ``` #### 步骤4:主函数调用 ```c int main() { HAL_Init(); SystemClock_Config(); I2C_Init(); AHT20_Init(); float temp, humi; while (1) { AHT20_ReadData(&temp, &humi); HAL_Delay(2000); // 每2秒采集一次 } } ``` #### 注意事项 1. **延时函数**需根据实际时钟频率调整(示例中`Delay_us`需自行实现) 2. **GPIO模式**需根据硬件设计选择(开漏输出需外接上拉电阻) 3. **数据校验**需检查状态字(参考AHT20手册)[^1][^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值