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

基于Mbed OS的HS3000传感器I2C通信读写故障排查

Arduino Nano 33 BLE Sense + Mbed OS + HS3000 I2C通信故障排查

问题现象

使用Mbed OS在Arduino Nano 33 BLE Sense上通过I2C连接HS3000温湿度传感器时,读取"Who Am I"寄存器持续失败,代码输出如下:

I2C write error on 'Who Am I'!
I2C read error on 'Who Am I'!
Received from sensor: 0x97 0x01

代码片段

#include "mbed.h"
#include "USBSerial.h"
#include "I2C.h"

// Define memory-mapped GPIO registers for controlling the LEDs
#define DIRSET (uint32_t*) 0x50000514  // Set GPIO direction (Input/Output)
#define OUTSET (uint32_t*) 0x50000508  // Set LED Pin (Turn ON)
#define OUTCLR (uint32_t*) 0x5000050c  // Clear LED Pin (Turn OFF)

#define HUMIDITY_FLAG (1UL << 0)
#define TEMPERATURE_FLAG (1UL << 1)

//Ticker ticker;
EventFlags event_flags;
USBSerial serial;

void set_i2c_pullup(){
    *DIRSET |= (1 << 0);
    *OUTSET |= (1 << 0);
}

void ISR(){
    static bool toggle = true;
    if (toggle){
        event_flags.set(HUMIDITY_FLAG);
    }
    else{
        event_flags.set(TEMPERATURE_FLAG);
    }
    toggle = !toggle;
}

Mutex print_mutex;

I2C i2c(I2C_SDA1, I2C_SCL1);
const int HS3000_ADDR = 0x44 << 1;  // 0x44 shifted for 7-bit I2C address

int main(void){
    set_i2c_pullup();

    char who_am_i_addr[] = {0x1E};  // Register to read ID
    char who_am_i_data[2];

    if (i2c.write(HS3000_ADDR, who_am_i_addr, 1) != 0) {
        serial.printf("I2C write error on 'Who Am I'!\r\n");
    }
    ThisThread::sleep_for(200ms);

    if (i2c.read(HS3000_ADDR, who_am_i_data, 2) != 0) {
        serial.printf("I2C read error on 'Who Am I'!\r\n");
    }

    serial.printf("Received from sensor: 0x%02X 0x%02X\r\n", who_am_i_data[0], who_am_i_data[1]);

    //ticker.attach(&ISR, 1s);
    
    while(true){
        // Main loop
    }
}

设备配置

  • 开发板:Arduino Nano 33 BLE Sense
  • 传感器:HS3000温湿度传感器

HS3000手册关键信息

  1. HS3xxx系列支持100kHz和400kHz I2C比特率
  2. 默认7位I2C地址为0x44
  3. 非易失性寄存器表:
寄存器地址描述
0x06湿度传感器分辨率(读寄存器,位11:10)
0x46湿度传感器分辨率(写寄存器,位11:10)
0x11温度传感器分辨率(读寄存器,位11:10)
0x51温度传感器分辨率(写寄存器,位11:10)
0x1E传感器ID高2字节
0x1F传感器ID低2字节

已知问题细节

  • 无编译错误
  • 写入0x1E寄存器时触发I2C写入错误
  • 读取传感器响应时触发I2C读取错误
  • 读取到的ID为0x97 0x01,与预期不符
  • 已初步检查接线,但可能存在疏漏

疑问

  1. 问题是否由I2C地址或传感器通信配置导致?
  2. 排查HS3000 I2C通信故障还有哪些步骤?

排查与解决方案

1. 确认I2C地址与通信模式

  • 代码中HS3000_ADDR = 0x44 << 1的写法是正确的(Mbed OS的I2C API要求7位地址左移一位,包含读写位),但可以尝试直接使用7位地址让API自动处理:const int HS3000_ADDR = 0x44;,无需手动移位。
  • 检查传感器ADDR引脚连接:HS3000默认地址为0x44,若ADDR接VDD会变为0x45,接GND保持0x44,确认硬件接线是否符合预期。

2. 修复I2C读写流程

HS3000要求寄存器地址写入与数据读取在同一个I2C事务中完成,分开的write和read操作会导致传感器丢失寄存器上下文,修改代码如下:

// 替换原有的write和read步骤
int ret = i2c.write(HS3000_ADDR, who_am_i_addr, 1, true); // true表示不释放总线
if (ret != 0) {
    serial.printf("I2C write error on 'Who Am I'!\r\n");
}
ret = i2c.read(HS3000_ADDR, who_am_i_data, 2);
if (ret != 0) {
    serial.printf("I2C read error on 'Who Am I'!\r\n");
}

3. 修正I2C总线配置

  • 显式设置I2C速率匹配传感器:在set_i2c_pullup()后添加i2c.frequency(100000);(或尝试400kHz)。
  • 修复无效的上拉配置:原set_i2c_pullup()操作的是Pin 0,而非I2C引脚,替换为:
void set_i2c_pullup(){
    DigitalOut sda_pull(I2C_SDA1, 1);
    DigitalOut scl_pull(I2C_SCL1, 1);
    sda_pull.mode(PullUp);
    scl_pull.mode(PullUp);
}

同时确认硬件上是否接了4.7kΩ的上拉电阻(I2C总线必须有上拉,部分开发板自带,若传感器模块未集成需外接)。

4. 硬件排查步骤

  • 重新核对接线:SDA接D14、SCL接D15、VCC接3.3V(HS3000为3.3V器件,禁止接5V)、GND接开发板GND。
  • 用万用表测量SDA/SCL引脚空闲电压,正常应接近3.3V,通信时会有波动。
  • 更换传感器或开发板,排除硬件损坏可能。

5. 扫描I2C总线验证设备存在性

添加I2C扫描函数,确认传感器是否被检测到:

void scan_i2c() {
    serial.printf("Scanning I2C bus...\r\n");
    for (int addr = 0; addr < 128; addr++) {
        if (i2c.write(addr << 1, NULL, 0) == 0) {
            serial.printf("Found device at 0x%02X\r\n", addr);
        }
    }
}

在main函数中调用scan_i2c(),查看是否能扫到0x44地址的设备。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 08:53:13