I²C总线SDA一直被拉低,为什么重启MCU也救不回来?
MCU复位了,I²C驱动也重新初始化了,可一读传感器就返回 BUSY;示波器一看,SDA从上电到现在一直趴在低电平。继续重启主控往往没有用,因为被复位的是Controller,没被复位的Target可能还停在上一笔交易的第5位、第8位,甚至正在等ACK后的后续时钟。
这种故障最容易被误判成“软件死锁”。真正要先回答的是:谁在拉低线、它为什么认为这一笔传输还没有结束、主控有没有能力把总线重新带回Idle。I²C是开漏共享总线,任何一个挂在SDA上的器件都能让整条总线保持LOW;只重启主控,并不会自动清掉外围器件内部的I²C状态机。

一、先分清:是SDA卡低,还是SCL卡低
SDA卡低常见于Controller在一次读写中途被看门狗、掉电检测或软件复位打断。Target已经收到了START和若干个时钟,还在等待剩余bit或ACK周期;主控重新启动后却从“空闲总线”的假设出发,两边状态机自然对不上。
SCL卡低则不能简单套“补9个时钟”。可能是Target在clock stretching,也可能是器件异常、线路短路、未完全上电或IO被钳位。因为Controller连一个完整的SCL上升沿都制造不出来,此时优先要查的是拉低SCL的器件、供电和复位条件。
NXP现行UM10204 Rev.7.0在Bus clear里给的处理边界很明确:SCL stuck LOW时,优先用器件硬件复位,若没有复位脚则对器件重新上电;SDA stuck LOW时,Controller应发送9个时钟脉冲,持有总线的器件应在这些时钟内释放SDA,否则再进入硬件复位或掉电恢复。
二、为什么是9个时钟:它是在“把上一字节走完”
I²C每个字节本质上是8个数据位加1个ACK/NACK时钟。主控如果恰好在一个字节中途复位,外围器件可能仍在按自己的bit counter向前走。连续给出时钟,目标不是“玄学地敲9下”,而是给Target足够的边沿,让它从当前bit推进到字节边界并释放SDA。

但工程实现里不要只写一个固定for循环然后宣布“恢复成功”。每发一个SCL脉冲都应该重新采样SDA:一旦SDA释放,就有机会在SCL为HIGH时构造STOP,把总线恢复到SCL=HIGH、SDA=HIGH的Idle。若9个脉冲后SDA仍低,继续无限打时钟通常没有意义,应转向Target reset、局部电源重启或硬件故障定位。
三、恢复代码要服从开漏电气规则,而不是只服从驱动API
实际做Bus clear时,常见做法是先关闭I²C外设,把SCL/SDA临时切到GPIO。但GPIO配置必须保持开漏语义:LOW可以主动下拉,HIGH应通过释放引脚让上拉电阻拉高。如果误把SCL或SDA配置成推挽高电平,而另一个器件正在拉低,就会形成总线争用,软件恢复动作反而可能变成硬件过流。
恢复顺序建议固定下来:读取SCL/SDA当前状态 → 判断是哪根线被占用 → 若SCL可释放则按低/释放方式产生Bus-clear时钟并逐次采样SDA → 条件允许时生成STOP → 再把管脚交还I²C外设 → 清状态寄存器并重新发起一次已知安全的探测事务。整个过程最好记录恢复发生在哪个地址、哪一次读写和哪个复位原因之后。
还要特别查部分供电。如果上拉电阻接在仍然存在的3.3 V,而某个Target的VDD已经掉电,它的IO保护结构可能通过SDA/SCL被反向供电,表现成线拉不高、阈值异常或器件半醒。此时软件发再多时钟也解决不了根因,必须把上拉电源域、Target供电域和掉电顺序一起看。
四、怎样证明“恢复机制真的有效”,而不是偶尔碰巧恢复
Bring-up阶段可以主动做故障注入:在地址阶段、数据阶段、ACK附近随机触发MCU复位;同时用逻辑分析仪抓SCL、SDA,再加一条MCU_RESET或Target_RESET。你要看到的是:复位后总线被哪一方拉住、Bus clear发了几个有效时钟、SDA在哪个边沿释放、STOP是否出现、驱动何时重新接管。
如果板上有多个Target,再逐个隔离或通过电源/复位域缩小范围。若每次都是同一器件在特定事务后锁住,总线恢复只是兜底,真正的问题可能是Target固件/硅bug、掉电时序、超时策略或主控在关键窗口被复位。量产设计要同时解决“能自动恢复”和“为什么会进入异常状态”两件事。
I²C总线恢复的核心不是“重启驱动”,而是让共享总线上的所有状态机重新回到一致的Idle状态。先看SCL/SDA是谁在拉低,再决定补时钟、发STOP、复位Target还是重启它的电源;这才是一条可以验证、可以复现、可以量产签核的恢复链。
声明:
本文由凡亿教育整理,转载请注明来源!
投稿/招聘/广告/课程合作/资源置换 请加微信:13237418207

扫码关注





































