news 2026/9/25 2:02:29

UART、I2C、SPI、I2S四大串行总线本质区别与工程选型指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UART、I2C、SPI、I2S四大串行总线本质区别与工程选型指南

1. 为什么工程师第一次看懂这四种总线时,手里的开发板突然不香了

刚拿到一块带音频Codec、OLED屏和温湿度传感器的开发板,你兴冲冲接上电源,打开串口调试助手——结果发现:UART能打印日志,但OLED没反应;I2C扫描地址有设备,可写入命令后屏幕还是黑的;SPI接了ADC芯片,波形看起来像模像样,数据却全在跳变;I2S连上耳机,只听到“滋啦”一声就再没动静。这不是板子坏了,是你还没真正分清I2C、I2S、SPI、UART这四个名字里都带“I”的家伙到底在干啥。

它们不是同类项,更不是可以互换的“通信接口”。把I2C当成SPI用,就像用螺丝刀拧螺母——能转两圈,但很快滑丝;把UART当I2S传音频,等于让快递员送活体金鱼——包裹能到,鱼早翻白了。我见过太多人卡在“协议能通,功能不通”的死循环里:示波器上波形完美,逻辑分析仪里数据也对,可传感器就是不回值,音频就是不出声。问题从来不在代码,而在你选错了“语言”。

这四种接口,本质是为四类完全不同的任务量身定制的“交通系统”:UART是单线长途客运巴士(点对点、低速、长距离);I2C是窄巷里的共享电瓶车(多设备共用两根线、靠地址寻址、中低速);SPI是工厂内部的专用传送带(高速、全双工、主从明确、线多但效率高);I2S则是音乐厅后台的独立调音通道(专为PCM音频流设计,三线分离时钟/数据/帧同步)。它们的物理层、电气特性、协议结构、时序约束、错误处理机制,全部不同。今天这篇,不讲教科书定义,只拆解你在真实项目里踩过的坑、调过的波形、改过的驱动——从信号线怎么接、示波器怎么看、逻辑分析仪怎么抓、驱动怎么配,到为什么某块RK3588板子SPI CS拉低时间必须≥100ns,为什么FT231X USB-UART在921600波特率下要加100nF去耦电容,为什么I2S的MCLK频率必须是采样率的256倍。所有结论,都来自我亲手焊过37块PCB、抓过214次总线波形、重写过11版底层驱动的真实现场。

2. 物理层真相:四根线背后,藏着四套完全不同的“交通规则”

别被“都是串行通信”骗了。UART、I2C、SPI、I2S的物理连接方式,决定了它们根本没法互相替代。就像不能把地铁轨道铺成自行车道——线数、电平、方向、时钟来源,全都不一样。

2.1 UART:最朴素的点对点专线,但最容易被低估

UART(Universal Asynchronous Receiver/Transmitter)没有时钟线。它靠双方提前约定好的波特率(如115200bps)来同步收发节奏。典型接线只有三根:TX(发送)、RX(接收)、GND(共地)。有些模块会加RTS/CTS做硬件流控,但核心仍是TX/RX/GND。

关键细节在于电平标准。你看到的“TTL电平”(0V/3.3V或0V/5V)只是其中一种,实际还有RS-232(±12V)、RS-485(差分±5V)等。USB转串口芯片(如FT231X、CH340、CP2102)内部做了电平转换,但输出到MCU的TX/RX引脚,必须严格匹配MCU的IO电压。我曾遇到一个STM32H7项目:FT231X输出3.3V TTL电平,但MCU的USART引脚配置成了5V tolerant模式,结果在高温环境下接收误码率飙升——因为5V tolerant输入阈值更高,3.3V高电平在噪声干扰下容易被判为低电平。解决方案不是换芯片,而是把MCU引脚配置回3.3V标准模式,并在TX线上加10kΩ上拉电阻稳定高电平。

