0
收藏
微博
微信
复制链接

I²C总线SDA一直被拉低,为什么重启MCU也救不回来?

2026-09-17 16:31
5

I²C总线SDA一直被拉低,为什么重启MCU也救不回来?

MCU复位了,I²C驱动也重新初始化了,可一读传感器就返回 BUSY;示波器一看,SDA从上电到现在一直趴在低电平。继续重启主控往往没有用,因为被复位的是Controller,没被复位的Target可能还停在上一笔交易的第5位、第8位,甚至正在等ACK后的后续时钟。

这种故障最容易被误判成“软件死锁”。真正要先回答的是:谁在拉低线、它为什么认为这一笔传输还没有结束、主控有没有能力把总线重新带回Idle。I²C是开漏共享总线,任何一个挂在SDA上的器件都能让整条总线保持LOW;只重启主控,并不会自动清掉外围器件内部的I²C状态机。

I2C共享总线与上拉结构现成技术图
图1|I²C的SCL、SDA是多器件共享的开漏总线。只要某个Target仍认为事务未结束并继续拉低SDA,Controller即使已经重启,看到的仍然是一条“忙”的总线。

一、先分清:是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。

I2C Start地址ACK数据Stop时序现成技术图
图2|一笔典型I²C事务包含Start、地址/读写位、ACK、数据、ACK和Stop。主控若在中间复位,Target仍可能停在原来的bit/ACK状态;Bus clear的时钟就是在帮助它把状态机推进到可释放总线的位置。

但工程实现里不要只写一个固定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

登录后查看更多
0
评论 0
收藏
侵权举报
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表凡亿课堂立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。

热门评论0

相关文章

凡亿教育

凡亿教育打通了“人才培养+人才输送”的闭环,致力于做电子工程师的梦工厂,打造“真正有就业保障的电子工程师职业教育平台”。帮助电子人快速成长,实现升职加薪。 为了满足学员多样化学习需求,凡亿教育课程开设了硬件、PCB、仿真、电源、EMC、FPGA、电机、嵌入式、单片机、物联网、人工智能等多门主流学科。

开班信息