第4章 起始条件与停止条件时序

做I2C调试,起始条件和停止条件可以说是最容易被忽略、又最容易出问题的两个边角。很多人盯着数据字节看半天,结果发现从机根本不理你——回头一查,原来是起始条件没满足保持时间,或者停止条件丢了一拍。

我个人习惯先拿逻辑分析仪抓一下START和STOP的波形,确认时序参数在规格范围内,再去查数据内容。你想想看,如果握手信号都不对,后面传什么都是白搭。

4.1 时序波形长什么样

标准I2C协议里,起始条件(Start Condition)定义为:SCL为高电平时,SDA由高到低跳变。停止条件(Stop Condition)相反:SCL为高电平时,SDA由低到高跳变。就这么简单?嗯,硬件工程师都知道,问题就出在那个“高电平”到底要稳多久。

下面这张图是我经常贴在调试台前的时序备忘,你可以直接当作参考模板:

起始条件与停止条件时序示意图 SCL … SDA START STOP tHD;STA tSU;STA tSU;STO 图例 SCL SDA —— tHD;STA —— tSU;STA —— tSU;STO

看到波形上的三个关键时间参数了吗?tHD;STA、tSU;STA、tSU;STO。我从项目里总结了一个经验:很多从机(尤其是那些便宜的温度传感器)对tHD;STA特别敏感,少一两个时钟周期就直接罢工。

4.2 建立时间 tSU;STA

tSU;STA定义为:SDA从高跳低之后,到SCL第一次变为低电平之前需要保持的建立时间。说白了就是让从机有足够时间去检测到SDA的下降沿,并且确认这是一个合法的起始条件。

不同模式的时序要求差异很大,我列个表方便你对照:

模式 tSU;STA(最小值) 典型时钟频率
标准模式(Standard)4.0 µs100 kHz
快速模式(Fast)0.6 µs400 kHz
快速+模式(Fast+)0.26 µs1 MHz
高速模式(Hs)160 ns3.4 MHz

我曾经遇到过一块定制ASIC,它在快速模式下fIH=0.6µs的规格下死活不响应。抓波形发现主机的tSU;STA只有450ns,勉强够用但噪声影响下就偶尔出错。换成更严格的400ns设计,问题消失——千万别卡着规格下限跑,留20%裕量是基本修养。

调试技巧:如果怀疑建立时间不足,可以在逻辑分析仪上测量SDA下降沿到SCL下降沿的时间。如果测出来低于规格最小值,说明你的主机GPIO或I2C外设的时序配置有问题。常见原因:主机CPU时钟分频没算对、上拉电阻太小导致边沿变慢。

4.3 保持时间 tHD;STA

tHD;STA是SCL变低之后,SDA还需要保持低电平多长时间。这个参数的意义在于:从机需要在SCL低电平期间采样到SDA为低,以确保起始条件不被误解为数据位。

注意规格书里通常标注的是最小值,没有最大值(实际上最大值受整个帧长度的限制)。我见过的常见范围是:

模式tHD;STA(最小值)
标准模式4.0 µs
快速模式0.6 µs
快速+模式0.26 µs
高速模式160 ns

嗯,这里要注意:tHD;STA和tSU;STA在标准模式下数值相同,但物理含义完全不同。一个是建立前的准备时间,一个是保持中的稳定时间。我曾经在调试一款FPGA实现的I2C从机时,发现主控在快速模式下把tHD;STA做成了200ns(只差了60ns),导致从机偶尔采不到起始条件。最后在FPGA的RTL里加了一个D触发器的延迟,才把保持时间拉到400ns以上。

警告:有些廉价MCU的I2C硬件模块在快速模式下tHD;STA实际输出可能偏小。如果你的系统同时使用多个从机,必须保证所有从机中最严格的tHD;STA要求都能满足。我曾经换过一款国产MCU,它的I2C外设手册写的最小值是0.6µs,但实测只有400ns——最后只能降速到标准模式用。

4.4 停止条件时序要求

停止条件只有一个关键参数:tSU;STO(停止条件的建立时间)。它定义为:SCL变为高电平之后,SDA从低到高跳变之前需要保持的时间。

规格值如下:

模式tSU;STO(最小值)
标准模式4.0 µs
快速模式0.6 µs
快速+模式0.26 µs
高速模式160 ns

这个参数通常很好满足,但有一个容易踩的坑:如果你在重复起始条件(Repeated START)时误把SDA边沿弄成了停止条件。有些主机为了省一个时钟周期,在发送完数据后直接拉低SDA同时让SCL变高——这样从机就会错误地识别到停止条件,然后reset内部状态机。

实战建议:调试时如果发现从机在连续读写过程中莫名其妙丢数据,先用逻辑分析仪看帧结尾有没有意外的STOP条件。我曾经花了两天才发现是软件工程师在中断里多写了一个I2C_Stop()函数——每传输一个字节就发一次STOP。那叫一个酸爽。

4.5 个人总结的检查清单

每次做I2C从机时序验证,我会按照以下步骤检查起始/停止条件:

  1. 用逻辑分析仪抓取START、REPEATED START、STOP波形,标出SCL/SDA边沿位置。
  2. 测量tSU;STA、tHD;STA、tSU;STO,对照规格书看最小值裕量。
  3. 特别关注重复起始条件——最容易出现时序违规的地方。
  4. 检查上拉电阻:电阻太大会使边沿变缓,等效缩短建立时间;太小则功耗大但时序更好。通常4.7kΩ适合100kHz,1.5kΩ适合400kHz以上。
  5. 在从机端加一个简易的时序检测:比如用示波器探头直接量从机引脚上的SCL/SDA波形,排除主机驱动能力不足导致的波形畸变。

最后说一句:千万别把时序参数当摆设。我见过太多新同事拿着厂商的例程直接跑,改个从机地址就完事——然后抱着一堆“通信失败”的工单来找我。其实只要花五分钟抓一下起始条件,往往就能定位问题。