ARTICLE DETAIL

建站实战干货

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

I2C、SPI、UART、I2S总线选型指南:从原理到实战避坑

2026/9/26 12:21:55 拓冰建站 浏览量
I2C、SPI、UART、I2S总线选型指南:从原理到实战避坑 1. 四种总线协议到底该怎么选从一次选型翻车说起前两年接手一个多传感器采集板项目主控用的是STM32F103板上挂了EEPROM、一颗六轴IMU、一个旋转编码器、一块小尺寸TFT屏另外还要跟一颗外置ADC通信。方案评审的时候我拍脑袋定了一版接口分配结果板子打回来调试SPI那路死活读不到数据逻辑分析仪抓波形才发现片选拉低到第一个时钟沿之间只有几纳秒从机器件根本反应不过来。那次翻车让我把I2C、I2S、SPI、UART这四兄弟的脾气重新捋了一遍也才有了这篇对比总结。这四个词在嵌入式圈子里出现的频率极高但真正能把它们放在一张表里说清楚“什么场景用哪个、为什么”的人并不多。I2C是两根线的低速总线SPI是四根线的高速总线UART是异步点对点I2S则是专门为音频数据流设计的同步串行接口。它们各自解决的问题完全不同却经常被新手混为一谈。这篇文章适合刚入行的嵌入式工程师、做硬件选型的系统工程师以及那些被“为什么这里用I2C不用SPI”这类问题困扰过的朋友。我会从协议原理、时序细节、典型应用、参数计算、踩坑经验几个维度把这四种总线彻底拆开讲读完你至少能做到拿到一个外设手册五分钟内判断该用哪种总线并且知道配置时哪些参数是坑。2. 四种总线的核心定位与设计哲学2.1 先搞清楚它们各自解决什么问题I2C的全称是Inter-Integrated Circuit飞利浦在1980年代搞出来的核心诉求是“用最少的引脚连接多个芯片”。两根线SDA和SCL一条数据一条时钟所有器件挂在同一组总线上靠7位或10位地址区分。它的设计哲学是省引脚、支持多主多从、有应答机制保证可靠性代价是速度上不去标准模式100kHz快速模式400kHz高速模式3.4MHz而且总线电容限制在400pF以内挂太多器件或者走线太长波形就烂了。SPI是Motorola提出的Serial Peripheral Interface四根线SCLK、MOSI、MISO、CS。它的哲学是简单粗暴跑得快没有地址概念靠片选线选器件全双工同时收发时钟可以跑到几十甚至上百MHz。代价是每增加一个从机就要多一根CS线引脚消耗大而且没有硬件应答机制数据对不对全靠软件校验。UART是Universal Asynchronous Receiver/Transmitter最古老的串行通信方式之一。它没有时钟线收发双方靠约定的波特率各自计时起始位触发同步停止位收尾。哲学是极简、点对点、跨设备通用从16550行业标准UART芯片时代一直沿用至今。代价是只能一对一速率和距离受限而且双方波特率必须匹配误差超过2%到3%就开始丢帧。I2S是Inter-IC Sound专门为数字音频传输设计。它脱胎于SPI的电气特性但时序完全为音频采样数据服务有专门的帧时钟WS区分左右声道有连续的位时钟SCK数据在WS变化后固定延迟一个时钟沿开始传输。哲学是保证音频流的连续性和声道对齐不关心地址、不应答、不校验就是闷头把PCM数据从A搬到B。2.2 一张表看清四者的本质差异维度I2CSPIUARTI2S线数2SDA/SCL4SCLK/MOSI/MISO/CS2TX/RX3SCK/WS/SD拓扑多主多从总线式一主多从星形式点对点一主一从或一主多从寻址方式7/10位地址片选线无无时钟同步同步异步同步双工半双工全双工全双工半双工单数据线典型速率100k-3.4M1M-100M9.6k-12M取决于音频采样率应答机制有ACK/NACK无无可加校验无引脚开销极低高低中典型器件EEPROM、传感器、PMICFlash、ADC、屏幕模块、调试口、GPS音频Codec、MEMS麦克风这张表不是让你背的而是让你在选型时快速定位。比如你要接八个传感器引脚紧张那I2C几乎是唯一选择如果你要读一颗采样率1MSPS的ADCSPI是标配如果你只是跟一个WiFi模块通信UART最省事如果你要接音频Codec别想了I2S专用。2.3 为什么不能“一种总线打天下”很多人问过SPI这么快为什么不全用SPI原因有三。第一是引脚SPI每挂一个从机多一根CS挂八个就是八根加上三根公共线一共十一根而I2C挂八个还是两根。第二是地址能力I2C器件出厂就带地址同一总线可以挂不同型号的器件SPI没有地址概念全靠片选软件上要维护一张片选映射表。第三是生态大量传感器、EEPROM、PMIC只出I2C版本因为厂商也知道客户引脚紧张。反过来I2C速度上不去大块数据搬运必须用SPI比如刷屏、读Flash。UART和I2S则各自守着通信和音频两个垂直领域互不侵犯。3. I2C深度拆解两根线背后的门道3.1 时序本质与起始停止条件I2C的时序核心就三件事起始条件、数据传输、停止条件。起始条件是SCL高电平期间SDA从高变低停止条件是SCL高电平期间SDA从低变高。这两个条件必须由主机发出从机检测到起始条件后开始监听地址。数据传输时SDA只能在SCL低电平期间变化SCL高电平期间必须稳定否则会被误判为起始或停止条件。这个规则是I2C调试中最容易踩的坑软件模拟I2C时如果时序没控制好波形上就会出现莫名其妙的“假起始”。地址帧是7位地址加1位读写位共8位第9个时钟周期从机拉低SDA表示ACK。如果从机没响应SDA保持高电平就是NACK。很多新手调试I2C时发现“设备找不到”第一件事就是用逻辑分析仪看第9个时钟有没有ACK没有ACK说明地址错了或者从机没上电。3.2 上拉电阻怎么算I2C的SDA和SCL都是开漏输出必须外接上拉电阻。这个电阻值不是随便选的它由两个因素决定上升时间和总线电容。上升时间公式是tr 0.847 × R × C标准模式要求tr ≤ 1000ns快速模式要求tr ≤ 300ns。假设总线电容C是200pF快速模式下R ≤ 300ns / (0.847 × 200pF) ≈ 1.77kΩ。同时电阻不能太小否则灌电流超过器件能力一般I2C器件灌电流能力在3mA左右3.3V供电下R ≥ 3.3V / 3mA 1.1kΩ。所以快速模式常用1.5k到2.2k标准模式常用4.7k到10k。注意总线电容是累加的每个器件的引脚电容大约10pF走线每厘米约1pF。挂十个器件加10cm走线电容就超过200pF了这时候要么降低速率要么用I2C缓冲器分段。3.3 时钟拉伸与仲裁机制时钟拉伸是I2C从机的一种流控手段。从机如果处理不过来可以在ACK之后把SCL拉低强制主机等待。主机必须检测SCL实际电平如果发现自己释放了SCL但线还是低的就要继续等。这个机制在读写EEPROM时特别常见因为EEPROM写周期需要5ms左右期间从机会一直拉低SCL。多主仲裁是I2C另一个精妙设计。两个主机同时发起传输时谁先发出低电平谁就赢输的那个检测到SDA电平跟自己发的不一致就自动退出。这个机制保证多主系统不会冲突但实际项目中很少用多主因为调试复杂度太高。3.4 典型应用与踩坑记录I2C最典型的应用是EEPROM读写。以AT24C02为例写操作是起始条件、设备地址加写位、字地址、数据、停止条件。写完之后必须等5ms才能发起下一次操作否则从机不响应。读操作稍微复杂先发起“写”操作设置字地址再发起“读”操作中间要有一个重复起始条件。我踩过的一个坑是I2C HID设备报“该设备找不到足够资源可以使用代码12”。这个问题通常出现在Windows下原因是I2C HID设备在枚举时申请的资源被其他设备占用了。解决办法是在设备管理器里卸载冲突设备或者检查BIOS里I2C控制器的资源分配。另一个常见问题是GT911触摸屏I2C通信失败九成是上拉电阻没焊或者地址配错了GT911的地址由INT引脚在上电时的电平决定0x5D或0x14很多人不看手册直接写0x5D结果模块出厂配置是0x14。4. SPI深度拆解速度与灵活的代价4.1 四种模式与时钟极性相位SPI的时序核心是CPOL和CPHA两个参数组合出四种模式。CPOL决定时钟空闲电平0为空闲低1为空闲高。CPHA决定采样沿0为第一个沿采样1为第二个沿采样。模式0是CPOL0、CPHA0最常用模式3是CPOL1、CPHA1也常见。模式1和模式2用得少但有些ADC只支持模式1。调试SPI时如果数据错位第一件事就是确认模式。我见过一个案例STM32用模式0读AD7606数据总是差一位后来发现AD7606要求模式2改过来就正常了。逻辑分析仪抓波形时重点看数据在哪个时钟沿变化、哪个沿稳定变化沿和稳定沿之间的间隔就是建立保持时间。4.2 硬件片选与软件片选的取舍硬件片选是SPI外设自动控制CS引脚传输开始拉低结束拉高时序精准。软件片选是GPIO手动控制灵活但容易出问题。我前面提到的翻车就是软件片选CS拉低后立刻发时钟从机还没准备好。硬件片选一般会在CS拉低和第一个时钟之间插入几个时钟周期的延迟具体看芯片手册。实操心得如果非要用软件片选CS拉低后至少延时100ns再发时钟保险起见加个for循环空转几个周期。另外CS拉高后也要延时给从机时间完成内部处理特别是Flash的写操作。4.3 片选最小脉宽能到多少有人问过“CS最小能做到多少纳秒”这个问题没有统一答案取决于从机器件。比如W25Q系列Flash的CS高电平最小时间是50nsCS低电平到第一个时钟沿的建立时间是5ns。而有些ADC要求CS低电平至少保持10ns才能开始转换。选型时必须翻手册的AC Characteristics章节里面会写tCSS、tCSH、tSU、tHD这些参数。如果手册没写保守做法是CS拉低后延时1us再通信虽然慢但稳。4.4 典型应用Flash、ADC、屏幕SPI最典型的三个应用是Flash、ADC和屏幕。Flash读写用模式0或模式3命令字加地址加数据的格式。ADC比如AD7606用模式2转换结果在时钟下降沿输出。屏幕比如ST7789用模式0命令和数据靠DC引脚区分。RK3588的SPI接口支持多片选但要注意引脚复用有些SPI引脚跟I2C或UART复用配置错了就出不来波形。STM32CubeMX配置SPI DMA时有个坑DMA请求要在SPI使能之前配置好否则第一次传输会丢数据。另外SPI的NSS引脚如果配置成硬件模式在DMA传输结束后会自动拉高但如果配置成软件模式需要手动拉高。5. UART深度拆解最古老也最实用5.1 异步通信的同步逻辑UART没有时钟线靠起始位同步。空闲时线是高电平起始位是一个比特时间的低电平接收方检测到下降沿后开始按波特率计时在每个比特时间的中间采样。停止位是高电平长度可以是1、1.5或2个比特时间。波特率误差是关键收发双方误差超过2%到3%就会采样错位。比如双方都用内部RC振荡器温漂5%通信就会间歇性出错。5.2 波特率计算与误差分析以STM32F103为例波特率公式是baud fCK / (16 × USARTDIV)fCK是APB时钟USARTDIV是分频系数。假设APB2是72MHz要115200波特率USARTDIV 72000000 / (16 × 115200) 39.0625。整数部分是39小数部分0.0625 × 16 1所以USARTDIV 39.0625实际波特率 72000000 / (16 × 39.0625) 115200误差0%。如果APB时钟是36MHzUSARTDIV 36000000 / (16 × 115200) 19.53125整数19小数0.53125 × 16 8.5取8实际USARTDIV 19.5实际波特率 36000000 / (16 × 19.5) 115384误差0.16%可以接受。注意误差超过2%就要换时钟源或者降低波特率。用外部晶振比内部RC稳定得多特别是长距离通信。5.3 DMA收发与中断处理STM32F103标准库配置UART DMA接收常见做法是DMA循环模式加空闲中断。DMA循环模式让DMA一直往缓冲区写空闲中断在总线空闲时触发这时候读取DMA剩余计数就能知道收到多少字节。这个方案比每字节中断效率高得多适合不定长数据包。发送用DMA普通模式发送完成中断里拉高DE引脚如果是RS485或者启动下一次发送。注意DMA发送完成中断和UART发送完成中断不是一回事DMA完成只表示数据搬完了UART发送完成才表示最后一个字节真正移出去了。RS485方向切换必须等UART发送完成否则最后几个字节会被截断。5.4 常见问题波形、驱动、电平UART波形调试看三样起始位下降沿是否干净、比特宽度是否一致、停止位是否到位。如果波形上比特宽度忽宽忽窄说明波特率不对或者时钟源不稳。FT232R和FT231X是常用的USB转UART芯片驱动安装失败通常是VID/PID没匹配上Windows下需要手动指定驱动路径。电平方面TTL电平是0到3.3V或5VRS232是负逻辑正负12VRS485是差分接错电平会烧芯片。6. I2S深度拆解音频数据的专用通道6.1 与SPI的异同I2S电气上跟SPI很像都是同步串行但时序完全不同。SPI的数据在CS有效期间连续传输I2S的数据是连续的WS信号每帧翻转一次左声道WS为低右声道WS为高。数据在WS变化后的第二个时钟沿开始传输MSB先行。I2S没有地址和应答就是单向数据流所以它不需要CS线但需要WS线。6.2 时钟关系与采样率计算I2S的时钟关系是SCK 2 × 声道数 × 采样率 × 位深。比如立体声、48kHz采样率、16位深度SCK 2 × 2 × 48000 × 16 3.072MHz。如果是32位深度SCK 2 × 2 × 48000 × 32 6.144MHz。主时钟MCLK通常是SCK的256倍或384倍给Codec内部PLL用。ESP32-C3的I2S输出配置时要注意它的I2S外设支持多种格式包括标准I2S、左对齐、右对齐。标准I2S是WS变化后第二个时钟沿传输数据左对齐是WS变化后第一个时钟沿就传输。配错了声音会左右声道颠倒或者出现杂音。6.3 逻辑分析仪抓I2S波形的要点抓I2S波形时触发条件设在WS下降沿然后看SCK、WS、SD三根线的关系。正常波形是WS每帧翻转一次SD在WS变化后固定延迟开始输出数据。如果SD数据在WS变化沿附近跳变说明采样沿配错了。另外注意MCLK是否正常输出有些Codec没有MCLK就不工作。7. 选型决策与混合使用实战7.1 一张决策流程图选型逻辑可以简化为几个问题需要接多个器件且引脚紧张吗是选I2C。需要高速传输大块数据吗是选SPI。只是点对点跟模块通信吗是选UART。是音频数据流吗是选I2S。如果同时有多个需求就混合使用。比如一个典型项目EEPROM用I2CFlash用SPI调试口用UART音频Codec用I2S四者互不干扰。7.2 混合使用时的引脚复用与冲突混合使用时最大的坑是引脚复用。很多MCU的SPI和I2S共用引脚I2C和UART共用引脚。配置时要注意外设映射比如STM32的SPI1默认在PA5/PA6/PA7但也可以映射到PB3/PB4/PB5。如果同时用SPI1和I2S2要确认引脚不冲突。RK3588的引脚复用更复杂需要配置设备树配错了外设就不工作。7.3 电平匹配与隔离不同总线电平可能不同I2C通常是3.3VSPI可能是1.8VUART可能是5V。混合使用时需要电平转换芯片比如TXS0108E用于I2C和SPIMAX3232用于RS232。隔离方面长距离UART用光耦隔离I2C用数字隔离器SPI高速信号一般不加隔离除非工业环境。8. 常见问题速查与避坑清单问题现象可能原因排查方法I2C设备无ACK地址错、上电时序、上拉电阻逻辑分析仪看第9时钟SPI数据错位模式配错、CS时序确认CPOL/CPHA加CS延时UART丢帧波特率误差、DMA溢出测波特率加大缓冲区I2S杂音采样沿错、MCLK缺失抓WS和SD关系多总线冲突引脚复用、中断优先级查手册引脚表调优先级避坑清单I2C上拉电阻别省SPI片选延时别抠UART波特率用晶振I2S时钟别断混合使用先画引脚分配表。9. 我个人在实际操作中的几点体会调这四种总线逻辑分析仪是必备的几百块的国产逻辑分析仪就能抓I2C、SPI、UART抓I2S也够用。抓波形之前先确认探头接地良好否则波形全是毛刺。另外手册的时序图比任何教程都靠谱遇到问题先翻手册的AC Characteristics章节里面写的建立保持时间、最小脉宽都是硬指标。最后软件模拟总线只在低速场景用高速场景老老实实用硬件外设省下来的调试时间够你写好几版代码了。