1. I2C 总线概述:从历史到多主多从架构

各位同学,咱们今天聊聊 I2C 总线。说实话,这玩意儿在嵌入式圈子里太常见了。你随便拆开一个电子产品,里面大概率能找到 I2C 的踪迹。我最早接触 I2C 是在做传感器采集板的时候,当时觉得这东西简单,结果一上手就踩了不少坑。嗯,咱们今天就把 I2C 的底裤扒干净。

1.1 I2C 的历史:飞利浦的“小发明”

I2C 全称是 Inter-Integrated Circuit,中文叫“集成电路间总线”。1982 年,飞利浦半导体(现在的 NXP)搞出了这个东西。初衷很简单——他们想减少芯片之间的连线数量。

你想想看,早期的电路板,每个芯片都有自己的地址线、数据线、控制线,密密麻麻的。飞利浦的工程师一拍脑袋:能不能只用两根线就把所有芯片串起来?于是 I2C 诞生了。

关键时间节点:

  • 1982 年:飞利浦提出 I2C 总线概念,最初用于电视机的调谐器控制
  • 1992 年:发布 I2C 规范 1.0,支持 100 kHz 标准模式
  • 1998 年:规范升级到 2.0,增加 400 kHz 快速模式
  • 2007 年:NXP 发布 3.0 规范,引入 1 MHz 快速模式+
  • 2012 年:推出 5 MHz 超快速模式(UFm)

我记得有一次做项目,客户要求用 I2C 接 12 个传感器。我查了查规范,标准模式理论上能挂 128 个设备,但实际电容限制会让你哭。这个咱们后面细说。

3.2 物理层特性:两根线走天下

I2C 物理层就两根线:SDA(串行数据线)和 SCL(串行时钟线)。所有设备都挂在这两根线上,通过开漏输出实现“线与”逻辑。

说白了,就是任何设备都能把总线拉低,但没人能主动拉高。拉高靠的是上拉电阻。这个设计很巧妙——避免了多设备同时驱动总线时的短路问题。

参数 标准模式 快速模式 快速模式+ 高速模式
最大时钟频率 100 kHz 400 kHz 1 MHz 3.4 MHz
最大总线电容 400 pF 400 pF 550 pF 100 pF
最小上拉电阻 ≈1.6 kΩ ≈1.6 kΩ ≈1.2 kΩ ≈0.8 kΩ
最大上拉电阻 ≈10 kΩ ≈4.7 kΩ ≈2.2 kΩ ≈1.5 kΩ

我曾经踩过的坑: 有一次我图省事,用了 10 kΩ 上拉电阻跑 400 kHz。结果示波器一看,SCL 的上升沿慢得像蜗牛爬。后来一算,总线电容 200 pF,RC 常数 2 μs,400 kHz 的周期才 2.5 μs,上升沿就占了 80% 的时间。信号根本没法看。

1.3 协议层基础:起始、停止、应答

I2C 的协议层其实不复杂。核心就几个动作:起始条件、停止条件、数据发送、应答。

咱们先看时序图:

I2C 基本时序:起始 → 数据 → 应答 → 停止 SCL SDA 起始 SCL高时 SDA下降 停止 SCL高时 SDA上升 数据位 D7-D0 SCL低时改变SDA SCL高时采样SDA 应答 第9个SCL脉冲 从机拉低SDA

协议流程其实就这几步:

  1. 起始条件:SCL 高电平时,SDA 从高切换到低。这表示“我要开始通信了”。
  2. 发送地址:主设备发送 7 位从机地址 + 1 位读写位(0=写,1=读)。
  3. 等待应答:第 9 个时钟周期,从机拉低 SDA 表示“我收到了”。
  4. 数据传输:每 8 位数据后跟一个应答位。数据在 SCL 低电平时改变,高电平时采样。
  5. 停止条件:SCL 高电平时,SDA 从低切换到高。表示“通信结束”。

小技巧: 我习惯在写驱动时,把起始和停止条件封装成独立函数。这样代码可读性高,调试也方便。比如:

void i2c_start(void) {
    SDA_HIGH();
    SCL_HIGH();
    delay_us(5);
    SDA_LOW();   // SCL高时SDA下降 → 起始
    delay_us(5);
    SCL_LOW();   // 准备发数据
}

1.4 多主多从架构:谁说了算?

I2C 支持多主多从架构。什么意思?就是总线上可以挂多个主设备,每个主设备都能主动发起通信。

但问题来了——如果两个主设备同时抢总线怎么办?

I2C 的解决方案是仲裁。说白了,就是谁先拉低总线谁赢。具体机制是这样的:

  • 每个主设备在发送数据时,会同时监测 SDA 电平
  • 如果自己发送的是高电平,但检测到 SDA 是低电平,说明有其他主设备在拉低总线
  • 这个主设备就自动退出,让另一个继续

我刚开始做多主系统时,觉得仲裁很神奇。后来用示波器抓了一次波形才明白——其实就是“线与”逻辑的自然结果。谁先拉低,谁就占住总线。

场景 主设备 A 发送 主设备 B 发送 SDA 实际电平 仲裁结果
情况 1 1(高) 0(低) 0(低) B 获胜,A 退出
情况 2 0(低) 0(低) 0(低) 继续仲裁下一 bit
情况 3 1(高) 1(高) 1(高) 继续仲裁下一 bit

注意: 仲裁只发生在 SDA 上。SCL 是“线与”的——任何主设备都可以拉低 SCL 来延长时钟周期(这叫时钟拉伸)。我遇到过一些从机芯片,处理数据慢时会拉低 SCL 让主设备等一等。如果你的主设备不支持时钟拉伸,通信就会出错。

1.5 知识结构总览

咱们把这一章的核心知识点串起来,画个图:

I2C 总线知识体系 I2C 总线 历史与演进 物理层特性 协议层基础 多主多从架构 1982年飞利浦 标准→快速→高速 SDA + SCL 两根线 开漏输出 + 上拉电阻 总线电容限制 起始/停止条件 7位地址 + 读写位 应答机制 多主设备仲裁 时钟拉伸

这张图把 I2C 的核心知识点串起来了。后面咱们会逐个深入——特别是总线电容计算和上拉电阻选型,这是实战中最容易出问题的地方。

本章要点回顾:

  • I2C 是飞利浦 1982 年发明的双线串行总线,初衷是减少芯片间连线
  • 物理层只有 SDA 和 SCL 两根线,采用开漏输出 + 上拉电阻
  • 协议层核心:起始条件、7 位地址、读写位、应答、停止条件
  • 多主架构通过 SDA 仲裁解决总线冲突,时钟拉伸是从机的“慢下来”信号
  • 总线电容直接影响上拉电阻选型和通信速率——这是咱们课程的核心

好了,第一章就到这里。记住这些基础概念,后面咱们要动手算电容、选电阻、写驱动了。嗯,到时候你会发现,理论懂了,实战才是真正的考验。