I²C 通信时序基础:起始条件、停止条件、数据有效性
说起 I²C 时序,很多新手会盯着波形图发懵。总觉得两根线 SCL 和 SDA 来回跳,好像没什么规律。其实你把规则拆开看,核心就三个东西:怎么开始、怎么结束、中间怎么传数据。
我个人习惯把 I²C 时序比作两个人打旗语。SCL 是节拍器,SDA 是那面旗。没有节拍器,旗子挥得再花哨对方也看不懂。这点先刻在脑子里。
起始条件——SCL 高电平时,SDA 从高往低跳
你想象一下这个场景:总线上本来空闲着,SCL 和 SDA 都被上拉电阻拉成了高电平。这时候主机想说话,就先把 SDA 拉低,然后 SCL 才变低开始提供时钟。这个 SDA 在 SCL 高电平时下拉的动作,就叫起始条件。
我见过不少朋友在写驱动时搞反顺序。他们在 SCL 低电平时去拉 SDA,结果从机根本不响应。嗯,这里要注意,起始条件的本质是 SCL 高平时 SDA 的 下降沿。顺序不对,总线不认。
- 空闲状态:SCL = 1,SDA = 1
- 起始条件:SCL 保持 1 → SDA 从 1 变 0 → SCL 变 0 开始传数据
- 关键点:整个跳变过程必须在 SCL 高电平时完成
停止条件——SCL 高电平时,SDA 从低往高跳
停止条件刚好反着来。数据传输完了,主机先把 SCL 拉到高,然后让 SDA 从低变高。这表示:我要收工了,总线给你们用。
注意一点,停止条件之后总线会回到空闲高电平状态。如果主机不想释放总线,可以不发停止,而是发一个重复起始条件。这在多字节读写时很常用。
- SCL 先变高,SDA 保持之前的低电平
- 在 SCL 高电平期间,SDA 从低变高
- 总线回到空闲状态
数据有效性——SCL 低电平时变,高电平时读
这是 I²C 里最容易被忽略却又极其重要的规则。说白了就是一句话:数据要在 SCL 低电平时改变,在 SCL 高电平时被采样。
为什么会这样?因为从机只在 SCL 高电平时才去看 SDA 上的电平。如果你在 SCL 高电平时去动 SDA,从机就会认为你是在发送起始或停止条件。这一点在使用逻辑分析仪抓波形时非常有用:你可以一眼看出数据段里有没有违规的跳变。
| SCL 状态 | SDA 的行为 | 从机反应 |
|---|---|---|
| 低电平 | 允许变化(主机可以改数据) | 不采样,等待 |
| 高电平 | 必须稳定(不能跳变) | 采样当前电平作为有效位 |
| 高电平 + 下降沿 | SDA 从 1 变 0 | 识别为起始条件 |
| 高电平 + 上升沿 | SDA 从 0 变 1 | 识别为停止条件 |
你想想看,这个规则有多微妙。同样是 SDA 跳变,发生在低电平时是正常数据传输,发生在高电平时就成了协议控制信号。所以逻辑分析仪在解析 I²C 时也会先判断跳变发生时 SCL 的电平。
时序上的容限——其实没你想的那么严格
很多人刚接触 I²C 时会特别紧张,觉得时序必须分毫不差。其实它的设计本身就很宽容。标准模式 100kHz,快模式 400kHz,上升时间、保持时间都有明确的容限范围。你只要保证数据在 SCL 高电平前稳定下来就行。
用一张图搞懂 I²C 时序的核心逻辑
下面这张图把起始、停止、数据有效三个核心要素串在了一起。你盯着看几秒,脑子里就有画面了。
这张图上 SCL 和 SDA 的波形关系很直观。你能看到起始条件那里 SDA 先掉下去,然后 SCL 才开始打拍子。数据段里 SCL 高电平时 SDA 纹丝不动,只有低电平时才允许变化。停止条件跟起始完全反着来。
实际用逻辑分析仪抓 I²C 时,我就是按这个图去对波形的。先找 SCL 高平时 SDA 的下降沿,那就是起始位置。然后数 8 个数据位加 1 个应答位,一直到 SCL 高平时 SDA 出现上升沿,那就是停止。百试百灵。
三个规则串起来干活
好了,现在我们把这三个规则拼在一起看一个完整的数据帧:
- 起始条件:主机拉低 SDA,再拉低 SCL
- 发送 7 位地址 + 读写位:每个 bit 在 SCL 低电平时设置,高电平时被采样
- 等待应答:从机在第九个 SCL 脉冲拉低 SDA 表示 ACK
- 发送/接收数据:每 8 位数据跟着一个应答位
- 停止条件:主机拉高 SCL,再拉高 SDA
整个过程环环相扣,一个规则出错整帧数据就废了。但反过来,只要严格按照起始、数据有效、停止这三个规则来,I²C 通信的稳定性非常高。
我的建议: 初学者别急着上手写代码。先拿逻辑分析仪抓几段已知正常的波形,用肉眼把起始位、数据位、停止位一个个标出来。等你能在波形上清晰辨认每个阶段时,再去写驱动或分析故障就会轻松很多。