I2C 与 SPI:两种总线的取舍
义眼流光
6 分钟阅读
I2C 与 SPI 没有绝对的优劣,取舍取决于引脚数、速率、拓扑和功耗。一句话结论:要省引脚、多设备共享、速率不高的传感与配置场景选 I2C;要高速、全双工、确定性强选 SPI。很多板子两者并存,I2C 挂配置类慢速器件,SPI 挂显示屏、存储器这类吞吐大户。
物理层差异
I2C 只用两根线:SDA(数据)和 SCL(时钟),均为开漏输出并外加上拉电阻。开漏意味着任何设备只能把线拉低、不能主动拉高,释放后靠上拉电阻把线拉回高电平,所以上拉电阻是必选项而非可选项。正因为线是线与关系,任何设备都能拉低它,天然支持多主多从与总线仲裁,但也带来一个约束:上拉电阻限制了上升速度,速率越高电阻要越小,总线电容也要越小,否则高电平爬不上去。标准模式 100kbps、快速 400kbps,再往上受限于电容与驱动能力。
SPI 用四根线:SCLK(时钟)、MOSI、MISO、CS(片选)。主设备用 CS 选中某个从机,全双工、无寻址、无仲裁,时钟由主设备自由给出,速率可以轻松到几十 MHz。代价是每个从机都要一根独立 CS,引脚随设备数线性增长,布线也随设备数变复杂。SPI 没有标准电气规定,各器件电平、模式、位序需要逐一匹配。
配置与代码
I2C 起始条件为 SCL 高时 SDA 由高变低,停止反之。读从机寄存器典型流程:
i2c_start();
i2c_write(slave_addr << 1); // 写方向
i2c_write(reg_addr);
i2c_restart();
i2c_write((slave_addr << 1) | 1); // 读方向
data = i2c_read_nack();
i2c_stop();
SPI 需要约定时钟极性 CPOL 与采样边沿 CPHA,主从必须一致,否则收到乱码:
spi_set_mode(CPOL_0, CPHA_0); // 模式0:空闲低电平,第一个边沿采样
spi_cs_low();
spi_transfer(0x9F); // 发送命令,同时 MISO 回数据
id = spi_transfer(0x00);
spi_cs_high();
信号完整性与速率
I2C 上拉电阻取值要在速率和功耗/驱动间折中:电阻小上升快但功耗大,电阻大则高波特率下上升沿塌陷、高电平不足。经验上 100kbps 用 4.7kΩ 到 10kΩ,400kbps 用 2.2kΩ 左右,并控制总线电容在百余 pF 内,长走线或挂太多设备时这一项最先成为瓶颈。SPI 虽速率高,但 SCLK 是单向高速方波,走线过长会反射、串扰,MISO 在多个从机共享时各从机必须三态输出,否则会互相打架把线拉死。
选型对比
| 维度 |
I2C |
SPI |
| 信号线 |
2(可多设备) |
4 + 每从机 1 根 CS |
| 速率 |
通常 ≤ 3.4Mbps |
可达数十 Mbps |
| 双工 |
半双工 |
全双工 |
| 寻址 |
软件地址 |
硬件片选 |
| 多主 |
支持仲裁 |
不支持 |
| 距离/抗扰 |
一般,依赖上拉 |
较好,但走线需短 |
| 复杂度 |
协议栈较厚 |
几乎无协议 |
调试手段的差异
I2C 出问题优先用逻辑分析仪抓波形,看起始停止、地址是否为 ACK、数据字节对错,最常见是地址错一位或没等 ACK。SPI 由于没有应答,逻辑分析仪只能看到主从各自发出的位,对错要靠协议层自校验,示波器看 CS 是否在传输期间稳定拉低、时钟极性是否匹配更直接。两者都能用示波器量电平幅值,确认从机是不是没上电或电平不匹配。
常见坑
I2C 地址冲突是高频问题,同地址两器件无法共存,需靠硬件引脚改地址或软件切换电源。SPI 的"模式"理解错是最常见调试噩梦,示波器看不出逻辑错误,只能逐位比对。I2C 总线上任一从机拉死 SDA 会导致整条总线锁死,复位时若从机仍占用时钟,主设备需发额外时钟脉冲解救。SPI 没有应答机制,从机没收到命令时主设备也无感知,必须靠协议层自校验。
电平匹配与转换
I2C 和 SPI 的逻辑电平大多跟随 IO 电压,常见 3.3V,老器件可能是 5V。直接把 5V 器件的输出接到 3.3V 器件的输入,轻则识别不了,重则击穿输入端。正确做法是做电平转换:双向的 I2C 可用漏极开路加两侧各自上拉到本侧电源实现;单向的 SPI 可用电平转换芯片或电阻分压(仅适合从高到低的单向场景)。转换器件本身也会引入一点延时,高速 SPI 要确认其带宽足够。
多从机挂载的细节
I2C 靠地址区分从机,挂同一总线的器件地址必须唯一,很多传感器用硬件引脚或 EEPROM 存地址来错开。SPI 每增加一个从机就要多一根 CS,GPIO 紧张时可以用译码器把少量 GPIO 扩展出多路 CS,但要注意切换 CS 时旧从机及时释放 MISO,否则新选中从机的数据会被旧从机拖住。多从机共享 MISO 时,未被选中的从机输出必须呈高阻,这是器件规格里容易忽略的一项。
两种总线都不合适的时候
超出板级、距离到米级以上时,I2C 和 SPI 都扛不住,要换差分总线:工业场景用 RS485,车内与高可靠场景用 CAN,两者抗共模干扰强、可组网。速率到百 MHz 以上或需要长距离高吞吐时,并口或 LVDS、以太网才是归宿。总线选型本质是距离、速率、抗扰、成本四者的折中,I2C 和 SPI 只是其中适合短距离板内的两个选项。
浏览 0
点赞 0
评论 0