ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

USB转I2C 1000KHz总线速率扫描测试与Excel数据归档实战

USB转I2C 1000KHz总线速率扫描测试与Excel数据归档实战 1. 项目缘起与整体设计思路1.1 这个测试到底在测什么先把标题拆开看USB TO I2C_(Excel)_Scan ---- 1000KHz总线速率测试_A。核心链路是PC 通过 USB 转 I2C 适配器去扫描一条 I2C 总线上的从机设备同时把总线速率拉到 1000KHz也就是 1MHz用 Excel 作为结果记录和呈现的载体。这里有几个关键词需要先对齐认知USB TO I2CPC 端没有原生 I2C 接口必须借助一颗 USB 转 I2C 的桥接芯片常见的有 FTDI 的 FT232H/FT2232H、Cypress 的 CY7C65215、Silicon Labs 的 CP2112 等把 USB 协议转换成 I2C 时序。Scan指的是 I2C 总线地址扫描逐个地址发起始条件地址字节看从机是否 ACK从而判断总线上挂了哪些设备。1000KHzI2C 标准模式是 100KHz快速模式 400KHz快速模式 是 1MHz高速模式能到 3.4MHz。1000KHz 已经踩在 Fast-mode Plus 的边界上对硬件和时序要求都不低。Excel不是让你用 Excel 去算 I2C而是把扫描结果、每个地址的响应情况、耗时、错误码等结构化数据落到 Excel 里方便做批量对比和趋势分析。我做这个测试的初衷很直接手头有一批板子要量产前抽检需要快速确认每块板子上的 I2C 从机EEPROM、传感器、IO 扩展芯片是否都能在 1MHz 下正常应答。用示波器一个个看太慢用逻辑分析仪抓包又不够批量所以搭了这套USB 转 I2C 脚本扫描 Excel 归档的流水线。1.2 为什么选 USB 转 I2C 而不是 MCU 直连很多人第一反应是拿一块 STM32 写个扫描程序串口打印结果。这条路我走过问题在于速率上限受 MCU 主频和 I2C 外设限制。STM32F103 的硬件 I2C 在 1MHz 下经常出问题很多人最后退化成软件模拟速率更上不去。批量测试时烧录麻烦。每换一块被测板都要重新接线、复位效率低。PC 端数据处理不方便。串口打印的文本还要再解析一遍才能进 Excel。USB 转 I2C 方案的优势在于PC 端直接用 Python 或厂商 SDK 调用扫描逻辑写在脚本里结果直接写 Excel改一行代码就能换扫描范围。适配器本身是标准 USB 设备插上就能用不占用被测板的任何资源。注意选适配器时一定要确认它支持的最高 I2C 速率。市面上大量廉价 CH341A 方案最高只到 400KHz根本跑不了 1000KHz。FT232H 的 MPSSE 模式可以到 1MHz 甚至更高CP2112 官方标称 400KHz实际超频到 1MHz 不稳定。1.3 Excel 在链路里扮演的角色Excel 在这里不是顺便用一下而是整个测试流程的数据中枢。我设计了三张表工作表名用途关键字段ScanResult单次扫描的原始结果地址、ACK/NACK、耗时us、错误码Summary多板对比汇总板号、通过地址数、失败地址、总耗时Timing速率相关时序数据目标速率、实测速率、上升沿时间这样设计的好处是ScanResult 是原始数据Summary 是给产线看的结论Timing 是给硬件工程师排查信号完整性用的。三张表用同一个脚本自动生成不需要人工整理。2. 核心细节解析与实操要点2.1 I2C 在 1000KHz 下的电气约束I2C 总线速率上不去90% 的问题出在上拉电阻和总线电容上。I2C 是开漏输出上拉电阻的结构上升沿的时间常数由 R上拉电阻和 C总线寄生电容决定t_r ≈ 0.847 × R × CFast-mode Plus 规范要求上升时间 t_r 不超过 120ns1000KHz 下。假设总线电容 C 是 100pF一条 10cm 的排线加上几个从机的引脚电容很容易到这个量级那么R ≤ 120ns / (0.847 × 100pF) ≈ 1.4kΩ也就是说1MHz 下上拉电阻要降到 1kΩ 左右而标准模式常用的 4.7kΩ 在 1MHz 下上升沿会拖到 400ns 以上波形直接变成圆顶从机根本采不到正确的电平。但电阻也不能无限小。电阻越小灌电流越大I2C 规范规定单条总线总灌电流不超过 3mA。3.3V 供电下R_min 3.3V / 3mA 1.1kΩ所以 1MHz 下的合理区间是1.1kΩ ~ 1.4kΩ我实测用 1.2kΩ 最稳。这个计算过程建议每个做高速 I2C 的人都自己算一遍不要照抄别人的电路。实操心得如果总线上挂了多个从机每个从机的引脚电容按 10pF 估算5 个从机就是 50pF加上 PCB 走线和连接器很容易超过 100pF。这时候要么减小上拉电阻要么缩短走线要么减少从机数量。我遇到过一条总线上挂 8 个传感器的场景1MHz 下怎么调都不稳最后拆成两条总线才解决。2.2 适配器选型与驱动确认我这次用的是 FT232H 模块市面上常见的 CJMCU-232H 小板原因有三MPSSE 模式原生支持 I2C速率可配置到 1MHz 以上FTDI 官方提供 D2XX 驱动和 Python 库pyftdi不用自己写 USB 协议栈模块便宜坏了直接换驱动安装这一步经常被忽略。Windows 下要装FTDI D2XX 驱动不是 VCP虚拟串口驱动。很多人装了 VCP 驱动后发现 pyftdi 找不到设备就是因为驱动类型不对。Linux 下相对简单内核自带 ftdi_sio但需要先卸载该模块让 pyftdi 直接接管sudo modprobe -r ftdi_sio sudo modprobe -r usbserial确认设备被识别from pyftdi.ftdi import Ftdi Ftdi.show_devices()输出里能看到ftdi://ftdi:232h/1这样的 URL 就说明驱动没问题。2.3 扫描逻辑的设计I2C 地址扫描的本质是对 7 位地址空间 0x08~0x77避开保留地址逐个发起起始条件 地址字节 读位看从机是否拉低 SDA 应答。这里有个细节地址要左移一位。7 位地址 0x50 在总线上传输时是1010 0000写或1010 0001读。pyftdi 的 API 接受的是 7 位地址内部会自动处理但如果你用底层 MPSSE 命令自己拼字节就要手动左移。扫描时还要注意每个地址扫描后要发停止条件否则总线一直处于占用状态下一个地址扫不了超时时间要设合理。1MHz 下一个地址的完整事务大约 30us超时设 1ms 足够设太长会拖慢整体扫描连续 NACK 不代表总线坏了可能只是那个地址没设备要区分无应答和总线错误3. 实操过程与核心环节实现3.1 环境搭建先列一下我用的软硬件清单项目型号/版本说明USB 转 I2C 适配器FT232H 模块MPSSE 模式上拉电阻1.2kΩ × 2SDA、SCL 各一个被测板自研板挂 3 个 I2C 从机PC 系统Windows 10 / Ubuntu 22.04两个都测过Python3.10关键库pyftdi 0.55, openpyxl 3.1接线很简单FT232H 的 AD0 接 SDAAD1 接 SCLAD2 接 GND可选用于复位VCC 接 3.3V。上拉电阻从 SDA/SCL 各拉到 3.3V。注意FT232H 模块的 IO 电平默认是 3.3V但如果你的被测板是 5V 系统需要加电平转换。直接接 5V 上拉会把 FT232H 的 IO 打坏。我有个同事就是这么烧掉两块模块的。3.2 扫描脚本核心代码from pyftdi.i2c import I2cController from openpyxl import Workbook import time # 初始化控制器 i2c I2cController() i2c.configure(ftdi://ftdi:232h/1, frequency1000000) # 1000KHz # 准备 Excel wb Workbook() ws wb.active ws.title ScanResult ws.append([地址(hex), 地址(dec), 应答, 耗时(us), 错误信息]) results [] for addr in range(0x08, 0x78): t0 time.perf_counter() try: port i2c.get_port(addr) port.read(1) # 尝试读一个字节 ack ACK err except Exception as e: ack NACK err str(e)[:50] t1 time.perf_counter() elapsed (t1 - t0) * 1e6 ws.append([hex(addr), addr, ack, round(elapsed, 1), err]) if ack ACK: results.append(addr) wb.save(scan_result.xlsx) print(f扫描完成发现设备地址: {[hex(a) for a in results]})这段代码有几个关键点frequency1000000就是 1000KHzpyftdi 内部会计算 MPSSE 的时钟分频port.read(1)会触发完整的起始地址读事务比只发地址更可靠因为有些从机对纯地址探测不响应耗时用perf_counter()测精度到微秒级比time.time()靠谱3.3 实测数据与速率验证跑完一轮扫描Excel 里的数据长这样截取部分地址(hex)地址(dec)应答耗时(us)错误信息0x4872ACK42.30x5080ACK41.80x68104ACK43.10x088NACK38.5NackError0x099NACK38.2NackErrorACK 的地址耗时约 42usNACK 的约 38us。理论上 1MHz 下一个字节 9 个时钟周期是 9us加上起始和停止条件一个完整事务大约 25~30us。实测 42us 说明 MPSSE 的 USB 传输开销占了相当一部分——每次port.read()都要走一次 USB 往返这部分延迟是固定的。实测速率怎么算用逻辑分析仪抓 SCL 波形测量连续两个时钟上升沿之间的间隔。我实测下来 SCL 周期约 1.02us对应频率约 980KHz和设定的 1000KHz 有 2% 偏差这是 MPSSE 时钟分频的量化误差属于正常范围。实操心得如果你需要精确的 1000KHz不要指望 USB 转 I2C 适配器能做到。MPSSE 的时钟是从 60MHz 基准分频出来的分频系数是整数所以实际频率只能是 60MHz/N。1000KHz 对应的 N60实际就是 1000KHz但如果你设 900KHzN66.67只能取 67实际是 895.5KHz。这个误差在扫描场景下无所谓但在做时序一致性测试时要注意。3.4 Excel 数据的后处理扫描完的原始数据只是第一步我通常还会加一段后处理脚本把 Summary 表自动生成出来from openpyxl import load_workbook wb load_workbook(scan_result.xlsx) ws wb[ScanResult] summary wb.create_sheet(Summary) ack_count 0 nack_count 0 total_time 0 for row in ws.iter_rows(min_row2, values_onlyTrue): if row[2] ACK: ack_count 1 else: nack_count 1 total_time row[3] summary.append([统计项, 数值]) summary.append([ACK 地址数, ack_count]) summary.append([NACK 地址数, nack_count]) summary.append([总耗时(us), round(total_time, 1)]) summary.append([平均耗时(us), round(total_time / (ack_count nack_count), 1)]) wb.save(scan_result.xlsx)这样一份 Excel 里既有原始数据又有汇总产线人员看 Summary硬件工程师看 ScanResult各取所需。4. 常见问题与排查技巧实录4.1 扫描结果全是 NACK 怎么办这是最常见的问题按以下顺序排查确认上拉电阻接了。我见过有人忘了接上拉SDA/SCL 一直是低电平扫描全 NACK。确认电压匹配。适配器 3.3V被测板 5V中间没做电平转换从机根本识别不到。确认地址范围。有些从机的地址不在 0x08~0x77 之间比如某些 EEPROM 的地址是 0x50~0x57如果你只扫 0x08~0x0F 当然扫不到。降低速率试试。把frequency改成 100000如果 100KHz 能扫到1MHz 扫不到那就是信号完整性问题回去调上拉电阻。4.2 部分地址能扫到部分扫不到这种情况通常是总线电容过大导致边沿变缓某些对时序敏感的从机在 1MHz 下采不到数据。解决方法减小上拉电阻从 4.7kΩ 降到 1.2kΩ缩短总线走线减少同时挂载的从机数量我遇到过一块板子单独测每个从机都正常三个一起挂就有一个扫不到。最后发现是 PCB 上 SDA 走线太长加了 1.2kΩ 上拉后解决。4.3 Excel 写入乱码或格式错乱openpyxl 默认写入的是 UTF-8一般不会乱码。如果出现乱码检查地址字段用hex(addr)生成的是字符串没问题耗时字段用round()返回的是 floatExcel 会自动识别为数字错误信息里如果有特殊字符用str(e)[:50]截断避免超长注意openpyxl 写入大量数据时超过 10 万行会变慢扫描 7 位地址空间最多 112 行完全不用担心性能。4.4 常见问题速查表现象可能原因解决方法全 NACK上拉电阻未接接 1.2kΩ 上拉全 NACK电压不匹配加电平转换1MHz 扫不到100KHz 能扫到信号完整性差减小上拉电阻、缩短走线部分地址扫不到总线电容过大减少从机、拆分总线pyftdi 找不到设备驱动类型错误装 D2XX 驱动卸载 ftdi_sio实测速率偏差大MPSSE 分频量化误差接受 2% 以内偏差或换适配器Excel 打开报错文件被占用关闭 Excel 再运行脚本4.5 几个容易被忽略的细节第一扫描顺序会影响结果。如果你先扫 0x50 再扫 0x48和反过来扫耗时可能差几微秒。这是因为 USB 传输的调度不是完全确定的。做对比测试时建议固定扫描顺序。第二停止条件的处理。pyftdi 的get_port()在异常时会自动发停止条件但如果你用底层 MPSSE 命令一定要手动发停止否则总线会卡死后续所有扫描都失败。第三Excel 文件的版本兼容。openpyxl 生成的是 .xlsx 格式Excel 2007 以上都能打开。如果你需要兼容更老的版本要另存为 .xls但 openpyxl 不支持 .xls 写入得用 xlwt 库。第四多次扫描取平均。单次扫描的耗时数据波动较大USB 调度影响我通常连扫 5 次取每个地址耗时的中位数这样数据更可靠。这个逻辑可以在脚本里加个循环把 5 次结果都写进 Excel再用公式算中位数。5. 速率测试的进阶玩法5.1 用逻辑分析仪交叉验证USB 转 I2C 适配器报告的速率是设定值实际总线上的波形还得用逻辑分析仪看。我用的是一款 24MHz 采样率的廉价逻辑分析仪接在 SDA/SCL 上抓 1MHz 的 I2C 波形。采样率 24MHz 对 1MHz 信号来说只有 24 个采样点/周期勉强够看。如果要精确测量上升沿时间采样率至少要到 100MHz。逻辑分析仪的软件里一般有 I2C 协议解码功能直接能看到地址、数据、ACK/NACK和脚本扫描的结果对照两边一致才说明测试可信。5.2 把扫描结果做成甘特图Excel 里有个很实用的功能用条件格式把 ACK 的地址标绿NACK 标红一眼就能看出哪些地址有设备。如果要做更直观的展示可以用 Excel 的条形图横轴是地址纵轴是耗时ACK 的用绿色条NACK 的用灰色条。这样一张图就能看出总线上设备的分布和响应速度差异。5.3 扩展到 EEPROM 读写测试扫描只是确认设备存在要进一步验证 1MHz 下的读写可靠性可以加一段 EEPROM 读写测试port i2c.get_port(0x50) test_data bytes([0xAA, 0x55, 0x00, 0xFF]) port.write_to(0x0000, test_data) # 写入 4 字节到地址 0 time.sleep(0.01) # 等待 EEPROM 内部写周期 readback port.read_from(0x0000, 4) assert readback test_data, 读写不一致这段代码在 1MHz 下跑 1000 次统计错误率就能评估总线在高速率下的可靠性。我实测 FT232H 1.2kΩ 上拉 10cm 排线1000 次读写零错误。5.4 多板批量测试的自动化产线场景下一块板子扫完要换下一块。手动换线太慢我做了个简单的夹具用 pogo pin 顶住板子上的 I2C 测试点夹具上带 1.2kΩ 上拉换板子只需要按下压扣。脚本里加个循环每扫完一块就提示请更换板子按回车继续结果自动追加到 Excel 的新行。这样一套下来单板扫描时间约 5 秒112 个地址 × 42us USB 开销加上换板时间一小时能测 300 块以上比人工用示波器看快了一个数量级。6. 我在这个项目里踩过的坑第一个坑是上拉电阻想当然。一开始我用了手边现成的 4.7kΩ100KHz 下一切正常切到 1MHz 后扫描成功率只有 60%。用示波器一看SCL 上升沿拖到 500ns从机在时钟高电平期间根本采不到稳定数据。换成 1.2kΩ 后成功率 100%。这个教训是速率每提高一个档位上拉电阻都要重新算。第二个坑是驱动装错。Windows 下 FTDI 的 VCP 驱动和 D2XX 驱动是两套东西设备管理器里看都是USB Serial Converter但 pyftdi 只认 D2XX。我折腾了半天以为是模块坏了后来在设备属性里看到驱动版本不对才反应过来。第三个坑是Excel 文件被占用。脚本跑完保存时如果 Excel 正开着这个文件openpyxl 会报 PermissionError。后来我在脚本开头加了检测如果文件存在就先重命名备份避免覆盖失败。第四个坑是误判 NACK。有些从机在上电后需要一段初始化时间比如 100ms如果扫描脚本跑太快从机还没准备好就会误报 NACK。后来我在扫描前加了 200ms 延时问题解决。这个细节在从机数据手册里通常不会写得自己试出来。这套 USB 转 I2C Excel 的扫描方案核心价值不在于技术有多高深而在于把确认总线上有哪些设备、能不能在目标速率下工作这件事做成了可重复、可归档、可对比的流程。硬件调试最怕的就是这次好了下次又不行有了 Excel 里的历史数据任何异常都能追溯到具体是哪块板、哪个地址、哪次测试出的问题。
返回列表