STM32F103基于I2C协议的AHT20温湿度传感器数据采集
·
STM32F103基于I2C协议的AHT20温湿度传感器数据采集
一、I2C总线通信协议基础
1.1 什么是I2C协议
I2C(Inter-Integrated Circuit)是一种同步、多主从、半双工的串行通信总线,由Philips公司开发。它只需要两根线即可实现设备间的通信:
- SDA:串行数据线
- SCL:串行时钟线
1.2 软件I2C vs 硬件I2C
硬件I2C
- 定义:使用STM32芯片内部专用的I2C外设控制器
- 特点:
- 有专门的I2C引脚(如PB6-SCL, PB7-SDA)
- 硬件自动处理时序、ACK/NACK响应
- 支持中断和DMA传输
- 编程简单,调用HAL库函数即可
- 优点:
- 效率高,不占用CPU资源
- 时序精确,稳定性好
- 支持高速模式(400kHz)
- 缺点:
- 引脚固定,配置不够灵活
- 调试相对复杂
二、AHT20温湿度传感器介绍
2.1 AHT20特性
- 高精度:温度精度±0.3℃,湿度精度±2%RH
- 数字输出:I2C接口
- 工作电压:2.2V-5.5V
- 低功耗:测量期间1.2mA,空闲状态0.2μA
2.2 AHT20器件地址
AHT20的7位器件地址为0x70
三、硬件设计
3.1 硬件连接
| STM32F103 | AHT20 | 说明 |
|---|---|---|
| PB6 | SCL | I2C时钟线 |
| PB7 | SDA | I2C数据线 |
| 3.3V | VCC | 电源正极 |
| GND | GND | 电源地 |
| PA9 | TX | 串口输出(接USB转TTL) |
四、软件实现
4.1 工程配置
使用STM32CubeMX配置:
- 系统时钟:72MHz
- I2C1:标准模式(100kHz)
- USART1:115200波特率,8数据位,无校验
- GPIO:PB6(SCL),PB7(SDA),PA9(TX)
4.2 核心代码实现
主程序 (main.c)
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
#include <stdio.h>
#include <string.h>
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1;
// AHT20相关定义
#define AHT20_ADDRESS 0x70 // 器件地址
#define AHT20_CMD_INIT 0xBE // 初始化命令
#define AHT20_CMD_MEASURE 0xAC // 测量命令
#define AHT20_CMD_RESET 0xBA // 软复位命令
void SystemClock_Config(void);
/**
* @brief AHT20初始化函数
* @retval 1-成功, 0-失败
*/
uint8_t AHT20_Init(void)
{
uint8_t cmd[3] = {AHT20_CMD_INIT, 0x08, 0x00};
uint8_t status = 0;
// 发送初始化命令
if(HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS << 1, cmd, 3, 100) != HAL_OK)
{
return 0;
}
HAL_Delay(10); // 等待初始化完成
// 读取状态字
if(HAL_I2C_Master_Receive(&hi2c1, (AHT20_ADDRESS << 1) | 0x01, &status, 1, 100) != HAL_OK)
{
return 0;
}
// 检查校准位(bit[3]应该为1)
if((status & 0x08) == 0)
{
return 0; // 校准失败
}
return 1; // 初始化成功
}
/**
* @brief AHT20软复位
* @retval 1-成功, 0-失败
*/
uint8_t AHT20_Reset(void)
{
if(HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS << 1, &AHT20_CMD_RESET, 1, 100) != HAL_OK)
{
return 0;
}
HAL_Delay(20);
return 1;
}
/**
* @brief 读取AHT20温湿度数据
* @param temperature: 温度值(摄氏度)
* @param humidity: 湿度值(百分比)
* @retval 1-成功, 0-失败
*/
uint8_t AHT20_Read_Data(float *temperature, float *humidity)
{
uint8_t data[6];
uint8_t cmd[3] = {AHT20_CMD_MEASURE, 0x33, 0x00};
uint32_t temp_raw, humi_raw;
// 发送测量命令
if(HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS << 1, cmd, 3, 100) != HAL_OK)
{
return 0;
}
// 等待测量完成(最大80ms)
HAL_Delay(80);
// 读取6字节数据
if(HAL_I2C_Master_Receive(&hi2c1, (AHT20_ADDRESS << 1) | 0x01, data, 6, 100) != HAL_OK)
{
return 0;
}
// 检查状态位,确保数据有效
if((data[0] & 0x80) == 0x80)
{
return 0; // 设备忙
}
// 转换湿度数据(20bit)
humi_raw = ((uint32_t)data[1] << 12) | ((uint32_t)data[2] << 4) | ((uint32_t)data[3] >> 4);
*humidity = (float)humi_raw * 100.0 / (1 << 20);
// 转换温度数据(20bit)
temp_raw = (((uint32_t)data[3] & 0x0F) << 16) | ((uint32_t)data[4] << 8) | data[5];
*temperature = (float)temp_raw * 200.0 / (1 << 20) - 50.0;
return 1;
}
/**
* @brief 重定向printf到串口
*/
int _write(int file, char *ptr, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, 1000);
return len;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
float temperature, humidity;
char buffer[100];
uint32_t last_tick = 0;
printf("STM32F103 AHT20 Temperature & Humidity Monitor\r\n");
printf("Initializing AHT20...\r\n");
// 初始化AHT20
if(AHT20_Init())
{
printf("AHT20 Initialize Success!\r\n");
}
else
{
printf("AHT20 Initialize Failed! Trying reset...\r\n");
AHT20_Reset();
HAL_Delay(100);
if(AHT20_Init())
{
printf("AHT20 Initialize Success after reset!\r\n");
}
else
{
printf("AHT20 Initialize Failed! Check hardware connection.\r\n");
while(1);
}
}
printf("Start Reading Temperature and Humidity...\r\n");
printf("Time(s)\tTemperature(C)\tHumidity(%%) \r\n");
while (1)
{
// 每隔2秒读取一次数据
if(HAL_GetTick() - last_tick >= 2000)
{
last_tick = HAL_GetTick();
if(AHT20_Read_Data(&temperature, &humidity))
{
// 输出格式化的数据
sprintf(buffer, "%.1f\t%.2f\t\t%.2f\r\n",
(float)last_tick/1000.0, temperature, humidity);
printf("%s", buffer);
}
else
{
printf("Read Data Failed!\r\n");
}
}
HAL_Delay(100);
}
}
I2C配置 (i2c.c)
#include "i2c.h"
I2C_HandleTypeDef hi2c1;
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000; // 100kHz标准模式
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_I2C1_CLK_ENABLE();
// PB6 - SCL, PB7 - SDA
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 开漏输出
GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉电阻
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}
串口配置 (usart.c)
#include "usart.h"
UART_HandleTypeDef huart1;
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
// PA9 - TX, PA10 - RX
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
}
五、程序运行结果
编译下载程序后,通过串口调试助手可以看到如下输出:
六、常见问题及解决方法
6.1 初始化失败
- 问题:AHT20初始化失败
- 解决:
- 检查硬件连接是否正确
- 确认电源电压为3.3V
- 检查I2C上拉电阻(通常4.7kΩ)
- 尝试软件复位AHT20
6.2 读取数据失败
- 问题:读取温湿度数据失败
- 解决:
- 检查I2C时序配置
- 增加测量等待时间
- 检查状态字是否正常
七、总结
本项目成功实现了基于STM32F103的AHT20温湿度传感器数据采集系统,主要特点包括:
- 硬件I2C通信:使用STM32硬件I2C外设,通信稳定可靠
- 精确数据采集:按照AHT20数据手册协议正确读取和转换数据
- 实时串口输出:通过USART将数据实时发送到上位机
- 完善的错误处理:包含初始化检测、状态字检查等错误处理机制
此实验可以广泛应用于各种需要温湿度监测的嵌入式系统中,如环境监测、智能家居、农业物联网等领域。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)