ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

IIC与SPI总线选型指南:从原理到嵌入式实战决策

IIC与SPI总线选型指南:从原理到嵌入式实战决策

1. 从一根线说起:为什么IIC和SPI总被放在一起比

但凡做过嵌入式开发的人,几乎都绕不开一个场景:主控芯片选好了,传感器、存储器、显示屏的型号也定了,打开原理图准备画连线的时候,突然发现——有的器件标着IIC,有的标着SPI,还有的两种都支持。这时候脑子里第一个冒出来的问题往往就是:到底接哪个?能不能都接?选错了会怎样?

IIC和SPI是嵌入式系统里最常用的两种板级串行通信总线,几乎每一颗MCU都至少带一路IIC和一路SPI。它们解决的问题本质上是一样的:让主控和外围芯片之间用尽量少的引脚、尽量简单的协议完成数据交换。但两者的设计哲学完全不同,一个追求“用最少的线挂最多的设备”,一个追求“用最直接的方式跑最高的速度”。这个根本差异,决定了它们在速率、引脚数、拓扑结构、软件开销、抗干扰能力上的所有区别。

这篇文章面向的是正在做硬件选型或驱动开发的嵌入式工程师,尤其是那些手头有一堆传感器和外设、需要决定“这个器件挂哪条总线”的人。我会从协议原理讲到实际项目中的选型逻辑,把两种总线的脾气秉性拆开揉碎讲清楚,再给出可以直接对照使用的选型决策表。不管你是刚入行的新手,还是做了几年但一直“凭感觉选”的老手,看完之后应该能建立起一套清晰的判断框架。

需要提前说明的是,IIC和SPI没有绝对的优劣之分,只有适不适合当前场景的区别。很多项目里两种总线同时存在、各司其职,这才是常态。所以这篇文章不会给你一个“选IIC就对了”或者“SPI永远更好”的结论,而是帮你搞清楚在什么条件下该偏向谁。

2. 两种总线的底层逻辑:先搞懂它们是怎么工作的

2.1 IIC总线的工作原理与关键特征

IIC的全称是Inter-Integrated Circuit,中文常叫“集成电路总线”。它的物理层非常简洁:两根线,一根是SDA(串行数据线),一根是SCL(串行时钟线)。两根线都是开漏输出,需要外接上拉电阻到电源正极。所有挂在总线上的设备都并联在这两根线上,每个设备有自己唯一的7位(或10位)地址。

通信过程是这样的:主设备发起起始条件(SCL为高时SDA从高拉低),然后发送目标设备的地址加读写位,等待从设备应答。从设备拉低SDA表示ACK,主设备收到应答后开始传输数据。每传输一个字节(8位),接收方都要回一个ACK位。传输结束后,主设备发停止条件(SCL为高时SDA从低拉高)。

这套机制的核心特点是多主多从、地址寻址。总线上可以挂很多个设备,主设备通过地址来选择跟谁说话。理论上7位地址可以挂128个设备,实际因为地址冲突和电容负载限制,一般挂几个到十几个比较常见。

IIC的速率标准分为几档:标准模式100kHz,快速模式400kHz,快速模式+1MHz,高速模式3.4MHz。实际项目中400kHz用得最多,1MHz以上对布线和上拉电阻的要求会明显提高。

IIC还有一个容易被忽视但非常重要的特性:时钟拉伸。从设备如果处理不过来,可以把SCL线拉低,强制主设备等待。这个机制在传感器数据还没准备好的时候特别有用,但也意味着主设备必须支持时钟拉伸,否则会出问题。

2.2 SPI总线的工作原理与关键特征

SPI的全称是Serial Peripheral Interface,串行外设接口。它的物理层比IIC多两根线,通常是四根:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。有些变种会省略MISO或MOSI,变成三线甚至两线模式,但标准形态是四线。

SPI的通信机制非常直接:主设备拉低某个从设备的CS线,表示“我要跟你通信了”,然后在SCLK上产生时钟,数据在MOSI和MISO上同时双向传输。每个时钟周期传一位,通常是8位为一个字节。传输完成后拉高CS,结束通信。

SPI没有地址的概念,靠的是片选线来选设备。一个从设备对应一根CS线,主设备有多少个从设备就需要多少根CS线(或者用译码器扩展)。这是SPI引脚数随设备数量线性增长的根本原因。

SPI的速率可以做到很高,几十MHz是常规操作,上百MHz也不罕见。因为没有协议开销(不需要起始条件、地址、ACK),SPI的有效数据吞吐率非常高。SPI有四种工作模式,由CPOL(时钟极性)和CPHA(时钟相位)组合决定,主从设备的模式必须匹配,否则数据会错位。

