I2C-Lab — I2C 总线监控调试台
更新:2026-10-02。由 RP2040 probe 固件(
firmware/,pico-sdk C,刷入 BPI-Pico-RP2040)+ PC 端 GUI(src// 打包版release/I2C-Lab.exe)组成。 在任意 I2C 总线上纯被动实时监听:事务流解码 + 逻辑分析仪式波形快照。 前身 I2C-Inject(LT8619C 寄存器择机注入)保留在仓库备查;本工具是其 "完整 I2C 调试台"路线的第一阶段(监控),主机读写与从机模拟见 §7 路线。
1. 它能做什么
| 能力 | 说明 |
|---|---|
| 实时事务流 | START→STOP 完整解码: 7bit 地址/RW/每字节 ACK/NAK/数据/收尾方式(含 repeated-START 标记) |
| 地址过滤 | 只看关心的地址(十六进制空格分隔), 其余只计数不入表 |
| 波形快照 | 一次抓取最近 256~16384 个 SDA/SCL 边沿, 逻辑分析仪视图: 滚轮缩放(光标锚点)/拖动平移/双击适配/START-STOP 刻线/事务标签 |
| CSV 导出 | 全量事务(≤2 万条滚动池)导出, Excel 直接打开 |
| 固件计数 | 边沿数/事务数/环形覆盖丢包/疑似丢沿, 判断总线活动与负载 |
| 演示模式 | 无硬件看界面: 模拟 LT8619C demo 板 ~500ms 轮询流量 |
被动性保证: probe 两脚为纯输入(PIO 只读电平), 不加上拉、不驱动、 不改总线时序——挂在运行中的 demo 板上零干扰(与 I2C-Inject 同一接线规矩)。
2. 硬件准备
| BPI-Pico-RP2040 | 目标总线 |
|---|---|
| GP8(物理脚 11) | SDA |
| GP9(物理脚 12) | SCL |
| GND | GND |
- 不接 VCC、不外加上下拉(总线由目标板自带上拉)
- 独立台架总线(无主)另说: 需 4.7kΩ 上拉×2 到 3.3V 才有静态高电平
- 固件把系统时钟超到 250MHz(vreg 1.15V), 100/400kHz 总线余量充足; 官方 USB 枚举不受影响
3. 刷固件(一次性)
- 按住 BOOTSEL 上电, 出现
RPI-RP2U 盘 - 把
release/firmware/i2c_lab.uf2拖进去, 板子自动重启 - 设备管理器出现
USB 串行设备(VID 2E8A)即就绪; LED 上电快闪 3 次后, 常亮 = 监控流开启
重新构建固件见 firmware/ 源码与 §6。
4. GUI 使用
双击 I2C-Lab.exe(或 python src/main.py; --demo 进演示模式):
- 固件串口卡: 选带
[RP2040]标记的端口 → 连接(日志出现版本横幅) - 监控卡: 「开始监控」→ 事务表开始滚动; 「暂停滚动」冻结表格方便读
- 地址过滤: 如
32 50(十六进制); 空格分隔多个; 留空看全部 - 波形卡: 设边沿数(默认 2048) → 「抓取波形」→ SCL/SDA 双线时序图; 滚轮缩放, 拖动平移, 双击适配全宽; 绿/红虚线 = START/STOP
- 导出CSV: 保存当前全量事务池(不只表内可见行)
- 主题: 跟随系统/浅色/深色(DLPilot/SerialMate 同款三件套)
表格列: # | t0(us) | 时长us | 地址 | RW | ACK | 数据 | 收尾。
地址 NAK 红色、截断/半字节断橙色、超 16 字节数据显示省略号(悬停看全量)。
5. 固件串口命令(可直接用串口终端调)
命令行一行一回, = 正常 / ! 告警(全仓约定):
? 帮助
v 版本/时钟/角色
mon start 开 T 行事务流(监控中)
mon stop 停流
stats 计数: edges/trans/trans_drop/susp/ring_ovf/最近边沿距今
wave [n] 倒出最近 n(默认1024, 上限16384)个边沿: W 行 + 'W.' 收尾
boot 重进 BOOTSEL(免按按键)
T 行语法(与 PC 端 i2cdec.py 互为权威, 自测往返覆盖):
T <t0_us> <dur_us> <addr7:02X> <R|W> <flags> <acks> <n> <b1..bn>
flags: '-' stop | 'r' repeated-START 收尾 | 'c' 流截断 | 'p' 半字节断
可追加 'L' = 长事务截断(>56 字节只保留前段)
acks : n+1 个 'A'/'N', 首个是地址应答
W <t_us> <pins> pins bit0=SDA bit1=SCL
6. 重新构建固件
依赖(本机已装齐, 新机器对照):
- pico-sdk 2.3.1 + tinyusb 子模块(锁定提交), Arm GNU 13.x, CMake ≥3.16, Ninja
- pioasm 由 SDK 构建时自动编译; 宿主若无 C++ 编译器(如本机), 预置
firmware/build/pioasm/CMakeCache.txt的CMAKE_CXX_COMPILER为分号列表 形式的 zig(pip install ziglang后指向 ziglang/zig.exe, 见 AGENTS.md 踩坑表) - SDK 2.x 的 UF2 依赖 picotool(要拉 github); 本仓改用
make_uf2.py(ELF→objcopy→bin→UF2, 与真机 UF2 逐字段核对 + 往返自检)
cd firmware
cmake -B build -G Ninja -DPICO_SDK_PATH=D:/toolchain/pico-sdk `
-DPICO_TOOLCHAIN_PATH=D:/toolchain/arm-gnu-toolchain-13.3.rel1 `
-DPICO_BOARD=pico
cmake --build build
<arm-none-eabi-objcopy> -O binary build\i2c_lab.elf build\i2c_lab.bin
python make_uf2.py build\i2c_lab.bin build\i2c_lab.uf2
copy build\i2c_lab.uf2 ..\release\firmware\
7. 路线(与 I2C-Inject 的关系)
- v0.1 监控(本版): 纯被动监听 + 事务流 + 波形快照
- 主机模式: probe 作为 I2C 主机发起读写/总线扫描(复活 I2C-Inject 的 择机注入语义——避让主控轮询、静置窗口注入、读回校验), GUI 加寄存器读写卡
- 从机模拟: probe 应答主机, 应答内容由 PC 端配置(RP2040 硬件 I2C 从机 + 应答表), 用于顶替传感器/MCU 验证驱动
- 监控增强: 字段级协议插件(如 LT8619C bank/寄存器语义注释)、触发抓取、 长时记录落盘
8. 故障排查
- 连接后无 T 行:
stats看 edges 是否增长; 不增长查接线/共地/上拉 - 事务乱码: 确认 SDA/SCL 没接反(GP8=SDA!);
wave 512看原始边沿 trans_drop/susp持续增长: 总线负载过高或毛刺多, 减小监控过滤范围- 波形抓取期间的事务流有缺口: 正常(
wave快照优先, 见固件注释)
9. 目录内容
| 位置 | 用途 |
|---|---|
src/ |
PC 端: main.py(GUI)/i2cdec.py(解码权威)/probelink.py(链路)/waveview.py(波形)/theme.py + 自检/打包/发布脚本 |
firmware/ |
probe 固件: main.c + bus_watch.pio + CMakeLists + make_uf2.py + pico_sdk_import.cmake |
assets/ |
图标(沿用 I2C 橙色母题) |
release/ |
I2C-Lab.exe + firmware/i2c_lab.uf2/.bin(交付物本地保留,不入库); zip 不入库 |