1. I2C 总线概述

I2C(Inter-Integrated Circuit)总线由 Philips 半导体(现 NXP)于 1982 年发明,最初用于电视接收机内部芯片间的低速通信。经过 40 余年发展,它已成为嵌入式系统中最广泛使用的板级总线之一,被几乎所有微控制器、传感器、存储器、I/O 扩展芯片所支持。

1.1 总线历史与演进

版本 发布年份 最大速率 关键特性
Standard-mode (Sm) 1982 100 kbit/s 原始规范,7 位地址
Fast-mode (Fm) 1992 400 kbit/s 兼容 Sm,增加快速模式器件
Fast-mode Plus (Fm+) 2007 1 Mbit/s 更强驱动能力,更大总线电容
High-speed mode (Hs) 2000 3.4 Mbit/s 主从间电流提升传输,需额外 I/O 电平
Ultra Fast-mode (UFm) 2012 5 Mbit/s 单向推挽,不再需要上拉电阻
驱动开发提示: 当前嵌入式 Linux 内核 I2C 子系统原生支持 Sm、Fm、Fm+ 模式。Hs 模式需要芯片级特殊时序支持,UFm 因单向特性较少用于传统 I2C 从设备。

1.2 物理层特性:SDA 与 SCL

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

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

两条线均为开漏(open-drain)结构,即器件只能将线拉低,不能主动拉高。高电平由外部上拉电阻提供。这种结构允许多个主设备共存,且支持线与(wired-AND)仲裁。

关键概念: 开漏输出 + 上拉电阻 = 多主设备仲裁的基础。任何设备都可以拉低总线,但只有所有设备都释放时总线才会回到高电平。
I2C 总线物理连接拓扑 主设备 (Master) 从设备 1 从设备 2 从设备 3 SDA SCL Rp SDA Rp SCL VDD (3.3V / 5V) 所有设备通过开漏输出连接到 SDA 和 SCL,外部上拉电阻 Rp 确保总线空闲时为高电平

1.3 电气特性与上拉电阻选择

上拉电阻的取值直接影响总线功耗、信号上升时间和最大通信速率。选择不当会导致信号畸变、通信失败甚至器件损坏。

上拉电阻计算公式

最小上拉电阻受 VOL 和 IOL 限制:

Rp(min) = (VDD - VOL(max)) / IOL(max)

其中:
  VDD     = 总线供电电压(典型 3.3V 或 5V)
  VOL(max)= 输出低电平最大电压(标准 0.4V @ 3mA)
  IOL(max)= 器件最大灌电流(标准 3mA)

最大上拉电阻由总线电容 Cb 和所需上升时间 tr 决定:

Rp(max) = tr / (0.8473 × Cb)

其中:
  tr  = 最大允许上升时间(Sm: 1000ns, Fm: 300ns, Fm+: 120ns)
  Cb  = 总线总电容(PCB 走线 + 器件引脚电容,典型 10~400pF)

常见场景推荐值

总线模式 VDD 总线电容 推荐 Rp 说明
Standard (100kHz) 3.3V ~100pF 4.7kΩ 最通用,兼容性好
Fast (400kHz) 3.3V ~100pF 2.2kΩ 平衡功耗与速度
Fast+ (1MHz) 3.3V ~50pF 1.0kΩ 需强驱动,注意功耗
多从设备 (≥8个) 5.0V ~400pF 1.8kΩ 补偿大电容,保证上升沿
驱动开发避坑: 在 Linux 内核中,I2C 适配器驱动通常不直接控制上拉电阻。但设备树中 clock-frequency 属性会影响总线时序参数。如果硬件上拉电阻选择过小(如 330Ω),会导致 SCL/SDA 低电平无法被拉低到 VOL 以下,造成总线锁死。务必在原理图阶段确认 Rp 取值。

1.4 总线空闲状态与起始/停止条件

理解总线空闲状态是编写 I2C 驱动的基础:

  • 空闲状态: SDA 和 SCL 均为高电平(由上拉电阻维持)。
  • 起始条件(START): SCL 为高电平时,SDA 从高电平切换到低电平。
  • 停止条件(STOP): SCL 为高电平时,SDA 从低电平切换到高电平。
I2C 起始条件与停止条件时序 SCL SDA START STOP 数据传输期间 SDA 在 SCL 低电平时变化,SCL 高电平时采样

1.5 地址与数据传输基本单元

每个 I2C 从设备拥有唯一的 7 位或 10 位地址。主设备通过起始条件后发送的地址字节选择从设备:

  • 7 位地址模式: 地址字节高 7 位为地址,最低位为 R/W(0=写,1=读)。
  • 10 位地址模式: 第一个字节高 5 位为 11110,后跟地址高 2 位 + R/W;第二个字节为地址低 8 位。

每个字节传输后,接收方必须发送一个应答位(ACK):

  • ACK(0): 接收方在第 9 个 SCL 周期将 SDA 拉低,表示成功接收。
  • NACK(1): 接收方在第 9 个 SCL 周期保持 SDA 高电平,表示未就绪或传输结束。
驱动开发要点: Linux I2C 核心层自动处理地址发送和 ACK/NACK 检测。驱动开发者只需通过 struct i2c_msg 填充地址、数据缓冲和读写标志,由 i2c_transfer() 完成总线事务。NACK 会以错误码 -EIO 或 -EREMOTEIO 返回。