1. I2C 总线协议基础

1.1 I2C 总线历史

I2C(Inter-Integrated Circuit)总线由 Philips Semiconductors(现 NXP Semiconductors)于 1982 年发明。最初设计目的是为电视、录像机等消费电子产品提供一种简单、低成本、仅需两根线的芯片间通信方案。1992 年发布了第一个标准化版本(I2C-bus Specification Version 1.0),定义了 100 kHz 的标准模式(Standard-mode, Sm)。后续版本逐步扩展:1998 年增加 400 kHz 快速模式(Fast-mode, Fm),2007 年引入 1 MHz 快速模式+(Fast-mode Plus, Fm+)和 3.4 MHz 高速模式(High-speed mode, Hs-mode),2012 年发布超快速模式(Ultra Fast-mode, UFm,单向 5 MHz)。I2C 现已成为嵌入式系统中最广泛使用的板级总线之一,被 SMBus(System Management Bus)、PMBus(Power Management Bus)等衍生标准继承。

关键里程碑: 1982 年发明 → 1992 年标准化(100 kHz) → 1998 年快速模式(400 kHz) → 2007 年 Fm+/Hs 模式 → 2012 年 UFm 模式。

1.2 物理层特性:SDA/SCL 开漏结构

I2C 总线物理层仅使用两条信号线:串行数据线(SDA,Serial Data Line)和串行时钟线(SCL,Serial Clock Line)。两条线均采用开漏(Open-Drain)结构,配合外部上拉电阻连接到电源电压 VDD。开漏结构的关键特性:

  • 线与(Wired-AND)逻辑:任何设备都可以将总线拉低(输出 0),但无法主动驱动总线为高(输出 1)。总线高电平由外部上拉电阻实现。当所有设备释放总线(输出高阻)时,上拉电阻将总线拉高。
  • 多主控仲裁:多个主控设备可以同时尝试驱动时钟和数据线,开漏结构允许无冲突的仲裁——检测到总线被其他设备拉低的主控自动退出。
  • 电平灵活性:上拉电阻连接到 VDD,因此总线高电平由 VDD 决定。不同电压域的设备(如 3.3V 和 5V)可通过选择合适的 VDD 和上拉电阻实现电平兼容。
  • 双向性:SDA 和 SCL 均为双向线,主控设备驱动时钟,从设备可拉低 SCL 实现时钟拉伸(Clock Stretching)以进行流控。
上拉电阻选择要点: 上拉电阻值影响总线上升时间和功耗。标准模式常用 4.7 kΩ,快速模式常用 2.2 kΩ,Fm+ 模式可能需要 1 kΩ 以下。总线电容越大,所需上拉电阻越小。电阻过小会导致灌电流过大,超出器件 IOL 规格。
I2C 总线物理层开漏结构示意图 主控设备 从设备 1 从设备 2 SDA SCL Rₚ Rₚ VDD 开漏输出 开漏输出 开漏输出 开漏结构核心特性 • 任何设备只能拉低总线(输出 0),不能主动驱动高电平 • 总线高电平由外部上拉电阻 Rₚ 实现 → 线与逻辑 • 支持多主控仲裁和时钟拉伸,无需额外片选信号

1.3 I2C 与 SPI、UART 对比

I2C、SPI(Serial Peripheral Interface)和 UART(Universal Asynchronous Receiver-Transmitter)是嵌入式系统中最常用的三种串行通信协议。它们在信号线数量、通信模式、速度、拓扑结构等方面存在显著差异。下表从多个维度进行对比:

对比维度 I2C SPI UART
信号线数量 2 线(SDA + SCL) 4 线(MOSI + MISO + SCLK + CS) 2 线(TX + RX)
通信模式 同步,主从或多主 同步,单主多从 异步,点对点
拓扑结构 总线型(多设备共享两根线) 星型(每个从设备独立片选) 点对点(仅两个设备)
设备寻址 7 位或 10 位地址,软件寻址 硬件片选(CS 引脚) 无寻址,直接连接
数据方向 半双工(分时读写) 全双工(同时收发) 全双工(同时收发)
典型速度 100 kHz ~ 3.4 MHz 10 MHz ~ 80 MHz 9.6 kbps ~ 10 Mbps
从设备数量 理论 127 个(7 位地址) 受限于主控 CS 引脚数 仅 1 对 1
硬件复杂度 中等(需 I2C 控制器) 低(GPIO 模拟即可) 低(UART 外设常见)
流控机制 时钟拉伸(从设备控制速率) 无标准流控 硬件流控(RTS/CTS)
错误检测 ACK/NACK 应答 无标准错误检测 奇偶校验位
典型应用 传感器、EEPROM、RTC、ADC 显示屏、SD 卡、ADC、Flash GPS 模块、蓝牙模块、调试串口
选型注意事项: 当需要连接多个低速外设且引脚数量受限时,I2C 是首选。当需要高速、全双工数据传输时,SPI 更具优势。UART 适合点对点异步通信,常用于调试和无线模块。I2C 的 ACK/NACK 机制提供了硬件级错误反馈,这是 SPI 和 UART 不具备的。
I2C / SPI / UART 拓扑结构对比 I2C:总线型 主控 从设备 从设备 从设备 SDA + SCL 共享总线 SPI:星型 主控 从设备 从设备 独立 CS 片选 + 共享 MOSI/MISO/SCLK UART:点对点 设备 A 设备 B TX ↔ RX 交叉连接 三种协议核心差异总结 • I2C:2 线共享总线,支持多主控,半双工,硬件 ACK,适合多设备低速场景 • SPI:4 线全双工,单主多从,无标准应答,速度最高,适合高速数据流 • UART:2 线异步全双工,点对点,需双方约定波特率,适合调试和无线模块 • 引脚效率:I2C(2 线 → N 设备)> UART(2 线 → 1 设备)> SPI(4+N 线 → N 设备) • 驱动复杂度:I2C 需处理地址、时钟拉伸、仲裁;SPI 需管理片选;UART 需配置波特率

1.4 I2C 总线协议基本时序

I2C 总线上的数据传输遵循严格的时序规范。每次传输以起始条件(START condition)开始,以停止条件(STOP condition)结束。数据在 SCL 高电平时采样,在 SCL 低电平时变化。基本时序要素包括:

  • 起始条件(S):SCL 为高电平时,SDA 从高电平切换到低电平。
  • 停止条件(P):SCL 为高电平时,SDA 从低电平切换到高电平。
  • 数据有效性:SCL 高电平时 SDA 必须保持稳定,SCL 低电平时 SDA 允许变化。
  • 字节格式:每个字节 8 位,MSB 先传,后跟一个应答位(ACK/NACK)。
  • 应答(ACK):接收设备在第 9 个 SCL 周期将 SDA 拉低,表示成功接收。
  • 非应答(NACK):接收设备在第 9 个 SCL 周期保持 SDA 为高,表示传输结束或错误。
驱动开发提示: 在设备树中配置 I2C 时序参数时,需要关注 clock-frequency、i2c-scl-rising-time-ns、i2c-scl-falling-time-ns 等属性。这些参数直接影响总线时序的合规性,尤其是在高速模式下,上升/下降时间不匹配会导致通信失败。
I2C 总线基本时序(起始条件 + 数据字节 + 应答) SCL SDA S P D7 D6 D5 D4 D3 D2 D1 D0 ACK 起始条件:SCL 高时 SDA 下降沿 → 停止条件:SCL 高时 SDA 上升沿 → 数据在 SCL 高时采样