通过I2C读取TCA9535输出寄存器始终返回255的问题排查
问题分析与修复
原代码始终返回255的核心原因是I2C读操作流程完全错误,没有遵循TCA9535的时序要求,导致实际未读取到有效数据,返回的是Wire.read()的默认无效值。
错误点拆解
- 用
Wire.beginTransmission(0x21)开启读模式是错误的:Arduino Wire库中,beginTransmission仅用于写操作,读操作需通过Wire.requestFrom发起。 - 第一次写入寄存器地址后,未执行“不发送停止条件的结束传输”就开启新传输,破坏了I2C重复起始的时序逻辑。
- 未调用
Wire.requestFrom直接执行Wire.read(),此时读取的是无意义的默认值(255)。
修正后的代码
uint8_t readOutputRegister(){ uint8_t res = 0xFF; // 默认返回无效值 // 第一步:写入要读取的寄存器地址(输出端口0,地址0x02) Wire.beginTransmission(0x20); // 设备写地址(RW=0) Wire.write(0x02); // 指定目标寄存器 // 发送写数据后不发送停止条件,准备重复起始 if (Wire.endTransmission(false) == 0) { // 第二步:发起读操作,请求1字节数据 // 0x21是设备读地址(RW=1,即0x20 | 0x01) if (Wire.requestFrom(0x21, 1) == 1) { res = Wire.read(); // 读取有效数据 } } // Wire.requestFrom结束后会自动发送停止条件 return res; }
关键流程说明
- 指定读取寄存器:先通过设备写地址告知TCA9535要读取的寄存器,用
endTransmission(false)保留总线连接,不发送停止条件,为重复起始做准备。 - 发起读操作:通过
Wire.requestFrom(0x21, 1)发送重复起始信号+设备读地址,同时请求1字节数据,成功后读取有效内容。 - 错误防护:加入通信状态判断,避免I2C连接失败时返回错误数据。
额外注意事项
- 确认TCA9535硬件连接正确(SDA/SCL引脚需上拉,地址引脚A0-A2配置要与代码中0x20的地址匹配)。
- 输出寄存器初始值为0xFF(所有引脚高电平),若未修改过输出状态,读取到255是正常现象,可先调用写输出寄存器的函数修改后再验证读取结果。
内容的提问来源于stack exchange,提问作者mardari
相关产品推荐
相关产品推荐

