SDA被卡低,为何要先补9个时钟?
SDA被卡低,为何要先补9个时钟?

MCU看门狗复位后,I²C驱动初始化成功,第一笔访问却一直返回总线忙。示波器上SCL为高,SDA持续为低,重新调用发送函数也没有边沿。这个现象常发生在上一次传输被截断:MCU忘了先前状态,目标器件却仍记得自己正处于一个字节的中间。
01先分清是谁把哪根线拉低
I²C的SCL和SDA通常是开漏或开集电极结构,器件只主动拉低,高电平由上拉电阻形成。任何挂在总线上的器件都可能把线保持为低,因此软件读到低电平时,不能默认是MCU端口坏了。要先看SCL能否回高,再看SDA是否会随额外时钟释放。
若SCL被目标持续拉低,可能是时钟延展、目标掉电、引脚短路或器件异常。NXP当前I²C规范对这种情况给出的恢复边界是复位或重新上电,不能假定九个脉冲一定有效。九时钟针对的是SCL可用、SDA卡低的场景,两者不能混成一个通用复位动作。

02目标为什么可能正在等剩余位
一帧数据按位在SCL边沿上传输,接收方在第九个时钟给出应答。若控制器在目标发送第几位时突然复位,目标可能继续保持当前数据位,等待时钟把一个字节走完。MCU重启后只看到SDA低,却不知道目标卡在第几位。补充时钟的作用,是给这个未知状态一个退出机会。
最多九个时钟覆盖一个完整字节加应答位置。每送一个脉冲都应观察SDA,一旦它回到高电平,就不必机械地继续。随后可在总线条件允许时形成STOP,让所有器件回到空闲边界。这个动作不是向某个地址写九位数据,而是在没有正常事务的情况下恢复总线状态机。


03恢复脉冲也要按开漏规则生成
软件模拟SCL时,低电平可以主动拉低,高电平应通过释放引脚让上拉形成,不能强推高电平与目标器件对抗。每次释放后还要读回SCL,确认线路真的到达高电平;若目标仍在时钟延展或线路被短接,程序应超时退出,而不是继续快速翻转GPIO。
SDA也不应在SCL高电平时随意改变,否则可能被器件解释成START或STOP。常见实现会先释放SDA,再以受控节奏产生SCL脉冲,检测到SDA释放后构造一个合法STOP。引脚复用切换、上拉电压和GPIO输出类型都要在恢复代码前确定。

04九个时钟无效,就别再无限循环
确认目标器件供电稳定,避免未上电器件通过SDA、SCL保护结构反向供电。
测量SCL与SDA低电平幅度,排除焊接短路、上拉错误和电平转换器方向问题。
检查是否存在目标合法时钟延展,以及驱动超时是否短于器件最坏处理时间。
九时钟后SDA仍不释放时,执行器件复位或受控电源循环,并记录故障前末笔事务。
恢复成功后重新初始化控制器外设和目标寄存器,不能沿用复位前的软件状态。
多电压域系统还要注意关机顺序。目标掉电而MCU仍通过上拉保持总线高,保护二极管可能让目标处在半上电状态;此时它既不满足正常逻辑,又未必完全释放线路。恢复策略应与电源时序一起设计,必要时使用具有关断隔离能力的电平转换器或开关。
总线清除适合做成启动前的有界动作,而不是掩盖驱动缺陷的常驻循环。还应追查原始中断来自看门狗、掉电、噪声、超时还是错误的中止流程。把故障前事务、SCL/SDA波形和复位原因同时保留,才能从“每次开机敲九下”走到真正消除卡总线。
恢复函数还要处理并发。若中断、DMA或另一任务仍能访问I²C外设,GPIO模式下的清除脉冲可能与硬件控制器争用引脚。进入恢复前应锁住总线、停用外设并清除挂起状态,完成STOP后再按时序重新打开。把恢复动作封装在驱动层,比让多个业务任务各自翻转SCL更可控。
声明:
本文由凡亿教育整理,转载请注明来源!
投稿/招聘/广告/课程合作/资源置换 请加微信:13237418207






哔哩哔哩
微信公众号
小红书
抖音
知乎
西瓜视频
头条
微信视频号
