2. 硬件基础:I2C总线物理层协议、时序与地址
I2C(Inter-Integrated Circuit)总线是一种由Philips(现NXP)开发的同步、多主从、串行通信总线。在嵌入式Linux驱动开发中,理解I2C的硬件基础是正确配置设备树、调试驱动时序的前提。本节从物理层、时序协议、地址与读写操作三个维度展开。
2.1 I2C总线物理层协议
I2C总线仅使用两条双向开漏线:SCL(串行时钟线)和SDA(串行数据线)。所有设备通过这两条线并联在总线上,通过唯一地址进行区分。
| 信号线 | 类型 | 功能描述 | 电气特性 |
|---|---|---|---|
| SCL | 时钟线 | 由主设备驱动,同步数据传输 | 开漏输出,需上拉电阻 |
| SDA | 数据线 | 双向传输地址和数据 | 开漏输出,需上拉电阻 |
关键点:开漏结构允许多个设备共享总线,通过“线与”逻辑实现仲裁。上拉电阻通常选择4.7kΩ(标准模式)或1.5kΩ(快速模式),具体值取决于总线电容和速率。
I2C总线支持多种速率模式,常见标准如下:
- 标准模式(Sm):100 kbit/s
- 快速模式(Fm):400 kbit/s
- 快速模式+(Fm+):1 Mbit/s
- 高速模式(Hs):3.4 Mbit/s
在嵌入式Linux系统中,大多数传感器、EEPROM、RTC、音频编解码器使用标准模式或快速模式。设备树中通过 clock-frequency 属性指定总线速率。
2.2 I2C时序:起始条件、停止条件与数据有效性
I2C总线的数据传输由主设备控制,每个传输周期以起始条件(START)开始,以停止条件(STOP)结束。数据在SCL时钟的配合下逐位传输。
2.2.1 起始条件(S)
当SCL为高电平时,SDA从高电平切换到低电平。此信号表示总线从空闲状态进入忙碌状态,所有从设备开始监听后续地址。
2.2.2 停止条件(P)
当SCL为高电平时,SDA从低电平切换到高电平。此信号表示传输结束,总线释放为空闲状态。
2.2.3 数据有效性
- 数据稳定:在SCL高电平期间,SDA上的数据必须保持稳定。
- 数据变化:仅在SCL低电平期间,SDA允许变化。
- 字节格式:每次传输8位数据(MSB先行),后跟1位应答位(ACK/NACK)。
驱动调试提示:在Linux中,I2C控制器驱动负责硬件时序的精确生成。如果设备树中配置的
clock-frequency 过高,或上拉电阻不匹配,可能导致SCL高电平时间不足,造成从设备无应答(NACK)。此时应检查逻辑分析仪抓取的时序波形。
2.3 I2C地址与读写操作
每个I2C从设备都有一个唯一的设备地址,用于主设备在通信开始时进行寻址。地址分为7位和10位两种格式,嵌入式系统中以7位地址最为常见。
2.3.1 7位地址格式
主设备在起始条件后发送的第一个字节包含7位地址和1位读写标志(R/W)。
| 位序 | 7 (MSB) | 6 | 5 | 4 | 3 | 2 | 1 | 0 (LSB) |
|---|---|---|---|---|---|---|---|---|
| 内容 | A6 | A5 | A4 | A3 | A2 | A1 | A0 | R/W |
| 说明 | 7位设备地址 | 0=写,1=读 | ||||||
地址示例:EEPROM AT24C02的7位地址为
0x50(二进制 1010000)。写操作时发送字节 0xA0(10100000),读操作时发送字节 0xA1(10100001)。
2.3.2 读写操作流程
一次完整的I2C传输遵循以下步骤:
- 主设备发送起始条件(S):总线从空闲变为忙碌。
- 主设备发送从设备地址 + R/W位:所有从设备接收并比对地址。
- 被寻址的从设备发送应答位(ACK):拉低SDA表示确认。
- 数据传输:主设备(写模式)或从设备(读模式)逐字节发送数据,每字节后跟ACK。
- 主设备发送停止条件(P):总线释放为空闲。
2.4 多主设备与仲裁
I2C总线支持多个主设备同时尝试控制总线。仲裁机制基于开漏结构的“线与”特性:
- 仲裁过程:多个主设备同时发送起始条件,在SDA上逐位比较。如果某个主设备试图拉低SDA而检测到高电平(另一主设备已拉低),则该主设备失去仲裁,立即释放总线。
- 仲裁不丢失数据:由于数据位本身是“线与”结果,赢得仲裁的主设备继续传输,不会破坏已发送的数据。
- 时钟同步:多个主设备通过SCL的“线与”实现时钟同步,所有设备以最慢的SCL低电平周期为准。
嵌入式开发注意:在Linux系统中,I2C控制器驱动通常只配置为主设备模式。如果系统需要多主设备支持,必须确保硬件控制器支持多主模式,并在设备树中正确配置
multi-master 属性。大多数嵌入式SoC的I2C控制器默认仅支持单主模式。
2.5 总结:I2C硬件基础要点
| 知识点 | 核心内容 | 驱动开发关联 |
|---|---|---|
| 物理层 | SCL/SDA开漏 + 上拉电阻 | 设备树中配置clock-frequency影响上拉电阻选择 |
| 起始/停止条件 | SCL高电平时SDA的下降沿/上升沿 | 控制器驱动自动生成,但需检查时序是否满足从设备要求 |
| 数据有效性 | SCL高电平数据稳定,低电平变化 | 驱动中数据移位操作需与SCL边沿对齐 |
| 7位地址 | 地址字节高7位为设备地址,最低位为R/W | 设备树中 reg 属性填写7位地址值 |
| 读写操作 | 写:地址+0 + 数据;读:地址+1 + 接收数据 | Linux I2C核心层通过 i2c_msg 结构体封装读写操作 |
| 多主仲裁 | 基于“线与”的逐位仲裁 | 设备树中 multi-master 属性控制 |