2. I2C协议详解:起始条件、停止条件、数据有效性、应答机制、7位与10位地址模式
I2C(Inter-Integrated Circuit)总线是一种由Philips公司(现NXP)开发的两线式串行通信协议,广泛应用于车载嵌入式系统中连接传感器、执行器、编解码器、触摸控制器等低速外设。本章深入剖析I2C协议的五个核心要素:起始条件、停止条件、数据有效性、应答机制以及地址模式,为后续驱动开发和设备挂载调试奠定坚实的协议基础。
2.1 总线基本结构
I2C总线仅需两根线:串行数据线(SDA)和串行时钟线(SCL)。所有设备通过开漏输出方式连接到总线,并通过上拉电阻接至电源电压。总线空闲时,SDA和SCL均为高电平。
2.2 起始条件(START Condition)与停止条件(STOP Condition)
I2C总线上数据传输的起始和结束由SDA和SCL的特定电平变化定义,这两种条件具有唯一性,确保总线状态的明确切换。
| 条件类型 | 信号变化顺序 | 说明 |
|---|---|---|
| 起始条件(S) | SCL保持高电平 → SDA从高电平跳变为低电平 | 表示一次新的传输开始;主设备在发送起始条件后获得总线控制权 |
| 重复起始条件(Sr) | 与起始条件相同,但在一次传输中间产生 | 用于改变数据传输方向(读/写切换)或重新寻址,而不释放总线 |
| 停止条件(P) | SCL保持高电平 → SDA从低电平跳变为高电平 | 表示一次传输结束;主设备释放总线,总线恢复空闲状态 |
i2c_master_send()、i2c_master_recv())发起传输,无需手动操作SDA/SCL电平。但在调试阶段,使用逻辑分析仪捕获起始/停止条件是判断通信是否正常启动和结束的关键手段。
2.3 数据有效性(Data Validity)
I2C协议规定,数据在SCL时钟的配合下进行传输,每个数据位对应一个时钟脉冲。数据有效性遵循以下规则:
- 数据稳定期: SCL为高电平时,SDA上的数据必须保持稳定,此时接收方采样SDA电平。
- 数据变化期: SCL为低电平时,SDA允许发生变化(即发送方更新下一个数据位)。
- 字节格式: 每次传输以字节(8位)为单位,高位(MSB)在前,低位(LSB)在后。
- 传输速率: 标准模式(100 kbit/s)、快速模式(400 kbit/s)、高速模式(3.4 Mbit/s)。车载系统常用标准模式和快速模式。
2.4 应答机制(ACK/NACK)
I2C协议采用应答机制确保数据传输的可靠性。每发送一个字节(8位数据)后,接收方必须在第9个时钟周期内给出应答信号。
| 应答类型 | SDA电平(第9个SCL周期) | 含义 |
|---|---|---|
| ACK(应答) | 低电平 | 接收方已成功接收上一个字节,可以继续发送下一个字节 |
| NACK(非应答) | 高电平 | 接收方未成功接收或不再接收数据;主设备应发送停止条件终止传输 |
应答机制在车载驱动中的典型场景:
- 地址寻址应答: 主设备发送从设备地址后,若总线上存在该地址的从设备,则从设备回复ACK;否则回复NACK,驱动应返回
-ENXIO错误。 - 数据写入应答: 从设备每接收一个字节后回复ACK;若从设备忙或写保护,可能回复NACK。
- 数据读取应答: 主设备每接收一个字节后,由主设备回复ACK表示继续读取,回复NACK表示读取结束。
i2c_transfer()返回负值表示NACK或总线错误。在调试阶段,使用i2cget、i2cset等用户空间工具可以快速验证从设备是否正常应答。
2.5 7位地址模式与10位地址模式
I2C协议支持两种从设备地址格式:7位地址模式和10位地址模式。车载系统中,绝大多数从设备使用7位地址模式,10位地址模式用于需要更多设备挂载的场景。
2.6 地址模式在Linux内核中的处理
Linux I2C子系统通过struct i2c_client中的addr字段表示从设备地址,地址类型由flags字段中的I2C_CLIENT_TEN标志区分。
// 7位地址设备声明示例
static struct i2c_board_info my_sensor_info = {
I2C_BOARD_INFO("tmp117", 0x48), // 7位地址 0x48
};
// 10位地址设备声明示例
static struct i2c_board_info my_10bit_device = {
I2C_BOARD_INFO("my_codec", 0x2A0), // 10位地址 0x2A0
.flags = I2C_CLIENT_TEN, // 标记为10位地址
};
reg = <0x48>; 表示。10位地址需要在 reg 中填入完整10位值,并在驱动中通过 I2C_CLIENT_TEN 标志识别。绝大多数车载I2C从设备使用7位地址,驱动开发时优先查阅数据手册确认地址格式。
2.7 完整I2C数据传输流程
结合上述所有要素,一次完整的I2C写操作流程如下:
- 主设备发送起始条件(S):SCL高电平时,SDA由高变低。
- 主设备发送从设备地址 + 写标志(R/W = 0):共8位,高位在前。
- 从设备回复ACK:拉低SDA表示确认。
- 主设备发送寄存器地址/命令字节:8位数据,高位在前。
- 从设备回复ACK。
- 主设备发送数据字节:可连续发送多个字节。
- 从设备每接收一个字节回复ACK。
- 主设备发送停止条件(P):SCL高电平时,SDA由低变高。
读操作流程类似,但在发送从设备地址后,R/W位设置为1(读),且主设备在接收数据后由主设备回复ACK(继续读)或NACK(结束读)。
2.8 本章小结
I2C协议的起始条件、停止条件、数据有效性、应答机制和地址模式构成了总线通信的基石。在车载Linux驱动开发中,理解这些底层细节有助于:
- 正确配置I2C控制器时序参数(时钟频率、上升/下降时间)。
- 准确解析从设备数据手册中的通信时序图。
- 快速定位总线调试中的常见问题(无ACK、总线挂死、数据错位)。
- 合理选择7位或10位地址模式,优化系统设备挂载方案。