基于STM32F411的AM2320温湿度传感器

一、硬件连接配置

// 硬件连接定义(根据实际引脚调整)
#define AM2320_I2C_ADDR 0x5C << 1  // 7位地址左移1位(0xB8写/0xB9读)
#define AM2320_SDA_PIN  GPIO_PIN_9
#define AM2320_SCL_PIN  GPIO_PIN_8
#define AM2320_PORT     GPIOB

// 上拉电阻配置(需外接5.1KΩ电阻)
void AM2320_GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    __HAL_RCC_GPIOB_CLK_ENABLE();
    
    // SDA配置为开漏输出
    GPIO_InitStruct.Pin = AM2320_SDA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(AM2320_PORT, &GPIO_InitStruct);
    
    // SCL配置为推挽输出
    GPIO_InitStruct.Pin = AM2320_SCL_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(AM2320_PORT, &GPIO_InitStruct);
}

二、I2C通信协议实现

// 基本I2C操作函数
void AM2320_I2C_Start(void) {
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SDA_PIN, GPIO_PIN_SET);
    HAL_Delay(2);
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SCL_PIN, GPIO_PIN_SET);
    HAL_Delay(4);
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SDA_PIN, GPIO_PIN_RESET);
    HAL_Delay(3);
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SCL_PIN, GPIO_PIN_RESET);
}

void AM2320_I2C_Stop(void) {
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SDA_PIN, GPIO_PIN_RESET);
    HAL_Delay(3);
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SCL_PIN, GPIO_PIN_SET);
    HAL_Delay(4);
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SDA_PIN, GPIO_PIN_SET);
    HAL_Delay(5);
}

uint8_t AM2320_I2C_WriteByte(uint8_t data) {
    uint8_t ack;
    for (int i=0; i<8; i++) {
        HAL_GPIO_WritePin(AM2320_PORT, AM2320_SDA_PIN, 
                        (data & 0x80) ? GPIO_PIN_SET : GPIO_PIN_RESET);
        HAL_Delay(4);
        HAL_GPIO_WritePin(AM2320_PORT, AM2320_SCL_PIN, GPIO_PIN_SET);
        HAL_Delay(4);
        HAL_GPIO_WritePin(AM2320_PORT, AM2320_SCL_PIN, GPIO_PIN_RESET);
        data <<= 1;
    }
    // 接收ACK
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SDA_PIN, GPIO_PIN_IN);
    HAL_Delay(4);
    ack = HAL_GPIO_ReadPin(AM2320_PORT, AM2320_SDA_PIN);
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SDA_PIN, GPIO_PIN_OUT);
    HAL_Delay(4);
    return ack;
}

uint8_t AM2320_I2C_ReadByte(uint8_t ack) {
    uint8_t data=0;
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SDA_PIN, GPIO_PIN_IN);
    for (int i=0; i<8; i++) {
        HAL_GPIO_WritePin(AM2320_PORT, AM2320_SCL_PIN, GPIO_PIN_SET);
        HAL_Delay(4);
        data <<= 1;
        data |= HAL_GPIO_ReadPin(AM2320_PORT, AM2320_SDA_PIN);
        HAL_GPIO_WritePin(AM2320_PORT, AM2320_SCL_PIN, GPIO_PIN_RESET);
        HAL_Delay(4);
    }
    HAL_GPIO_WritePin(AM2320_PORT, AM2320_SDA_PIN, ack ? GPIO_PIN_SET : GPIO_PIN_RESET);
    HAL_Delay(4);
    return data;
}

三、传感器数据采集流程

#define AM2320_REG_HUMI_HIGH 0x00
#define AM2320_REG_TEMP_HIGH 0x02

