逻辑分析仪协议解码:I2C/SPI 总线时序抓取与触发条件设置
逻辑分析仪是嵌入式调试的“第三只手”,但很多工程师把它当示波器用——一按 Start 录一大段,然后在密密麻麻的波形里手动数 SCL 边沿。真正高效的用法是先设好触发条件,让分析仪只抓你关心的那一段,再配合协议解码器自动翻译,几分钟就能定位 I2C 应答丢失或 SPI 时钟极性配错。下面以 Saleae Logic 2(兼容 Kingst LA5016)为例,覆盖 I2C/SPI 最常见的抓取场景。
一、I2C 抓取:触发条件决定效率
I2C 调试最常见的问题是“设备无应答(NACK)”或“总线挂死”。如果用默认的 Rising Edge 触发,录 10 秒可能抓到几百次传输,手动翻到崩溃。
1. 触发 Start Condition + 特定地址
Saleae Logic 2 的 I2C 解码器支持 Trigger on Address。设置步骤:
• 添加 I2C 解码器,分配 SCL/SDA 通道
• 在 Decoder Settings 里勾选 Trigger on address,填入设备地址(7 位,如 0x3C)
• 选择 Read/Write/Both,点击 Apply
此时逻辑分析仪只会在检测到 Start Condition + 匹配地址后才开始采集(或停止,取决于触发模式)。这样抓到的波形必然包含你要的设备通信,不会浪费缓冲区。
2. 触发 NACK 条件
如果怀疑某个从设备偶尔不应答,可以用 Trigger on NACK(Kingst 的 PulseView 也有类似功能)。在 Saleae 中,可以在 I2C 解码器的 Trigger 选项卡中选择 NACK,然后设置为 Stop condition,这样一旦出现 NACK,采集立即停止,方便查看上下文。
# Saleae Logic 2 的 Python SDK 示例:设置 I2C 地址触发
from saleae import Saleae
dev = Saleae()
dev.set_active_channels([0, 1]) # SCL=0, SDA=1
dev.set_sample_rate(24e6) # 24 MS/s 足够 I2C
dev.set_digital_triggers([ # 自定义触发:Start + 地址 0x3C Write
{"type": "i2c", "address": 0x3C, "direction": "write"}
])
dev.capture_seconds(1)
data = dev.get_analyzed_data('I2C', 0, 1)
for packet in data:
print(packet)
3. 总线挂死的抓取
I2C 挂死通常表现为 SCL 或 SDA 被拉低超过 1 ms。可以用 Pulse width trigger:设置 SDA 低电平时间 > 1 ms 触发。在 Saleae 里选择 Digital → Pulse Width → Less than / Greater than,设 SDA 低电平 > 1 ms,这样一旦总线被拉死,立刻捕捉到前后波形,方便分析是谁拉低的。
二、SPI 抓取:时钟极性和片选是关键
SPI 比 I2C 简单,但容易在 CPOL/CPHA 配置上栽跟头——波形看起来对,解码出来全是乱码。
1. 先确认 CPOL/CPHA
抓一段已知数据(如写入 0x55),观察 SCLK 空闲电平(CPOL)和数据在哪个边沿采样(CPHA)。Saleae 的 SPI 解码器有 Preset 下拉菜单,可以直接选 Mode 0~3,如果不确定,先用 Auto Detect 功能(Kingst 也有类似),它会根据实际波形自动推断模式。
2. 触发特定 CS 片选
多 SPI 设备共用总线时,触发条件设为 CS falling edge(片选有效),然后配合 Data pattern 触发第一个字节。例如要抓 FLASH 的 Read ID 命令(0x9F),设置:
• Digital trigger: CS 下降沿
• SPI decoder: Trigger on first byte = 0x9F
这样分析仪只会在 FLASH 被选中且发送 0x9F 时才停下,忽略其他设备的通信。
3. 捕获 CS 毛刺
CS 毛刺(短暂拉低后又拉高)会导致 SPI 传输错位。用 Glitch trigger:设置 CS 低电平时间 < 100 ns 触发。在 Saleae 中选择 Pulse Width → Less than 100 ns,这样任何小于 100 ns 的 CS 低脉冲都会被捕捉,便于检查 CS 信号完整性。
# Saleae Python 设置 SPI 触发:CS 下降沿 + 第一个字节 0x9F
dev.set_digital_triggers([
{"type": "spi", "cs_channel": 2, "first_byte": 0x9F}
])
三、采样率与存储深度取舍
• I2C:标准模式 100 kHz,快速模式 400 kHz,采样率 ≥ 4 MS/s 即可(Nyquist 的 10 倍),一般设 8–12 MS/s。
• SPI:常见 10–50 MHz,采样率至少要 5 倍(50 MHz SPI 用 250 MS/s 以上),否则边沿采样不准。Saleae Logic Pro 16 最高 500 MS/s,够用。
• 存储深度:触发条件设得好,1 M samples 足够抓一次完整传输;不设触发,10 M 也可能不够。
四、实战案例:I2C 从设备 NACK 定位
问题:传感器偶尔返回 NACK,导致系统卡死。
1. 设置触发:I2C 地址 0x76 + NACK stop condition
2. 长时间采集(30 秒),等待触发
3. 抓到一次 NACK 后,查看波形:SCL 在第 9 个时钟后 SDA 仍为高(NACK),往前看发现主机发送的寄存器地址是 0xFF(非法地址),原来是固件在某些条件下写错了寄存器地址。
如果没有触发,要在 30 秒波形里找到那一次 NACK 如同大海捞针。
逻辑分析仪的价值不在于“录得久”,而在于用触发条件精准截取目标事件。I2C 用地址+NACK 触发,SPI 用 CS+首字节触发,配合合适的采样率和解码器预设,大多数总线问题能在 5 分钟内定位。下次调试时,先花 30 秒设好触发,再按 Start。





