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

I2C(Inter-Integrated Circuit)总线是Sensor驱动开发中最核心的物理层通信协议。RK平台上的绝大多数Sensor(如加速度计、陀螺仪、磁力计、温湿度传感器)均通过I2C接口与主控芯片交互。理解I2C协议的时序细节,是正确读写寄存器地址与数据的前提。

本章将从信号线定义出发,逐项拆解I2C协议的五个关键要素:起始条件、停止条件、数据有效性、字节传输格式以及应答机制。每个要素均配有内联SVG时序图,帮助你在RK驱动开发中快速定位时序问题。

2.1 I2C总线物理层与信号线

I2C总线仅使用两条双向信号线:

  • SCL(Serial Clock Line):时钟线,由主设备(Master)驱动,控制数据传输的节奏。
  • SDA(Serial Data Line):数据线,用于传输地址、数据和应答信号,由主设备或从设备驱动。

两条线均通过上拉电阻接至VDD(通常为1.8V或3.3V)。空闲状态时,SCL和SDA均为高电平。

RK平台提示: RK芯片的I2C控制器内部集成了数字滤波和毛刺抑制功能。在设备树中配置 clock-frequency 时,建议从100kHz(标准模式)开始验证,再逐步提升至400kHz(快速模式),避免因信号质量导致通信失败。

2.2 起始条件(START Condition)

起始条件标志着一次I2C传输的开始。主设备通过特定的电平变化通知总线上的所有从设备:准备接收地址。

时序定义: 当SCL为高电平时,SDA从高电平切换到低电平。

起始条件(START)时序图 SCL SDA下降 SCL高电平期间 START

关键点:

  • 起始条件由主设备独占产生,从设备只能检测。
  • 在起始条件之后,总线进入忙状态,其他主设备不得发起传输。
  • RK驱动中,起始条件由I2C控制器硬件自动生成,驱动只需写入从设备地址即可触发。

2.3 停止条件(STOP Condition)

停止条件标志着一次I2C传输的结束。主设备释放总线,从设备恢复监听状态。

时序定义: 当SCL为高电平时,SDA从低电平切换到高电平。

停止条件(STOP)时序图 SCL SDA上升 SCL高电平期间 STOP

关键点:

  • 停止条件之后,总线进入空闲状态,其他主设备可以发起新的传输。
  • 在RK驱动中,如果连续读写多个寄存器,主设备可以在不发送停止条件的情况下,通过重复起始条件(Repeated START)切换读写方向,提高效率。
常见错误: 在Sensor驱动调试中,如果I2C总线卡死(SDA被拉低),通常是因为从设备未释放SDA或主设备未正确发送停止条件。此时可尝试用逻辑分析仪检查停止条件是否完整。

2.4 数据有效性(Data Validity)

I2C协议规定,SDA线上的数据必须在SCL时钟的配合下才能被正确采样。

规则:

  • 在SCL的高电平期间,SDA上的数据必须保持稳定(不变)。
  • 在SCL的低电平期间,SDA上的数据允许发生变化(切换)。
数据有效性规则示意图 SCL 数据有效 数据有效 数据有效 数据有效 允许变化 允许变化 允许变化

驱动开发含义: 在编写RK平台的I2C驱动时,无需手动控制SCL和SDA的电平变化——I2C控制器IP核会自动遵循数据有效性规则。但理解此规则有助于分析逻辑分析仪抓取的波形,判断数据采样点是否正确。

2.5 字节传输格式与帧结构

I2C协议以字节(8位)为基本传输单位。每个字节传输后,必须跟随一个应答位(ACK/NACK)。

完整帧结构(以写操作为例):

阶段 位数 内容 方向
起始条件 1 START 主→总线
从设备地址 7 Slave Address (高7位) 主→从
读写位 1 0=写, 1=读 主→从
应答位 1 ACK (0) 或 NACK (1) 从→主
寄存器地址 8 Reg Address (1字节) 主→从
应答位 1 ACK 从→主
数据字节 8 Data (1字节) 主→从
应答位 1 ACK 从→主
停止条件 1 STOP 主→总线

字节传输顺序: 高位在前(MSB first)。例如发送地址0x1C(二进制0001 1100),先发送bit7(0),最后发送bit0(0)。

I2C写操作完整帧结构 START Slave Addr (7bit) R/W ACK Reg Addr (8bit) ACK Data (8bit) ACK STOP 主→从 从→主 从→主 从→主
RK驱动代码示例: 在Linux内核I2C子系统下,写Sensor寄存器的典型调用链如下:
// 构造I2C消息
struct i2c_msg msg;
u8 buf[2] = { reg_addr, data };

msg.addr  = client->addr;   // 从设备7位地址
msg.flags = 0;              // 写操作
msg.len   = 2;              // 寄存器地址 + 数据
msg.buf   = buf;

// 通过I2C控制器发送
i2c_transfer(client->adapter, &msg, 1);

内核I2C核心会自动处理起始条件、停止条件、应答检测等底层细节。

2.6 应答机制(ACK/NACK)

应答机制是I2C协议可靠性的核心。每个字节传输完成后,接收方必须在第9个SCL时钟周期内拉低SDA(ACK)或保持高电平(NACK)。

应答规则:

场景 发送方 接收方 SDA状态 含义
地址匹配 主设备 从设备 低电平(ACK) 从设备确认地址,准备通信
地址不匹配 主设备 从设备 高电平(NACK) 无此设备或设备忙
写数据成功 主设备 从设备 低电平(ACK) 从设备已接收数据
读数据结束 从设备 主设备 高电平(NACK) 主设备不再需要更多数据
应答位(ACK/NACK)时序 SCL 8位数据字节 ACK 第9个SCL时钟
驱动调试要点: 在RK平台上,如果I2C通信返回 -EREMOTEIO(-121)错误,通常意味着从设备未应答(NACK)。常见原因包括:
  • 从设备地址错误(7位地址与设备树不匹配)。
  • Sensor处于休眠或复位状态,未响应I2C请求。
  • I2C时钟频率过高,从设备无法跟上。
此时应使用逻辑分析仪抓取SDA/SCL波形,确认地址字节后是否出现ACK。

2.7 重复起始条件(Repeated START)

在需要改变数据传输方向(例如先写寄存器地址,再读数据)时,主设备可以在不发送停止条件的情况下,再次发送起始条件。这称为重复起始条件,常用于Sensor寄存器读取操作。

典型读操作帧结构:

  1. 主设备发送START + 从设备地址(写方向)+ ACK。
  2. 主设备发送寄存器地址 + ACK。
  3. 主设备发送重复起始条件(Repeated START)。
  4. 主设备再次发送从设备地址(读方向)+ ACK。
  5. 从设备发送数据字节,主设备发送NACK表示读取结束。
  6. 主设备发送STOP。
重复起始条件(Repeated START)读操作帧结构 S Addr+W A RegAddr A Sr Addr+R A Data N P ← 上一章 📖 返回目录 下一章 →