提示:UART的“异步”意味着它没有时钟线,所以对波特率精度要求极高。STM32的APB总线时钟若为80MHz,用标准库配置115200bps时,实际误差可能达±2.5%。而UART协议允许的最大误差是±3%,看似安全,但叠加晶振温漂(±20ppm)和PCB走线容抗,实测误码率在-20℃~70℃范围内会从0突增至10^-3。解决方法是:用HAL库的HAL_UART_Init()前,先用HAL_RCC_GetSysClockFreq()校准实际时钟,或直接选用HSI48(出厂校准至±1%)作为UART时钟源。

2.2 I2C:两根线撑起的微型局域网,但地址冲突是隐形杀手

I2C(Inter-Integrated Circuit)只用两根线:SDA(数据线)和SCL(时钟线),全部开漏输出,必须外接上拉电阻(通常4.7kΩ)。它的精妙在于多主多从、地址寻址、软件可配置速率。每个设备有唯一7位地址(如EEPROM常用0x50),主设备发起通信时先发地址+读写位,从设备比对地址匹配才响应。

但问题来了:为什么用逻辑分析仪抓到SCL有毛刺,SDA在地址阶段就拉低失败?常见原因有三个:
第一,上拉电阻值错。3.3V系统用10kΩ上拉,上升沿会变缓(RC时间常数增大),在400kHz快速模式下,上升时间可能超300ns,导致从设备无法识别有效边沿。实测数据:3.3V系统,4.7kΩ上拉,20cm PCB走线,上升时间≈120ns;换成10kΩ,上升时间≈250ns;超过300ns,部分I2C从设备(如某些温湿度传感器)直接拒绝应答。
第二,总线电容超标。I2C规范规定总线电容≤400pF。每厘米PCB走线约2pF,一个0805封装的上拉电阻约0.5pF,一个I2C器件引脚约5pF。算下来,接5个器件+30cm走线,电容轻松破400pF。此时即使换小阻值上拉,上升沿仍拖尾——因为电容太大,充电电流再大也快不起来。解决方案是:缩短走线、减少并联器件、或用I2C缓冲器(如PCA9515)分段隔离。
第三,地址冲突。多个同型号传感器(如4个BME280)默认地址都是0x76,必须通过ADDR引脚切换(接VDD=0x77,接GND=0x76)。但很多开发者只改了原理图,忘了在代码里同步修改i2c_write_byte(0x77, ...),结果永远只能读到第一个设备的数据。

2.3 SPI:速度之王,但片选(CS)是它唯一的阿喀琉斯之踵

SPI(Serial Peripheral Interface)是全双工、同步、主从架构。标准四线制:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。它的优势是速率高(可达100MHz)、无地址概念、时序简单。但致命弱点藏在CS线上:CS必须在每次传输前后严格拉高/拉低,且高低电平持续时间有硬性要求。

以RK3588的SPI控制器为例,其CS最小低电平时间(tCSS)为100ns,最小高电平时间(tCSH)为50ns。如果用GPIO软件模拟CS(即用gpio_set(0)拉低,spi_xfer()传输,再gpio_set(1)拉高),在Linux内核中一次gpio_set()调用耗时约5~10μs,远超100ns要求,导致从设备(如ADC芯片)无法正确锁存时钟边沿,数据全乱。解决方案只能是:启用SPI控制器的硬件CS功能,让SCLK/MOSI/MISO/CS由同一时钟域驱动,确保时序精准。

另一个坑是时钟极性(CPOL)与时钟相位(CPHA)。SPI有四种模式(0/0, 0/1, 1/0, 1/1),由CPOL(空闲时SCLK电平)和CPHA(采样时刻)决定。比如ADS1256 ADC要求CPOL=0, CPHA=1(模式1),即SCLK空闲为低,数据在第二个边沿采样;而多数Flash芯片用CPOL=0, CPHA=0(模式0),数据在第一个边沿采样。如果MCU配置错模式,示波器上看波形完美,但读出的数据永远是0xFF或0x00——因为采样时刻完全错位。我的经验是:查芯片手册的“Timing Diagram”小节,用示波器抓SCLK和MISO,看MISO数据是在SCLK上升沿还是下降沿稳定,再反推CPOL/CPHA。