SPI还有一个特点是全双工。MOSI和MISO同时工作,主设备在发送数据的同时也在接收数据。这个特性在某些场景下非常有用,比如读取ADC转换结果的同时发送下一个通道的配置。

2.3 两种总线的本质差异对比

把两种总线的核心特征放在一起对比,差异一目了然:

对比维度IICSPI
引脚数(单设备)2根(SDA+SCL)4根(SCLK+MOSI+MISO+CS)
引脚数(N个设备)2根(所有设备并联)3+N根(时钟和数据共用,CS独立)
寻址方式7位地址寻址片选线选择
最高速率通常400kHz~1MHz,高速3.4MHz通常10~50MHz,可达100MHz+
双工方式半双工全双工
协议开销起始+地址+ACK+停止几乎无开销
多主支持支持不支持(标准SPI)
时钟拉伸支持不支持
上拉电阻需要不需要
抗干扰能力较弱(开漏+上拉)较强(推挽驱动)
典型应用传感器、EEPROM、RTCFlash、显示屏、ADC

这张表是选型的起点,但光看表还不够,因为实际项目里的约束条件往往比表格复杂得多。接下来我会把每个维度背后的“为什么”讲清楚。

3. 选型的核心逻辑:从项目约束反推总线选择

3.1 引脚资源:最直观但也最容易误判的因素

很多人选总线的第一反应是“IIC省引脚”,这个判断在设备数量少的时候是对的,但在设备数量多的时候需要重新算账。

假设你要挂8个SPI从设备,需要3根共用线(SCLK、MOSI、MISO)加上8根CS线,总共11根引脚。如果换成IIC,只需要2根线。这时候IIC的引脚优势非常明显。

但反过来,如果只挂1个SPI Flash,4根线就够了,而IIC虽然只用2根线,但速率可能满足不了Flash的读写需求。这时候引脚数的差异就不是决定性因素了。

还有一个容易被忽略的点:CS线可以用译码器扩展。比如用3-8译码器,3根GPIO可以控制8个CS信号,这样8个SPI设备只需要3+3=6根引脚。虽然增加了译码器芯片,但在引脚极度紧张的时候这是一个可行的折中方案。

实操心得:在引脚预算阶段,不要只看“IIC只要2根线”就做决定。先把所有外设列出来,分别算出IIC方案和SPI方案的总引脚数,再结合速率需求综合判断。我见过不少项目因为一开始没算清楚,画到一半发现引脚不够,被迫换器件或者加译码器,返工成本很高。

3.2 速率需求:什么时候IIC真的不够用

IIC在400kHz下的理论最大吞吐率大约是40KB/s(考虑起始、地址、ACK开销后实际更低)。这个速率对于大多数传感器(温度、湿度、加速度、陀螺仪)是够用的,因为传感器本身的数据更新率就不高,比如温度传感器每秒采样几次到几十次,每次读几个字节,400kHz绰绰有余。

但以下几种场景IIC会明显吃力:

  • SPI Flash读写:页编程和扇区擦除需要传输大量数据,400kHz下写1MB数据要几十秒,完全不可接受。
  • TFT显示屏刷新:全屏刷新需要传输几百KB的像素数据,IIC的速率会导致肉眼可见的卡顿。
  • 高速ADC连续采样:比如音频采样,每秒需要传输几十KB到几百KB的数据,IIC带宽不够。
  • 摄像头模块:虽然摄像头配置寄存器常用IIC,但图像数据传输必须走SPI或并口。

SPI在10MHz下的吞吐率大约是1.25MB/s,是IIC 400kHz的30倍以上。这个差距在需要传大量数据的场景下是决定性的。

但也要注意,SPI的高速率是有代价的:PCB布线要求更高,走线太长或太密容易出信号完整性问题;从设备的SPI接口也有最高速率限制,不是所有SPI器件都能跑50MHz。

3.3 设备数量与拓扑结构:谁更适合“挂一堆”

IIC的地址寻址机制天生适合挂多个设备。只要地址不冲突,理论上可以挂很多个。实际项目中挂5~10个IIC设备很常见,比如一个环境监测节点上挂温度、湿度、气压、光照、PM2.5传感器,全部走IIC,只用2根线。

但IIC挂多了有两个问题:一是总线电容,每个设备的引脚都有输入电容,加上PCB走线电容,总电容超过400pF后信号上升沿会变缓,通信可靠性下降。二是地址冲突,有些传感器的地址是固定的,挂两个同型号的器件就会冲突,需要用到IIC多路复用器来隔离。

