第1章 I2C与SPI基础:物理层对比、电气特性差异、应用场景选择
做嵌入式通信接口设计这么多年,我经常被问到同一个问题:「I2C和SPI到底该选哪个?」 说实话,这问题没有标准答案。但如果你不理解它们的物理层差异,选错接口的代价——可能是整个项目推倒重来。
这一章,咱们就从最底层的物理层开始,把这两个协议扒开来看。嗯,先别急着翻数据手册,听我慢慢说。
1.1 物理层架构:两根线 vs 四根线
先看一张对比图,把整体结构理清楚。
从图上能看得很清楚: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Ω 就完事
- 电平转换方案不同,混合电压系统要提前规划