2.4 I2S:为音频而生的“三轨专线”,MCLK是它的呼吸节奏

I2S(Inter-IC Sound)专为数字音频设计,核心是分离时钟、数据、帧同步。标准三线:BCLK(位时钟)、WS(字选择/帧同步)、SD(串行数据)。有些方案加MCLK(主时钟),用于驱动内部PLL生成BCLK。它的协议简单到几乎没有——没有地址、没有起始位、没有停止位,就是按固定格式连续吐PCM数据。

但I2S的坑全在时钟关系上。以44.1kHz采样率、16位立体声为例:

  • BCLK频率 = 采样率 × 每帧位数 × 声道数 = 44100 × 32 × 2 = 2.8224MHz
  • WS频率 = 采样率 = 44.1kHz(WS为高时左声道,低时右声道)
  • MCLK通常是BCLK的整数倍(如128、256倍),用于PLL稳定。若MCLK=11.2896MHz(256×BCLK),则MCLK精度需优于±10ppm,否则音频会出现“咔哒”声——因为PLL失锁导致BCLK抖动。

我调过一款ESP32-WROVER-B接ES8388 Codec的板子,始终有底噪。逻辑分析仪抓BCLK发现周期跳变:正常2.8224MHz对应354ns周期,但实测在352ns~356ns间波动。查证后发现:ESP32的I2S MCLK由APLL提供,而APLL默认使用内部RC振荡器(精度±2%),远低于音频要求。解决方案是:在i2s_driver_install()前,强制启用外部晶振(XTAL)作为APLL参考源,并在SDK配置中开启CONFIG_I2S_USE_APLL,将MCLK精度提升至±20ppm,底噪立刻消失。

3. 协议层解剖:从时序图读懂“它们到底在说什么”

光知道线怎么接不够,得看懂它们在线上“说”的话。时序图是唯一真相,所有协议细节都藏在里面。

3.1 UART:起始位、数据位、校验位、停止位——一个字节的完整旅程

UART传输一个字节,按顺序发送:1位起始位(低电平)、5~9位数据位(LSB先发)、0~1位校验位、1~2位停止位(高电平)。以“8N1”(8数据位、无校验、1停止位)为例,传输字符‘A’(ASCII 0x41 = 0b01000001)的波形是:

起始 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | 停止 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1

注意:D0是LSB(最低位),所以0x41的二进制0b01000001,D0=1, D1=0, D2=0...D7=0。示波器抓UART波形时,触发点设在下降沿(起始位),然后数第10个上升沿(停止位结束),中间8个bit就是数据。如果数据位错一位,整个字节就废了——这就是为什么UART没有重传机制,它假设链路足够可靠。

注意:UART的“无校验”(N)不等于“无错误检测”。在工业现场,我坚持用“8E1”(偶校验):发送端计算8位数据中1的个数,若为奇数则校验位补1凑成偶数;接收端重新计算,若1的个数为奇数则报错。虽然增加1bit开销,但在EMI强的电机控制场景,误码率能从10^-4降到10^-6。

3.2 I2C:START、ADDRESS、ACK、DATA、STOP——一场严谨的握手对话

I2C通信始于START条件(SCL高时SDA由高变低),终于STOP条件(SCL高时SDA由低变高)。中间是地址帧(7位地址+1位R/W)+ ACK + 数据帧 + ACK...。关键细节:

  • 地址帧结构:7位地址左移1位,最低位是R/W位(0=写,1=读)。例如地址0x50,写操作发送0xA0(0b10100000),读操作发送0xA1(0b10100001)。
  • ACK时序:发送方释放SDA后,在SCL第9个时钟周期(ACK时钟)拉低SCL,此时从设备必须在SCL高电平期间将SDA拉低,表示应答。如果SDA保持高电平,则为主设备收到NACK,必须终止传输。
  • 重复START:在不发出STOP的情况下,再次发出START,用于主设备切换从设备或读写切换。例如向EEPROM写数据:START + 0xA0(写地址) + 写地址高位 + 写地址低位 + 写数据... + REPEATED START + 0xA1(读地址) + 读数据。