float Read_Humidity(void) {
    uint8_t data[4] = {0};
    
    // 唤醒传感器
    AM2320_I2C_Start();
    AM2320_I2C_WriteByte(AM2320_I2C_ADDR);  // 发送设备地址
    HAL_Delay(1000);  // 等待唤醒
    
    // 发送读取指令
    AM2320_I2C_Start();
    AM2320_I2C_WriteByte(AM2320_I2C_ADDR | 0x01);  // 读模式
    data[0] = AM2320_I2C_ReadByte(1);  // 湿度高字节
    data[1] = AM2320_I2C_ReadByte(1);  // 湿度低字节
    data[2] = AM2320_I2C_ReadByte(1);  // 温度高字节
    data[3] = AM2320_I2C_ReadByte(0);  // CRC校验
    
    AM2320_I2C_Stop();
    
    // CRC校验
    if (CRC16_Check(data, 4, data[4]) != 0) {
        return -999;  // 错误值
    }
    
    return (data[0] << 8 | data[1]) / 10.0f;
}

float Read_Temperature(void) {
    // 类似湿度读取流程,修改寄存器地址为0x02
    // 省略重复代码...
}

// CRC16校验算法
uint16_t CRC16_Check(uint8_t *buf, uint8_t len, uint8_t crc_buf) {
    uint16_t crc = 0xFFFF;
    for (int i=0; i<len; i++) {
        crc ^= (uint16_t)buf[i] << 8;
        for (int j=0; j<8; j++) {
            if (crc & 0x8000) crc = (crc << 1) ^ 0x1021;
            else crc <<= 1;
        }
    }
    return crc ^ crc_buf;
}

四、完整工程配置

  1. STM32CubeMX配置
    • 时钟配置:HSE 8MHz → PLL 168MHz
    • GPIO配置:PB8/PB9设为GPIO_Output(开漏模式)
    • 禁用HAL库默认I2C驱动
  2. 系统初始化
int main(void) {
    HAL_Init();
    SystemClock_Config();
    AM2320_GPIO_Init();
    
    while (1) {
        float hum = Read_Humidity();
        float temp = Read_Temperature();
        
        printf("Temp: %.1fC, Hum: %.1f%%\r\n", temp, hum);
        HAL_Delay(2000);
    }
}

参考代码 AM2320的温度湿度采集的STM32F411程序 www.3dddown.com/cna/51683.html

五、关键参数说明

参数 数值 说明
工作电压 3.3V-5V 推荐3.3V供电
测量范围 -40℃~80℃ 温度精度±0.5℃
0-99.9%RH 湿度精度±3%RH
通信方式 I2C 默认地址0x5C(7位)
数据更新周期 2秒 连续读取需间隔>2秒

六、调试技巧

  1. 逻辑分析仪捕获

    • 捕获I2C波形验证时序(起始/停止条件)
    • 检查数据帧格式是否符合规范
  2. 错误处理

    if (hum < -40 || hum > 80) {
        // 触发错误处理
    }
    
  3. 低功耗优化

    // 进入睡眠模式前关闭GPIO
    HAL_GPIO_DeInit(AM2320_PORT, AM2320_SDA_PIN | AM2320_SCL_PIN);
    

七、扩展功能实现

1.数据存储

#define EEPROM_ADDR 0x50
void Save_Calibration(uint16_t offset) {
    HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDR, 0x00, I2C_MEMADD_SIZE_8BIT, 
                     (uint8_t*)&offset, 2, 100);
}

2.OLED显示

void Display_Data(float temp, float hum) {
    OLED_Clear();
    OLED_ShowString(0,0,"Temp:");
    OLED_ShowNum(0,4,temp,1,16);
    OLED_ShowString(0,6,"C  ");
    OLED_ShowString(1,0,"Hum:");
    OLED_ShowNum(1,4,hum,1,16);
    OLED_ShowString(1,6,"%");
}

该方案通过标准I2C协议实现AM2320数据采集,实际应用中需注意:

  1. 确保SCL/SDA上拉电阻(建议4.7KΩ)
  2. 首次读取前需等待传感器唤醒(>200ms)
  3. 连续读取需间隔>2秒避免数据冲突
  4. 建议添加软件滤波算法处理异常数据
posted @ 2025-12-19 15:29  我是一只小小鸟~  阅读(0)  评论(0)    收藏  举报