3. I2C总线协议基础

I2C(Inter-Integrated Circuit)总线是嵌入式系统中应用最广泛的板级通信协议之一,也是RK Sensor驱动与物理传感器芯片之间最核心的数据通道。本章从物理层到协议层,系统讲解I2C总线的完整工作机制,为后续分析RK平台I2C控制器驱动与Sensor设备驱动奠定基础。

3.1 I2C物理层:双线结构与电气特性

I2C总线仅使用两条双向信号线完成所有通信:

  • SCL(Serial Clock Line):串行时钟线,由主设备驱动,用于同步数据传输。
  • SDA(Serial Data Line):串行数据线,用于双向传输地址和数据。

两条线均通过上拉电阻连接到电源电压(通常为1.8V、3.3V或5V)。总线空闲时,SCL和SDA均为高电平。

关键电气特性:
  • 开漏输出(Open-Drain):设备只能将总线拉低,释放后由上拉电阻恢复高电平。
  • 线与逻辑(Wired-AND):多个设备可同时挂接在同一总线上,任一设备拉低则总线为低。
  • 最大电容负载:标准模式400pF,快速模式550pF,限制总线上设备数量与走线长度。

下图展示了I2C总线物理连接结构:

I2C总线物理连接结构 Rₚ Rₚ VDD (1.8V / 3.3V) SDA SCL 主设备 RK SoC (I2C控制器) 从设备1 Sensor (0x48) 从设备2 Sensor (0x4A) 说明:所有设备通过开漏输出挂接在SDA和SCL上,上拉电阻Rₚ确保总线空闲时为高电平。 RK SoC作为主设备控制时钟,Sensor芯片作为从设备响应地址。

3.2 起始条件与停止条件

I2C总线上所有通信由主设备发起,通过SCL和SDA的特定电平变化定义传输的起始与结束:

条件 SDA电平变化 SCL电平 时序要求
起始条件(S) 高电平 → 低电平 高电平 SCL高电平期间SDA下降沿
停止条件(P) 低电平 → 高电平 高电平 SCL高电平期间SDA上升沿
驱动开发要点:在RK平台I2C控制器驱动中,起始和停止条件由硬件自动生成,驱动开发者只需配置寄存器中的START和STOP位。但在GPIO模拟I2C时,必须严格按时序手动控制GPIO电平翻转。

下图展示了起始与停止条件的时序波形:

起始条件与停止条件时序 SCL SDA 起始条件 S SDA↓ while SCL=H 停止条件 P SDA↑ while SCL=H 数据传输阶段(SCL低电平期间SDA变化,高电平期间采样)

3.3 数据帧格式与字节传输

I2C总线以字节(8位)为基本传输单位,每个字节后跟随一个应答位(ACK/NACK)。数据传输遵循高位先行(MSB First)原则。

3.3.1 单字节写操作帧格式

| 起始条件 | 7位从机地址 | R/W=0 | ACK | 寄存器地址 | ACK | 数据字节 | ACK | 停止条件 |
|    S     |   A6...A0   |   0   |  A  |   RA7..RA0 |  A  |  D7...D0 |  A  |    P     |

3.3.2 多字节读操作帧格式

| S | 从机地址 | W=0 | A | 寄存器地址 | A | Sr | 从机地址 | R=1 | A | 数据1 | A | 数据2 | NA | P |
应答机制:
  • ACK(应答):接收方在第9个SCL周期将SDA拉低,表示成功接收字节。
  • NACK(非应答):接收方在第9个SCL周期保持SDA高电平,表示传输结束或错误。
  • 主设备在读取最后一个字节后发送NACK,通知从设备停止发送。

下图展示了I2C完整的数据帧传输流程:

I2C完整数据帧传输流程(写操作示例) S 从机地址 7位 R/W 1位 ACK 寄存器地址 8位 ACK 数据字节 8位 ACK P 帧格式说明: 1. 主设备发送起始条件S,占用1个SCL周期。 2. 发送7位从机地址 + 1位读写方向位(W=0写,R=1读)。 3. 从设备在第9个SCL周期回复ACK,表示地址匹配成功。 4. 发送8位寄存器地址,从设备再次回复ACK。 5. 发送/接收8位数据字节,每字节后跟ACK/NACK。 6. 主设备发送停止条件P,释放总线。

