ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

深入解析I2C、SPI、UART、I2S四种串行总线的原理与实战

深入解析I2C、SPI、UART、I2S四种串行总线的原理与实战 搞嵌入式的人迟早都得跟 i2c、i2s、spi、uart 这四兄弟打交道。不管你是画板子的硬件工程师写驱动的软件工程师还是做 FPGA 逻辑的人只要板子上有传感器、音频 Codec、Flash、蓝牙模块、串口屏就不可能绕开这四类串行总线。很多刚入行的朋友拿到原理图时第一反应基本一模一样“芯片上这么多引脚SCL、SDA、MISO、MOSI、TX、RX、BCLK、WS……到底有什么区别为什么有的要上拉有的不用选型时到底看什么”这篇文章就把这四种协议摊开来讲清楚每一根线为什么存在、时序长什么样、最适合干什么、以及实际调板子时最常踩的坑。我会从底层原理讲到实际操作不会只给你一张对比表了事。适合正在学单片机、正在调传感器、正在写 Linux 驱动或者正在用 FPGA 接外设的人读读完之后你再看到原理图上的这几种接口标签心里会踏实很多。1. 先把四个名字摆在一起它们分别解决什么问题1.1 四种协议各自的基本定位串行总线本质上就干一件事用尽量少的线把数据从 A 点搬到 B 点。但“少用线”和“传得快”“传得稳”“支持很多设备”之间是有矛盾的。i2c、spi、uart、i2s 就是针对不同场景选出来的四个典型解。uart是最古老、最简单的异步串口。只需要 TX、RX 两根线双方各自按约定的波特率收发不需要时钟线。微控制器、PC 串口调试、蓝牙模块、GPS、串口屏全都在用它。它解决的是“两个设备之间简单可靠地传字节”的问题。i2c是低速设备互连总线。两根线SDA 数据、SCL 时钟但支持一根总线上挂几十个设备每个设备靠地址区分。EEPROM、温湿度传感器、加速度计、触摸控制器、GPIO 扩展芯片全是它的主场。它解决的是“用最少的线连接大量小设备”的问题。spi是高速全双工管道。通常四根线SCLK、MOSI、MISO、CS每个从设备独占一条片选线。速率轻松上几十 MbpsFlash、SD 卡、ADC/DAC、显示屏、FPGA 配置全都偏好 SPI。它解决的是“要高带宽、低延迟且设备数量别太多”的问题。i2s其实是更窄众的协议专门给音频用的。它也是三根线加一个可选的主时钟BCLK 位时钟、WS 声道选择、SD 数据线。I2S 里没有地址、没有应答、没有片选数据是持续流式发送的。Codec、功放、数字麦克风、蓝牙音频都用它传 PCM 音频数据。1.2 为什么不能只看速率选型我见过有人看到 SPI 速率高就想把温湿度传感器也挂上去理由是“反正都能传数据”。这种想法在实践中会撞很多墙。SPI 速率虽高但每加一个设备就要占用一个片选引脚而且很多时候传感器本身出厂就是 I2C 接口。反过来有人想把音频数据用 SPI 从 MCU 发给 Codec发现音频是“必须连续不断地流”而 SPI 是“主设备发起、按 CS 选择、传完就停”中间哪怕是几个微秒的停顿音响里都能听到“啪嗒”一声。选型不能只看峰值速率要看协议形态跟应用是否匹配。I2C 的“总线式连接 地址寻址 应答机制”适合智能外设SPI 的“高速数据管道 无协议负担”适合存储和高吞吐采集I2S 的“连续时钟 声道对齐”天生就是给音频流准备的UART 的“异步、无时钟、点对点”适合调试和不方便拉时钟线的长距离场景。2. I2C两根线下的小设备总线2.1 I2C 通信模型与核心机制I2C 最有意思的地方是它用两根线完成三件事传输数据、传输时钟、设备寻址。SCL 提供时钟SDA 传数据而设备地址、读/写标志、数据、应答位全部在 SDA 上按位串行出现。一次完整的 I2C 传输大概是这样的流程主设备先拉低 SDA 的同时拉低 SCL产生一个“启动条件”然后发送 7 位从机地址加 1 位读写标志这 8 个 bit 会被总线上所有设备接收只有地址匹配的从机在第 9 个时钟周期拉低 SDA发送 ACK 应答之后主设备按字节发送或接收数据每字节后面照样有应答位最后主设备在 SDA 拉高、SCL 拉高的状态下产生“停止条件”结束传输。这个机制决定了三个很重要的特性每个从机必须有在总线上唯一的地址。两个器件默认地址一样时只能通过改引脚电平、加多路复用器、或者换地址可变的批次来解决。主设备能实时知道从机是否正常响应。从机拉低 SDA 是 ACK不从机拉低即 SDA 保持高就是 NACK这是排查硬件问题最好的线索。从机可以“拖慢”主设备。在 I2C 标准里从机如果还没准备好可以把 SCL 拉低让主设备进入等待状态这就是时钟拉伸。很多低功耗传感器在读数据前需要时间准备都会用这招。除了常规的写地址、读地址、顺序读写我还碰到过不少特殊需求。比如“i2c 从机主动更新主机寄存器”这种问题本质上 I2C 是主从模式从机没法主动发起通信但你可以让从机准备好最新数据用一根 GPIO 中断线通知主机“我来读吧”或者让主机定时轮询从机的状态寄存器。这种做法在 PMBus 电源管理、电池电量计、触摸屏上报坐标时非常常见。2.2 I2C 上拉电阻怎么算接线注意什么I2C 的 SDA、SCL 是开漏输出必须外部接上拉电阻到电源。开漏的目的是让多个设备可以安全地“线与”任何一个设备拉低总线就是低谁都不拉低总线靠上拉电阻回到高。没有上拉电阻或者上拉电阻太大上升沿会变得很慢波形变成圆弧状直接导致通信失败。上拉电阻大小的经验公式是这样最小阻值受输出级灌电流能力限制在 VDD3.3V、VOL 取 0.4V、灌电流 3mA 时Rp_min (3.3 - 0.4) / 0.003算出来大约 1kΩ。最大阻值受总线电容和上升时间限制上升时间 tr 与 RC 成正比tr ≈ 0.8473 × Rp × Cbus标准模式要求 tr ≤ 1000ns快速模式要求 tr ≤ 300ns。所以总线电容越大上拉电阻就得越小。常规实践里100pF 到 200pF 的总线配 2.2kΩ 到 4.7kΩ 上拉电阻基本都能跑 400kHz如果线上挂了很多设备、拉线很长降到 1kΩ 到 2.2kΩ 更稳但功耗也会跟着上去。接线时还要注意几点上拉电阻要接到 I2C 所对应的电源轨不是随便接一个 VCC。如果 I2C 总线上混了 5V 和 3.3V 器件一定确认器件引脚是否支持 5V 耐受否则要么用电平转换芯片要么保持整个总线 3.3V。我踩过一次明显的坑一块板子上 I2C 总线电容太大40cm 的飞线接了三个传感器用 4.7k 上拉在标准模式 100kHz 下频繁出错后来把电阻换成 2.2k、并把速率降到 100kHz才稳定下来。2.3 实际中的常见形态EEPROM、传感器、扩展器、触摸屏I2C 最常见的应用就是读写 EEPROM比如 24C02、24C64容量小的 EEPROM 地址通常是 A0-A2 引脚决定总线地址可能是 0x50 到 0x57。这类芯片也催生了很多“i2c 读写 eeprom 代码 verilog”之类的需求FPGA 上自己写 I2C 主机控制器时重点要处理好启动/停止条件、ACK 采样和页写时的延时。传感器方面加速度计、磁力计、温湿度计几乎都有 I2C 接口。我第一次调 GT911 触摸屏时就遇上了“gt911 i2c 通信失败”的典型问题原理图上 I2C 没问题上拉也没问题最后发现是芯片的复位引脚一直被拉高没释放导致内部状态不正常。新板子调 I2C 设备失败时第一反应应该是量供电、查复位引脚、确认中断引脚有没有被人为拉死然后才是拿逻辑分析仪看波形。I2C 扩展器也是高频率器件TCA9535、PCA9535 这类芯片能把两个 I2C 地址扩展成 16 路 GPIO省下 MCU 引脚。对于“i2c 控制的多路复用”比如接多个地址相同的传感器可以用 TCA9548A 这类 I2C 多路开关先选通某一路再访问对应子总线上的设备。这里不小心容易出错的是多路开关自身的地址要跟后端设备区分开而且切换通道后要重新枚举设备不然驱动里缓存了错误的总线拓扑。3. SPI一路高速率、各说各话的总线3.1 SPI 的底层通信模型SPI 的典型拓扑是“一主多从”四根线各司其职SCLK 由主设备输出时钟MOSI 是主出从入主机发数据给从机MISO 是从出主入从机回数据给主机CS 片选信号选择当前要通信的从机通常低电平有效。SPI 的数据交换本质是一个移位寄存器环。主设备把要发送的数据装进自己的移位寄存器每个时钟边沿主设备从 MOSI 移出一位同时从 MISO 移入一位。所以 SPI 永远是“发的同时在收”这叫全双工而不是“一问一答”。这意味着很多时候你读一个寄存器主设备必须先通过在 MOSI 上写一个读命令和寄存器地址把从机要回的数据“顶”回来。数据是否有效取决于通信双方在哪条边沿发送、哪条边沿采样这也就是 SPI 模式参数的由来。与 I2C 不同SPI 没有 ACK、没有地址仲裁。主设备只要把 CS 拉低就可以跟指定从机开始通信。这个特点让它非常适合纯数据搬运比如 FPGA 通过 SPI 读写 ADC 的采样结果、MCU 把固件写到 SPI NOR Flash、显示屏控制器接收像素数据。但缺点是没有应答机制从机没收到或者收到错的命令主设备可能完全不知道。3.2 CPOL、CPHA 四种模式与常见匹配错误SPI 的时序由 CPOL时钟极性和 CPHA时钟相位两个参数决定组合成模式 0 到模式 3。CPOL 决定空闲时 SCLK 是高还是低CPOL0 时空闲低CPOL1 时空闲高。CPHA 决定数据采样边沿CPHA0 时在第一个时钟边沿采样CPHA1 时在第二个时钟边沿采样。模式CPOLCPHA空闲电平采样边沿常见外设Mode 000低上升沿多数 Flash、SD 卡、显示屏Mode 101低下降沿部分 ADCMode 210高下降沿部分 EEPROMMode 311高上升沿常见 QSPI、部分传感器大多数器件手册会直接告诉你支持的模式或者用图画出什么时候采样。如果你拿示波器看到数据波形每个字节里都有毛刺、读到的数据是 0xFF 或者整体错一位第一反应就是检查主设备和从设备的 SPI 模式是否一致。有一种偷懒办法先试 Mode 0不行再试 Mode 3这两个是绝大多数外设默认支持的模式。在 Linux 下设备树里经常看到spi-max-frequency和spi-cpha、spi-cpol这些属性。比如 RK3588 的 SPI 接口在设备树中给某个从设备配置了错误模式时报错并不明显很多时候表现为读寄存器超时、CRC 校验失败。折腾半天不如直接用逻辑分析仪抓波形一眼就能看出采样边沿是否跟数据变化边沿错位了。3.3 硬件片选与软件片选CS 宽度、DMA 与常见应用SPI 的片选有两种实现方式。硬件片选是指 MCU 的 SPI 外设自己控制 CS 引脚在传输开始时自动拉低结束时自动拉高时序精准方便配 DMA。软件片选则是用普通 GPIO 手动模拟 CS好处是引脚分配灵活、可以同时连接大量设备坏处是 CS 拉低的时机和第一个时钟边沿之间可能有延迟需要精心处理。有一个经常被问到的问题“CS 最小能做到多少 us”片选拉低后通常需要一段t_cs_setup时间让从机准备好接收拉高后也需要一段t_cs_hold时间保证最后一个字节可靠写入这个时间因外设而异一般在几十纳秒到几微秒不等。用硬件 SPI 时片选由外设自动控制用软件 GPIO 模拟时至少要保证 CS 拉低后延迟几个微秒再发起时钟否则有些苛刻的从机根本不睬你。高速 SPI 时我会优先使用硬件 CS不是因为它快而是因为它不会引入软件调度抖动。SPI 配合 DMA 的收益非常大。STM32 上配置 SPI DMA 传输比如 SPI 读 Flash 的一大段数据CPU 只需要发起传输剩下的数据搬运由 DMA 完成。这里要注意一个细节SPI 接收 DMA 必须在时钟开始前就准备好缓冲区因为 SPI 是全双工你发命令字节的时候同一时刻 MISO 上的数据已经在往里涌了。处理阶段式读操作时常见做法是先发送读命令和地址再用 DMA 接收后续的有效数据中间千万不要关闭 SPI 时钟否则时序会断。SPI 的应用场景多到你列不完。比如 FPGA 做 SPI ADC 采集高速 ADC 通过 SPI 输出采样值FPGA 侧要严格按 SCLK 边沿采数据不能漏位。RK3588 这类 SoC 会把 SPI NOR Flash 当成引导介质用来替代 eMMC 承担系统引导同时把 NVMe SSD 留作系统和数据盘这种混合存储方案的踩坑点往往在 SPI Flash 的时序余量上PCB 上走线太长就会导致引导偶尔失败。另一个常见场景是用 USB 转 SPI 工具调试比如用 FT232H 在 Python 里模拟 SPI 主机from pyftdi.spi import SpiController ctrl SpiController() ctrl.configure(ftdi://ftdi:232h/1, frequency10e6) slave ctrl.get_port(cs0, mode0) slave.write(b\x9F) # 发送读 ID 命令 flash_id slave.read(4) print(flash_id)这类工具调试新芯片时特别顺手不需要先写 MCU 代码就能确认从机的基本读写时序。4. UART最老派的异步通用协议4.1 帧格式、波特率与电平标准UART 是纯异步协议收发双方没有时钟线依靠约定好的波特率和帧格式来同步。典型的 8N1 帧是1 位起始位低电平、8 位数据位LSB 在前、1 位停止位高电平可选校验位。空闲时 TX 线保持高电平起始位的下降沿告诉接收方“开始采数据了”接收方按波特率产生本地采样时钟在每个数据位中间采样。波形看起来是这样的发送 0x55二进制 01010101时帧就是“低、0、1、0、1、0、1、0、1、高”高低电平规则地交替。0x55、0xAA 这类交替型数据是调试 UART 时最常用的测试数据因为能在示波器上方便地验证波特率是否准确。波特率误差是异步通信的命门。如果两个设备的时钟源偏差太大一帧 10 位下来接收端采样点会逐渐偏移最后在停止位上采错表现为乱码。MCU 内部晶振误差一般要求控制在 ±2% 以内使用内部 RC 振荡器时尤其要注意温度漂移。串口乱码时我会用逻辑分析仪抓一个字节测量起始位下降沿到停止位之间的实际时间反推实际波特率很快就能定位是配置错还是晶振偏。电平标准也要分清。TTL 电平的 UART 是 3.3V/5V 电平而 RS-232 是 ±12V 左右RS-485 是差分信号。MCU 上的串口通常是 TTL 电平跟 PC 连接时必须经过 USB-TTL 转换或者 RS-232 电平转换直接连轻则读不到数据重则烧 IO。USB 转串口芯片出镜率最高的就是 FT232R、FT231X、CH340、CP2102 这批。FT232R 这类老芯片需要装驱动Windows 上如果报“该设备找不到足够资源可以使用代码 12”一般是 USB 控制器资源冲突或者驱动陈旧卸载设备、清除残留驱动再重新安装往往能解决。4.2 流控、16550 与 DMA 收发UART 除了 TX、RX还有一对硬件流控线 RTS、CTS。RTS/CTS 的作用是让接收方有能力“叫停”发送方接收方缓冲区快满时拉高 RTS发送方看到 CTS 无效就停下。嵌入式里大多数调试场景不需要流控但如果接蓝牙模块或旧式 Modem流控用不用、极性对不对会影响对方是否给你回包。软件层面很多 MCU 和 SoC 的 UART 都兼容 16550 行业标准寄存器布局包括发送保持寄存器、接收缓冲寄存器、中断使能、FIFO 控制等。16550 这个名字听起来古老但它定义了现代串口驱动的基本行为Linux 下看8250驱动就能找到它的影子。STM32 之类 MCU 的串口也有类似划分HAL 库或者标准外设库里用 DMA 空闲中断做不定长接收是常用套路。思路是开启 USART 接收 DMA同时开启空闲检测DMA 把数据连续搬到内存空闲中断里根据 DMA 当前计数算出本次收到的长度。这种方案比逐字节中断更高效适合接收不定长命令帧。4.3 UART 波形怎么看调 UART 时逻辑分析仪比示波器还好用。接上 TX 和 GND设置好波特率直接解码。我自己的检查顺序是看空闲电平正常空闲是高电平如果一直是低说明 TX 对地短路或者被对方拉死了。看起始位正常每一帧都从低电平开始如果看不到低脉冲可能接到了 RX 而不是 TX。数一帧的长度8N1 下一帧应该是 10 位时隙长度和波特率必须吻合。查停止位如果每帧尾巴高电平持续不到 1 个位时隙多半是波特率不匹配。5. I2S为音频而生的串行协议5.1 I2S 的时序模型与引脚分工I2S 跟前面三种协议最大的区别在于它根本不是为了“传命令”而设计的它是在持续不断地搬运 PCM 音频采样点。标准的 I2S 有三个关键信号BCLK 位时钟每个 bit 一个脉冲WS 声道选择低电平通常是左声道、高电平是右声道SD 串行数据按位输出 PCM 数据。很多 Codec 还要求一个 MCLK 主时钟频率一般是采样率的 256 倍或 512 倍比如 48kHz 采样率下 MCLK 常用 12.288MHz。数据的排列规则是每个采样点从 MSB 开始发送先左声道后右声道标准 I2S 协议里 WS 翻转要提前于最高位一个 BCLK。你可以把 WS 当一条特殊的“片选”它不像 SPI 那样只在通信期间有效而是持续翻转因为音频流不能停。所以 I2S 主设备要连续输出 BCLK 和 WS哪怕没有音频数据也要送零数据保证 Codec 时钟不断。逻辑分析仪上看 I2S 波形会看到一串非常规律的 BCLK 脉冲WS 以采样率频率翻转SD 上跟着变电平。如果音频有严重的噪声或杂音先看 BCLK 有没有抖动再看 WS 翻转频率对不对。用 I2S 时主从角色一定要明确I2S 主设备输出 BCLK、WS接收方作为从机。如果两个设备都配成主模式时钟会直接打架表现为一边声音断续一边爆音。5.2 I2S 的格式变种标准 I2S、左对齐、右对齐、TDMI2S 被称为“标准”其实是历史巧合实际工程里常见的还有左对齐和右对齐两种变体。区别主要是 WS 边沿和数据的对齐关系标准 I2S 中 WS 边沿变化后延迟一个 BCLK 才开始发送 MSB左对齐则是 WS 变化的同时 MSB 就出现右对齐是 MSB 和 WS 的边沿对齐在最后一位而不是第一位。在配置 MCU 的 I2S 外设时这些分别对应不同的std或alignment选项。除了对齐方式位宽也要匹配。如果 MCU 按 16bit 发送Codec 配置成 24bit 接收会出现在数据后面补零或者数据整体偏移的问题。PCM 数据位宽选 16bit 是兼容性最好的24bit 通常用于对信噪比要求高的音频系统。多个声道同时传输时要上 TDM 模式一帧里容纳 4、8、16 个声道WS 不再只是左右声道区分而是一个“帧同步”标志这种模式常用于多麦克风阵列或 DSP 级联。5.3 ESP32-C3、STM32 等平台上的 I2S 实操要点ESP32 系列的 I2S 是音频项目的常用接口但 ESP32-C3 跟原版 ESP32 不一样它只有一个 I2S 控制器而且没有数模转换器想直接输出模拟音频必须外接 Codec。ESP-IDF v5 之后I2S 驱动改成了i2s_std这种面向标准 I2S 风格的 API配置流程大概是初始化通道、配置标准模式、使能通道i2s_chan_config_t chan_cfg { .id I2S_NUM_0, .role I2S_ROLE_MASTER, .dma_desc_num 4, .dma_frame_num 240, .auto_clear true, }; i2s_new_channel(chan_cfg, tx_chan, NULL); i2s_std_config_t std_cfg { .clk_cfg I2S_STD_CLK_DEFAULT_CONFIG(48000), .slot_cfg I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), .gpio_cfg { .mclk GPIO_NUM_3, .bclk GPIO_NUM_4, .ws GPIO_NUM_5, .dout GPIO_NUM_6, .din I2S_GPIO_UNUSED, }, }; i2s_channel_init_std_mode(tx_chan, std_cfg); i2s_channel_enable(tx_chan);STM32 平台的 I2S 经常跟 SAI 混在一起。F4 系列上 I2S 可以从 SPI 外设复用出来配置时除了位宽、标准还要小心主时钟输出频率。这里我要提醒一件事I2S 和 SPI 共用同一套引脚和外设模块时如果之前跑过 SPI 的 DMA没有完全复位 DMA 请求切换到 I2S 后可能出现 DMA 错误中断。调试音频时建议先不要接 Codec直接用逻辑分析仪抓主设备的 BCLK、WS确认识别到的采样率和声道选择都对再接音频链路。6. 交叉对比表与选型思路6.1 一张表总结四者的关键维度我平时做选型会把四类总线按几个维度列成一张表然后对着应用场景看。维度I2CSPIUARTI2S引脚数SDA SCLSCLK MOSI MISO CSTX RXBCLK WS SDMCLK时钟线有有无有是否异步同步同步异步同步传输方向半双工全双工全双工单向流为主也可双向分时寻址方式从机地址片选点对点无应答机制ACK/NACK无无无典型速率100k/400k/1M/3.4M几十Mbps 以上9600 到数Mbps典型 BCLK 1.5M-6.4M 48k 16/24bit典型设备传感器、EEPROM、扩展器Flash、SD 卡、ADC、屏调试口、模组、GPSCodec、数字麦、功放优点省引脚、多设备、带应答快、简单、无协议开销简单、远距离、跨平台专门为连续流设计缺点速率低、上拉麻烦、无大吞吐设备多时占引脚、无应答需要波特率一致、无寻址只适合音频需持续时钟6.2 选型时真正要想清楚的事选总线时我一般会按这个顺序问自己数据是命令/寄存器还是一整块数据流寄存器读写用 I2C 或 SPI音频流用 I2S调试输出用 UART。从设备数量有多少数量多、速率要求不高的尽量 I2C靠地址区分数量少、速率要高的用 SPI每设备加一根 CS。要不要应答反馈要靠谱地知道数据是否被接收I2C 的 ACK 机制有优势SPI 只能靠从机返回的数据自己判断。距离多远能不能拉时钟线远距离选 UART 或 RS-485短板上芯片放在同一 PCB 上才用同步协议。功耗有没有要求I2C 开漏结构待机功耗容易做低很多传感器只在需要时拉低总线。有些场景我会故意混着用。比如一块 RK3588 主板上引导用 SPI NOR Flash系统盘用 NVMe SSD音频走 I2S 接 Codec传感器走 I2C调试串口走 UART这几种总线出现在同一块板上非常正常。关键是想清楚每条总线的定位而不是用神器一把梭。6.3 组合使用方案的实际案例举一个典型的穿戴设备主板例子主控 MCU 通过 I2C 挂加速度计、陀螺仪、屏的触摸控制器通过 SPI 挂一块大容量 Flash 用来存音频文件通过 I2S 把音频数据发给 Codec 播放通过 UART 接蓝牙模块做数据透传调试口再留一路 UART。这个系统里I2C 负责“慢速但繁多”的设备管理SPI 负责“高速大块”的数据存取I2S 负责“不允许断流”的音频UART 负责“点对点”的通信每个协议都恰好在它擅长的位置。如果你上一个系统经验不足最容易犯的错误是为了省一个引脚把本来可以走 I2C 的传感器硬塞到 SPI 总线上结果 SPI 总线被低速传感器占了大量时间Flash 的吞吐反而上不去。总线的选择不是“哪个好”而是“哪个合适”。7. 排查与波形验证别让信号跟你玩躲猫猫7.1 逻辑分析仪和示波器的接法调这四类总线逻辑分析仪是你最好的朋友。USB 逻辑分析仪现在很便宜几十块钱就能买到 8 通道、100M 采样率左右的型号足够看 I2C、SPI、UART、I2S。接线时注意共地逻辑分析仪的 GND 必须和被测板子共地否则解码全是乱码。采样率设置上我一般把采样率设为信号时钟的 10 到 20 倍不能太低。I2C 400kHz 总线用 4M 以上采样率已经能看清边沿SPI 10MHz 时钟最好用 50M 以上采样率UART 115200 波特率用 2M 采样率绰绰有余I2S BCLK 几 MHz 的话采样率 25M 也够了。采样率太高时文件会很大不必盲目拉满。接线的位置也有讲究。抓波形时要从主设备引脚上直接接最好避免从连接线很长的末端去量那样只会抓到反射和谐波。量 I2C 时同时接 SDA、SCL捕获一次失败的通信重点看应答位有没有被拉低量 SPI 时接 SCLK、MOSI、MISO、CS 四条线一起看才能看出片选边沿和时钟的先后关系量 UART 只要一根 TX 线就行量 I2S 则建议 BCLK、WS、SD 三条线一起接最好把时钟通道名字标清楚再保存。7.2 常见问题与定位步骤速查表现象可能原因优先排查步骤I2C 一直 NACK地址错误、器件供电或复位异常用i2cdetect -y 0扫描可用地址确认芯片供电和复位脚I2C 波形边沿很缓上拉电阻偏大、总线电容大换小上拉电阻降低速率缩短走线SPI 数据错位或者全 FF模式不匹配CS 控制时序不对抓波形看采样边沿与数据变化边沿试 Mode 0/3SPI 最后一个字节丢DMA 收尾未处理CS 拉高太快检查 DMA 完成中断和 SPI 停止时机必要时加大 CS 高电平间隔UART 乱码波特率不匹配、晶振偏差逻辑分析仪测一帧长度反推实际波特率I2S 爆音/失声主从矛盾BCLK 断了位宽不匹配抓 BCLK、WS确保持续输出且采样率正确UART USB 转串口代码 12驱动异常或 USB 资源冲突设备管理器卸载设备清理残留驱动重启后再装触摸屏 I2C 失败复位脚未释放、地址线拉死确认复位脚高电平量 INT 脚是否被外部下拉一个我比较推荐的排查原则先看波形再改代码。很多时候我们盯着代码消耗一两个小时最后发现是某根线没焊上。逻辑分析仪抓一次波形所有电气层面的问题一目了然。看到波形完全正常但软件还是报错再把精力放到驱动和状态机上。8. 我的几点实操习惯这几条习惯是这几年折腾各种板子攒下来的。第一新板子拿回来第一件事不是跑业务代码而是先点灯、通串口、抓一次 UART 日志确保最小系统活着。第二I2C 出现问题永远先量 SDA/SCL 的空闲电平空闲必须被拉到高电平这一点能排除一大半问题。第三SPI 设备如果读写不稳定我会先在低速下调试比如 1MHz 时钟等程序逻辑全对再往上调速率这样能区分“逻辑错”和“时序差不稳”。第四音频项目里 I2S 的时钟不要选得太紧主时钟余量留 10% 到 20%对布局走线不理想的板子特别有用。还有一个很小的技巧板上排针标签建议直接写协议名加引脚功能比如“SPI0_CS0”“UART2_TX”“I2S_BCLK”不要只写“IO15”“IO16”。真到了用示波器测量的时候一个清晰的丝印能为你省掉大量对照原理图的时间。这些协议互相之间没有高低之分把它们的脾气摸透了做项目时就能少一点玄学多一点确定性。
返回列表