第1章 I2C与SPI基础:物理层对比、电气特性差异、应用场景选择

做嵌入式通信接口设计这么多年,我经常被问到同一个问题:「I2C和SPI到底该选哪个?」 说实话,这问题没有标准答案。但如果你不理解它们的物理层差异,选错接口的代价——可能是整个项目推倒重来。

这一章,咱们就从最底层的物理层开始,把这两个协议扒开来看。嗯,先别急着翻数据手册,听我慢慢说。

1.1 物理层架构:两根线 vs 四根线

先看一张对比图,把整体结构理清楚。

I2C 与 SPI 物理层架构对比 I2C 总线(2线制) 主设备 从设备1 从设备2 从设备3 SDA(数据线) SCL(时钟线) Rₚ Rₚ SPI 总线(4线制) 主设备 从设备1 从设备2 从设备3 SCLK(时钟) MOSI(主出从入) MISO(主入从出) SS(片选,每设备一根) 每从设备独立SS

从图上能看得很清楚:I2C 只用两根线——SDA(数据)和 SCL(时钟),所有设备都挂在这两根线上。而 SPI 至少四根线——SCLK、MOSI、MISO,外加每增加一个从设备就要多一根片选线(SS)。

核心差异一句话:I2C 用地址选设备,SPI 用片选线选设备。前者省引脚,后者省协议开销。

1.2 电气特性差异:谁更抗干扰?

这里我要说点实际的。很多工程师只看速率选接口,忽略了电气特性对系统稳定性的影响。我在一个工业控制项目里吃过亏——用 I2C 连接 5 个传感器,线长超过 30cm,结果数据时不时就乱飞。

为什么会这样?看下表就明白了。

参数 I2C SPI
信号类型 开漏输出(OD) 推挽输出(Push-Pull)
驱动方式 需要上拉电阻 直接驱动
典型速率 100kHz / 400kHz / 1MHz 10MHz ~ 50MHz+
抗干扰能力 较弱(高阻态窗口) 较强(低阻驱动)
最大线长(经验值) ≤30cm(400kHz时) ≤1m(10MHz时)
总线电容限制 ≤400pF 无严格限制

注意看「信号类型」这一行。I2C 是开漏输出,说白了就是管子只能拉低,不能主动拉高。高电平全靠上拉电阻把线拽上去。这就导致了一个问题——上升沿很慢。

你想想看,如果总线电容大了(线长了、设备多了),RC 充电时间常数变大,上升沿就变成软绵绵的斜坡。这时候外界一点噪声耦合进来,接收端就可能误判电平。

避坑指南:我曾经在一个产品上把 I2C 总线拉到 50cm,用的 4.7kΩ 上拉电阻。结果 400kHz 下波形完全变形,SCL 上升沿超过 300ns,从设备频繁丢失 ACK。后来换成 1.5kΩ 上拉,把线长砍到 20cm,问题才解决。

SPI 就不一样了。推挽输出,管子既能拉高又能拉低,驱动能力很强。信号边沿陡峭,抗噪声能力自然好。这也是为什么 SPI 能跑到几十 MHz 的原因。

1.3 应用场景选择:什么时候用谁?

我个人习惯把场景分成三类,直接对号入座:

场景一:板内低速传感器采集 → 选 I2C

  • 温度传感器(LM75、TMP102)
  • 湿度传感器(SHT30)
  • 加速度计(MPU6050)
  • EEPROM 存储(24LCxx 系列)

这些器件数据量不大,几十到几百字节每秒。I2C 两根线就能挂一 bus,省引脚。而且这些传感器通常自带地址引脚,可以挂 8 个同型号设备。

场景二:高速数据流传输 → 选 SPI

  • SD 卡读写
  • LCD 显示屏驱动
  • ADC 高速采样(如 ADS1256)
  • Flash 存储器(W25Qxx 系列)

SPI 全双工,收发可以同时进行。我做过一个音频采集项目,用 SPI 接 ADC,采样率 192kHz,24bit 数据,SPI 时钟 10MHz 轻松搞定。换成 I2C 的话,400kHz 下光传数据就占满总线了。

场景三:多设备混合系统 → 灵活组合

很多复杂系统会同时用两种总线。比如一个主控 MCU,用 I2C 挂传感器和 RTC,用 SPI 挂 Flash 和 LCD。各取所长,互不干扰。

我的经验法则:

  • 设备数量 > 3 且数据量小 → I2C
  • 速率需求 > 5MHz → SPI
  • 线长 > 30cm → 优先 SPI
  • 引脚紧张 → I2C
  • 需要从设备主动上报 → I2C(支持多主)

1.4 上拉电阻计算:I2C 的命门

既然说到 I2C 的电气特性,上拉电阻必须单独拎出来讲。这个电阻选不对,整个总线都别想稳定。

计算公式其实不复杂:

Rₚ(min) = (Vcc - Vₒₗ(max)) / Iₒₗ(max)
Rₚ(max) = tᵣ(max) / (0.8473 × C_bus)

其中:

  • Vcc:总线电压(3.3V 或 5V)
  • Vₒₗ(max):输出低电平最大值(通常 0.4V)
  • Iₒₗ(max):输出低电平电流(通常 3mA ~ 20mA)
  • tᵣ(max):上升沿最大允许时间(100kHz 时 1000ns,400kHz 时 300ns)
  • C_bus:总线总电容(引脚电容 + 走线电容 + 过孔电容)

举个例子,3.3V 系统,400kHz,总线电容估算 100pF:

Rₚ(min) = (3.3 - 0.4) / 0.003 = 967Ω
Rₚ(max) = 300ns / (0.8473 × 100pF) ≈ 3540Ω

所以电阻范围在 1kΩ ~ 3.3kΩ 之间。我一般取中间值 2.2kΩ,留点余量。

注意:如果总线电容超过 400pF,I2C 规范已经不保证正常工作了。这时候要么降低速率,要么换 SPI。别硬扛。

1.5 电平转换:混合电压系统的坑

现在很多系统是混合电压的——MCU 是 3.3V,传感器是 5V,或者反过来。I2C 和 SPI 的电平转换方式完全不同。

I2C 电平转换:因为开漏结构,用一颗 MOSFET(如 BSS138) 就能实现双向电平转换。电路简单,成本低。我常用的方案是 NXP 的 PCA9306,或者直接用分立 MOSFET 搭。

SPI 电平转换:推挽输出不能简单用 MOSFET 了。需要双向缓冲器,比如 TXB0104、SN74LVC4245。或者直接用电阻分压 + 二极管钳位,但只适合低速场景。

这里有个容易踩的坑——SPI 的片选信号。很多工程师只转换了 MOSI/MISO/SCLK,忘了 SS 也要转。结果片选信号电平不匹配,从设备时而选中时而掉线,查半天找不到原因。

一句话总结:I2C 电平转换简单便宜,SPI 电平转换需要专用芯片。如果你的系统必须混合电压,优先考虑 I2C。

1.6 本章小结

这一章我们从物理层把 I2C 和 SPI 拆开看了个遍。核心就几点:

  • I2C:两根线、开漏输出、需要上拉电阻、省引脚、抗干扰弱、适合板内低速多设备
  • SPI:四根线起步、推挽输出、高速、抗干扰强、适合高速数据流
  • 上拉电阻是 I2C 设计的重中之重,别随便焊个 10kΩ 就完事
  • 电平转换方案不同,混合电压系统要提前规划