STM32F103通过IIC读取HTU21D温湿度传感器程序(HAL库实现)

一、系统概述

基于STM32F103C8T6(Cortex-M3,72MHz)和HAL库,通过IIC总线读取HTU21D数字温湿度传感器数据,实现环境温度(-40125℃,精度±0.3℃)和相对湿度(0100%RH,精度±2%RH)的实时采集。核心功能包括:IIC总线初始化、HTU21D命令发送、数据读取与校验、温湿度值转换,适用于智能家居、工业环境监测等场景。

二、硬件设计

2.1 核心组件选型

模块 型号/参数 功能说明
主控 STM32F103C8T6(64KB Flash,20KB RAM) IIC通信控制、数据处理、温湿度转换
传感器 HTU21D(IIC接口,3.3V供电) 采集温度/湿度(出厂校准,数字输出)
IIC接口 PB6(SCL)、PB7(SDA)(I2C1) 连接HTU21D的SCL/SDA引脚(开漏输出,需上拉)
电源 3.3V DC(STM32与传感器共电源) 为传感器和MCU供电(HTU21D工作电流0.6mA)

2.2 硬件连接

HTU21D引脚 STM32引脚(F103C8T6) 说明
VDD 3.3V 电源正极(3.3V±5%)
GND GND 电源负极
SCL PB6(I2C1_SCL) IIC时钟线(需4.7kΩ上拉)
SDA PB7(I2C1_SDA) IIC数据线(需4.7kΩ上拉)

三、软件设计(STM32 HAL库)

3.1 开发环境

  • IDE:STM32CubeIDE 1.13.0+

  • :STM32Cube_FW_F1_V1.8.0(HAL库)

  • 通信协议:IIC(标准模式,100kHz),HTU21D 7位地址0x40(写地址0x80,读地址0x81)

3.2 核心原理

HTU21D通过IIC接收命令后,启动内部ADC转换,完成后将数据存入寄存器。读取流程:

  1. 发送命令:主机(STM32)向HTU21D发送测量命令(温度:0xE3,湿度:0xE5);

  2. 等待转换:HTU21D转换时间约50ms(最大);

  3. 读取数据:主机读取2字节数据(MSB+LSB)+ 1字节CRC校验(可选);

  4. 数据转换:原始数据(16位)转换为实际温湿度值(温度= -46.85 + 175.72×Raw/65536,湿度= -6 + 125×Raw/65536)。

3.3 核心代码实现

3.3.1 头文件 htu21d.h(寄存器定义与函数声明)

#ifndef __HTU21D_H
#define __HTU21D_H

#include "stm32f1xx_hal.h"

// ==================== HTU21D IIC地址(7位地址0x40) ====================
#define HTU21D_ADDR_WRITE 0x80  // 写地址(0x40<<1)
#define HTU21D_ADDR_READ  0x81  // 读地址(0x40<<1 | 1)

// ==================== HTU21D命令字节 ====================
#define CMD_TEMP_HOLD  0xE3  // 触发温度测量(保持总线)
#define CMD_HUMI_HOLD  0xE5  // 触发湿度测量(保持总线)
#define CMD_TEMP_NOHOLD 0xF3  // 触发温度测量(不保持总线)
#define CMD_HUMI_NOHOLD 0xF5  // 触发湿度测量(不保持总线)
#define CMD_RESET      0xFE  // 软复位(恢复默认配置)

// ==================== 函数声明 ====================
HAL_StatusTypeDef HTU21D_Init(I2C_HandleTypeDef *hi2c);  // 初始化传感器(软复位)
HAL_StatusTypeDef HTU21D_ReadTemp(I2C_HandleTypeDef *hi2c, float *temp);  // 读取温度(℃)
HAL_StatusTypeDef HTU21D_ReadHumi(I2C_HandleTypeDef *hi2c, float *humi);  // 读取湿度(%RH)
HAL_StatusTypeDef HTU21D_SoftReset(I2C_HandleTypeDef *hi2c);  // 软复位传感器

#endif

3.3.2 源文件 htu21d.c(驱动逻辑实现)

#include "htu21d.h"
#include "main.h"

// ==================== 软复位传感器 ====================
HAL_StatusTypeDef HTU21D_SoftReset(I2C_HandleTypeDef *hi2c) {
    uint8_t cmd = CMD_RESET;
    return HAL_I2C_Master_Transmit(hi2c, HTU21D_ADDR_WRITE, &cmd, 1, 100);  // 发送复位命令
}

// ==================== 读取原始数据(2字节+CRC) ====================
HAL_StatusTypeDef HTU21D_ReadRaw(I2C_HandleTypeDef *hi2c, uint8_t cmd, uint16_t *raw) {
    uint8_t data[3] = {0};  // 2字节数据+1字节CRC
    HAL_StatusTypeDef status;

    // 1. 发送测量命令(保持总线模式)
    status = HAL_I2C_Master_Transmit(hi2c, HTU21D_ADDR_WRITE, &cmd, 1, 100);
    if (status != HAL_OK) return status;

    // 2. 等待转换完成(HTU21D转换时间约50ms)
    HAL_Delay(50);

    // 3. 读取数据(3字节:MSB, LSB, CRC)
    status = HAL_I2C_Master_Receive(hi2c, HTU21D_ADDR_READ, data, 3, 100);
    if (status != HAL_OK) return status;

    // 4. 校验CRC(可选,此处省略,直接使用原始数据)
    *raw = (data[0] << 8) | data[1];  // MSB在前,LSB在后
    return HAL_OK;
}

