3. I2C 通信时序:起始条件、停止条件、数据有效性
做嵌入式这些年,调试 I2C 设备少说也有上百次了。说实话,每次用逻辑分析仪抓波形,我最先看的永远是那三个关键点:起始条件、停止条件、数据有效性。这三样搞明白了,I2C 通信的骨架就在你脑子里。
今天我就用实际项目的经验,把这些时序要点掰开揉碎了讲清楚。
3.1 先看懂 SDA 与 SCL 的时序关系图谱
在深入细节之前,我们先看一下 I2C 总线上的“交通规则”长什么样。下面这张图概括了整个时序核心节点,建议你仔细看看,后面讲的内容都会和它呼应。
核心思路:SCL 是时钟线,它控制节奏。SDA 是数据线,它在时钟的特定时刻传递信息。所有的“条件”都发生在 SCL 高电平期间。
3.2 起始条件与停止条件
这两个条件,是 I2C 通信的“打招呼”和“说再见”。逻辑分析仪触发设置,基本就是靠抓这两个条件。
起始条件 (START Condition)
- 电平变化:SCL 保持高电平期间,SDA 从高电平跳变到低电平。
- 关键点:这是 SCL 高电平期间,SDA 唯一“被允许”发生跳变的时刻。
- 我个人的习惯:在设置逻辑分析仪触发时,我一般会选“下降沿触发”在 SDA 上,同时锁住 SCL 高电平条件。这样基本不会漏抓。
停止条件 (STOP Condition)
- 电平变化:SCL 保持高电平期间,SDA 从低电平跳变到高电平。
- 关键点:同样,只有这个时刻允许 SDA 在 SCL 高电平跳变。
- 避坑指南:我曾经调试过一个 NTC 温度传感器,因为是漏极开路,SDA 上拉太弱,总线一直被拉低。逻辑分析仪永远抓不到停止条件。查了两天,才发现是上拉电阻选到了 10kΩ,对于那条长走线来说太大了。
| 条件类型 | SCL | SDA | 逻辑分析仪触发设置 |
|---|---|---|---|
| 起始条件 | 高电平 (H) | 高→低 (下降沿) | SDA 下降沿触发 + SCL 高电平使能 |
| 重复起始条件 | 高电平 (H) | 高→低 (下降沿) | 与起始条件相同,但发生在数据阶段之后 |
| 停止条件 | 高电平 (H) | 低→高 (上升沿) | SDA 上升沿触发 + SCL 高电平使能 |
一个小技巧:当你的逻辑分析仪捕获到一个完整事务,但数据全是 0xFF 或 0x00 时,大概率是起始条件或停止条件没抓对,导致数据帧边界偏移了。
3.3 数据有效性规则
这个规则是 I2C 协议能准确传数据的基础。说白了就是一句话:SCL 高电平时采样 SDA,SCL 低电平时 SDA 才能变。
规则拆解
- 数据建立 (Data Setup):在 SCL 上升沿之前,SDA 上的数据必须先稳定下来。
- 数据保持 (Data Hold):在 SCL 下降沿之后,SDA 上数据还需要保持一小段时间。
- 变化窗口:只有在 SCL 为低电平时,SDA 上的电平才可以改变。
为什么这样设计?你想想看,如果数据在时钟变化时跳变,那读取就会出错。同步时序电路最怕这种情况。
典型的时序参数(以标准模式 100kHz 为例)
| 参数名称 | 符号 | 最小值 | 说明 |
|---|---|---|---|
| SCL 时钟频率 | f_SCL | 0 Hz | 标准模式 100kHz,快速模式 400kHz |
| 数据建立时间 | t_SU;DAT | 250 ns | SCL 上升沿前数据需保持稳定 |
| 数据保持时间 | t_HD;DAT | 0 | SCL 下降沿后数据保持(实际需 > 0 |
| SCL 低电平时间 | t_LOW | 4.7 μs | 时钟低电平持续时间 |
| SCL 高电平时间 | t_HIGH | 4.0 μs | 时钟高电平持续时间 |
注意:我见过很多工程师在调试低速从机时,不小心把数据建立时间设得太短。比如从机是 5V 老器件,主控是 3.3V 新器件,电平转换后信号会边沿变缓。建立时间不足,逻辑分析仪上会看到 SDA 信号刚好在 SCL 上升沿时还在抖,这时候读到的数据肯定乱码。
3.4 字节格式与应答机制
数据从最高位开始传,一个字节 8 位,传完必须紧跟一个应答位。这个我单独拎出来讲,因为它在逻辑分析仪上最明显。
- 地址帧:7 位从机地址 + 1 位 R/W 位(0 写,1 读)。主机发送,从机应答。
- 数据帧:8 位数据,主机发送写数据,或从机发送读数据。
- 应答位 (ACK/NACK):第 9 个时钟周期,发送方释放 SDA,接收方拉低 SDA 表示 ACK,保持高表示 NACK。
逻辑分析仪上的解读技巧
当你在波形图上看到一组 9 个时钟脉冲,第一个字节就是从机地址,紧接着的第 9 个脉冲就是应答。如果一直是高电平(NACK),那就是从机没响应。我在实验里十有八九是地址写错了,或者从机挂了。
// 逻辑分析仪捕获的一帧示例(十六进制)
// 0 1 0 1 0 0 0 | 0 | 0
// 地址=0x28 W ACK
// 地址帧结束,接下来是数据字节
3.5 个人经验:常见时序错误汇总
- 起始条件被误判为数据:如果 SDA 在 SCL 高电平时偶然跳变(比如噪声),逻辑分析仪会错误开始解码。我建议打开“毛刺滤波”功能。
- 停止条件缺失:如果总线拉不到高电平(上面提过的上拉问题),你就永远等不到停止条件。
- 数据建立时间不足:波形上 SDA 信号还没有平就迎来了 SCL 上升沿。我一般在 SCL 上升沿前加一个 NOP 延迟,或者在代码里调整 I2C 时序寄存器。
- 应答位采样点偏移:有些逻辑分析仪默认在 SCL 的中间采样,而 I2C 规定在末尾采样。这个配置一定要手动校准。
总结一下:起始条件和停止条件是总线的“开关”,数据有效性是传输的“规则”。三者缺一不可。在逻辑分析仪上,你只要掌握了这三个点的波形特征,80% 的 I2C 通信问题都能一眼看穿。