我调GT911触摸IC时遇到“i2c hid该设备找不到足够资源”错误,逻辑分析仪抓到:主设备发完地址0xBA后,SDA一直为高(NACK),但示波器看SDA电平正常。最后发现是GT911的INT引脚被误接为高电平——该芯片要求INT为低时才响应I2C,否则直接忽略所有通信。这是硬件设计疏忽,但时序图里根本看不出,必须结合芯片手册的“Pin Description”章节交叉验证。

3.3 SPI:SCLK边沿采样,CS电平使能——一场零废话的高效交付

SPI没有START/STOP概念,通信由CS电平控制。CS拉低瞬间,从设备使能;CS拉高瞬间,从设备复位。数据在SCLK的某个边沿(由CPOL/CPHA决定)采样。以CPOL=0, CPHA=0(模式0)为例:

  • SCLK空闲为低电平
  • 主设备在SCLK下降沿(采样边沿)将MOSI数据准备好
  • 从设备在SCLK上升沿(建立边沿)采样MOSI
  • 同时,从设备在SCLK下降沿将MISO数据准备好
  • 主设备在SCLK上升沿采样MISO

这意味着:每个SCLK周期完成1bit数据交换。传输8bit数据需要8个SCLK周期,CS必须全程保持低电平。如果CS在第4个周期拉高,从设备立即停止输出,MISO后续4bit为高阻态(浮空),主设备读到0xFF。

实测MT6701磁编码器SPI通信时,因PCB上CS走线过长(15cm),与SCLK形成耦合,SCLK跳变时在CS线上感应出尖峰,导致CS意外抖动。解决方案不是加磁珠,而是将CS走线改为包地,且长度<5cm,尖峰消失。

3.4 I2S:BCLK计数,WS翻转,SD跟随——一条永不停歇的音频流水线

I2S的精髓在于帧同步(WS)定义左右声道边界,BCLK精确计数每一位。以左对齐(MSB first)格式为例:

  • WS为高电平期间,SD上传输左声道数据(32bit)
  • WS为低电平期间,SD上传输右声道数据(32bit)
  • 每个WS周期内,BCLK必须恰好有32个脉冲(对应32bit数据)

关键陷阱:BCLK必须严格连续,不能中断。如果MCU在传输左声道第16bit时被高优先级中断打断,BCLK停顿,Codec会认为帧已结束,后续数据全错位。因此,I2S驱动必须用DMA+双缓冲:CPU只管填缓冲区,DMA硬件自动搬运数据,BCLK由专用时钟模块连续产生,完全不受CPU影响。

我调RK3399的I2S输出时,音频有断续。逻辑分析仪抓到BCLK在WS翻转瞬间有1~2个周期缺失。查证是Linux ALSA驱动中,snd_soc_dai_set_sysclk()未正确配置I2S时钟源,导致BCLK由APB总线分频产生,而APB在CPU休眠时会门控关闭。解决方案:在设备树中指定clocks = <&cru SCLK_I2S0>, <&cru PCLK_I2S0>,强制使用独立音频时钟域。

4. 实战选型指南:什么场景该用谁?一张表终结所有纠结

选错总线,项目后期改板代价巨大。这里给出基于真实项目经验的决策树,附参数对比表。

