I2C通信时序:起始条件、停止条件、数据有效性、字节格式与ACK/NACK机制

说实话,I2C的时序看起来就那么几条线,但真正在示波器上抓波形的时候,很多人就懵了。我见过不少工程师,协议背得滚瓜烂熟,一上逻辑分析仪就不知道哪是哪。这一章咱们就把I2C通信的每个动作拆开来看,从波形角度理解它到底在干什么。

起始条件与停止条件

I2C总线的空闲状态很简单:SCL和SDA都是高电平。这时候总线是释放的,任何设备都可以发起通信。

起始条件:SCL保持高电平时,SDA从高电平跳变到低电平。这个下降沿告诉所有从设备:“注意,要开始传数据了。”

停止条件:SCL保持高电平时,SDA从低电平跳变到高电平。这个上升沿表示传输结束,总线恢复空闲。

关键点:起始和停止条件都是由主机产生的。从设备只能被动响应,不能主动发起或终止传输。

我在项目中遇到过一个问题:某个传感器偶尔会锁死总线,SCL被拉低不放。后来发现是起始条件没发完整,从设备状态机卡住了。从那以后我每次写I2C驱动,都会在起始条件前后加一个总线恢复流程——先把SCL和SDA都拉高,再发起始。

数据有效性:什么时候采样,什么时候更新

I2C的数据有效性规则其实就一句话:SCL高电平时采样数据,SCL低电平时更新数据。

具体来说:

  • SCL为高电平时,SDA上的电平必须保持稳定,不能变化
  • SCL为低电平时,SDA可以变化,发送方准备好下一个bit
  • 数据在SCL的上升沿被采样,在下降沿之后更新

你想想看,如果SCL高电平时SDA变了,从设备会怎么想?它会认为这是一个起始或停止条件。这就是为什么很多I2C通信异常都是因为时序违规——SDA在SCL高电平时抖动了一下,从设备误判了。

调试技巧:用示波器抓I2C波形时,先看SCL高电平期间SDA是否稳定。如果看到SDA在SCL高电平有毛刺,基本可以断定是硬件问题——上拉电阻太小、走线过长、或者地线回路有问题。

字节格式:8位数据 + 1位应答

I2C传输的基本单位是字节。每个字节8位,MSB先传。传完8位数据后,紧接着跟一个应答位(ACK/NACK)。所以一个完整的字节传输需要9个SCL时钟周期。

我记得第一次用逻辑分析仪抓I2C波形时,数了半天时钟周期,总觉得哪里不对。后来才反应过来:那个第9个时钟是应答位,不是数据的一部分。

时钟周期 SCL状态 SDA行为 说明
1-8 高低交替 发送方逐位输出数据(MSB→LSB) SCL高电平时采样
9 高低交替 接收方拉低SDA(ACK)或保持高(NACK) 应答位由接收方控制

ACK与NACK机制

应答机制是I2C协议里最容易被忽视但又最关键的部分。说白了,就是接收方告诉发送方:“我收到了,继续发”或者“我收不了,别发了”。

ACK(应答):在第9个时钟周期,接收方将SDA拉低。表示数据接收成功,可以继续传输下一个字节。

NACK(非应答):在第9个时钟周期,接收方保持SDA为高电平。表示接收失败或传输结束。

什么时候会出现NACK?我总结了几种常见情况:

  • 从设备地址不匹配——没有设备响应这个地址
  • 从设备忙——正在处理上一个命令,没空接收新数据
  • 读操作结束——主机发送NACK告诉从设备“别再发了”
  • 从设备不支持该操作——比如只写的设备收到了读请求

避坑指南:我曾经在一个项目里遇到I2C通信间歇性失败,查了三天。最后发现是从设备在ACK阶段拉低SDA的时间不够长,主机采样时SDA已经释放了。标准规定ACK必须在第9个时钟的上升沿之前建立,保持到下降沿之后。很多从设备芯片的ACK保持时间刚好卡在边界上,遇到时钟频率偏高就容易出问题。

完整字节传输的波形解读

把上面几个概念串起来,一个完整的字节传输流程是这样的:

  1. 主机产生起始条件(SCL高,SDA下降沿)
  2. 主机发送8位数据,MSB先发,每个bit在SCL上升沿被采样
  3. 主机在第8个时钟下降沿后释放SDA(拉高),准备接收应答
  4. 主机产生第9个时钟,从设备在SCL低电平时拉低SDA(ACK)或保持高(NACK)
  5. 主机在第9个时钟上升沿采样SDA,判断应答状态
  6. 如果需要继续传输,重复步骤2-5;否则产生停止条件

嗯,这里要注意:主机在发送完8位数据后,必须释放SDA总线控制权,让从设备来拉低。如果主机不释放,从设备没法给出ACK,通信就卡死了。

知识结构图:I2C通信时序核心要素

下面这张图把I2C通信时序的核心要素串起来了,从总线空闲到传输结束,每个环节的波形特征和关键动作都标了出来。

I2C通信时序核心要素 总线空闲 SCL=H, SDA=H 起始条件 SCL=H, SDA↓ 数据字节 8位, MSB先传 应答位 ACK/NACK 停止条件 SCL=H, SDA↑ 数据有效性规则 SCL高电平 → 采样数据(SDA必须稳定) | SCL低电平 → 更新数据(SDA可以变化) 字节格式 8位数据 + 1位应答 共9个SCL时钟周期 ACK(应答) 第9时钟,SDA被拉低 表示“继续传输” NACK(非应答) 第9时钟,SDA保持高 表示“停止/错误” 常见NACK场景 ① 从设备地址不匹配 ② 从设备忙 ③ 读操作结束(主机主动NACK) ④ 不支持的操作 调试时先确认地址是否正确,再检查从设备是否处于正常工作状态

实际调试中的波形识别

拿到示波器或逻辑分析仪的波形图,怎么快速判断通信是否正常?我一般按这个顺序检查:

  1. 看起始条件:SCL高电平时,SDA有没有一个干净的下降沿?如果有毛刺或斜率太缓,说明上拉或驱动有问题
  2. 看数据字节:SCL高电平时,SDA是否稳定?每个bit的建立时间和保持时间是否满足要求
  3. 看应答位:第9个时钟,SDA有没有被拉低?如果一直是高电平,说明没有设备应答
  4. 看停止条件:SCL高电平时,SDA有没有一个干净的上升沿?如果上升沿太缓,可能是总线电容太大

实用工具:我习惯用逻辑分析仪抓I2C波形,设置触发条件为起始条件(SDA下降沿+SCL高电平)。这样每次按下开始按钮,抓到的第一个事件就是起始条件,方便定位问题。示波器的话,建议用余晖模式观察SDA和SCL的边沿质量。

说白了,I2C时序的核心就是那几条规则:起始/停止条件看SDA在SCL高电平时的跳变方向,数据有效性看SCL高电平时SDA的稳定性,字节格式是8+1,应答机制是接收方在第9个时钟控制SDA。把这些搞清楚了,看波形就跟看文字一样自然。