SPI挂多个设备靠CS线,没有地址冲突的问题,但CS线数量随设备增加而增加。如果主控GPIO不够,就需要译码器或者用GPIO扩展芯片。SPI的总线电容问题比IIC小,因为它是推挽驱动,驱动能力更强。

注意事项:IIC总线上的上拉电阻值需要根据总线电容和速率来选。400kHz下常用4.7kΩ,100kHz下可以用10kΩ。上拉电阻太小会增加功耗,太大则上升沿变缓。如果总线上挂了多个设备,建议先用示波器看一下实际波形再定阻值。

3.4 软件复杂度:驱动开发的工作量差异

从驱动开发的角度看,IIC的软件复杂度通常比SPI高。原因有几个:

IIC有起始条件、停止条件、地址帧、ACK/NACK、时钟拉伸等机制,状态机比较复杂。特别是时钟拉伸,如果主设备的硬件IIC控制器不支持,就需要用GPIO模拟,软件开销很大。IIC的多主仲裁机制也增加了复杂度,虽然大多数项目用不到多主。

SPI的协议非常简单,基本上就是“拉低CS、发时钟、移数据、拉高CS”。用GPIO模拟SPI很容易,用硬件SPI控制器更简单。SPI没有ACK机制,主设备发了数据不需要等从设备确认,软件流程更直接。

但SPI也有自己的软件坑:四种工作模式(CPOL/CPHA组合)必须和从设备匹配,搞错了数据就是乱的。有些器件的datasheet里写的模式描述比较绕,需要仔细对照时序图确认。

从调试角度看,IIC因为有时钟拉伸和ACK机制,出问题时更容易定位(比如用逻辑分析仪可以看到哪个环节没有ACK)。SPI出问题时往往表现为数据错位或全零,需要检查模式设置和CS时序。

3.5 抗干扰与可靠性:工业场景下的考量

在工业环境或长距离板间通信场景下,SPI的抗干扰能力通常优于IIC。原因在于SPI是推挽输出,驱动能力强,信号边沿陡峭,不容易受外界干扰。IIC是开漏输出加外部上拉,上升沿由RC充电决定,边沿较缓,在噪声环境下更容易出错。

但这不意味着IIC在工业场景就不能用。很多工业传感器用的就是IIC接口,关键在于PCB布线要规范:SDA和SCL尽量短、尽量平行走线、远离高频信号源、上拉电阻靠近主设备放置。如果通信距离超过几十厘米,IIC就需要加缓冲器或改用差分总线。

SPI在长距离通信时也有问题:时钟线在高频下容易产生振铃和反射,需要串联端接电阻。CS线如果走线太长,片选信号的边沿可能变形,导致从设备误触发。

实操心得:在电机驱动、开关电源等强干扰场景下,如果非要用IIC,建议降低速率到100kHz,上拉电阻减小到2.2kΩ,并且在SDA/SCL上并联小电容(几十pF)滤高频噪声。SPI则建议在时钟线上串联22~33Ω电阻,减少反射。

4. 实战选型决策:一张表覆盖90%的场景

4.1 按器件类型快速判断

实际项目中,大多数器件的总线选择其实是有惯例的。下面这张表整理了常见器件类型的推荐总线:

器件类型推荐总线理由
温度/湿度/气压传感器IIC数据量小,更新率低,IIC够用且省引脚
加速度计/陀螺仪IIC或SPI低速采样用IIC,高速采样用SPI
EEPROMIIC小容量存储,读写不频繁,IIC足够
SPI FlashSPI需要高速读写,IIC带宽不够
TFT/OLED显示屏SPI像素数据量大,必须高速
ADC/DACSPI需要连续采样和高速传输
RTC实时时钟IIC数据量极小,IIC是标准配置
数字电位器SPI需要快速更新,SPI更合适
射频模块SPI配置和数据传输都需要较高速度
电机驱动SPI或IIC看具体型号,SPI更常见

这张表是经验总结,不是硬性规定。有些器件同时支持IIC和SPI,比如某些加速度计和ADC,这时候就需要结合系统整体情况来选。

4.2 混合使用:大多数项目的真实状态

实际项目中,IIC和SPI往往同时存在。比如一个典型的数据采集终端:

  • IIC总线:挂温度传感器、EEPROM、RTC
  • SPI总线:挂SPI Flash、ADC、显示屏

这种混合架构的好处是各取所长:低速小数据量的器件走IIC,省引脚;高速大数据量的器件走SPI,保带宽。两条总线互不干扰,软件上分别初始化即可。

