2. I2C总线协议基础

I2C(Inter-Integrated Circuit)总线是嵌入式系统中最常用的板级通信协议之一,由Philips(现NXP)在1980年代开发。在车载嵌入式系统中,I2C广泛用于连接传感器(如温度、压力、光照)、编解码器、触摸控制器、EEPROM、RTC、ADC/DAC等外设。本章从物理层、通信时序、地址模式三个维度深入剖析I2C协议,为后续Linux内核I2C子系统与设备树配置打下坚实基础。

2.1 I2C物理层

2.1.1 总线信号与拓扑

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

  • SDA(Serial Data Line):串行数据线,用于传输地址、数据和控制信息。
  • SCL(Serial Clock Line):串行时钟线,由主设备产生,同步所有数据传输。

总线采用开漏(Open-Drain)结构,所有设备的SDA和SCL引脚均为开漏输出,通过外部上拉电阻连接到电源电压(VDD)。这种结构允许多个设备共享总线,实现“线与”逻辑:任何设备拉低总线时,总线即为低电平;只有所有设备释放总线时,总线才被上拉至高电平。

车载设计要点: 在IVI(车载信息娱乐系统)和T-Box(远程通信终端)中,I2C总线长度通常不超过30cm,上拉电阻值一般选择2.2kΩ~4.7kΩ(取决于总线电容和通信速率)。对于高速模式(Fast-mode Plus,1MHz),需使用更小的上拉电阻(如1.5kΩ)以缩短上升时间。

2.1.2 上拉电阻与电平

参数 标准模式 (100kHz) 快速模式 (400kHz) 高速模式 (1MHz)
最大上升时间 (tr) 1000 ns 300 ns 120 ns
最大总线电容 (Cb) 400 pF 400 pF 550 pF
推荐上拉电阻 (Rp) 4.7kΩ ~ 10kΩ 2.2kΩ ~ 4.7kΩ 1.5kΩ ~ 2.2kΩ
逻辑低电平 (VIL) ≤ 0.3 × VDD
逻辑高电平 (VIH) ≥ 0.7 × VDD

在车载系统中,I2C总线电平通常与主控SoC的I/O电压一致(如1.8V、3.3V或5V)。当连接不同电平的外设时,必须使用电平转换器(如PCA9306)或选择支持多电压的I2C缓冲器。

避坑指南: 在ADAS(高级驾驶辅助系统)摄像头模块中,I2C总线常与电源轨共用连接器。务必确保上拉电阻连接到正确的电源域,避免在SoC休眠时外设通过I2C引脚反向供电,导致漏电流或启动异常。

2.2 I2C通信时序

I2C通信以主设备(Master)发起、从设备(Slave)响应的方式进行。每次传输包含起始条件、从设备地址、读写位、数据字节和应答位,最后以停止条件结束。

2.2.1 起始条件与停止条件

起始条件(START)和停止条件(STOP)是I2C总线上的特殊信号,由主设备产生:

  • 起始条件(S):SCL为高电平时,SDA从高电平切换到低电平。
  • 停止条件(P):SCL为高电平时,SDA从低电平切换到高电平。

总线在起始条件后进入忙(Busy)状态,在停止条件后恢复空闲(Idle)状态。主设备可以在一次传输中连续发送多个数据帧,中间使用重复起始条件(Repeated START, Sr)而不产生停止条件,用于改变传输方向或切换从设备。

I2C起始条件与停止条件时序 SCL SDA 起始条件 停止条件

2.2.2 数据有效性

I2C协议规定:在SCL时钟的高电平期间,SDA上的数据必须保持稳定;在SCL的低电平期间,SDA允许变化。这意味着数据采样发生在SCL的上升沿或高电平期间,而数据更新发生在SCL的低电平期间。

每个数据字节长度为8位(MSB优先),后面紧跟一个应答位。因此,每传输一个字节需要9个SCL时钟周期。

2.2.3 应答机制(ACK/NACK)

