I2C 调试时,软件日志只能告诉你"失败了",SDA、SCL 的电压和波形才能告诉你"失败在哪里"。下面结合万用表与示波器,梳理一套实用的 I2C 信号排查方法。
1. 先回顾 I2C 通信I2C 以字节为基本传输单位,但传输 1 个字节实际需要 9 个时钟周期:前 8 个周期传输数据,第 9 个周期返回 ACK 或 NACK。I2C 采用高位在前(MSB first)。关键时序:- 起始 S: SCL 为高电平期间,SDA 从高电平跳变为低电平;- 停止 P: SCL 为高电平期间,SDA 从低电平跳变为高电平;- ACK: 接收器收到 8 bit 后,在第 9 个时钟周期把 SDA 拉低;- 数据稳定: SCL 为高电平时 SDA 必须保持稳定,只有 SCL 为低电平时 SDA 才允许变化。## 2. i2cdetect 扫不到设备怎么办设备树和控制器都打开了,但执行 i2cdetect -y 2 仍然扫不到设备时,不要立刻只改驱动。可以先把外设拆下,只保留 SoC 侧 SDA、SCL 和上拉电阻,先确认主控能否输出,再判断外设是否应答。## 3. 第一步:用万用表测空闲电压没有通信时,SDA 和 SCL 都应该是高电平。I2C 是开漏/开集输出,需要外部上拉电阻;例如上拉到 3.3V 时,两根线空闲状态都应接近 3.3V。如果电平不对,优先检查:- 上拉电阻是否漏焊、阻值是否合适;- 上拉电源是否正确;- SDA、SCL 是否短路或接反;- 某个外设是否把总线持续拉低;- 管脚复用和控制器供电是否正常。## 4. 第二步:用示波器抓波形确认空闲电压正常后,一边执行:bashi2cdetect -y 2一边用示波器观察 SDA 和 SCL。建议两个通道分别接 SDA、SCL,并使用合适的地线。主机会向不同地址发起访问,正常情况下应看到连续的起始、地址、数据和停止波形。至少确认:1. SCL 有规律的时钟;2. SDA 在 SCL 高电平期间基本稳定;3. 起始和停止条件符合定义;4. 地址发送后进入第 9 个时钟的 ACK 周期。如果连 SCL 都没有波形,检查控制器、管脚复用、总线编号和驱动是否真正发起传输;若 SCL 有波形但 SDA 异常,再检查 SDA 线路、上拉和外设拉低情况。## 5. 重点看第 9 个时钟的 ACK
调试初期不必一上来解出所有 bit,最关键的是看第 9 个时钟周期:SDA 有没有被拉低。
- SDA 在第 9 个时钟被拉低,说明从设备返回 ACK,至少表明地址访问建立了基本通信;
-
- SDA 没有被拉低,说明是 NACK,主机发出请求但没有设备应答。
拆掉外设后,看到主机发出地址和时钟但没有 ACK,是正常现象。接回外设后,如果供电、复位和地址都正确,对应地址应出现 ACK。还要注意地址格式:芯片手册常写 8 bit 地址,而 Linux 驱动和i2cdetect通常使用 7 bit 地址。
- SDA 没有被拉低,说明是 NACK,主机发出请求但没有设备应答。
6. 正常和异常波形
正常波形的特征是:空闲时 SDA、SCL 都为高;SCL 高电平期间 SDA 稳定;时钟周期稳定、边沿清晰;目标地址访问时第 9 个时钟有 ACK。
常见异常:
- SDA/SCL 一直低: 总线可能被拉死,检查短路、焊接、上拉、供电和占线设备;
-
- 两根线一直高且无波形: 主控可能没发起传输,检查设备树、管脚复用、控制器时钟和总线编号;
-
- 有时钟但无 ACK: 检查 7 bit 地址、供电、复位、接线和上拉;
-
- 纹波大、边沿差: 检查上拉阻值、总线电容、线长、地回路、探头接地和电源噪声。
7. 排查 Checklist
- 确认 I2C 总线编号;
-
- 测 SDA、SCL 空闲电压;
-
- 检查上拉电阻和上拉电源;
-
- 检查管脚复用、时钟和设备树;
-
- 用
i2cdetect确认是否产生 SCL;
- 用
-
- 检查 SDA 在 SCL 高电平期间是否稳定;
-
- 观察第 9 个时钟是否有 ACK;
-
- 核对 7 bit/8 bit 地址;
-
- 检查供电、复位、接线和外设模式;
10.10. 最后再分析驱动和上层协议。
- 检查供电、复位、接线和外设模式;
8. 总结
万用表可以判断上拉和空闲电平,示波器可以定位时钟、数据、边沿和 ACK。I2C 调不通时,先测 SDA/SCL 的电压和波形,看到 ACK 才说明主从通信真正建立起来。