1. I2C 总线概述

I2C(Inter-Integrated Circuit)总线是由 Philips(现 NXP)公司在 1980 年代初期开发的一种同步、多主从、串行通信总线。它最初用于连接电视、音响等消费电子产品中的微控制器与外设芯片,凭借其引脚少、结构简单、易于扩展的特点,迅速成为嵌入式系统中最广泛使用的板级总线之一。在 Linux 内核中,I2C 子系统是驱动开发者必须掌握的核心模块,几乎所有传感器、EEPROM、RTC、音频编解码器、电源管理芯片都通过 I2C 与主控通信。

核心要点:I2C 总线仅需两根线(SDA 数据线 + SCL 时钟线)即可连接多个设备,支持标准模式(100 kbit/s)、快速模式(400 kbit/s)和高速模式(3.4 Mbit/s),是嵌入式系统中最经济的板级通信方案。

1.1 I2C 总线历史与演进

年份 版本 / 里程碑 主要特性
1982 I2C 总线发明 100 kbit/s,7 位地址,简单主从通信
1992 I2C 规范 1.0 标准化时序,增加快速模式(400 kbit/s)
1998 I2C 规范 2.0 引入 10 位地址,扩展地址空间
2007 I2C 规范 3.0 增加高速模式(3.4 Mbit/s),超快速模式(5 Mbit/s)
2012 I2C 规范 4.0 增加超快速模式(5 Mbit/s),改进电气特性
2014 I2C 规范 5.0 增加 FM+ 模式(1 Mbit/s),增强驱动能力
2021 I2C 规范 7.0 增加 I3C 基础规范,向后兼容 I2C
驱动开发提示:Linux 内核 I2C 子系统支持所有上述模式,驱动开发者只需在设备树中配置 clock-frequency 属性即可选择总线速率。标准模式为 100000,快速模式为 400000,高速模式为 3400000。

1.2 物理层特性:SDA / SCL 线与上拉电阻

I2C 总线物理层极其简洁,只有两条双向信号线:

  • SDA(Serial Data Line):串行数据线,用于传输地址和数据。
  • SCL(Serial Clock Line):串行时钟线,由主设备产生时钟信号。

两条线都是 开漏(Open-Drain) 结构,即设备只能将线拉低(输出 0),不能主动拉高(输出 1)。高电平由外部上拉电阻提供。这种设计使得多个设备可以安全地共享总线,不会发生短路。

常见错误:上拉电阻阻值选择不当是 I2C 通信故障的首要原因。阻值过大导致上升沿变缓,信号完整性下降;阻值过小导致功耗增加,驱动能力不足。典型推荐值:5V 系统 4.7kΩ,3.3V 系统 2.2kΩ,1.8V 系统 1.0kΩ。
I2C 总线物理连接示意图 主设备 (Master) 从设备 1 (Slave) 从设备 2 (Slave) SDA (串行数据线) SCL (串行时钟线) Rp Rp VDD 开漏输出 + 上拉电阻:设备只能拉低总线,高电平由 VDD 通过上拉电阻 Rp 提供。 这种结构允许多个设备共享总线,实现多主机仲裁和从设备时钟拉伸。

1.3 I2C 协议核心特点

1.3.1 主从架构(Master-Slave)

I2C 总线采用严格的主从通信模型:

  • 主设备(Master):负责产生 SCL 时钟信号、发起 START 条件、发送从设备地址和读写位、控制数据传输方向。
  • 从设备(Slave):被动响应主设备的寻址,根据地址匹配结果决定是否参与通信。

在任意时刻,总线上只能有一个主设备控制时钟和数据传输。通信结束后,主设备发送 STOP 条件释放总线。

1.3.2 多主机支持(Multi-Master)

I2C 规范允许总线上存在多个主设备。当两个或多个主设备同时尝试发起通信时,通过 总线仲裁(Arbitration) 机制解决冲突:

  • 每个主设备在发送数据的同时监控 SDA 线电平。
  • 如果某个主设备试图拉高 SDA(发送 1),但检测到 SDA 被其他设备拉低(实际为 0),则该主设备失去仲裁,立即停止发送。
  • 仲裁过程不会破坏数据,也不会丢失时钟同步。
驱动开发要点:Linux I2C 核心层自动处理多主机仲裁,驱动开发者无需在从设备驱动中实现仲裁逻辑。但主设备驱动(通常由 SoC 厂商提供)必须正确实现仲裁检测和重试机制。

1.3.3 地址:7 位与 10 位

I2C 总线使用地址来唯一标识从设备。地址在 START 条件之后、读写位之前由主设备发送:

地址类型 地址范围 最大设备数 地址格式 兼容性
7 位地址 0x00 ~ 0x7F 112(保留 16 个) 高 7 位为地址,第 8 位为 R/W 所有设备都支持
10 位地址 0x000 ~ 0x3FF 1024 前 5 位为 11110,后跟高 2 位 + 低 8 位 需要主从设备都支持

7 位地址格式:

START | 7-bit Address | R/W (1 bit) | ACK | ... Data ... | STOP

10 位地址格式(第一帧):

START | 11110 | Addr[9:8] | R/W | ACK | Addr[7:0] | ACK | ... Data ... | STOP
实际开发建议:绝大多数 I2C 传感器和芯片使用 7 位地址。在 Linux 设备树中,reg 属性直接填写 7 位地址值(如 reg = <0x48>)。10 位地址需要额外配置 reg = <0x1A0> 并设置 reg-names = "10-bit"。
I2C 7 位地址帧结构 START 7 位从设备地址 R/W ACK 8 位数据 (N 字节) STOP 关键说明: 1. START 条件:SCL 高电平时 SDA 从高到低跳变,表示传输开始。 2. 从设备地址:主设备发送 7 位地址,与总线上所有从设备比较。 3. R/W 位:0 表示主设备写(发送数据),1 表示主设备读(接收数据)。 4. ACK:从设备在第 9 个 SCL 周期拉低 SDA 表示应答,否则为 NACK。 5. STOP 条件:SCL 高电平时 SDA 从低到高跳变,表示传输结束。

1.4 I2C 协议特点总结

特性 描述 驱动开发影响
同步串行 由 SCL 时钟同步数据传输 无需波特率配置,时序由硬件控制
主从架构 主设备控制时钟和通信方向 从设备驱动只需响应中断和寄存器读写
多主机仲裁 多个主设备通过 SDA 电平仲裁 Linux 核心层处理,驱动无需干预
7/10 位地址 支持 112 或 1024 个从设备 设备树中指定地址类型,驱动匹配地址
开漏输出 设备只能拉低,高电平由上拉电阻提供 确保总线电平兼容不同电压域
时钟拉伸 从设备可拉低 SCL 延长时钟周期 主设备必须支持时钟拉伸,否则通信失败
应答机制 每字节后接收方必须发送 ACK/NACK 驱动需处理 NACK 重试或错误恢复
本章小结:I2C 总线以其简洁的物理层(2 线 + 上拉电阻)、灵活的主从架构、成熟的多主机仲裁和可扩展的地址空间,成为嵌入式 Linux 驱动开发中最基础的板级通信协议。理解 SDA/SCL 的开漏特性、7 位/10 位地址格式以及 START/STOP/ACK 时序,是后续编写 I2C 设备驱动的前提。下一章将深入 I2C 协议的数据传输时序和 Linux I2C 子系统架构。