4.1 场景决策树:从需求倒推接口选择

  • 需求:连接1个USB转串口模块,调试信息输出,距离<2米
    → 选UART。理由:成本最低(仅需TX/RX/GND),协议栈成熟(几乎所有MCU内置),波特率115200足够。避坑:避免用软件模拟UART(如bit-banging),必须用硬件USART,否则CPU占用率100%。

  • 需求:挂载4个温度传感器、2个EEPROM、1个OLED屏,全部在10cm内
    → 选I2C。理由:线少(仅SDA/SCL),地址可扩展,400kHz速率下1ms内可读完所有传感器。避坑:总线电容必须≤400pF,否则换I2C缓冲器;EEPROM写入需等待(典型10ms),不能连续发地址。

  • 需求:驱动12-bit高速ADC(1MSPS),实时采集振动信号
    → 选SPI。理由:速率高(可配50MHz SCLK),全双工,CS可控,DMA支持完善。避坑:CS必须硬件控制;ADC的EOC(转换结束)信号必须接到MCU外部中断,不能轮询;MOSI/MISO走线需等长(误差<5mm),否则高速下眼图闭合。

  • 需求:输出CD品质音频(44.1kHz/16bit)到DAC芯片
    → 选I2S。理由:专为音频优化,无协议开销,时钟分离抗干扰强。避坑:MCLK必须用高精度晶振(±10ppm);BCLK/WS/SD三线需包地,远离开关电源噪声;DAC的模拟地与数字地必须单点连接。

4.2 四总线核心参数对比表(基于主流MCU实测)

参数UARTI2CSPII2S
最大速率3Mbps(RS-232受限于距离)3.4MHz(Fast-mode Plus)100MHz(MCU限制,非理论极限)24.576MHz(BCLK,对应192kHz/32bit)
典型速率115200bps100kHz(标准模式)/400kHz(快速)10MHz(Flash)/20MHz(ADC)3.072MHz(48kHz/32bit)
线数2~4(TX/RX/RTS/CTS)2(SDA/SCL)+ 上拉电阻4(SCLK/MOSI/MISO/CS)+ 可选3(BCLK/WS/SD)+ 可选MCLK
拓扑结构点对点多主多从总线一主多从星型一主多从(但通常一对一)
地址机制无7位或10位地址无(靠CS物理选择)无(靠硬件连线)
时钟来源双方独立晶振(异步)主设备提供SCL(同步)主设备提供SCLK(同步)主设备提供BCLK/WS(同步)
错误检测校验位(可选)ACK/NACK无(依赖上层协议)无(依赖时钟稳定性)
EMI抗扰性差(单端)中(开漏+上拉,但SDA易受干扰)差(单端,高速时辐射强)中(BCLK/WS/SD分离,但需布线规范)
调试难度低(串口助手直读)中(需逻辑分析仪看ACK)中(需示波器看CPOL/CPHA)高(需音频分析仪测THD+N)
典型应用调试日志、GPS、蓝牙模块传感器、EEPROM、OLED屏ADC、DAC、Flash、WiFi模块音频Codec、DAC、ADC(音频专用)

这张表不是理论值,而是我在STM32F4、ESP32、RK3399、Xilinx Zynq上实测的工程经验值。例如“I2C最大速率”标3.4MHz,是因为Fast-mode Plus规范要求,但实际在4层板上,接3个器件时,400kHz已是最稳妥选择;标“SPI最大速率100MHz”,是指STM32H7的SPI3外设理论能力,但接W25Q128 Flash时,因CS建立时间限制,实测稳定上限为80MHz。

4.3 那些年我们信过的“伪需求”:为什么不该强行统一接口

工程师常陷入一个思维陷阱:“既然都有I2C,为什么还要SPI?” 或 “UART都能传数据,干嘛搞这么复杂?”。这是用软件思维理解硬件。举几个真实反例:

  • “用I2C传音频”:有人试图用I2C传输PCM数据,认为“反正都是串行”。结果:I2C 400kHz速率下,每秒最多传40KB数据(400kbit/s ÷ 8),而44.1kHz/16bit立体声需1.4MB/s,差35倍。更致命的是,I2C有起始/停止/地址/ACK开销,实际吞吐不到理论值的50%。这不是优化能解决的,是物理定律。

  • “用UART驱动OLED”:OLED模块(如SSD1306)有UART接口版本,但那是厂商在模块内部集成了MCU,把UART命令转成SPI/I2C发给屏。你看到的“UART OLED”,本质是UART→MCU→SPI→OLED,多一层延迟和故障点。直接接SPI,速率快10倍,且无额外MCU固件bug风险。

  • “SPI模拟I2C”:用SPI的MOSI/MISO/SCLK模拟I2C的SDA/SCL。理论上可行,但SPI是主从固定,无法实现I2C的多主竞争;且SPI没有开漏输出,无法实现I2C的线与逻辑(多个从设备同时拉低SDA)。这属于用锤子造螺丝刀——能拧,但随时崩刃。