混合使用时需要注意引脚分配。主控的IIC和SPI引脚通常是复用的,需要在初始化时正确配置。有些MCU的SPI和IIC共用同一组引脚,不能同时使用,选型时要查清楚引脚复用表。

4.3 选型决策流程图(文字版)

如果你面对一个具体器件不知道选哪个,可以按以下顺序判断:

  1. 器件支持哪些总线?如果只支持一种,那就没得选。
  2. 如果两种都支持,看数据量:需要传大量数据(>10KB/s)选SPI,否则可以选IIC。
  3. 看引脚预算:引脚紧张且设备多,优先IIC;引脚充裕或设备少,SPI也可以。
  4. 看速率要求:需要>1MHz的时钟选SPI,否则IIC够用。
  5. 看系统已有总线:如果板上已经有IIC总线且地址不冲突,优先挂IIC;如果已经有SPI且CS够用,优先挂SPI。
  6. 看干扰环境:强干扰场景优先SPI,或者IIC降速使用。

这个顺序不是绝对的,但能覆盖大多数情况。关键是不要孤立地看一个器件,要放在整个系统的上下文里判断。

5. 实操中的坑与排查技巧

5.1 IIC常见问题与解决方法

问题一:通信完全无响应,示波器看SDA和SCL都是高电平。

这是最常见的IIC问题。排查步骤:先确认上拉电阻是否焊接、阻值是否合适;再用示波器看主设备有没有发出起始条件;如果起始条件都没有,检查GPIO配置是否正确(开漏模式);如果有起始条件但没有ACK,检查从设备地址是否正确(7位地址左移一位后的值)。

问题二:通信偶尔成功,大部分时候失败。

这种间歇性故障通常是时序问题。检查SCL频率是否超过从设备支持的最高速率;检查上拉电阻是否太大导致上升沿太慢;检查总线电容是否过大(挂太多设备或走线太长)。用示波器看SCL和SDA的上升沿时间,如果超过1μs,说明上拉电阻偏大。

问题三:读数据时第一个字节正确,后续字节错误。

这通常是ACK处理的问题。IIC读数据时,主设备在接收完一个字节后需要发送ACK(继续读)或NACK(停止读)。如果ACK/NACK发错了,从设备会停止发送或继续发送导致数据错位。检查驱动代码中ACK/NACK的发送时机。

问题四:多设备总线上某个设备不响应。

先确认该设备的地址是否与其他设备冲突。如果地址冲突,需要用IIC多路复用器(如TCA9548A)来隔离。如果没有冲突,检查该设备的电源和地是否正常,有些传感器需要先配置寄存器才能响应。

5.2 SPI常见问题与解决方法

问题一:数据完全错乱,读出来全是0xFF或0x00。

首先检查CPOL和CPHA设置是否与从设备匹配。这是SPI最容易出错的地方。查从设备datasheet的时序图,确认时钟空闲电平和数据采样边沿。如果模式对了还是错,检查CS线是否在传输期间保持低电平,有些器件的CS在字节之间不能拉高。

问题二:高速通信时数据偶尔出错。

高速SPI对信号完整性要求高。检查SCLK走线是否太长、是否有过孔、是否靠近干扰源。在SCLK上串联22~33Ω电阻可以减少反射。如果从设备支持,适当降低SPI时钟频率试试,如果降速后正常,说明是信号完整性问题。

问题三:多个SPI设备互相干扰。

检查CS线的时序:在切换CS时,确保SCLK处于空闲电平,避免产生毛刺时钟导致从设备误动作。如果CS线走线太长,考虑加缓冲器。另外,MISO线在多个从设备之间共享时,未选中的从设备必须将MISO置为高阻态,否则会冲突。

问题四:DMA传输时数据不完整。

SPI配合DMA传输时,要注意DMA的传输长度和SPI的数据帧长度匹配。有些MCU的SPI FIFO深度有限,DMA请求触发阈值设置不当会导致数据丢失。检查DMA配置中的传输宽度(8位/16位)是否与SPI数据帧大小一致。

5.3 逻辑分析仪的使用技巧

不管是IIC还是SPI,逻辑分析仪都是最有效的调试工具。几个实用技巧:

  • IIC解码时,设置触发条件为“起始条件”或“特定地址”,可以快速定位问题帧。
  • SPI解码时,正确设置CPOL/CPHA和位顺序(MSB/LSB),否则解码结果全是错的。
  • 用逻辑分析仪的协议解码功能可以直接看到地址、数据、ACK等字段,比看波形快得多。
  • 如果逻辑分析仪采样率不够,高速SPI的信号会失真,建议采样率至少是SPI时钟的5倍以上。

