2. I2C时序详解:起始条件、停止条件、数据有效性、字节格式、应答机制

好,咱们进入正题。

I2C的时序,说白了就是一根时钟线(SCL)和一根数据线(SDA)怎么配合干活。很多新手一上来就被各种时序图吓住了,其实没那么复杂。我当年第一次用逻辑分析仪抓I2C波形时,也是一脸懵,后来发现只要抓住几个关键节点,整个协议就通了。

2.1 起始条件(Start Condition)

先说说怎么开始一次通信。

SCL在高电平的时候,SDA从高电平跳变到低电平。这就是起始条件。记住这个特征:SCL高,SDA下降沿

我习惯叫它「握手信号」。主设备想跟从设备说话,先得把这个信号发出去。从设备看到这个波形,就知道「哦,有人要找我说话了」。

起始条件判定口诀:

SCL高电平,SDA下降沿 → 起始条件

有个坑我得提醒你。我曾经在一个项目里,主控芯片的I2C引脚初始化顺序搞反了,导致每次发起始条件时SDA先拉低,SCL还没稳定在高电平。逻辑分析仪抓出来波形看着像起始条件,但从设备就是不认。查了两天才发现是时序违规。

注意:起始条件必须在总线空闲时发出。总线空闲的定义是:SCL和SDA都是高电平。

2.2 停止条件(Stop Condition)

有开始就有结束。

停止条件正好反过来:SCL在高电平时,SDA从低电平跳变到高电平。也就是SCL高,SDA上升沿

从设备看到这个信号,就知道「通信结束了,我可以休息了」。

停止条件判定口诀:

SCL高电平,SDA上升沿 → 停止条件

你想想看,如果主设备忘了发停止条件,会怎样?总线就一直被占用着,其他设备没法通信。我遇到过这种情况,一个传感器模块在异常复位后,SDA被拉低不释放,整个总线就卡死了。解决办法?要么硬件复位,要么发一个假的时钟脉冲把总线「救」回来。

2.3 数据有效性

数据怎么才算有效?规则很简单:

  • SCL高电平时,SDA上的数据必须稳定
  • SCL低电平时,SDA上的数据可以变化

说白了,就是时钟的高电平期间,数据线不能乱跳。你想想看,如果SCL高电平时SDA还在抖动,接收方根本不知道你传的是0还是1。

我的经验:抓波形时,重点看SCL上升沿附近的SDA状态。因为接收方就是在SCL上升沿采样数据的。如果SDA在上升沿附近有毛刺,那数据大概率是错的。

2.4 字节格式

I2C传输数据是以字节为单位的。每个字节8位,从最高位(MSB)开始传。

举个例子,你要传数据0x4A(二进制0100 1010),发送顺序是:

  1. 先传bit7:0
  2. 再传bit6:1
  3. 然后bit5:0
  4. ...以此类推
  5. 最后传bit0:0

为什么从MSB开始?我猜是为了兼容早期的串行通信习惯。反正咱们记住就行:高位在前,低位在后

每个字节后面紧跟着一个应答位(ACK/NACK)。所以实际上,每传输9个时钟周期才算完成一个字节的传输:8个数据位 + 1个应答位。

字节传输结构:

起始条件 → 8位数据(MSB→LSB) → 应答位 → ... → 停止条件

2.5 应答机制(ACK/NACK)

这是I2C协议里最巧妙的设计之一。

每发完一个字节,发送方会释放SDA总线(拉高),然后接收方需要在第9个时钟周期拉低SDA,表示「我收到了」。这就是应答(ACK)。

如果接收方不拉低SDA(保持高电平),那就是非应答(NACK)。

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

  • 地址不匹配:主设备呼叫的从设备地址不存在
  • 设备忙:从设备正在处理上一条指令,没空理你
  • 传输结束:从设备不想再接收数据了
  • 读操作结束:主设备读完最后一个字节后,主动发NACK告诉从设备「够了,别发了」

避坑指南:我曾经调试一个温湿度传感器,读数据时总是卡在第一个字节。用逻辑分析仪一看,从设备发了NACK。查了半天,发现是地址搞错了——那个传感器的7位地址是0x5C,但我写成了0xB8(忘了左移一位)。记住:I2C地址在发送时是左移一位的,最低位是读写标志位。

2.6 完整时序示例

咱们看一个完整的写操作时序:

// 主设备向从设备0x5C写入0x4A
// 时序步骤:
// 1. 起始条件
// 2. 发送地址0x5C左移一位 + 写标志0 = 0xB8
// 3. 等待从设备ACK
// 4. 发送数据0x4A
// 5. 等待从设备ACK
// 6. 停止条件

用逻辑分析仪抓出来的波形,你应该能看到:

  • 起始条件:SCL高,SDA下降沿
  • 地址字节:9个时钟周期(8位地址+1位ACK)
  • 数据字节:9个时钟周期(8位数据+1位ACK)
  • 停止条件:SCL高,SDA上升沿

调试小技巧:我习惯在逻辑分析仪里设置触发条件为「起始条件」。这样每次抓波形都能从通信开始处捕获,方便分析完整的数据包。另外,把SCL和SDA的采样率设到4倍以上时钟频率,才能看清细节。

2.7 常见时序问题

最后,我列几个实际项目中遇到过的时序Bug,你以后碰到了可以少走弯路:

问题现象 可能原因 排查方法
从设备无应答 地址错误、设备未上电、总线被拉死 检查地址、测量供电、看SDA电平
数据错位 SCL频率太高、上拉电阻太小 降低时钟频率、增大上拉电阻
总线卡死 从设备异常、缺少停止条件 硬件复位、发9个时钟脉冲恢复
波形毛刺多 走线过长、地线回路大 缩短走线、加滤波电容

嗯,这一章的内容就到这儿。时序这东西,光看文字可能觉得抽象。我建议你拿逻辑分析仪抓一段真实的I2C波形,对照着看,很快就能上手。下一章咱们聊聊I2C的几种传输模式,包括标准模式、快速模式和高速模式的区别。