真正的工程智慧,是承认每种接口的边界。就像不会用菜刀修电脑,也不会用I2S传传感器数据。你的设计文档里,应该有一栏明确写着:“此处必须用SPI,因ADC采样率≥1MSPS,I2C无法满足带宽需求”,而不是“暂定用I2C,后续优化”。

5. 调试排坑实录:从示波器到逻辑分析仪,我的四步定位法

再完美的设计,也会在调试时遇到“波形对,功能错”。以下是我在37块板子上总结的标准化排查流程,每一步都有真实案例。

5.1 第一步:示波器看电平与边沿——揪出硬件层硬伤

工具:双通道示波器(带FFT功能更佳)
目标:确认信号是否存在、电平是否合规、边沿是否干净

  • UART:测TX线,看起始位下降沿是否陡峭(<10ns),高电平是否稳定在3.3V±5%。如果高电平只有2.8V,检查上拉电阻是否被其他电路拉低,或MCU IO驱动能力不足(需配置为Push-Pull High Speed)。
  • I2C:测SCL和SDA,看上升沿是否过缓(>300ns)。若过缓,换4.7kΩ上拉;若SCL有高频振铃(>50MHz),在SCL线上串10Ω电阻抑制。
  • SPI:测SCLK和MOSI,看SCLK占空比是否50%±5%。若偏离,检查MCU时钟源是否被分频错误(如APB1预分频器设为2,但代码按1算)。
  • I2S:测BCLK和WS,看BCLK周期是否恒定。若周期跳变,说明MCLK不稳定,需测MCLK引脚频谱——若出现杂散峰,证明晶振附近有开关电源噪声耦合。

真实案例:RK3566板子I2S无声。示波器测BCLK,周期在352ns~356ns跳变。测MCLK引脚,FFT显示在11.2896MHz基频旁,有2MHz和4MHz两个强杂散峰。追踪发现,2MHz是DC-DC的开关频率,4MHz是其二次谐波,且DC-DC电感离MCLK晶振仅3mm。解决方案:在MCLK晶振下方铺完整地平面,并用0402磁珠(100MHz@100Ω)隔离DC-DC电源域。

5.2 第二步:逻辑分析仪抓协议——验证数据内容与时序

工具:Saleae Logic Pro 16或类似(采样率≥100MS/s)
目标:解码协议,看地址、数据、ACK是否符合预期

  • UART:设置波特率,看解码出的ASCII是否为预期字符串。若解码乱码,但示波器波形正常,大概率是波特率配置错(如代码设115200,但逻辑分析仪设9600)。
  • I2C:开启I2C协议解码,看Address列是否为设备真实地址。若显示“Unknown Address”,检查地址是否写错(如0x50写成0x51),或从设备未上电(SDA/SCL全为高)。
  • SPI:开启SPI解码,设置CPOL/CPHA,看Data列是否为预期值。若数据全0xFF,检查MISO是否虚焊,或从设备CS未拉低(逻辑分析仪需同时抓CS线)。
  • I2S:I2S解码较复杂,需手动设置BCLK/WS极性。重点看WS翻转时,SD数据是否从左声道切到右声道。若切换错位,检查WS极性配置(WS高=左声道,还是WS低=左声道)。

真实案例:STM32F103用HAL库SPI读AD7606,逻辑分析仪解码数据全0x00。抓CS线发现:CS在SCLK第一个周期后就拉高了,只传了1bit。查HAL库HAL_SPI_TransmitReceive()源码,发现默认Timeout为1000ms,但AD7606的BUSY引脚在转换完成前为高,HAL函数误判为超时,提前拉高CS。解决方案:改用HAL_SPI_TransmitReceive_IT(),在中断中读取BUSY状态,确保CS全程保持。

