2. I2C时序分析:标准模式、快速模式、高速模式
I2C的时序,说白了就是一根时钟线(SCL)和一根数据线(SDA)怎么配合干活。很多新手拿到示波器,看到波形就懵了——这跳来跳去的到底对不对?
我个人习惯,先把I2C的三种模式搞清楚。标准模式、快速模式、高速模式,它们的时序参数差别很大。你要是用快速模式的器件,却按标准模式的时序去抓波形,那大概率会误判。
2.1 三种模式的核心参数对比
先看一张表,把关键参数列出来。我建议你把这表打印出来贴在工位上,调试时随时瞄一眼。
| 参数 | 标准模式 (100 kHz) | 快速模式 (400 kHz) | 高速模式 (3.4 MHz) |
|---|---|---|---|
| SCL 时钟频率 | 0 - 100 kHz | 0 - 400 kHz | 0 - 3.4 MHz |
| SCL 低电平时间 (tLOW) | ≥ 4.7 μs | ≥ 1.3 μs | ≥ 0.16 μs |
| SCL 高电平时间 (tHIGH) | ≥ 4.0 μs | ≥ 0.6 μs | ≥ 0.12 μs |
| 上升时间 (tr) | ≤ 1000 ns | ≤ 300 ns | ≤ 160 ns |
| 下降时间 (tf) | ≤ 300 ns | ≤ 300 ns | ≤ 160 ns |
| 数据建立时间 (tSU;DAT) | ≥ 250 ns | ≥ 100 ns | ≥ 10 ns |
| 数据保持时间 (tHD;DAT) | ≥ 0 ns | ≥ 0 ns | ≥ 0 ns |
关键点:高速模式(Hs-mode)的上升时间要求非常苛刻,只有160 ns。这意味着你的PCB走线寄生电容必须很小,否则波形会严重畸变。我在一个项目中用过3.4 MHz的速率,结果因为线缆太长,波形直接变成了正弦波——根本没法用。
2.2 时序波形详解
I2C的时序,核心就几个动作:起始条件、数据传输、应答、停止条件。咱们一个一个拆开看。
2.2.1 起始条件 (START)
SCL为高电平时,SDA从高电平切换到低电平。这个动作告诉所有从机:总线要开始干活了。
- 时序要求:SCL高电平期间,SDA必须保持稳定,然后下降。
- 示波器抓取技巧:触发方式设为下降沿触发,触发电平设在SDA的50%处。这样每次起始条件都能稳稳抓住。
2.2.2 数据传输
每个时钟周期传输1位数据。SCL高电平时,SDA上的数据必须稳定;SCL低电平时,SDA可以变化。
- MSB先行:先传高位,再传低位。这个顺序别搞反了。
- 字节格式:每8位数据后跟一个应答位(ACK/NACK)。
我的经验:调试时,我习惯先看SCL高电平期间的SDA波形。如果SDA在SCL高电平期间有毛刺或抖动,那多半是建立时间不够,或者上拉电阻太小了。
2.2.3 应答 (ACK/NACK)
第9个时钟周期,发送方释放SDA,接收方拉低SDA表示应答(ACK),保持高电平表示非应答(NACK)。
- 正常情况:每个字节后都应该有ACK。如果看到NACK,要么地址错了,要么从机忙不过来。
- 特殊情况:主机在读取最后一个字节后,会主动发送NACK,告诉从机别再发了。
2.2.4 停止条件 (STOP)
SCL为高电平时,SDA从低电平切换到高电平。总线恢复空闲状态。
2.3 示波器抓取技巧
示波器是调试I2C的利器。但很多人不会用,抓出来的波形一塌糊涂。我分享几个实战技巧。
2.3.1 触发设置
- 边沿触发:用SCL的下降沿触发,适合看单个字节的细节。
- 码型触发:如果你的示波器支持,可以设置起始条件(SDA下降沿 + SCL高电平)作为触发条件。这样能精准抓到通信的开始。
- 序列触发:对于高速模式,建议用序列触发,先抓起始条件,再抓特定地址字节。
2.3.2 采样率和存储深度
- 采样率:至少是信号最高频率的5倍。对于3.4 MHz的高速模式,采样率建议≥ 20 MSa/s。
- 存储深度:抓取完整的数据包时,存储深度要够。我一般设到1 Mpts以上,不然只能看到波形的一小段。
2.3.3 探头和接地
注意:探头的地线要尽量短!长地线会引入噪声,让波形看起来像长了毛刺。我曾经因为用了10 cm长的地线夹,抓出来的波形全是振铃,折腾了半天才发现是探头的问题。
- 推荐:用探头自带的短接地弹簧,或者直接用接地环。
- 带宽:探头带宽至少是信号频率的3倍。100 kHz用100 MHz探头就够了,但3.4 MHz建议用200 MHz以上的探头。
2.4 常见时序问题与定位
调试中遇到最多的问题,我列几个典型的。
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| SCL波形上升沿缓慢 | 上拉电阻太大,或总线电容过大 | 减小上拉电阻(如从10 kΩ改为4.7 kΩ) |
| SDA在SCL高电平时变化 | 建立时间不足,或从机响应太慢 | 降低时钟频率,或检查从机时序参数 |
| 起始条件后无应答 | 从机地址错误,或从机未上电 | 用示波器确认地址字节的每一位 |
| 波形上有明显毛刺 | 地线环路太大,或电源噪声 | 缩短探头地线,加去耦电容 |
避坑指南:我曾经调试一个传感器模块,每次读到第3个字节就卡死。用示波器一看,发现从机在第3个字节后拉低了SCL(时钟拉伸)。主机没处理这个情况,一直等。后来在驱动里加了时钟拉伸超时处理,问题解决。
2.5 知识结构图
下面这张图把I2C时序的核心知识点串起来了。你可以把它当作调试时的快速参考。
2.6 实战建议
最后,给几个实战中的小建议。
- 先看波形,再看代码:遇到I2C通信问题,别急着改代码。先上示波器,看看波形对不对。很多时候是硬件问题,代码只是背锅的。
- 从慢速开始:调试新器件时,先用标准模式(100 kHz)跑通。没问题了再逐步提高频率。我见过太多人一上来就开400 kHz,结果死活调不通。
- 记录波形:把正常的波形截图保存下来。出了问题,拿异常波形和正常波形对比,问题一目了然。
我的习惯:每次调试I2C,我都会在示波器上同时显示SCL和SDA,然后打开余晖模式。这样能看到波形的抖动范围,判断时序裕量够不够。