// ==================== 读取温度(℃) ====================
HAL_StatusTypeDef HTU21D_ReadTemp(I2C_HandleTypeDef *hi2c, float *temp) {
    uint16_t raw_temp;
    HAL_StatusTypeDef status = HTU21D_ReadRaw(hi2c, CMD_TEMP_HOLD, &raw_temp);
    if (status != HAL_OK) return status;

    // 原始数据转换(去掉低4位状态位:HTU21D数据格式为14位有效数据,bit15-14为状态)
    raw_temp &= 0xFFFC;  // 清除bit1-0(状态位)
    *temp = -46.85f + 175.72f * (float)raw_temp / 65536.0f;  // 公式:-46.85 + 175.72*Raw/2^16
    return HAL_OK;
}

// ==================== 读取湿度(%RH) ====================
HAL_StatusTypeDef HTU21D_ReadHumi(I2C_HandleTypeDef *hi2c, float *humi) {
    uint16_t raw_humi;
    HAL_StatusTypeDef status = HTU21D_ReadRaw(hi2c, CMD_HUMI_HOLD, &raw_humi);
    if (status != HAL_OK) return status;

    // 原始数据转换(去掉低4位状态位)
    raw_humi &= 0xFFFC;  // 清除bit1-0(状态位)
    *humi = -6.0f + 125.0f * (float)raw_humi / 65536.0f;  // 公式:-6 + 125*Raw/2^16
    // 限幅(0~100%RH)
    if (*humi > 100.0f) *humi = 100.0f;
    if (*humi < 0.0f) *humi = 0.0f;
    return HAL_OK;
}

// ==================== 初始化传感器(软复位+检查ID) ====================
HAL_StatusTypeDef HTU21D_Init(I2C_HandleTypeDef *hi2c) {
    uint8_t id_reg = 0xE7;  // 制造商ID寄存器(可选,HTU21D固定返回0x32)
    uint8_t id = 0;
    HAL_StatusTypeDef status;

    // 1. 软复位
    status = HTU21D_SoftReset(hi2c);
    if (status != HAL_OK) return status;
    HAL_Delay(20);  // 复位后等待20ms

    // 2. (可选)读取制造商ID验证传感器存在
    status = HAL_I2C_Master_Transmit(hi2c, HTU21D_ADDR_WRITE, &id_reg, 1, 100);
    if (status != HAL_OK) return status;
    status = HAL_I2C_Master_Receive(hi2c, HTU21D_ADDR_READ, &id, 1, 100);
    if (status != HAL_OK || id != 0x32) return HAL_ERROR;  // ID错误

    return HAL_OK;
}

3.3.3 IIC初始化与主函数(CubeMX配置+示例)

CubeMX配置步骤

  1. 启用I2C1(PB6=SCL,PB7=SDA),模式为I2C,速率100kHz(标准模式);

  2. 启用USART1(PA9=TX,PA10=RX),用于打印温湿度数据(调试用);

  3. 生成代码(含HAL库初始化)。

主函数示例

#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "htu21d.h"

I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1;

int main(void) {
    HAL_Init();
    SystemClock_Config();  // 72MHz时钟配置
    MX_I2C1_Init();        // I2C1初始化(100kHz)
    MX_USART1_UART_Init(); // USART1初始化(115200bps)

    float temp = 0.0f, humi = 0.0f;

    // 初始化HTU21D
    if (HTU21D_Init(&hi2c1) != HAL_OK) {
        printf("HTU21D初始化失败!\r\n");
        while (1);
    }
    printf("HTU21D初始化成功!\r\n");

    while (1) {
        // 读取温度
        if (HTU21D_ReadTemp(&hi2c1, &temp) == HAL_OK) {
            printf("温度:%.2f℃\r\n", temp);
        } else {
            printf("温度读取失败!\r\n");
        }

        // 读取湿度
        if (HTU21D_ReadHumi(&hi2c1, &humi) == HAL_OK) {
            printf("湿度:%.2f%%RH\r\n", humi);
        } else {
            printf("湿度读取失败!\r\n");
        }

        HAL_Delay(1000);  // 1秒刷新一次
    }
}

// printf重定向到USART1(调试用)
int fputc(int ch, FILE *f) {
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 100);
    return ch;
}

四、测试与验证

  1. 硬件连接:按2.2节连接HTU21D与STM32,确保上拉电阻焊接正确。

  2. 功能测试:用手捂住传感器,观察湿度值上升(如从40%升至70%);用热源(如热水杯)靠近,观察温度值上升。

  3. 精度验证:对比商用温湿度计,误差<±0.5℃(温度)、±3%RH(湿度)。

参考代码 STM32F103通过IIC读HTU21D温湿度传感器 www.youwenfan.com/contentcnt/182383.html

五、总结

基于STM32 HAL库实现了HTU21D的IIC驱动,核心是命令发送、数据读取与原始值转换。通过模块化设计,可扩展CRC校验、低功耗模式(周期性唤醒)或多传感器组网(IIC总线挂载多个设备)。

posted @ 2026-04-14 17:18  hczyydqq  阅读(31)  评论(0)    收藏  举报