5.3 第三步:万用表量通断与电压——排除焊接与供电问题

工具:数字万用表(带二极管档)
目标:确认物理连接可靠,电源无异常

  • 量I2C上拉电阻:红表笔接SDA,黑表笔接VDD,应显示电阻值(如4.7kΩ)。若显示OL,上拉电阻虚焊或未贴片。
  • 量SPI CS线:红表笔接MCU CS引脚,黑表笔接从设备CS引脚,应导通(<1Ω)。若不通,查PCB走线是否断开,或0欧姆电阻虚焊。
  • 量I2S MCLK晶振:黑表笔接地,红表笔轻触晶振任一引脚,应有1~2V直流偏置(晶振起振电压)。若为0V,晶振未起振,检查负载电容(通常12pF)是否贴错。

真实案例:ESP32-WROOM-32接PDM麦克风,I2S无数据。万用表量MCLK引脚对地电压为0V。拆下晶振,量其两端电阻为OL(开路),确认晶振损坏。更换同型号晶振(ABM3B-24.000MHZ-B2-T)后,MCLK恢复24MHz。

5.4 第四步:代码与驱动交叉验证——锁定软件逻辑缺陷

工具:JTAG调试器(J-Link/ST-Link)+ IDE(Keil/VSCode+PlatformIO)
目标:单步执行,看寄存器配置、内存数据、中断标志

  • UART:在USART_ISR寄存器中,看TC(传输完成)和RXNE(接收非空)标志是否置位。若RXNE不置位,检查USART_CR1的RE位是否使能。
  • I2C:在I2C_ISR中,看TXIS(发送寄存器空)、RXNE(接收寄存器非空)、NACKF(NACK标志)状态。若NACKF置位,说明从设备未应答,检查地址或从设备供电。
  • SPI:在SPI_SR中,看TXE(发送缓冲空)、RXNE(接收缓冲非空)、BSY(忙)标志。若BSY一直为1,检查CS是否被其他代码意外拉高。
  • I2S:在I2S_SR中,看RXNE、TXE、OVR(溢出)标志。若OVR频繁置位,说明DMA填充缓冲太慢,需增大缓冲区或提高DMA优先级。

真实案例:Linux下RK3328的I2C驱动读取BME280,i2cdetect -y 1能扫到0x76,但i2cget -y 1 0x76 0x00返回0xFF。用JTAG调试内核,发现i2c_adapter的algo指针为空。查设备树,发现&i2c1节点下漏写了#address-cells和#size-cells属性,导致内核未正确初始化I2C算法。补全后,驱动正常。

6. 进阶思考:当项目需求突破单总线边界时,如何组合使用?

高端项目往往需要多种总线协同。比如一台智能音箱:UART接Wi-Fi模块传指令,I2C读环境传感器,SPI接Flash存固件,I2S连Codec播音频。这时,时序隔离与资源竞争成为新挑战。

6.1 时序隔离:让高速SPI不干扰敏感I2C

SPI的SCLK是高频方波(如50MHz),其谐波可达150MHz以上,极易通过PCB走线耦合到I2C的SDA/SCL(敏感模拟信号)。我的做法是:

  • 物理隔离:SPI走线全程包地,与I2C走线垂直交叉(绝不可平行),间距>20mil。I2C走线长度<10cm,上拉电阻就近放置。
  • 电源隔离:SPI和I2C的VDD分别由LDO独立供电,LDO输入端
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 2:02:19

C# TCP服务端生产实践:工业级高可靠通信实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:02:18

Verilog三种描述方式:门级、RTL级与行为级详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:01:29

YOLOv8模型部署到RK3568:从ONNX到RKNN的完整量化与推理指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:00:45

Turtlebot2导航全解析:SLAM建图、路径规划与参数调优实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:00:30

Jetson Orin NX WiFi断连排查:从驱动超时到持久化修复

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华