You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32-S3 ULP RISC-V读取HDC1080温度失败问题求助

ESP32-S3 ULP RISC-V 读取HDC1080温度失败问题解决

问题背景

我在ESP32-S3的ULP RISC-V协处理器深度休眠模式下,尝试通过I2C读取HDC1080传感器的温度值。Arduino环境下的测试代码运行正常,但移植到ESP-IDF的ULP RISC-V I2C库后,无法读取HDC1080的温度值,参考ESP-IDF提供的BMP180 I2C示例代码也无法解决问题。

根据ESP-IDF文档,ULP RISC-V I2C库要求指定从设备子寄存器地址,但HDC1080的温度寄存器地址为0x00,有效数据为[15:02]位,怀疑这是读取失败的核心原因。

Arduino下正常运行的代码

double temp() {

  Wire.beginTransmission((uint8_t)0x40);
  Wire.write((uint8_t)0x00);
  Wire.endTransmission();

  delay(20);

  Wire.requestFrom((uint8_t)0x40, (uint8_t)2);
  byte msb = Wire.read();
  byte lsb = Wire.read();

  uint16_t t = msb << 8 | lsb;
  return (t / pow(2, 16)) * 165.0 - 40.0;
}

当前ESP-IDF测试代码

uint8_t data_buffer[2] = {0, 0};
int a = 0;
while (1)
{
    vTaskDelay(pdMS_TO_TICKS(3000));
    printf("Ölçüm alınıyor...%d\n\n", a++);
    ulp_riscv_i2c_master_set_slave_addr(0x40); // HDC1080的I2C地址

    uint8_t cmd = 0x00; // 温度寄存器地址
    ulp_riscv_i2c_master_write_to_device(&cmd, 1);
    vTaskDelay(pdMS_TO_TICKS(10));

    ulp_riscv_i2c_master_set_slave_reg_addr(0x00); 
    ulp_riscv_i2c_master_read_from_device(data_buffer, 2); 

    uint16_t xut_data = ((uint16_t)data_buffer[0] << 8) | data_buffer[1];
    uint16_t temperatureValue = xut_data >> 2; // 丢弃低2位,取[15:02]有效位
    printf("temperatureValue: %" PRIu16 "\n", temperatureValue);
    printf("data_buffer[0]: %u\n", data_buffer[0]);
    printf("data_buffer[1]: %u\n", data_buffer[1]);
    // 计算实际温度
    float realTemperature = ((float)temperatureValue / (float)(1 << 14)) * 165.0 - 40.0;

    printf("Real Temp: %.2f°C\n", realTemperature);
}

错误输出

Fixaj: 04-07 15:19:26-414691 E (58576) ulp_riscv_i2c: Read Failed!
Fixaj: 04-07 15:19:26-420707 E (58576) ulp_riscv_i2c: RTC I2C Interrupt Raw Reg 0x16c
Fixaj: 04-07 15:19:26-426829 E (58576) ulp_riscv_i2c: RTC I2C Status Reg 0x65ff0000

问题分析与解决方案

核心问题

HDC1080的I2C读取流程和BMP180不同:

  • 写入温度寄存器地址0x00后,传感器开始转换温度,转换完成后,直接发起读操作即可获取结果,不需要再次发送寄存器地址。
  • 当前代码中,调用ulp_riscv_i2c_master_read_from_device前又设置了子寄存器地址,导致ULP I2C库再次发送0x00地址,违反了HDC1080的操作时序,因此读取失败。

修正步骤

  1. 移除ulp_riscv_i2c_master_set_slave_reg_addr调用,避免重复发送寄存器地址。
  2. 确保转换等待时间足够:HDC1080的温度转换时间最长为14ms,因此等待时间应设置为≥14ms(建议20ms,和Arduino代码保持一致)。
  3. 调整温度计算逻辑:原始16位数据的低2位为0,直接用16位计算即可,或者右移2位后用14位计算,结果一致。

修正后的代码

#include <stdio.h>
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ulp_riscv_i2c.h"

#define HDC1080_I2C_ADDR 0x40
#define HDC1080_TEMP_REG 0x00

void app_main(void)
{
    // 初始化ULP RISC-V I2C(需确保已完成硬件引脚配置)
    ulp_riscv_i2c_master_init();

    uint8_t data_buffer[2] = {0, 0};
    int a = 0;
    while (1)
    {
        vTaskDelay(pdMS_TO_TICKS(3000));
        printf("测量中...%d\n\n", a++);

        // 设置HDC1080的I2C地址
        ulp_riscv_i2c_master_set_slave_addr(HDC1080_I2C_ADDR);

        // 发送温度寄存器地址,启动转换
        uint8_t cmd = HDC1080_TEMP_REG;
        esp_err_t write_err = ulp_riscv_i2c_master_write_to_device(&cmd, 1);
        if (write_err != ESP_OK) {
            printf("写入寄存器地址失败: %d\n", write_err);
            continue;
        }

        // 等待温度转换完成(HDC1080最长需要14ms)
        vTaskDelay(pdMS_TO_TICKS(20));

        // 直接读取2字节转换结果,无需再次设置寄存器地址
        esp_err_t read_err = ulp_riscv_i2c_master_read_from_device(data_buffer, 2);
        if (read_err != ESP_OK) {
            printf("读取数据失败: %d\n", read_err);
            continue;
        }

        // 处理原始数据
        uint16_t raw_data = ((uint16_t)data_buffer[0] << 8) | data_buffer[1];
        // 计算实际温度:公式参考HDC1080 datasheet
        float real_temp = ((float)raw_data / 65536.0) * 165.0 - 40.0;

        printf("原始数据: 0x%04X\n", raw_data);
        printf("data_buffer[0]: %u\n", data_buffer[0]);
        printf("data_buffer[1]: %u\n", data_buffer[1]);
        printf("实际温度: %.2f°C\n\n", real_temp);
    }
}

额外注意事项

  • 确保ULP RISC-V的I2C引脚配置正确,使用的是RTC_GPIO引脚(因为ULP只能访问RTC域的硬件)。
  • 如果在深度休眠模式下运行,需确保ULP程序已正确加载并配置唤醒源,上述代码是在主CPU运行的测试代码,若要迁移到ULP协处理器,需将核心逻辑放入ULP汇编/C代码中,并通过主CPU加载。

内容的提问来源于stack exchange,提问作者mehmet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:54:55