3. I2C 总线协议基础:起始条件、停止条件、数据有效性、应答机制、7 位与 10 位地址
I2C(Inter-Integrated Circuit)总线是瑞芯微平台 Sensor 驱动中最常用的板级通信协议。它仅需两根线(SCL 时钟线、SDA 数据线)即可实现主控与多个从设备之间的半双工同步通信。理解 I2C 的时序基元——起始条件、停止条件、数据有效性、应答机制以及地址格式——是调试 Sensor 驱动中通信失败、无应答、数据错位等问题的前提。
3.1 起始条件与停止条件
I2C 总线的空闲状态为 SCL 和 SDA 均为高电平。主控通过产生起始条件(Start Condition)来启动一次传输,通过产生停止条件(Stop Condition)来结束传输。
- 起始条件(S): SCL 为高电平时,SDA 从高电平切换到低电平。
- 停止条件(P): SCL 为高电平时,SDA 从低电平切换到高电平。
- 重复起始条件(Sr): 在一次传输中,不产生停止条件而直接再次产生起始条件,用于改变数据传输方向(如读操作前的从写转读)。
3.2 数据有效性
I2C 协议规定,数据线 SDA 上的电平必须在时钟线 SCL 为高电平时保持稳定,只有在 SCL 为低电平时才允许 SDA 切换状态。这一规则确保了数据采样的确定性。
| SCL 状态 | SDA 允许行为 | 数据采样 | 说明 |
|---|---|---|---|
| 高电平 | 禁止切换(保持稳定) | 主控/从设备采样数据 | 数据有效窗口 |
| 低电平 | 允许切换(准备下一位) | 不采样 | 数据更新窗口 |
每个字节(8 位)传输完成后,主控会释放 SDA 并产生第 9 个 SCL 时钟脉冲,用于接收从设备的应答信号。数据以 MSB(最高有效位)优先的方式逐位传输。
clock-frequency 属性是否匹配 Sensor 规格书要求。
3.3 应答机制
应答(ACK)和非应答(NACK)是 I2C 协议中用于确认数据接收状态的机制。每传输完一个字节(8 位),接收方必须在第 9 个 SCL 时钟周期内将 SDA 拉低(ACK)或保持高电平(NACK)。
- ACK(应答): 接收方在第 9 个时钟周期将 SDA 拉低,表示已成功接收上一个字节,可以继续传输下一字节。
- NACK(非应答): 接收方在第 9 个时钟周期保持 SDA 高电平,表示未成功接收或不想继续传输。主控收到 NACK 后通常会产生停止条件终止传输。
在 Sensor 驱动中,ACK/NACK 的检测是判断从设备是否在线、寄存器地址是否正确、数据是否写入成功的关键依据。
3.4 7 位与 10 位地址
I2C 总线上的每个从设备都有一个唯一的地址。标准模式使用 7 位地址,支持最多 112 个设备(保留 16 个地址)。扩展模式支持 10 位地址,兼容 7 位地址总线。
3.4.1 7 位地址格式
主控在起始条件后发送的第一个字节包含 7 位从设备地址和 1 位读写标志(R/W)。
| 位序 | Bit 7 (MSB) | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 (LSB) |
|---|---|---|---|---|---|---|---|---|
| 含义 | 7 位从设备地址 | R/W:0=写,1=读 | ||||||
例如,Sensor 的 7 位地址为 0x6C(二进制 1101100),则写操作的发送字节为 0xD8(11011000),读操作为 0xD9(11011001)。
3.4.2 10 位地址格式
10 位地址使用两个字节传输。第一个字节的高 5 位固定为 11110,后跟 10 位地址的高 2 位和 R/W 位;第二个字节为 10 位地址的低 8 位。
| 字节 | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|---|---|---|---|---|---|---|---|---|
| 第 1 字节 | 1 | 1 | 1 | 1 | 0 | 地址高 2 位 | R/W | |
| 第 2 字节 | 地址低 8 位 | |||||||
reg 属性填写的是 7 位地址值(如 reg = <0x6C>),驱动中 I2C 核心会自动将其左移 1 位并拼接 R/W 位。切勿在设备树中填写左移后的地址(如 0xD8),否则会导致地址不匹配。
3.5 完整 I2C 写/读事务流程
结合上述所有要素,一次完整的 I2C 写事务和读事务的时序如下:
- 写事务: 起始条件 → 发送从设备地址(写)→ 等待 ACK → 发送寄存器地址 → 等待 ACK → 发送数据字节 → 等待 ACK → ... → 停止条件。
- 读事务: 起始条件 → 发送从设备地址(写)→ 等待 ACK → 发送寄存器地址 → 等待 ACK → 重复起始条件 → 发送从设备地址(读)→ 等待 ACK → 接收数据字节 → 发送 NACK → 停止条件。
3.6 常见 I2C 通信问题与排查思路
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 起始条件后无 ACK | 从设备地址错误、Sensor 未上电、I2C 引脚复用配置错误 | 核对设备树 reg 值;用 i2cdetect 扫描总线;检查电源域 |
| 写寄存器后无 ACK | 寄存器地址越界、Sensor 处于休眠状态、时钟拉伸超时 | 检查 Sensor 数据手册寄存器范围;确认上电时序 |
| 读数据返回全 0xFF | 从设备未应答(NACK)、总线被拉死、上拉电阻缺失 | 用示波器测量 SCL/SDA 波形;检查外部上拉电阻 |
| 通信偶尔失败 | 时钟速率不匹配、信号完整性差、中断干扰 | 降低 clock-frequency;增加 I2C 重试次数;检查电源噪声 |
i2cdetect -y <bus> 扫描总线上的设备地址;使用 i2cget、i2cset 直接读写寄存器,快速验证 Sensor 是否正常响应。