2. I2C通信协议详解:起始条件、停止条件、数据有效性、字节格式、应答与非应答机制

I2C(Inter-Integrated Circuit)总线协议由Philips(现NXP)设计,是一种同步、多主从、半双工的串行通信协议。它仅需两根线——串行数据线(SDA)和串行时钟线(SCL)——即可完成设备间的数据交换。本章将深入剖析I2C协议的核心时序单元,为后续编写Linux I2C驱动打下坚实的硬件基础。

2.1 总线空闲状态与电气特性

在开始分析具体时序之前,必须先明确总线的空闲状态。I2C总线采用开漏(Open-Drain)结构,这意味着任何设备都可以将SDA或SCL线拉低,但无法主动驱动为高电平。高电平由外部上拉电阻提供。

状态 SDA电平 SCL电平 说明
空闲(Idle) 高(H) 高(H) 总线释放,无设备占用
起始条件(S) 高→低 高 SCL为高时,SDA由高变低
停止条件(P) 低→高 高 SCL为高时,SDA由低变高
数据有效 稳定 高 SCL高电平期间,SDA数据必须稳定
驱动开发提示: 在Linux内核中,I2C适配器驱动通过操作GPIO或I2C控制器寄存器来模拟上述电平变化。理解空闲状态是正确初始化I2C控制器(如i2c-imx、i2c-omap等)的前提。

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

起始条件和停止条件是I2C通信的“帧头”和“帧尾”,由主机(Master)产生。所有从机(Slave)都持续监听总线,检测到起始条件后开始准备接收地址,检测到停止条件后复位内部状态机。

2.2.1 起始条件(S)

当SCL线为高电平时,SDA线从高电平切换到低电平。这个下降沿标志着一次I2C传输的开始。起始条件之后,总线被主机占用,其他设备不得发起传输。

2.2.2 停止条件(P)

当SCL线为高电平时,SDA线从低电平切换到高电平。这个上升沿标志着传输的结束。停止条件之后,总线恢复空闲状态,允许其他主机竞争总线。

2.2.3 重复起始条件(Sr)

在未产生停止条件的情况下,主机可以再次产生一个起始条件。这在多字节读写或改变数据方向(如从写地址切换到读数据)时非常有用,避免了总线释放后被其他主机抢占。

工程案例: 在读取I2C EEPROM(如AT24C02)时,主机先发送设备地址+写位,再发送内部寄存器地址,然后产生重复起始条件,最后发送设备地址+读位来读取数据。这种“组合传输”是I2C协议的高效用法。
I2C 起始条件与停止条件时序 SCL SDA 起始条件 (S) SDA↓ while SCL=H 停止条件 (P) SDA↑ while SCL=H 空闲 空闲 数据传输阶段(地址 + 数据 + 应答)

2.3 数据有效性(Data Validity)

I2C协议规定,在SCL时钟的高电平期间,SDA线上的数据必须保持稳定。只有在SCL为低电平时,SDA上的数据才允许发生变化。这一规则确保了数据采样的可靠性。

  • SCL高电平: 数据采样窗口。接收方在SCL上升沿或高电平期间读取SDA电平。
  • SCL低电平: 数据变化窗口。发送方在SCL低电平期间更新SDA电平,为下一个数据位做准备。
常见错误: 在SCL高电平时改变SDA数据会被误判为起始条件或停止条件。驱动开发中,必须确保I2C控制器的时序配置(如上升时间、保持时间)符合从机数据手册的要求。

2.4 字节格式与数据传输

I2C总线上的数据以字节(8位)为单位进行传输。每个字节后必须跟随一个应答位(ACK/NACK)。数据传输时,高位(MSB)在前,低位(LSB)在后。

2.4.1 标准字节传输流程

  1. 起始条件(S):主机产生起始条件。
  2. 发送7位从机地址 + R/W位:主机发送8位数据(高7位为地址,最低位为读写方向)。
  3. 从机应答(ACK):如果地址匹配,从机在第9个SCL周期拉低SDA作为应答。
  4. 发送/接收数据字节:根据R/W位,主机或从机发送8位数据。
  5. 应答/非应答:接收方在第9个SCL周期给出应答。
  6. 停止条件(P):主机产生停止条件,结束传输。

2.4.2 字节格式示意图

I2C 字节格式(MSB First) D7 D6 D5 D4 D3 D2 D1 D0 ACK MSB LSB 应答 SCL: 9个SCL周期

2.5 应答(ACK)与非应答(NACK)机制

应答机制是I2C协议可靠性的核心。每个字节传输完成后,接收方必须在第9个SCL周期给出反馈。

2.5.1 应答(ACK)

  • 定义: 在第9个SCL周期,接收方将SDA线拉低。
  • 含义: “我已成功接收到上一个字节,可以继续发送下一个字节。”
  • 场景: 地址匹配成功、数据写入成功、数据读取请求被接受。

2.5.2 非应答(NACK)

  • 定义: 在第9个SCL周期,接收方保持SDA线为高电平(不拉低)。
  • 含义: “我无法接收更多数据”或“我未识别到该地址”。
  • 场景: 从机忙、地址错误、读操作结束(主机主动发送NACK以通知从机停止发送)。
角色 发送ACK条件 发送NACK条件
从机(Slave) 地址匹配成功;数据写入成功 地址不匹配;数据写入失败;从机忙
主机(Master) 希望继续接收数据 已接收足够数据,准备停止传输
驱动调试技巧: 在Linux内核中,I2C传输失败通常表现为NACK。通过i2c-tools中的i2cdetect命令可以扫描总线上的设备地址。如果某个地址返回NACK,说明该设备不存在或地址错误。在驱动中,可以通过检查i2c_msg的返回状态来区分ACK/NACK错误。

2.6 完整数据传输流程示例

以下是一个完整的I2C写操作时序示例,展示了起始条件、地址、数据、应答和停止条件的组合。

I2C 完整写操作流程(主机→从机) 起始条件 (S) 从机地址 (7位) + 写位 (0) ACK (从机) 数据字节1 (8位) ACK (从机) 停止条件 (P) 说明 1. 主机控制SCL时钟,产生起始和停止条件。 2. 每个字节后,接收方(从机)必须发送ACK,否则主机视为传输失败。 读操作变体:重复起始条件 [S] + [从机地址 + 写位] + [ACK] + [寄存器地址] + [ACK] + [Sr] + [从机地址 + 读位] + [ACK] + [数据] + [NACK] + [P]

2.7 高速模式与协议变体

标准I2C模式(100 kbps)和快速模式(400 kbps)是最常用的。此外,还有高速模式(3.4 Mbps)和超快速模式(5 Mbps),但时序要求更严格,通常需要硬件I2C控制器支持。

模式 最大速率 驱动关注点
标准模式(Sm) 100 kbps 通用,软件模拟(Bit-banging)也可实现
快速模式(Fm) 400 kbps 需注意上升时间,通常使用硬件控制器
高速模式(Hs) 3.4 Mbps 需专用I2C控制器,从机必须支持Hs模式
Linux内核配置: 在设备树中,可以通过clock-frequency属性设置I2C总线速率。例如:clock-frequency = <400000>; 表示设置为400 kbps快速模式。驱动初始化时会根据该值配置控制器分频系数。

2.8 本章小结