2. I2C协议详解:起始条件、停止条件、数据有效性、应答机制、7位与10位地址模式

I2C(Inter-Integrated Circuit)总线协议由Philips(现NXP)公司开发,是一种同步、多主从、串行通信总线。它仅需两根双向信号线——串行数据线(SDA)和串行时钟线(SCL)——即可实现设备间的数据交换。本章将深入剖析I2C协议的核心时序与机制,为后续驱动开发和设备树配置奠定基础。

核心要点: I2C协议的精髓在于其严格的时序约束和灵活的地址机制。理解起始/停止条件、数据有效性、应答/非应答以及7位/10位地址模式,是掌握I2C驱动调试的关键。

2.1 起始条件(START Condition)与停止条件(STOP Condition)

I2C总线的空闲状态是SCL和SDA均为高电平。数据传输的起始和结束由主控制器通过特定的信号跳变来标志。

  • 起始条件(S): 当SCL为高电平时,SDA从高电平切换到低电平。此信号表示一次新的数据传输开始,主控制器在发送起始条件后,会立即发送从设备地址。
  • 停止条件(P): 当SCL为高电平时,SDA从低电平切换到高电平。此信号表示本次数据传输结束,总线恢复空闲状态。

起始和停止条件均由主控制器产生。在一次传输中,可以连续发送多个数据帧,但每个数据帧之间必须由起始和停止条件界定。

调试提示: 在逻辑分析仪上观察I2C波形时,起始条件表现为SDA在SCL高电平期间的下降沿,停止条件表现为SDA在SCL高电平期间的上升沿。这是判断总线状态转换的最直观依据。
I2C 起始条件与停止条件时序图 I2C 起始条件 (S) 与 停止条件 (P) 时序 SCL SDA S 起始条件 P 停止条件 空闲: SDA=H, SCL=H 空闲: SDA=H, SCL=H

2.2 数据有效性(Data Validity)

I2C协议规定,在SCL时钟的高电平周期内,SDA上的数据必须保持稳定。只有在SCL为低电平时,SDA上的数据才允许发生变化。

  • 数据采样: 接收方在SCL的上升沿或高电平期间对SDA进行采样。
  • 数据变化: 发送方必须在SCL为低电平时更新SDA上的数据位。
  • 字节格式: 每次传输的数据以字节(8位)为单位,高位(MSB)在前,低位(LSB)在后。
常见错误: 在SCL高电平期间改变SDA电平,会被误判为起始或停止条件,导致通信混乱。这是新手调试I2C时最容易犯的时序错误。
I2C 数据有效性时序图 I2C 数据有效性:SCL高电平时SDA必须稳定 SCL SDA D7 (MSB) D6 D5 D4 D3 D2 D1 允许变化 必须稳定

2.3 应答机制(ACK/NACK)

I2C协议要求每个字节传输完成后,接收方必须向发送方提供一个应答位(ACK)或非应答位(NACK),以确认数据是否成功接收。

  • 应答位(ACK): 在第9个SCL时钟周期,接收方将SDA拉低,表示已成功接收上一个字节,并准备好接收下一个字节。
  • 非应答位(NACK): 在第9个SCL时钟周期,接收方保持SDA为高电平,表示未成功接收或不再接收数据。

主控制器在发送完地址或数据后,必须释放SDA线,以便从设备拉低SDA产生ACK。如果主控制器未收到ACK,通常会发送停止条件终止传输。

I2C 应答机制行为对照表
场景 发送方 接收方 SDA状态(第9时钟) 后续操作
地址匹配成功 主控制器 从设备 低电平(ACK) 继续传输数据
地址匹配失败 主控制器 从设备 高电平(NACK) 主控制器发送停止条件
数据接收成功 发送方 接收方 低电平(ACK) 发送下一个字节
数据接收失败/结束 发送方 接收方 高电平(NACK) 发送方停止发送
调试技巧: 在驱动调试中,如果发现I2C传输总是卡在地址发送阶段,大概率是从设备没有响应ACK。此时应检查设备地址是否正确、设备是否上电、总线是否被拉死。
I2C 应答机制流程图 I2C 应答机制流程 主控制器发送字节 主控制器释放SDA 接收方在第9时钟采样SDA SDA=低 (ACK) 继续传输下一字节 SDA=高 (NACK) 发送停止条件终止

