ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

I2C、I2S、SPI、UART通信协议选型指南:从原理到实战

2026/9/27 10:32:56 拓冰建站 浏览量
I2C、I2S、SPI、UART通信协议选型指南:从原理到实战 1. 四种通信协议到底该怎么选从踩坑现场说起i2c、i2s、spi、uart这四个词凡是摸过单片机、写过驱动、调过传感器的人几乎每天都在跟它们打交道。但真要让人用一句话说清楚“什么时候该用哪个”很多人还是会卡壳。我自己在早期做项目时就干过拿UART去接高速ADC的蠢事也试过用I2C驱动音频编解码器结果发现根本带不动数据量。后来踩的坑多了才慢慢把这四者的脾气摸清楚。这篇内容就是把这四种协议拉到同一张桌子上从电气特性、时序结构、典型速率、拓扑方式、软硬件开销这几个维度做一次彻底对比。不管你是刚入门的新手还是已经能写驱动但想系统梳理一遍的老手都能从中找到可以直接拿去用的判断依据。我会尽量少堆术语多用实际项目里的场景来解释——比如为什么ESP32-C3的I2S输出要特别关注时钟配置为什么RK3588的SPI接口在挂NOR Flash时要注意片选建立时间为什么STM32F103用标准库做UART DMA接收时容易丢第一帧数据。核心关键词i2c、i2s、spi、uart会贯穿全文但不会为了堆词而堆词。每个协议我都会给出时序图级别的细节拆解同时配上实际选型时的决策逻辑。看完之后你至少能做到拿到一个传感器或外设扫一眼它的接口类型就能判断该用哪种总线、大概能跑多快、软件上要预留多少资源。2. 四兄弟的出身与定位先搞懂它们各自为什么被发明2.1 I2C两根线挂一堆设备的“公交车”I2C的全称是Inter-Integrated Circuit中文常叫“集成电路总线”。它诞生的初衷非常明确在板级芯片之间用最少的引脚实现多设备通信。两根线——SCL和SDA一根时钟一根数据所有设备都挂在这两条线上靠7位或10位地址区分彼此。这就好比一条公交线路所有乘客共享同一辆车每个人靠“名字”判断是不是叫自己。它的典型速率是100kbps、400kbps高速模式下能到3.4Mbps但实际项目中超过1Mbps的I2C并不多见。原因在于I2C是开漏输出需要外部上拉电阻上升沿的斜率直接受RC时间常数限制。你如果用过逻辑分析仪抓I2C波形会发现SCL和SDA的上升沿往往不是陡直的而是带一点弧度这就是上拉电阻和线容共同作用的结果。I2C最舒服的场景是挂一堆低速传感器、EEPROM、IO扩展芯片。比如温度传感器、加速度计、触摸屏控制器GT911这些设备数据量小、实时性要求不高用I2C既省引脚又省事。但它也有明显的短板半双工、速率有限、总线锁死风险高。我遇到过好几次I2C从机在异常复位后把SDA拉低不放的情况主机这边怎么发时钟都没用最后只能靠硬件复位或者手动发9个时钟脉冲来解锁。2.2 SPI四根线跑出高速的“点对点专线”SPI是Serial Peripheral Interface串行外设接口。它比I2C多两根线SCK时钟、MOSI主出从入、MISO主入从出再加上每个从机一根CS片选。四根线换来了全双工和更高的速率。SPI没有地址概念靠片选线选设备所以挂N个从机就需要N根CS线或者用译码器扩展。SPI的速率可以做到几十MHz甚至上百MHz具体取决于主控和从机的能力。比如STM32F103的硬件SPI最高能到18MHz而RK3588的SPI接口可以轻松跑到50MHz以上。这也是为什么高速ADC、LCD屏、Flash存储器几乎都选SPI——它就像一条点对点的专线没有总线仲裁开销数据可以连续不断地推。但SPI的“坑”也不少。首先是模式问题CPOL和CPHA组合出四种模式主从双方必须严格匹配否则采样时刻错位读回来的数据全是乱的。我见过太多人调试SPI Flash时因为模式设错读ID都读不出来。其次是片选管理硬件片选由控制器自动拉低拉高软件片选则需要手动控制GPIO后者在DMA传输时容易出问题因为DMA搬完数据后不会自动释放片选需要中断里手动处理。2.3 UART最古老也最顽强的“异步串口”UART是Universal Asynchronous Receiver/Transmitter通用异步收发器。它没有时钟线靠双方约定的波特率来同步。两根线TX和RX交叉连接即可通信。因为不需要时钟线UART的硬件成本极低这也是为什么它从计算机诞生初期一直活到现在16550行业标准UART至今仍在很多芯片里作为调试串口使用。UART的典型波特率是9600、115200、921600高一点的能到3Mbps甚至更高。但它是异步的没有时钟线意味着对波特率误差敏感。双方波特率偏差超过2%左右采样就会错位出现帧错误。我在用STM32F103标准库做UART DMA接收时就遇到过因为外部晶振精度不够导致高波特率下误码率飙升的情况后来换成内部RC校准才稳定下来。UART最适合的场景是调试信息输出、模块间低速通信、与PC通信。比如FT232R、FT231X这类USB转UART芯片就是用来把MCU的UART接到电脑USB口上的。它的协议简单到几乎不需要硬件控制器软件模拟一个UART也不难但高速时对中断响应要求较高。2.4 I2S为音频而生的“同步串行总线”I2S是Inter-IC Sound专门为数字音频传输设计。它和SPI长得很像都有时钟和数据线但I2S的时钟体系更复杂除了位时钟SCK还有帧时钟WS也叫LRCK用来区分左右声道。数据在WS变化后延迟一个SCK周期开始传输这个细节决定了I2S和SPI的本质区别。I2S的速率取决于采样率、位深和声道数。比如48kHz采样率、24位深、双声道位时钟就是48k×24×22.304MHz。如果是192kHz、32位、8声道位时钟能到49MHz以上。所以I2S的时钟配置非常关键尤其是用ESP32-C3做I2S输出时时钟源选择、分频系数、MCLK输出与否都会影响音频质量。I2S只传音频数据不传控制信息。所以音频编解码器通常还需要一个I2C接口来配置寄存器这就形成了“I2C管控制、I2S管数据”的经典组合。如果你用逻辑分析仪抓I2S波形会看到WS在左右声道间切换SD线上一串连续的位流SCK则均匀地跳动。3. 关键参数硬碰硬速率、拓扑、开销全对比3.1 电气特性与线数对比先看一张表把四者的物理层差异摆清楚协议线数方向时钟拓扑典型上拉I2C2半双工同步多主多从需要SPI4N全双工同步一主多从不需要UART2全双工异步点对点不需要I2S3半双工/全双工同步一主一从不需要I2C的开漏结构决定了它必须加上拉电阻典型值4.7kΩ或10kΩ。上拉越小上升沿越快但功耗越大。我一般会在400kbps速率下用4.7kΩ100kbps用10kΩ。SPI是推挽输出驱动能力强不需要上拉但线长了要注意阻抗匹配。UART也是推挽但异步采样对边沿要求高线太长容易受干扰。I2S的时钟线频率高PCB走线要尽量等长否则左右声道数据可能错位。3.2 速率与数据吞吐能力速率这块直接给结论SPI I2S UART I2C典型配置下。但具体数字要看实现I2C标准100kbps快速400kbps高速3.4Mbps。实际有效数据率要扣除地址、ACK、起始停止位大概只有标称的70%左右。SPI几MHz到上百MHz。比如STM32F103硬件SPI最高18MHzRK3588的SPI可以到50MHz。全双工意味着同时收发有效吞吐率接近时钟频率。UART常见115200bps到3Mbps。每字节有起始位和停止位有效数据率约为波特率的80%。I2S位时钟从几百kHz到几十MHz。只传音频数据没有地址和ACK开销有效数据率接近100%。这里要特别提一下SPI的片选建立时间。CS拉低到第一个SCK边沿之间需要一定延时这个时间由从机手册给出。比如某些SPI Flash要求CS建立时间最小20ns如果你主控SPI时钟太快CS还没稳定就开始发时钟第一个位就会丢。我在调试RK3588挂SPI NOR时就因为在设备树里没配好cs-setup-delay导致引导失败。3.3 软硬件开销与调试难度软件开销方面UART最简单配置好波特率、数据位、停止位、校验位就能收发。I2C需要处理起始、停止、ACK、地址、寄存器地址代码量中等。SPI需要管理片选、模式、DMA代码量稍大但逻辑直接。I2S最复杂时钟树配置、DMA双缓冲、左右声道对齐每一项都容易出错。硬件开销方面I2C最省引脚SPI最费引脚。UART和I2S居中。调试难度上UART最容易用示波器看波形I2C和SPI用逻辑分析仪抓一次就清楚I2S的波形最难看懂因为WS和SD的关系需要对着时序图慢慢数。4. 实战选型拿到项目该怎么拍板4.1 按数据量选小数据走I2C大数据走SPI这是最朴素的判断逻辑。如果你要接的是温度传感器、EEPROM、IO扩展芯片数据量每次几个字节速率要求不高I2C是首选。比如I2C读写EEPROM的代码Verilog里实现一个I2C主机控制器大概几百行Python用smbus库几行就能跑。如果你要接的是ADC、LCD、Flash、以太网控制器数据量大、速率要求高SPI更合适。比如FPGA通过SPI接ADC采样率几MSPS数据连续不断只有SPI能扛住。MT6701磁编码器用SPI输出角度数据也是因为SPI速率够快能满足实时控制需求。4.2 按实时性选UART适合异步I2S适合音频UART的异步特性决定了它不适合硬实时场景因为波特率误差和中断延迟都会引入抖动。但它非常适合调试输出和低速命令交互。比如STM32F103用UART DMA中断接收发送可以做到不阻塞主循环但接收超时判断需要额外定时器。I2S是音频专用实时性由硬件时钟保证。ESP32-C3的I2S输出配置时要特别注意MCLK是否需要输出给编解码器以及DMA缓冲区大小是否够大否则音频会断断续续。我试过用ESP32-C3做蓝牙音频接收I2S输出到DAC缓冲区设小了就会有咔哒声。4.3 按拓扑选多设备用I2C点对点用SPI/UARTI2C的多设备能力是它的核心优势。一条总线挂七八个传感器很常见地址不冲突就行。但要注意I2C的电容负载限制总线电容超过400pF就会影响上升沿。如果设备太多可以用I2C多路复用器扩展。SPI挂多设备需要多根CS线如果CS不够用可以用GPIO扩展或者译码器。UART是点对点两个设备之间通信不能挂多个。I2S也是一对一音频编解码器和主控之间直接连。4.4 混合使用I2C控制加I2S数据是经典组合很多音频编解码器同时提供I2C和I2S接口。I2C用来配置寄存器比如设置采样率、增益、输入输出通道I2S用来传音频数据。这种组合非常常见因为控制信息量小、速率低数据信息量大、速率高各取所长。类似的还有PMBus和I2C的关系。PMBus在物理层兼容I2C但协议层增加了电源管理专用命令。如果你用I2C去读PMBus设备可能能读到数据但命令格式不对读出来的值没有意义。5. 时序细节深挖逻辑分析仪抓波形时该看什么5.1 I2C时序起始、地址、ACK、数据、停止I2C的起始条件是SCL高时SDA从高变低停止条件是SCL高时SDA从低变高。地址帧是7位地址加1位读写位然后从机拉低SDA表示ACK。数据帧每8位后跟一个ACK位。如果从机不ACK主机就会发停止或重启。抓I2C波形时重点看几个地方起始条件是否干净、地址是否匹配、ACK是否正常、时钟频率是否稳定。我遇到过GT911 I2C通信失败抓波形发现地址发出去后从机不ACK后来查出来是上拉电阻太大上升沿太慢从机采样不到。I2C自由数据模式是一种特殊用法可以绕过寄存器地址直接读写数据但需要从机支持。这种模式在调试时很有用但正式产品里要谨慎因为兼容性不好。5.2 SPI时序模式0到模式3的区别SPI的四种模式由CPOL和CPHA决定模式CPOLCPHA采样边沿移出边沿000上升沿下降沿101下降沿上升沿210下降沿上升沿311上升沿下降沿模式0和模式3最常用。模式0是空闲低电平上升沿采样模式3是空闲高电平上升沿采样。调试SPI时先用示波器看SCK空闲电平确定CPOL再看数据在哪个边沿稳定确定CPHA。SPI硬件片选和软件片选的区别也很关键。硬件片选由SPI控制器自动管理传输开始拉低结束拉高时序精准。软件片选需要手动控制GPIO在DMA传输时容易提前释放或延迟释放。我一般建议高速传输用硬件片选低速或多设备用软件片选。5.3 UART时序起始位、数据位、校验位、停止位UART帧格式是1个起始位低电平、5到9个数据位、0或1个校验位、1或2个停止位高电平。接收方在起始位下降沿开始采样每个位采样一次或多次。波特率误差要控制在2%以内否则采样点会偏移。抓UART波形时先测位宽算出波特率。比如位宽8.68微秒波特率就是115200。然后看数据位是否对齐停止位是否完整。我遇到过UART通信时好时坏抓波形发现停止位偶尔变成低电平后来查出来是发送方在停止位期间被中断打断导致帧错误。5.4 I2S时序WS、SCK、SD的相位关系I2S的WS信号在左右声道间切换通常WS低电平是左声道高电平是右声道。数据在WS变化后的第二个SCK边沿开始有效。这个“延迟一个SCK周期”是I2S和SPI的关键区别也是很多人配置I2S时容易搞错的地方。抓I2S波形时先看WS频率应该是采样率。再看SCK频率应该是采样率×位深×声道数。最后看SD数据是否在WS变化后稳定。如果左右声道数据反了可能是WS极性设反了。6. 常见问题与排查技巧实录6.1 I2C总线锁死怎么救I2C从机异常时可能把SDA拉低不放导致总线锁死。解决方法有两种一是硬件复位从机二是主机手动发送9个SCK脉冲让从机完成当前位传输后释放SDA。具体操作是把SCL配置为GPIO输出发送9个时钟然后发停止条件。这个技巧我救过好几次现场。6.2 SPI读不到数据先查什么先查片选是否拉低再查时钟是否有时钟然后查模式是否匹配最后查MISO是否有数据。如果MISO一直高阻可能是从机没供电或片选没接对。如果数据错位多半是模式设错。如果数据偶尔错可能是时钟太快或线太长。6.3 UART丢数据怎么定位先看波特率误差用示波器测位宽。再看中断优先级UART接收中断是否被高优先级中断打断。然后看DMA配置缓冲区是否够大是否使能了空闲中断。STM32F103标准库UART DMA接收时如果没使能空闲中断最后一帧数据可能留在缓冲区里读不出来。6.4 I2S音频有杂音怎么调先查时钟配置MCLK、SCK、WS频率是否正确。再查DMA缓冲区是否太小导致欠载。然后查电源音频编解码器供电是否干净。最后查PCB布局I2S时钟线是否远离模拟信号。我遇到过ESP32-C3 I2S输出有咔哒声最后发现是DMA缓冲区只有64字节改成1024字节就消失了。6.5 常见问题速查表问题现象可能原因排查方法I2C无ACK地址错、上拉不对、从机没供电抓波形看地址和上拉SPI数据错位模式不匹配、时钟太快对时序图查CPOL/CPHAUART帧错误波特率偏差、停止位不足测位宽算波特率I2S左右声道反WS极性设反查WS高低电平对应声道片选不释放软件片选未手动拉高检查DMA完成中断7. 工具与调试手段没有逻辑分析仪怎么办逻辑分析仪是调这四种协议的神器但不是每个人都有。没有的话示波器也能凑合看。I2C和UART用双通道示波器就能看个大概SPI需要四通道I2S需要三通道。如果连示波器都没有可以用GPIO翻转法在代码里关键位置翻转一个IO用示波器或LED观察。软件层面Linux下可以用i2c-tools、spidev测试工具。Python调用USB模拟SPI接口也是一种办法适合快速验证。FT232R、FT231X这类USB转UART芯片装好驱动后就能当串口用调试UART很方便。对于FPGA开发者SPI、I2C、UART的Verilog实现都是经典练手项目。I2C读写EEPROM的Verilog代码网上很多但要注意时序参数要对着手册改。SPI主机控制器相对简单但高速时要注意跨时钟域处理。8. 选型决策树与个人经验收尾如果非要给一个决策树我会这样写先看数据量小数据低速选I2C大数据高速选SPI再看实时性音频选I2S调试选UART最后看拓扑多设备选I2C点对点选SPI或UART。混合场景就组合使用I2C管控制I2S或SPI管数据。我个人在实际操作中的体会是不要迷信任何一种协议也不要为了省引脚而牺牲性能。我见过太多项目因为选了不合适的总线后期改板改到崩溃。前期多花十分钟评估后期少花十天调试。另外逻辑分析仪一定要买一个哪怕是最便宜的它能让你少熬很多夜。