I2C 时序特性详解:从标准到超快速
搞 I2C 时序,说白了就是跟时间做朋友。你想想看,两根线(SCL 和 SDA)要承载数据、时钟、应答、甚至多主仲裁,全靠一套严谨的时序约束撑腰。我刚开始调 I2C 外设时,觉得时序表就是随便填几个数字,结果示波器上波形惨不忍睹。嗯,从那以后我就养成了对着数据手册逐条核对时序的习惯。
I2C 时序基础
先把底层的几个关键动作理清:
- 起始条件 (S):SCL 高电平时,SDA 从高→低跳变。所有从机都等着这个信号。
- 停止条件 (P):SCL 高电平时,SDA 从低→高跳变。告诉从机传输结束。
- 数据有效:SCL 高电平时,SDA 必须保持稳定;只有 SCL 低电平期间,SDA 才能变化。
- 时钟延展 (Clock Stretching):从机把 SCL 拉低,让主机等它准备好。这在高速模式下几乎不用,因为从机来不及反应。
这些动作背后都对应一组时间参数:保持时间、建立时间、上升/下降时间等。它们决定了 I2C 总线能跑多快、能挂多少设备。
四种模式的时序参数对比
我个人习惯把四种模式的核心参数记在一个表里,调板子的时候随时瞄一眼。下面的数据取自 I2C 总线规范 v7.0,不过在实际项目中你最好再跟芯片手册对一下——有些厂家的参数会写得比标准严。
| 参数 | 符号 | 标准模式 100 kHz |
快速模式 400 kHz |
高速模式 3.4 MHz |
超快速模式 5 MHz |
|---|---|---|---|---|---|
| SCL 时钟频率 | f_SCL | 100 kHz | 400 kHz | 3.4 MHz | 5 MHz |
| 起始条件保持时间 | t_HD:STA | 4.0 μs | 0.6 μs | 0.16 μs | 0.10 μs |
| 停止条件建立时间 | t_SU:STO | 4.0 μs | 0.6 μs | 0.10 μs | 0.08 μs |
| SCL 低电平时间 | t_LOW | 4.7 μs | 1.3 μs | 0.16 μs | 0.10 μs |
| SCL 高电平时间 | t_HIGH | 4.0 μs | 0.6 μs | 0.12 μs | 0.08 μs |
| 数据有效建立时间 | t_SU:DAT | 250 ns | 100 ns | 10 ns | 5 ns |
| 数据有效保持时间 | t_HD:DAT | 0 ns | 0 ns | 0 ns | 0 ns |
| 上升时间 (SCL & SDA) | t_r | 1000 ns | 300 ns | 120 ns | 40 ns |
| 下降时间 (SCL & SDA) | t_f | 300 ns | 300 ns | 120 ns | 40 ns |
重点提醒:超快速模式(UFM)是单向传输(无需应答),而且从机不允许时钟延展。如果你的器件支持这种模式,务必确认主机也能关闭时钟延展功能,否则通信会崩溃。
两个关键参数:t_HD:STA 与 t_SU:STO
为什么单独拎出来说?因为很多 I2C 通信失败都跟这两个参数有关。
t_HD:STA(起始条件保持时间)—— 从 SDA 下降沿到 SCL 下降沿的最小间隔。如果这个时间不够,从机可能误判为毛刺而忽略起始条件。个人习惯把这个值留两倍余量,尤其是带多个从机的总线。
t_SU:STO(停止条件建立时间)—— 从 SCL 上升到 SDA 上升沿的最小间隔。实际调试时,我最头疼的就是停止条件没建好,导致下一个起始条件被吞掉。你可以想象一下:总线刚发完停止,紧接着又来一个起始,如果 t_SU:STO 不够,SDA 还没来得及完全拉高就又被拉低,结果从机收不到干净的停止,下一次起始可能会被当作地址连续包的一部分。
我曾经因为 t_SU:STO 超标(快 30 ns)导致一个温度传感器时不时死掉。示波器量了半小时才看出停止条件后的 SDA 尾部有个小毛刺。后来加了一个 10 ns 软件延时才稳住。
实际项目中的避坑指南
- 上拉电阻要算:标准模式用 4.7 kΩ 还行,高速模式得换 1.5–2.2 kΩ,超快速模式可能要用 500 Ω 以下。但我建议别超过 400 Ω,否则驱动电流太大,有些 I/O 吃不消。
- 总线电容要控:每个从机都有输入电容,加上走线电容。标准模式允许 400 pF,快速模式 400 pF 是极限,高速模式只允许 100 pF 左右。我试过挂 5 个从机(每个 10 pF)在 20 cm 排线上,高速模式完全跑不了。
- 超快速模式不是所有 MCU 都支持:检查 MCU 的 I2C 外设是否支持 5 MHz 时钟,以及 IO 的最大切换速率。有些芯片内部逻辑跟不上的时候,会强制插入等待周期,实际频率远低于 5 MHz。
- 时钟延展不能乱开:快速模式以上,很多从机不支持时钟延展。如果你发现 SCL 莫名其妙被拉低,大概率是从机在延展,而你主机的超时处理没写好。
记住:时序余量一定要留足,尤其当电压域跨越时。
好了,把这些参数印在脑子里,下次调 I2C 的时候就不会手忙脚乱了。下面的图把时序和关键参数标了出来,你可以照着示波器波形比对。