2.4 7位地址模式

7位地址模式是I2C协议中最常用的寻址方式。主控制器在起始条件后发送的第一个字节包含7位从设备地址和1位读写标志位(R/W)。

  • 地址字节格式: 高7位(D7-D1)为从设备地址,最低位(D0)为读写标志。0表示写操作,1表示读操作。
  • 地址范围: 7位地址的有效范围是0x00到0x7F,但0x00和0x01通常保留用于特殊用途(如通用呼叫地址)。
  • 设备树配置: 在设备树中,7位地址通常以16进制格式直接指定,例如 reg = <0x48>;。
地址计算示例: 假设一个温度传感器的7位地址为0x48(二进制 1001000)。主控制器要读取数据时,发送的地址字节为 (0x48 << 1) | 0x01 = 0x91。要写入数据时,发送的地址字节为 (0x48 << 1) | 0x00 = 0x90。

2.5 10位地址模式

10位地址模式是为了扩展I2C总线上可挂载的设备数量而设计的。它兼容7位地址模式,通过保留的1111 0XX地址前缀来标识10位地址传输。

10位地址的传输分为两个阶段:

  1. 第一个字节: 高5位为11110,接着是10位地址的高2位(A9和A8),最后是读写标志位(R/W)。
  2. 第二个字节: 10位地址的低8位(A7-A0)。
7位与10位地址模式对比
特性 7位地址模式 10位地址模式
地址字节数 1字节(地址+读写位) 2字节(首字节+次字节)
最大设备数 112(0x08-0x77可用) 1024
首字节特征 地址高7位 + R/W 11110 + A9/A8 + R/W
兼容性 所有I2C设备支持 需要主从设备均支持
驱动复杂度 低 中(需处理两次地址发送)
注意事项: 在嵌入式Linux中,10位地址模式使用较少。设备树中通过 reg 属性指定地址时,如果地址值大于0x7F,内核会自动识别为10位地址。但并非所有I2C控制器驱动都完美支持10位地址,使用前需确认。
7位与10位地址格式对比 7位与10位地址格式对比 7位地址格式: S | A6 | A5 | A4 | A3 | A2 | A1 | A0 | R/W | ACK 起始条件 7位从设备地址 读写位 应答位 10位地址格式: S | 11110 | A9 | A8 | R/W | ACK | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 | ACK 起始条件 首字节(11110 + 高2位地址 + R/W) 次字节(低8位地址) 应答位

2.6 完整数据传输流程

结合上述所有机制,一次完整的I2C写操作流程如下:

  1. 起始条件: 主控制器在SCL高电平时将SDA拉低。
  2. 发送地址: 主控制器发送7位或10位从设备地址,后跟写标志位(0)。
  3. 等待应答: 主控制器释放SDA,从设备在第9个时钟周期拉低SDA作为ACK。
  4. 发送数据: 主控制器发送一个字节的数据(8位,MSB先发)。
  5. 等待应答: 从设备再次发送ACK。
  6. 重复步骤4-5: 直到所有数据发送完毕。
  7. 停止条件: 主控制器在SCL高电平时将SDA拉高,结束传输。
复合传输: I2C支持“重复起始条件”(Repeated START),即在一次传输中不发送停止条件,直接发送新的起始条件。这在读取寄存器时非常有用:先写寄存器地址,再重新起始读取数据。
完整I2C写操作流程图 完整I2C写操作流程 1. 起始条件 (S) 2. 发送地址 + W (0) 3. 等待从设备 ACK 4. 发送数据字节 5. 等待从设备 ACK 6. 停止条件 (P) 重复步骤4-5

2.7 总结

I2C协议通过简洁的时序和灵活的地址机制,实现了高效的板级通信。起始条件和停止条件定义了传输的边界,数据有效性规则保证了数据的正确采样,应答机制提供了可靠的流控,而7位/10位地址模式则满足了不同规模的设备寻址需求。掌握这些基础协议要素,是后续编写I2C设备驱动、配置设备树以及调试通信问题的前提。