2. 逻辑分析仪实战:用 Saleae Logic 抓 I2C/SPI/UART 时序

逻辑分析仪这东西,说白了就是嵌入式工程师的「示波器」——但它不关心电压多高,只关心电平是 0 还是 1。我最早用逻辑分析仪是在一个电机驱动项目里,I2C 总线老是丢数据,示波器看波形累得半死,换了 Saleae 之后,十分钟就定位到是时钟毛刺问题。嗯,从那以后,我的工具包里就再也没缺过它。

2.1 为什么是 Saleae Logic?

市面上逻辑分析仪很多,但 Saleae 系列(特别是 Logic 8 / Logic Pro 16)在嵌入式调试圈子里几乎是标配。原因很简单:

  • 软件体验好:跨平台,界面清爽,协议解析插件丰富
  • 采样深度够用:24MHz 采样率,对于 I2C(400kHz)、SPI(几十 MHz)、UART(115200bps)绰绰有余
  • 触发灵活:支持边沿、电平、协议帧触发,抓异常波形很方便
我的习惯:调试 I2C 时采样率设 4MHz 就够了,SPI 看速率设 16-24MHz。采样率不是越高越好——太高了数据量大,软件卡顿,反而影响效率。

2.2 连接与基础设置

连接其实很简单。Saleae 的探头是杜邦线,直接夹到目标板子的信号线上就行。但有几个坑,我踩过不止一次:

  1. 共地必须接:逻辑分析仪的 GND 不接,波形全是乱的。我见过有人折腾半小时,最后发现地线没夹紧。
  2. 信号线别太长:超过 20cm 的杜邦线在 SPI 高速模式下会引入振铃,波形看起来像有毛刺,其实是反射。
  3. 通道顺序记清楚:我习惯把 SCL 接 CH0,SDA 接 CH1,这样解析时不用来回对线。
总线类型 信号线 推荐通道 采样率建议
I2C SCL, SDA CH0=SCL, CH1=SDA 4MHz
SPI SCLK, MOSI, MISO, CS CH0-3 按顺序 16-24MHz
UART TX, RX CH0=TX, CH1=RX 2MHz(115200bps)

2.3 I2C 时序抓取与异常分析

I2C 的时序其实很规矩:起始条件、从机地址、读写位、应答、数据、停止条件。但实际项目中,异常往往出在「不规矩」的地方。

2.3.1 正常波形长什么样?

抓一个正常的 I2C 写操作,你会看到:

  • SCL 空闲时高电平
  • SDA 在 SCL 低电平时变化,高电平时采样
  • 起始条件:SCL 高电平时 SDA 从高拉低
  • 停止条件:SCL 高电平时 SDA 从低拉高
关键检查点:每个字节的第 9 个 SCL 时钟周期,SDA 上必须有一个低电平的 ACK。如果看到高电平(NACK),说明从机没响应——要么地址错了,要么从机忙。

2.3.2 我遇到过的 I2C 异常波形

案例 1:时钟拉伸导致超时

有一次调试温湿度传感器,读数据时偶尔卡死。用 Saleae 抓波形发现,从机在 ACK 之后把 SCL 拉低了 2ms——这是时钟拉伸。但主控的 I2C 超时设的是 1ms,直接报错了。

案例 2:总线竞争

两个主设备同时发数据,SDA 上出现「中间电平」——既不是 0 也不是 1。逻辑分析仪上看到的是毛刺。解决办法:加总线仲裁或改用多主模式。

注意:I2C 是开漏总线,正常波形应该是干净的高低电平。如果看到「爬坡」或「圆角」,说明上拉电阻太大或总线电容过高。我一般用 4.7kΩ 上拉,超过 20cm 走线时换 2.2kΩ。

2.4 SPI 时序抓取与异常分析

SPI 比 I2C 快,但信号完整性要求更高。我见过太多人 SPI 调不通,最后发现是相位极性配错了。

2.4.1 SPI 的四种模式

模式 CPOL CPHA 数据采样边沿
模式 0 0 0 上升沿采样
模式 1 0 1 下降沿采样
模式 2 1 0 上升沿采样
模式 3 1 1 下降沿采样

抓波形时,先看 SCLK 空闲电平(CPOL),再看数据在哪个边沿变化(CPHA)。我习惯用 Saleae 的 SPI 解析器自动识别,但也会手动对一下第一个字节——确保解析器没选错模式。