3.4 7位地址与10位地址

I2C总线支持两种从机地址格式,RK平台Sensor驱动中绝大多数使用7位地址:

地址模式 地址位宽 最大设备数 地址范围 保留地址 RK Sensor使用情况
7位地址 7 bit 112(128-16保留) 0x08 ~ 0x77 0x00~0x07, 0x78~0x7F 绝大多数Sensor使用
10位地址 10 bit 1008(1024-16保留) 0x000 ~ 0x3FF 0x00~0x0F保留 极少使用

3.4.1 7位地址传输格式

主设备发送的第一个字节高7位为从机地址,最低位为读写方向位:

第一个字节:| A6 | A5 | A4 | A3 | A2 | A1 | A0 | R/W |
              MSB                          LSB

3.4.2 10位地址传输格式

10位地址使用两个字节传输,第一个字节的前5位固定为11110,后2位为地址高2位:

第一个字节:| 1 | 1 | 1 | 1 | 0 | A9 | A8 | R/W |
第二个字节:| A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
驱动开发常见错误:在RK平台设备树中配置Sensor I2C地址时,必须使用7位原始地址(如0x48),而不是左移1位后的8位地址。左移操作由I2C控制器驱动在发送时自动完成。错误配置会导致地址不匹配,通信失败。

3.5 时钟同步与仲裁

时钟同步和总线仲裁是I2C总线实现多主设备共存的关键机制,在RK Sensor驱动中虽不常用,但理解其原理有助于排查总线异常。

3.5.1 时钟同步

当多个主设备同时驱动SCL时,通过线与逻辑实现时钟同步:

  • 每个主设备内部产生自己的SCL时钟。
  • SCL实际电平是所有主设备输出电平的线与结果。
  • 如果某个主设备拉低SCL,所有主设备必须等待其释放后才能继续。
  • 最终所有主设备的时钟被同步到最慢的那个设备。

3.5.2 总线仲裁

当多个主设备同时尝试控制总线时,通过SDA线的仲裁决定哪个主设备获得总线控制权:

仲裁阶段 仲裁机制 判定结果
地址阶段 多个主设备同时发送地址,SDA线与后比较 发送低电平的主设备获胜
数据阶段 多个主设备同时发送数据,SDA线与后比较 发送低电平的主设备获胜
丢失仲裁 主设备检测到SDA电平与自己发送的不一致 立即释放总线,转为从模式

下图展示了时钟同步与仲裁的协同工作过程:

时钟同步与总线仲裁过程 SCL1 SCL2 SCL SDA1 SDA2 SDA 仲裁获胜设备(SDA1)继续传输,SDA2释放总线

3.6 I2C总线速率模式

I2C总线定义了多种速率模式,RK平台Sensor驱动通常使用标准模式或快速模式:

模式 最大速率 SCL高电平最小时间 SCL低电平最小时间 RK平台支持
标准模式(Sm) 100 kbit/s 4.0 μs 4.7 μs 全系列支持
快速模式(Fm) 400 kbit/s 0.6 μs 1.3 μs 全系列支持
快速模式+(Fm+) 1 Mbit/s 0.26 μs 0.5 μs RK3588等高端型号
高速模式(Hs) 3.4 Mbit/s 0.16 μs 0.32 μs 部分型号支持
驱动配置建议:在RK平台设备树中,通过 clock-frequency 属性配置I2C总线速率。对于大多数Sensor(如加速度计、陀螺仪、磁力计),推荐使用400kHz快速模式,兼顾传输速度与兼容性。若Sensor数据手册指定最大速率低于400kHz,则必须降级配置。

3.7 I2C与RK Sensor驱动的关联

在RK Sensor驱动框架中,I2C通信是数据采集的底层基础。驱动开发者需要理解以下对应关系:

  • 设备树配置:在设备树中指定Sensor挂接的I2C总线编号、从机地址、速率。
  • I2C适配器:RK平台I2C控制器在Linux内核中注册为 struct i2c_adapter,提供数据传输接口。
  • I2C客户端:每个Sensor设备对应一个 struct i2c_client,包含地址、适配器指针等信息。
  • 数据传输接口:驱动通过 i2c_smbus_read_byte_data()、i2c_smbus