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

I2C(Inter-Integrated Circuit)总线协议由Philips(现NXP)设计,是一种同步、多主从、半双工的串行通信协议。它仅需两根线——串行数据线(SDA)和串行时钟线(SCL)——即可完成设备间的数据交换。理解其底层时序与信号规范,是驱动开发和性能调优的基石。

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

在总线空闲时,SCL和SDA均通过上拉电阻保持高电平。任何设备在开始通信前,必须检测总线是否空闲(即SCL和SDA均为高)。

关键点: 总线空闲状态 = SCL高 + SDA高。所有主设备在发起通信前必须检测此状态,避免总线冲突。

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

起始条件和停止条件是I2C通信的“帧头”和“帧尾”,由主设备产生。它们定义了数据传输的边界。

  • 起始条件(S): 当SCL为高电平时,SDA从高电平切换到低电平。
  • 停止条件(P): 当SCL为高电平时,SDA从低电平切换到高电平。
调试提示: 使用逻辑分析仪抓取波形时,首先寻找SDA在SCL高电平期间的下降沿(起始)和上升沿(停止)。这是判断通信是否开始或结束的最直观标志。
I2C 起始条件与停止条件时序图 I2C 起始条件 (S) 与 停止条件 (P) 时序 SCL SDA 起始条件 (S) SCL高时,SDA下降沿 停止条件 (P) SCL高时,SDA上升沿 空闲 空闲

2.3 数据有效性(Data Validity)

I2C协议规定,在数据传输过程中,SDA线上的数据必须在SCL的时钟周期内保持稳定。具体规则如下:

  • 数据变化: 仅在SCL为低电平时,SDA允许改变状态。
  • 数据采样: 接收方在SCL的上升沿(或高电平期间)对SDA进行采样。
常见错误: 如果SDA在SCL高电平期间发生跳变,会被误判为起始条件或停止条件,导致通信帧错乱。驱动中必须严格保证SCL低电平时才更新SDA输出。

2.4 字节格式与帧结构

I2C协议以字节(8位)为基本传输单位。每个字节后必须跟随一个应答位(ACK/NACK)。完整的通信帧结构如下:

字段 位数 说明
起始条件 (S) 1 由主设备产生,标志传输开始
7位从设备地址 7 指定目标从设备(高7位)
读/写位 (R/W) 1 0 = 写,1 = 读
应答位 (ACK) 1 从设备在第9个SCL周期拉低SDA表示应答
数据字节 (Data Byte) 8 传输的数据,MSB优先
应答位 (ACK/NACK) 1 接收方对每个数据字节的应答
停止条件 (P) 1 由主设备产生,标志传输结束
字节传输顺序: 数据字节总是高位在前(MSB first)。例如发送0x4A(二进制0100 1010),SDA上的顺序为:0 → 1 → 0 → 0 → 1 → 0 → 1 → 0。

2.5 应答机制(ACK/NACK)

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

  • ACK(应答): 接收方在第9个SCL周期将SDA拉低,表示“已收到,请继续发送”。
  • NACK(非应答): 接收方在第9个SCL周期保持SDA为高,表示“未准备好/传输结束/地址无效”。
驱动调试要点:
  • 主设备发送从设备地址后,若收到NACK,通常表示从设备不存在或忙。
  • 主设备读取数据时,在最后一个字节发送NACK,然后发送停止条件,通知从设备停止发送。
  • 在Linux内核I2C驱动中,i2c_msg结构体的flags字段控制是否发送NACK。
I2C 字节传输与应答机制时序图 I2C 字节传输 (0x4A) 与应答时序 SCL SDA 0 (MSB) 1 0 0 1 0 1 0 (LSB) ACK 下一字节 应答机制说明 • 主设备发送完8位数据后,释放SDA(置高),在第9个SCL周期采样SDA。 • 从设备拉低SDA = ACK(继续);从设备保持SDA高 = NACK(停止或错误)。

2.6 协议总结与对比

下表总结了I2C协议中关键信号与数据有效性的关系,便于驱动开发时对照检查:

信号/条件 SCL状态 SDA动作 协议含义
起始条件 (S) 高 下降沿 开始传输
停止条件 (P) 高 上升沿 结束传输
数据位传输 低 允许变化 设置数据
数据位采样 高 必须稳定 读取数据
应答位 (ACK) 第9个时钟高 被拉低 接收成功
非应答位 (NACK) 第9个时钟高 保持高 接收失败/结束
性能调优关联: 应答机制直接影响传输效率。如果从设备频繁NACK,主设备需要重试,这会显著降低总线吞吐量。在调试阶段,应优先排查NACK原因(如地址错误、从设备未初始化、时钟拉伸超时等)。