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均为高电平。
clock-frequency 时,建议从100kHz(标准模式)开始验证,再逐步提升至400kHz(快速模式),避免因信号质量导致通信失败。
2.2 起始条件(START Condition)
起始条件标志着一次I2C传输的开始。主设备通过特定的电平变化通知总线上的所有从设备:准备接收地址。
时序定义: 当SCL为高电平时,SDA从高电平切换到低电平。
关键点:
- 起始条件由主设备独占产生,从设备只能检测。
- 在起始条件之后,总线进入忙状态,其他主设备不得发起传输。
- RK驱动中,起始条件由I2C控制器硬件自动生成,驱动只需写入从设备地址即可触发。
2.3 停止条件(STOP Condition)
停止条件标志着一次I2C传输的结束。主设备释放总线,从设备恢复监听状态。
时序定义: 当SCL为高电平时,SDA从低电平切换到高电平。
关键点:
- 停止条件之后,总线进入空闲状态,其他主设备可以发起新的传输。
- 在RK驱动中,如果连续读写多个寄存器,主设备可以在不发送停止条件的情况下,通过重复起始条件(Repeated START)切换读写方向,提高效率。
2.4 数据有效性(Data Validity)
I2C协议规定,SDA线上的数据必须在SCL时钟的配合下才能被正确采样。
规则:
- 在SCL的高电平期间,SDA上的数据必须保持稳定(不变)。
- 在SCL的低电平期间,SDA上的数据允许发生变化(切换)。
驱动开发含义: 在编写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消息
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) | 主设备不再需要更多数据 |
-EREMOTEIO(-121)错误,通常意味着从设备未应答(NACK)。常见原因包括:
- 从设备地址错误(7位地址与设备树不匹配)。
- Sensor处于休眠或复位状态,未响应I2C请求。
- I2C时钟频率过高,从设备无法跟上。
2.7 重复起始条件(Repeated START)
在需要改变数据传输方向(例如先写寄存器地址,再读数据)时,主设备可以在不发送停止条件的情况下,再次发送起始条件。这称为重复起始条件,常用于Sensor寄存器读取操作。
典型读操作帧结构:
- 主设备发送START + 从设备地址(写方向)+ ACK。
- 主设备发送寄存器地址 + ACK。
- 主设备发送重复起始条件(Repeated START)。
- 主设备再次发送从设备地址(读方向)+ ACK。
- 从设备发送数据字节,主设备发送NACK表示读取结束。
- 主设备发送STOP。