尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

DTM命令实战:不依赖HCI/ACI的蓝牙射频测试指南

DTM命令实战:不依赖HCI/ACI的蓝牙射频测试指南 做射频测试的同行都知道HCI 和 ACI 是两个绕不开的接口词。可真到了蓝牙认证和产线量产测试环节我更习惯直接使用 DTM 命令去控制被测设备而不是费劲去跑协议栈。DTM 全称 Direct Test Mode蓝牙规范里专门为射频测试定义的直通模式它可以让芯片乖乖地发一个固定频率、固定功率的信号或者统计固定通道上的接收丢包率。最近后台不少人在问“wifi芯片aci测试”和 DTM 到底什么关系干脆写一篇完整实操向的文章把“用 DTM 命令控制、而不是 HCI / ACI 控制”这件事讲透。这篇内容适合刚接触蓝牙/WiFi 产测的工程师也适合做底层射频验证的硬件开发者读完你至少能知道 DTM 命令长什么样、怎么发、踩过哪些坑。1. 为什么是 DTM而不是 HCI / ACI1.1 三套接口分工完全不同很多人刚接触蓝牙和 WiFi 芯片时容易被 HCI、ACI、DTM 这三个缩写弄混。简单说HCI 是主机和控制器之间的标准通信接口蓝牙协议栈跑在上面用来发起扫描、创建连接、收发 GATT 数据是“正常工作模式”的总线。ACI 则是厂商私有的应用控制接口常见于 WiFi 芯片或者 Combo 芯片主要用来做射频校准、天线调优、固件参数配置不同厂家之间的命令格式甚至名字都可能不一样。DTM 是另一条路它不关心你怎么建连、怎么发包、怎么组网只做一件事直接控制射频前端进入发射或接收测试状态。你可以把 HCI 和 ACI 理解成“驾驶模式”车能跑、能转向、能停车而 DTM 是修车店里的“底盘测功机”不关心你踩刹车灵不灵只管把发动机拉到某个固定转速测输出功率、测振动、测油耗。所以标题里说“not HCI / ACI”核心意思就是测试射频指标时不要去依赖完整的协议栈也不要依赖厂商私有驱动接口而是走蓝牙社区和认证机构通用的 DTM 测试语义。严谨一点说很多芯片的 DTM 命令在底层传输时仍然会套一个 HCI 帧的壳子但它的命令语义和常用的连接管理 HCI 命令完全不是一回事它属于测试模式专用命令不参与协议状态机。1.2 用 DTM 到底解决了什么我在做蓝牙模块量产时最头疼的不是射频指标本身而是协议栈带来的不确定性。普通 HCI 命令控制蓝牙芯片发数据系统要跑完广播、扫描、连接、加密、重传、跳频这一整套流程任何环节有波动测试结果就千奇百怪。比如同一块板子上午测功率 -2dBm下午变成 -5dBm查了半天发现是对面工位的 WiFi 干扰了某个跳频频点。DTM 把这种不可控性直接砍掉。它关闭跳频、关闭重传、关闭协议状态机DUT 就像一台固定频率、固定速率、固定功率的“信号发生器”或“接收机”。这对认证测试特别重要蓝牙射频一致性测试RF PHY Conformance明确要求使用 DTM 流程因为只有这样才能确保每一台被测设备处于完全相同的物理状态。产线效率是另一个关键原因。用 HCI 建连测试每个 DUT 要额外花几百毫秒甚至几秒去握手、配对。而 DTM 命令可以在几十毫秒内切换信道和 PHY测试脚本一秒钟能跑好几个用例这对动辄几千片模组的产线来说节省的时间非常可观。对比维度HCI / ACI 路径DTM 路径控制内容建连、扫描、数据收发 / 厂商私有射频配置固定的发射/接收测试参数协议栈依赖完整协议栈或厂商驱动不需要协议栈测试可重复性受跳频、重传影响波动大高状态固定产测速度慢需要连接流程快直接切信道适用场景功能测试、协议测试射频认证、产线射频测试2. DTM 命令体系与核心参数拆解2.1 标准 DTM 命令家族蓝牙规范里DTM 的核心命令其实就三条发射测试Transmit Test、接收测试Receive Test、测试结束Test End。很多人以为 DTM 很复杂是厂商一大堆私有命令实际上底层标准很收敛复杂的是参数组合。发射测试命令的核心参数包括发射信道、PHY 类型、测试数据包长度、数据包负载模式。信道号直接决定中心频率例如 BLE 信道 0 对应 2402 MHz信道 n 对应 2402 2n MHz。PHY 类型在 BLE 5.x 里可以是 1M、2M、Coded S8、Coded S2这个参数决定调制速率和覆盖能力。测试数据包长度用于模拟不同负载下的射频信号一般产测用 37 字节或者 255 字节都比较常见。数据包负载模式很多人会忽略它其实是往发射数据里填什么样的比特流。标准里定义了多种模式比如 PRBS9 伪随机序列、连续 11110000、连续 10101010 等。我最常用的是 PRBS9因为伪随机序列会让信号频谱更接近真实数据功率测量、频谱模板测试都更有参考性。如果填连续 0 或连续 1频谱会变成一根很纯的单音谱线某些测试项反而不符合预期。接收测试命令相对简单核心参数是接收信道和 PHY。进入接收模式后DUT 会在硬件层统计收到的有效数据包数量、CRC 错误等。测试结束后通过 Test End 命令让芯片回传收到的包数量上位机再用“发送包数 - 接收包数”算出丢包率 PERPacket Error Rate这就是接收灵敏度的核心指标。2.2 一个 DTM 命令帧到底长什么样以最典型的 LE 发射测试为例命令的完整逻辑其实包含三部分操作码、参数长度、参数内容。操作码会告诉芯片“这是一条 DTM 测试命令”参数长度告诉芯片“后面还有几个字节要读”参数内容就是信道、PHY 这些具体配置。通用实现中LE Transmit Test 的操作码是 0x201BLE Receive Test 操作码是 0x201DLE Test End 操作码是 0x201F。传输到芯片时按小端顺序发送所以 0x201B 会变成1B 20两个字节。字段取值示例含义操作码1B 20LE Transmit Test参数长度04后面跟 4 个字节TX 信道00信道 0即 2402 MHz数据长度2537 字节测试包数据负载模式00PRBS9PHY011M PHY发送的时候很多芯片还会在命令前后加一层私有的帧头、帧尾或者校验字段。比如国内几家蓝牙 SoC 厂商会在标准 DTM 命令前加一个短的同步头后加 CRC。所以如果你直接用公版命令发过去没反应不要急着怀疑命令不对先看厂商文档里有没有封装要求。2.3 控制通道不一定要走 HCI / ACI这里必须解释一个容易杠的点DTM 命令在很多芯片上最终是通过 HCI 帧传下去的那标题为什么说不走 HCI因为 DTM 和 HCI 是不同层面的东西。DTM 是测试语义HCI 是传输容器。你如果使用完整的 HCI 协议栈去发扫描、建连命令那才叫“用 HCI 控制”而只发几条 DTM 测试命令不启动协议栈那它本质上是“用 DTM 命令控制”。ACI 就更特殊了。WiFi 芯片产测时很多工程师习惯用厂商 ACI 工具去下发射频指令比如调 TX 功率、切天线、配置带宽。这些工具确实好用但坑在于 ACI 命令完全私有化。同一个 WiFi 芯片换了新版本 SDK部分命令可能不兼容换了芯片厂商以前写的脚本全部作废。而 DTM 因为面向蓝牙标准化测试规则更稳定至少蓝牙侧的命令语义在协议版本之间基本可以沿用。所以如果你的 Wi-Fi 芯片支持蓝牙共存或者 Combo 测试模式优先把 DTM 流程跑通会比依赖 ACI 更稳。3. 实操从零跑通一个 DTM 射频测试3.1 前期准备先准备一套最小测试环境。DUT 方面需要一块可以烧录测试固件的开发板注意这里一定要烧 DTM 测试固件不是正常的应用固件。很多芯片原厂都会提供单独的 DTM 固件比如 Nordic 的 nRF Connect Desktop 里就有 DTM 相关工具TI 的 SmartRF Studio 也可以生成测试固件。烧录 DTM 固件的目的是绕开操作系统和蓝牙协议栈让芯片上电后进入纯测试状态。连接方面我习惯用 USB-UART 模块接到芯片 UART 测试口。电平要注意有些开发板是 3.3V IO有些是 1.8V最好直接确认原理图不要乱接。波特率通常选 115200、8N1关闭流控。如果芯片有测试模式选择引脚上电时要拉高或拉低具体以 datasheet 上电时序图为准。射频输出口要用质量好的同轴线连到频谱仪或者综测仪。如果环境有干扰强烈建议把 DUT 放进屏蔽盒尤其是做 RX 灵敏度测试时屏蔽盒能挡掉大部分环境杂波。3.2 进入 DTM 模式上电后先别急着发发射命令。我第一件事永远是先发一条 Test End 命令把芯片内部可能有残留的测试状态清干净。类似“关门之前先反锁一下”避免上次测试未正常退出导致状态机卡死。Test End 命令格式很简单通用实现是1F 20 00其中 1F 20 是操作码00 是参数长度。如果返回一个 HCI Command Complete 事件并且 Status 为 0说明 DTM 环境正常。然后就可以发 LE Transmit Test 命令了。下面是一个用 Python 和 pySerial 发 DTM 命令的最小示例适合产线自动化脚本快速验证import serial import time ser serial.Serial(COM10, 115200, timeout0.5) # 1. 先发送 Test End清空状态 test_end bytes.fromhex(1F 20 00) ser.write(test_end) time.sleep(0.05) print(Test End response:, ser.read(255).hex()) # 2. 进入 TX 测试信道0包长37PRBS91M PHY # 参数: 00 25 00 01 le_tx bytes.fromhex(1B 20 04 00 25 00 01) ser.write(le_tx) time.sleep(0.05) resp ser.read(255) print(TX start response:, resp.hex())需要注意的是这个示例是基于标准 HCI 事件帧的通用实现部分芯片会把响应帧加一层私有头。如果你用原厂工具能收到回复但脚本收不到多半就是私有封装的问题。3.3 跑通 TX 连续波测试命令发出去以后芯片应该会在指定信道持续发射。这时候在频谱仪上应该能看到以 2402 MHz 为中心的一根谱线带宽和 PHY 有关。如果频谱仪显示“无信号”先不要查命令先查射频线缆、接头和板子天线匹配。我做产测时经常遇到这种情况最后发现是 SMA 转接线断了。功率测试要等信号稳定一点再采样。芯片从收到命令到 PLL 锁定、PA 完全建立通常需要几十毫秒。脚本里发完命令后延时 50 到 100ms再去用频谱仪读取峰值功率否则第一次采样可能偏小。DTM 命令本身通常不带功率参数。发射功率主要由芯片内部 PA 配置决定你在 DTM 模式下测到的是默认功率一般接近最大发射功率。如果你需要测不同功率档位下的指标那就得配合厂商的私有校准命令去写功率等级。这种情况下还是会把厂商命令和 DTM 命令混合使用但需要注意先后顺序先写功率再启动 DTM 发射。3.4 跑通 RX 灵敏度测试接收测试要比发射测试稍微绕一点。DUT 进入 Receive Test 模式后只负责接收和统计不会主动发包。这时候需要另一个设备帮它发数据包可以是综测仪也可以是另一块支持 DTM 发射的开发板。在综测仪上设置好信道、PHY、包长和发包数量比如发 1000 包。DUT 侧执行 LE Receive Test等发包结束再发 Test End 命令让 DUT 返回它收到的包数量。PER 就是 (1000 - 收到包数) / 1000。用 Python 读取 Test End 响应里的统计数据时注意解析偏移。标准 HCI Command Complete 事件里状态字节之后才是两个字节的 Num Packets。片段示例test_end bytes.fromhex(1F 20 00) ser.write(test_end) time.sleep(0.05) resp ser.read(255) if len(resp) 8: status resp[5] num_packets int.from_bytes(resp[6:8], little) print(fstatus{status}, received_packets{num_packets})如果你的测试固件带私有帧头这个 offset 要跟着调整。最稳妥的方法是先抓一份“已知状态”的响应手动数一下哪个字节是状态。3.5 自动化产测流程参考一条完整的 DTM 产测流程可以写成固定序列上电 - 复位 Test End - TX 测试 - 频谱功率/频率检测 - Test End - RX 测试 - 读取 PER - Test End - 断电判定。每项测试都设独立超时避免一个用例卡死拖住整线。测试项参数示例合格阈值参考发射功率信道 01MPRBS9≥ -2 dBm中心频率误差信道 0≤ ±50 kHz接收 PER信道 01M发送 1000 包≤ 1%2M PHY 发射信道 02M指标不同平台差异大4. 常见问题与排查技巧实录4.1 DTM 命令发送后无回复这是新手问得最多的问题。第一反应先查最基础的三件事UART 接线有没有接反、波特率是否匹配、开发板是否真的进入了 DTM 模式。我见过有人把 DTM 固件烧进去以后测试引脚没拉对芯片一直跑在正常启动流程里发任何 DTM 命令都没反应。第二件事是检查命令格式。不同芯片厂商对 DTM 命令封装不同有的厂商要求每个命令前加两个字节帧头有些还要在命令末尾加 CRC 校验。你拿标准命令发过去芯片可能不识别甚至不回包。这种情况下用原厂工具抓一份正常通信的串口日志对比一下自己的命令是最快的排查方式。第三件容易忽略的是 DTM 状态机。如果上一次测试没有正确退出芯片可能还卡在 RX 或 TX 状态不会响应新的命令。发送任何命令前先发 Test End 并把返回值打印出来能省很多时间。4.2 测试功率或频率漂移如果发射测试功率忽高忽低先检查供电。芯片在发射时电流通常比较大如果开发板用的是 USB 供电USB 口输出能力不足会导致功率波动。换独立稳压电源后指标往往会立刻稳定。频率漂移则优先检查晶振。BLE 对晶振精度要求较高如果板子是低成本陶振温度一高频率就跑偏这时候看频谱仪的中心频率偏了多少。线缆损耗也要提前标定。我遇到过一块板子功率测试比标称低 1.8dB折腾半天才发现同轴线缆在 2.4GHz 频段插损有 2 个 dB校准之后所有数据都正常了。做产测前先用功率计或者综测仪校准整个射频链路记录补偿值。4.3 DTM 和 HCI / ACI 命令混用“混用”是产测脚本最容易出的隐性 bug。比如脚本一开始用厂商 ACI 命令关闭了天线切换到 DTM 模式后没有重新打开天线那发射功率就会异常偏低。再比如在 DTM 模式下用普通 HCI 命令去查询设备地址某些芯片会退出测试模式或者直接返回错误。我的经验是测试脚本里必须严格区分控制通道。DTM 命令只走 DTM 命令解析函数厂商私有命令只走厂商配置函数千万不要共用一个 write 函数。每次从 DTM 切到 ACI 配置之前先发 Test End从 ACI 配置切回 DTM 之前再发一次 Test End。这个“双重保险”看起来冗余但能避免大量诡异问题。4.4 WiFi 芯片 ACI 测试与 DTM 的关系做 WiFi 芯片的朋友看到 DTM 可能会疑惑我们平时测试不都用 ACI 工具吗没错WiFi 芯片射频测试中ACI 是厂商最常用的控制路径尤其用来配置信道、带宽、MCS、发射功率这些参数。但是如果项目要求“控制时不依赖 HCI / ACI”比如你在定制一套统测框架不希望被厂商驱动版本带偏就需要确认芯片有没有类似 DTM 的 RF Test Mode。很多 Combo 芯片在 WiFi 侧会提供一套私有的 RF 测试命令功能和 DTM 类似但不叫 DTM有的叫 RF Test Mode有的叫 Continuous TX Mode。查阅芯片手册时重点看“Direct Test Mode”或者“RF Test Mode”关键词。如果芯片只支持 ACI 配置没有底层测试命令那就不能硬套 DTM 流程这时候老老实实用 ACI 工具做校准再用 DTM 做蓝牙侧的统一验证才是合理的方案。5. 工具选型建议与 DTM 速查5.1 用什么工具发 DTM 命令最简单的方案是直接使用厂商提供的 DTM 测试工具。Nordic 有 DTM 固件配合 nRF Connect DesktopTI 有 SmartRF Studio这些工具可以在开发阶段快速验证射频指标。但这类工具通常只面向单板测试不适合产线自动化。产线阶段我更建议自己写一套基于串口的 DTM 控制脚本原因很简单厂商工具没法跟你的 MES 系统、数据库、测试治具联动。Python 的 pySerial 足够应对大部分场景关键是把命令封装成函数把测试项做成配置文件。如果测试量更大直接用综测仪是最稳的。RS CMW270、Anritsu MT8852B 这类设备内置 DTM 控制器可以自动完成发射、接收、PER 统计还带校准功能。劣势是设备贵产线初投成本高但大厂产线几乎都走这条路。工具适用阶段优点缺点原厂 DTM 工具研发验证上手快命令封装完整不适合产线自动化自写串口脚本产线调试灵活可集成需要处理私有协议综测仪量产/认证指标权威自动化完善设备成本高5.2 通用 DTM 命令速查表功能命令关键参数测试结束Test End无发射测试LE Transmit Test信道、包长、负载模式、PHY接收测试LE Receive Test信道、PHY结果返回Command Complete状态、接收包数量最后再分享一个小技巧产测脚本里每次切换信道之前先发一条 Test End再发新的 TX/RX 命令。这个习惯让我少踩了很多莫名其妙的坑。DTM 之所以好用就是因为它把射频测试变得足够“干净”干净的命令、干净的状态、干净的结果。不要一上来就搭协议栈先把 DTM 跑通把射频指标摸清楚再去碰 HCI 和 ACI会顺手得多。
返回列表