2.4.2 常见 SPI 异常

  • CS 毛刺:片选信号在传输过程中抖动,导致从机复位。解决办法:CS 加 10kΩ 上拉,软件里加去抖延时。
  • MISO 无数据:从机没拉低 CS 或没使能输出。用逻辑分析仪看 CS 拉低后 MISO 是否从高阻变推挽。
  • 数据错位:主从机的 MSB/LSB 顺序不一致。抓一个已知数据(如 0x55 或 0xAA)对比一下。
调试技巧:SPI 调试时,先发一个固定字节(比如 0x55,二进制 01010101),看波形是不是交替高低电平。如果是,说明时序基本对了;如果不是,先查模式配置。

2.5 UART 时序抓取与异常分析

UART 看起来简单——就 TX 和 RX 两根线。但波特率不对、极性反了、停止位少了,都会导致乱码。

2.5.1 用逻辑分析仪测波特率

抓一个 UART 波形,测量最短脉冲的宽度(就是 1 个 bit 的时间),然后算波特率:

波特率 = 1 / 最短脉冲宽度

例如:最短脉冲宽度 = 8.68μs
波特率 = 1 / 0.00000868 ≈ 115200 bps

我习惯在 Saleae 里直接加 UART 解析器,设好波特率,看解析出来的数据对不对。如果全是乱码,先检查波特率偏差——±2% 以内通常没问题,超过 5% 必乱。

2.5.2 我踩过的 UART 坑

坑 1:电平反了

有一次用 3.3V 的 STM32 和 5V 的 GPS 模块通信,RX 波形看起来正常,但数据全是 0xFF。后来发现 GPS 模块是 RS-232 电平(负逻辑),需要加电平转换芯片。

坑 2:波特率漂移

某个项目用内部 RC 振荡器做 UART,低温下波特率偏了 8%,通信时好时坏。用逻辑分析仪抓波形,发现每个字节的停止位宽度明显不对。解决办法:换外部晶振或做波特率自适应。

注意:UART 的起始位是低电平,停止位是高电平。如果看到 TX 线上一直低电平,可能是 TX 和 RX 接反了,或者对端在发 break 信号。

2.6 异常波形实战案例

下面这个案例来自我去年做的一个智能家居项目。主控通过 I2C 读取光照传感器,偶尔读到 0x00。用 Saleae 抓了 10 分钟波形,发现规律:

  1. 正常读操作:起始 → 地址+写 → ACK → 寄存器地址 → ACK → 重复起始 → 地址+读 → ACK → 数据 → NACK → 停止
  2. 异常读操作:起始 → 地址+写 → ACK → 寄存器地址 → 没有重复起始 → 直接发地址+读 → 从机不响应 → 超时

问题出在主控的 I2C 驱动库——在某种中断抢占场景下,重复起始条件没发出来。修复后,再也没出现过 0x00。

经验总结:异常波形往往不是随机出现的,而是特定条件触发的。用逻辑分析仪的「触发」功能,设好条件(比如 SDA 上出现 NACK),然后长时间抓取,很容易复现问题。

2.7 本章知识结构

下面这张图总结了逻辑分析仪调试三种总线的核心流程和常见异常点:

逻辑分析仪调试总线流程 逻辑分析仪调试总线流程 Saleae Logic 连接 I2C:SCL + SDA SPI:4 线全双工 UART:TX + RX I2C 关键检查 • 起始/停止条件是否完整 • 第 9 个时钟是否有 ACK • 时钟拉伸是否超时 SPI 关键检查 • CPOL/CPHA 模式匹配 • CS 片选有无毛刺 • MISO 是否高阻 UART 关键检查 • 波特率偏差 < 2% • 起始位/停止位正确 • 电平逻辑是否匹配 异常波形定位:触发 → 抓取 → 对比 → 修复 核心原则:先看时序完整性,再看协议正确性 异常往往藏在「看起来正常」的波形细节里

2.8 小结

逻辑分析仪是嵌入式调试的「眼睛」。用好它,你就能看到总线上到底在发生什么——而不是靠猜。我个人建议,每个嵌入式工程师都应该花半天时间,拿 Saleae 把自己手头项目的 I2C、SPI、UART 波形都抓一遍,看看「正常」长什么样。这样以后出问题时,你一眼就能看出哪里不对劲。

最后说一句:工具是死的,思路是活的。别光会点「开始抓取」,要学会设触发条件、用协议解析器、对比异常波形。这些技能练熟了,调试效率至少翻一倍。