应答机制是I2C协议可靠性的核心:

  • 应答(ACK):在第9个时钟周期,接收方将SDA拉低,表示已成功接收上一个字节。
  • 非应答(NACK):在第9个时钟周期,接收方保持SDA为高电平,表示未成功接收或希望结束传输。

主设备在以下情况会生成NACK:

  1. 读取操作的最后一次数据接收后,主设备发送NACK以通知从设备停止发送。
  2. 从设备地址不匹配或从设备忙时,从设备回复NACK。
  3. 数据校验错误或协议违规时。
调试经验: 在车载Linux启动阶段,如果I2C设备驱动probe失败,最常见的原因是应答异常。使用逻辑分析仪抓取SDA/SCL波形,检查第9个时钟周期SDA是否被从设备拉低。若始终为高,则可能是地址错误、从设备未上电或I2C总线被锁死(Bus Lock)。

2.3 7位与10位地址模式

2.3.1 7位地址模式

7位地址模式是I2C最常用的寻址方式。主设备在起始条件后发送的第一个字节包含:

  • 高7位(bit 7 ~ bit 1):从设备地址。
  • 最低位(bit 0):读写标志(0 = 写,1 = 读)。

理论上7位地址可支持128个从设备,但地址0x00(通用呼叫地址)和0x01(起始字节)被保留,实际可用地址范围为0x02~0x7F。许多外设通过配置引脚(如A0、A1、A2)选择多个可用地址,以支持同一总线上挂载多个相同型号的器件。

2.3.2 10位地址模式

10位地址模式用于需要超过128个从设备的场景。主设备发送两个字节来寻址:

  • 第一个字节:高5位为11110,紧接着高2位地址(bit 9~bit 8),最后是读写位。
  • 第二个字节:低8位地址(bit 7~bit 0)。

10位地址模式与7位地址模式在总线上兼容:从设备通过第一个字节的高5位(11110)识别是否为10位地址模式。在车载系统中,10位地址模式较少使用,但在高端ADAS摄像头模块或复杂传感器融合单元中可能遇到。

特性 7位地址模式 10位地址模式
地址范围 0x02 ~ 0x7F(126个可用) 0x000 ~ 0x3FF(1024个可用)
寻址字节数 1字节(含读写位) 2字节(首字节含11110前缀)
兼容性 所有I2C设备均支持 需从设备明确支持
车载使用频率 极高(95%以上外设) 低(仅特殊传感器/扩展器)
Linux内核表示 直接使用7位值(如0x48) 需设置I2C_TENBIT标志
7位地址与10位地址帧结构对比 7位地址帧: S 7位从设备地址 (A6~A0) R/W ACK → 后续数据字节... 10位地址帧: S 11110 + A9~A8 R/W ACK 8位地址 (A7~A0) ACK → 后续数据字节... 说明: • 7位地址:首字节高7位为地址,最低位为读写标志,后跟应答位。 • 10位地址:首字节高5位固定为11110,次高位为A9~A8;第二字节为A7~A0。两个字节后各跟一个应答位。

2.4 典型I2C通信流程

一个完整的I2C写操作时序如下(以7位地址为例):

  1. 主设备产生起始条件(S)。
  2. 主设备发送从设备地址 + 写标志(0)(共1字节)。
  3. 从设备回复ACK(拉低SDA)。
  4. 主设备发送寄存器地址/命令字节(1字节)。
  5. 从设备回复ACK。
  6. 主设备发送数据字节(1字节或多字节)。
  7. 每发送一个字节,从设备回复ACK。
  8. 主设备产生停止条件(P)。

读操作类似,但在发送寄存器地址后,主设备使用重复起始条件(Sr)重新发送从设备地址 + 读标志(1),然后从设备开始发送数据,主设备每接收一个字节后回复ACK,最后一个字节回复NACK并产生停止条件。

Linux内核视角: 在I2C设备驱动中,上述流程通过struct i2c_msg结构体数组描述,由i2c_transfer()函数执行。驱动开发者只需填充消息结构,无需手动操作SDA/SCL时序——这是I2C核心层和适配器驱动的职责。

2.5 本章小结