MCU I2C 总线挂死排查:从机拉低 SDA 与时钟拉伸的实战定位

光电手记 发表于 2026-11-06 01:06 · 3 次浏览 · 1 条回复
光
I2C 总线挂死是最让人头疼的现场问题之一:主机发完地址就没了下文,SDA 被拉低不释放,整个总线上的其他从机也跟着瘫痪。上周在一块 STM32 板子上又遇到一次,把排查过程记录下来。

一、先看波形,别急着复位
挂死时先用示波器同时看 SCL 和 SDA。如果 SDA 恒低、SCL 为高,大概率是从机在某个字节中间卡住了——最常见的是从机在等主机的 ACK,或者从机内部状态机跑飞。这时直接复位主机没用,SDA 还被从机拉着。

二、九个时钟脉冲解挂
标准解法是主机手动发 9 个 SCL 脉冲,让从机把卡住的字节吐完、释放 SDA。实现时注意两点:一是先把 SCL/SDA 切到 GPIO 模式再发脉冲,硬件 I2C 外设在挂死状态下往往发不出来;二是发完脉冲后检查 SDA 是否回到高电平,再发 STOP 条件。如果 9 个脉冲后 SDA 还低,基本可以判定从机死锁,只能断电重启从机。

三、时钟拉伸要设超时
很多从机在处理数据时会拉低 SCL 做时钟拉伸,正常。问题出在主机没有超时机制:从机一旦异常,主机就一直等下去。我的做法是在驱动层给每次等待加超时(比如 10ms),超时后走解挂流程并记一条错误日志,现场定位能省一半时间。

四、根因多半在时序不在代码
这次遇到的根因是总线电容偏大:走线长、上拉电阻选了 10k,上升沿变缓,从机在高电平采样窗口误判。把上拉改成 4.7k、缩短分支走线后,挂死再没复现。I2C 看着简单,物理层出问题比协议层多得多。

大家在 I2C 挂死时还遇到过哪些奇葩根因?欢迎分享。
广告位 A8广告位招商帖子页首楼下方通栏 · 728×90 · 查看报价 · 联系 ads@oeforum.com
论 论坛助手
【编辑部】@光电手记 「先看波形 → 九时钟解挂 → 再查主机超时与从机拉伸」这条链路写得很完整,I2C 挂死现场最怕的就是直接复位主机却不解 SDA。编辑部再补三点量产口径:

1)把「总线恢复」(9×SCL + STOP)写进驱动超时路径,不要只依赖看门狗整板复位;恢复后要重发未完成事务并记一次错误码。
2)从机侧:固件里时钟拉伸要有上限(常见几百微秒到数毫秒),超时必须释放 SDA;量产抽检用示波器扫最长拉伸。
3)多从机/长线:上拉与总线电容过大时边沿变慢,会被误判成拉伸——先用示波器量 30%–70% 边沿时间再定上拉阻值。

开放问题:你们量产更常栽在从机固件拉伸无上限,还是主机驱动缺超时恢复?有没有把总线恢复次数做成告警阈值的做法?
登录 后参与回复,还没有账号?立即注册
行业企业展示华工正源(HGGenuine)光模块与光电器件厂商,华工科技旗下访问官网 →行业企业展示,基于公开资料,如需撤下请联系 ads@oeforum.com