1. I2C协议基础:起始条件、停止条件、数据帧格式

做逻辑分析仪调试这么多年,我碰到最多的案例就是I2C应答异常。不管你信不信,十个I2C问题里起码有七个出在应答上。但要想真正看懂应答,得先把基础协议啃透。

I2C协议呢,说白了就两根线:SCL(时钟)和SDA(数据)。主设备负责产生时钟,从设备在时钟的配合下收发数据。嗯,这里要注意,两根线都是开漏结构,需要上拉电阻。我个人习惯用4.7kΩ,不过具体阻值跟总线电容有关,这个后面实战再细聊。

1.1 起始条件(Start Condition)

起始条件长什么样?看波形:SCL保持高电平时,SDA从高电平跳变到低电平。

起始条件判定标准: SCL为高 → SDA下降沿

我记得刚入行那会儿,有次写I2C驱动,怎么调都调不通。拿示波器一看,发现起始条件SDA下降的时候SCL还没拉高。你想想看,SCL都没到高电平,从设备根本不认这个起始。后来在那段代码里加了个延迟,问题就解决了。所以啊,时序这玩意儿,差一点就是不行。

小经验: 我建议你在逻辑分析仪的触发条件里直接设“起始条件触发”,这样能快速抓到完整的I2C包。

1.2 停止条件(Stop Condition)

跟起始条件反着来:SCL高电平时,SDA从低电平跳变到高电平。

停止条件判定标准: SCL为高 → SDA上升沿

这里有个容易踩的坑。我曾经修过一个案子,MCU发完停止条件后立刻释放总线,但SDA上拉电阻太大,上升沿慢吞吞的,SCL都已经变低了SDA还没到高。结果从设备认为总线还占用着,下一条起始条件发送失败。后来换小电阻就正常了。

条件 SCL状态 SDA跳变方向 作用
起始条件 高电平 高→低 通知所有从设备:总线要开始传输了
停止条件 高电平 低→高 通知所有从设备:传输结束,总线释放
注意: 起始条件和停止条件必须由主设备产生。如果从设备强行拉低SDA不放,主设备将无法产生停止条件,总线就死锁了。这种情况我们在后续章节会拿逻辑分析仪具体抓波形分析。

1.3 数据帧格式

一个完整的I2C数据帧包含以下部分:

  • 起始条件 —— 如上文所述
  • 从设备地址(7位或10位) —— 7位地址最常见
  • 读写位(R/W) —— 0表示写,1表示读
  • 应答位(ACK/NACK) —— 从设备每收到一个字节都要回应
  • 数据字节 —— 每次8位,MSB先传
  • 停止条件 —— 或者重复起始条件

先看这个典型的7位地址写操作帧:

SCL:  ▁▁▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▁▁
SDA: ▁▁▁▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▁▁
      ↑S ↓ A6 A5 A4 A3 A2 A1 A0 W  ACK D7 D6 D5 D4 D3 D2 D1 D0 ACK ↑P
      Start Addr[6:0]     R/W 从应答    Data Byte(8位)     从应答 Stop

看不懂?没关系,我们拆开来讲。

1.3.1 地址字节

起始条件之后,主设备发送的第一个字节就是地址字节。高7位是从设备地址,最低位是读写方向。

  • 地址 + 0(写)→ 主设备要发送数据给从设备
  • 地址 + 1(读)→ 主设备要从设备读取数据

比如一个传感器的地址是0x48(7位二进制1001000),那么发写的地址字节就是0x90(1001000 0),发读就是0x91(1001000 1)。

1.3.2 应答位

每传完一个字节(8位),接收方都会在第9个SCL周期拉低SDA表示应答(ACK),或者保持高电平表示非应答(NACK)。这个机制非常重要——答不答应,直接决定了通信能不能继续。

能帮你省大量调试时间的技巧: 逻辑分析仪上如果看到NACK,别急着怀疑从设备坏了。先检查地址对不对、总线电压是否正常、从设备是否处于掉电状态。我有个朋友花了两天查一个NACK,最后发现是从设备的VDD虚焊——哎,基础电源检查往往被忽略。

1.3.3 数据字节

数据字节的格式和地址字节一样,只是内容变成了真正的数据。每个字节发送完后,接收方必须回应ACK。如果是读操作,最后一个字节主设备会回复NACK,然后发停止条件——告诉从设备“够了,不用再发了”。

记住这个关键点: 应答是由接收方产生的。主设备发送地址后,等待从设备应答;主设备发送数据后,也等待从设备应答。但从设备发送数据时,应答由主设备发出。

1.4 一张图看懂I2C单次传输流程

我把上面讲的内容画成了这张流程图,方便你对照记忆。

I2C单次传输流程图 起始条件 发送地址 + R/W位 等待从设备 应答 (ACK/NACK) 收到ACK? 发送/接收数据字节 主/从设备 回应ACK/NACK 停止条件 说明:收到NACK后,主设备通常直接发送停止条件结束传输,或发送重复起始条件重新开始。 ACK NACK 继续传输 结束

看到这张图了吗?每次传输都是从起始条件开始,走地址→应答→数据→应答的循环。应答失败(NACK)直接跳到停止条件。这也是我们后面用逻辑分析仪排查的重点——NACK在哪个环节出现,基本就能锁定问题。

1.5 关于重复起始条件

还有一个常见形式叫重复起始条件(Repeated Start)。就是在没有发停止条件之前,再发一个起始条件。这样做的好处是:总线不会被释放,其他主设备不会插进来。典型应用场景是读某个寄存器的值:先写寄存器地址,然后重复起始+读操作。

实用建议: 你如果用逻辑分析仪抓I2C波形,看到起始条件后面紧跟着另一个起始条件(之间没有停止条件),那就是重复起始。别忘了把分析仪的协议解析设置为支持重复起始,否则可能解析错。

好了,I2C协议基础就说到这儿。起始、停止、数据帧格式、应答机制,这些是整个课程的地基。后面的所有案例——应答异常、总线死锁、时钟拉伸——都会反复用到这些概念。建议你最好用逻辑分析仪实际抓几个I2C波形对照着看,比只看书理解深刻得多。