基于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手册关键信息
- HS3xxx系列支持100kHz和400kHz I2C比特率
- 默认7位I2C地址为
0x44 - 非易失性寄存器表:
| 寄存器地址 | 描述 |
|---|---|
| 0x06 | 湿度传感器分辨率(读寄存器,位11:10) |
| 0x46 | 湿度传感器分辨率(写寄存器,位11:10) |
| 0x11 | 温度传感器分辨率(读寄存器,位11:10) |
| 0x51 | 温度传感器分辨率(写寄存器,位11:10) |
| 0x1E | 传感器ID高2字节 |
| 0x1F | 传感器ID低2字节 |
已知问题细节
- 无编译错误
- 写入
0x1E寄存器时触发I2C写入错误 - 读取传感器响应时触发I2C读取错误
- 读取到的ID为
0x97 0x01,与预期不符 - 已初步检查接线,但可能存在疏漏
疑问
- 问题是否由I2C地址或传感器通信配置导致?
- 排查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
相关产品推荐
相关产品推荐