实操心得:我习惯在PCB上给IIC和SPI的关键信号留测试点,调试时直接夹逻辑分析仪探头,不用飞线。测试点尽量靠近主控引脚,这样看到的波形最真实。另外,逻辑分析仪的探头地线要尽量短,否则高频信号会引入振铃。

6. 进阶话题:什么时候需要“不按常理出牌”

6.1 用GPIO模拟IIC或SPI的场景

有些项目因为主控的硬件IIC/SPI外设不够用,或者引脚复用冲突,需要用GPIO模拟总线。GPIO模拟IIC比较常见,因为IIC速率低,软件模拟完全跟得上。GPIO模拟SPI在低速下也可行,但高速(>1MHz)就比较吃力,因为软件翻转GPIO的速度有限。

GPIO模拟IIC的关键是开漏输出。如果MCU的GPIO不支持开漏模式,可以用“输出低+输入高阻”的方式模拟:要输出低电平时配置为推挽输出低,要输出高电平时切换为输入模式(靠外部上拉拉高)。这种方式切换方向需要时间,会影响最高速率。

GPIO模拟SPI的关键是时钟和数据的时间关系。在SCLK的边沿之前把数据准备好,在另一个边沿采样。用软件延时控制时序,延时长短取决于MCU主频和从设备的时序要求。

6.2 总线扩展与隔离方案

当IIC设备太多或地址冲突时,可以用IIC多路复用器。这类芯片把一路IIC分成多路,每路可以挂地址相同的设备。主设备通过写多路复用器的寄存器来选择当前通信的通道。

SPI设备太多导致CS线不够时,可以用译码器扩展。比如3-8译码器用3根GPIO控制8根CS线。也可以用SPI GPIO扩展芯片,通过SPI总线控制多根CS线。

在需要电气隔离的场景(比如高压侧和低压侧通信),可以用数字隔离器隔离IIC或SPI信号。IIC隔离需要注意双向信号的隔离,SPI隔离相对简单,因为MOSI和MISO是单向的。

6.3 高速SPI的PCB设计要点

当SPI时钟超过20MHz时,PCB设计就变得关键了。几个要点:

  • SCLK走线尽量短,避免过孔,如果必须过孔,尽量少。
  • SCLK和MOSI/MISO不要长距离平行走线,减少串扰。
  • 在SCLK源端串联端接电阻(22~33Ω),减少反射。
  • MISO线如果较长,考虑加缓冲器。
  • 地平面要完整,信号线尽量靠近地平面走。
  • 如果走线长度超过信号波长的1/10,就需要按传输线处理。

这些规则在低速SPI下可以忽略,但在高速下不注意就会导致通信不稳定。

7. 我的选型经验总结

做了这么多年嵌入式项目,我在IIC和SPI选型上踩过的坑不少,总结几条个人经验。

第一条:不要因为“IIC省引脚”就无脑选IIC。省引脚是有代价的,速率低、软件复杂、抗干扰弱。如果项目对速率有要求,或者环境干扰大,SPI多出来的两根线是值得的。

第二条:SPI的CS线要提前规划。很多项目画到一半才发现CS线不够用,这时候改方案很痛苦。建议在原理图设计阶段就把所有SPI设备的CS线列出来,算清楚GPIO够不够。

第三条:IIC的上拉电阻不要照抄参考设计。不同项目的总线电容不同,上拉电阻需要根据实际情况调整。4.7kΩ是常见值,但不是万能值。如果通信不稳定,先用示波器看波形再调电阻。

第四条:SPI模式一定要对照时序图确认。datasheet里写的“Mode 0”或“Mode 3”有时候和实际时序有出入,以时序图为准。我遇到过好几次datasheet写Mode 0但实际需要Mode 3的情况。

第五条:逻辑分析仪是必备工具。不管是IIC还是SPI,出问题时第一件事就是抓波形。没有逻辑分析仪,调试效率会低很多。现在几百块的逻辑分析仪就能解码IIC和SPI,性价比很高。

最后再分享一个小技巧:在驱动代码里加一个总线扫描功能。IIC可以扫描所有地址,看哪些设备有应答;SPI可以逐个拉低CS,看哪个设备有反应。这个功能在调试初期非常有用,能快速确认硬件连接是否正确。

这个内容后续还可以这样扩展:如果你在做多主IIC系统,可以研究一下IIC的仲裁机制;如果你在用SPI做高速数据采集,可以研究一下DMA和双缓冲的配合;如果你在做低功耗设计,可以对比一下两种总线在休眠模式下的功耗表现。每个方向都值得单独写一篇。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进