行业资讯
📅 2026/8/30 6:01:12
NUCLEO-WB55RG BLE广播失效排查:从硬件到协议栈的完整指南
从拿到第一块 NUCLEO-WB55RG到能稳定跑起 BLE 广播我中间踩过一个非常典型的坑程序烧进去了板载 LED 也正常闪但手机 nRF Connect 扫描列表里就是干干净净一个设备都看不到。当时第一反应是板子坏了后来翻官网、查社区、看协议栈日志折腾到大半夜才发现根本不是硬件问题而是地址类型没配对。这篇文章就把这类板卡没有发出 BLE 广播的问题完整拆开从硬件、协议栈、代码配置到调试工具一条条过。无论你是刚拆开 NUCLEO-WB55RG 包装的新手还是已经被厂商示例折腾到头秃的老玩家照着下面的排查顺序走一遍大概率能定位到问题。1. 问题现场还原先搞清楚是真的没广播还是扫描端的问题很多人一上来就去怀疑板卡硬件实际上手机搜不到广播这个现象有一半以上是扫描端或环境造成的假象。所以我建议先花五分钟做确认再动硬件。1.1 手机端那些最容易忽略的坑BLE 广播扫描和手机系统的权限绑定非常深。我实测过 Android 12 以上的设备如果你没给扫描 App 授权附近设备权限nRF Connect 打开后界面看起来正常但扫描列表永远空白。部分国产 ROM 更严格蓝牙扫描还需要定位权限你只开了蓝牙开关是不够的。iOS 稍微好一点但也要注意nRF Connect 默认会列出所有设备而一些第三方 BLE 工具会按 Service UUID 过滤如果你的广播数据里没有任何服务 UUID部分 App 会直接不显示。所以排查时至少要换两个工具交叉验证比如 nRF Connect 加 LightBlue或者 ST 官方的 ST BLE Sensor不要只靠一个 App 下结论。1.2 距离、干扰和信道问题BLE 广播虽然号称覆盖几十米但在室内环境下2.4GHz 频段被 Wi-Fi、蓝牙外设、甚至是微波炉严重占用板子放在电脑机箱后面或者金属桌面上信号衰减非常明显。建议把板卡和手机放到同一张桌面上距离控制在 1 米以内中间不要有金属遮挡。另外 BLE 广播只走 37、38、39 三个信道通俗讲就是它只在这三个频率点上轮流喊话每个信道停留时间很短。如果你所在环境刚好在这三个信道上干扰严重手机可能丢失全部广播包。你可以在 nRF Connect 里开启扫描所有信道或者把板卡换到另一个房间再试一次排除干扰因素。1.3 用第二块板子做交叉验证最靠谱的验证方式是双板互测。如果你手头有两块 NUCLEO-WB55RG给第二块烧一个最简单的 Beacon 工程或者仅仅用官方 BLE 示例然后用第一块作为扫描方反过来扫描第二块。如果第二块能收到第一块的广播说明问题出在第一块的射频路径或协议栈状态如果两边都收不到那大概率是两颗芯片都存在相同问题比如协议栈被擦除或者开发环境配置出错。还有一个更实用的手段是使用带 USB 口的 BLE Dongle比如 nRF52840 dongle配合 nRF Connect Desktop 抓包。电脑蓝牙适配器往往只做连接用途扫描效果不如专用 Dongle不要用 Windows 自带的蓝牙设置去判断是否有广播它经常会漏掉非可连接设备。2. 从硬件入手天线、供电和时钟如果确认手机和扫描端都没问题第二块板子也收不到广播那就要开始怀疑板卡自身了。硬件排查的顺序一般是从天线到供电到时钟层层往下收窄。2.1 天线路径从芯片到空气NUCLEO-WB55RG 的射频输出从 STM32WB55RG 引出后经过平衡不平衡转换器BALUN和 RF 开关最后接到板载 PCB 天线。板上通常还预留了 SMA 座用于外接天线这个路径切换由板上电阻或跳线决定。如果你在扩展板上插了某些 Arduino Shield或者用杜邦线从 morpho 排针引线刚好压在 PCB 天线区域天线性能会急剧下降甚至完全辐射不出去。我遇到过一次类似问题天线下面压了一根长杜邦线手机在 30 厘米内才能偶偶搜到广播拿开之后距离恢复到 10 米以上。建议先用肉眼检查天线区域有没有遮挡确认板卡背面没有异常焊锡残留。如果板子自己焊接过 ANT 引脚或者 BALUN 周边用放大镜仔细看看有没有短路或虚焊。如果你在代码里通过 GPIO 控制 RF 开关切换到了 SMA 路径但外接天线没接或者接了一个坏天线也会导致完全没有广播。这类配置在 CubeMX 里不一定有直观选项需要读取芯片参考手册中射频开关控制引脚的定义确认当前默认电平到底对应板载天线还是外部天线。2.2 供电不足会让射频悄悄罢工BLE 广播是典型的高脉冲电流负载广播瞬间电流可以达到十几毫安甚至更高。NUCLEO-WB55RG 通过 ST-LINK USB 口供电时3.3V 电源轨一般没有问题但如果你同时给传感器、OLED、舵机等外设供电板载稳压器的压降可能会让 3.3V 在广播瞬间掉到 3.0V 以下。很多芯片在欠压状态下不会立刻复位而是射频模块初始化失败表现出来的就是一点广播都没有。排查方法很简单用示波器或者万用表探头点住 3.3V 输出脚在程序循环开启广播时观察电压波动。如果发现广播瞬间电压跌落明显先断开所有外设只用 USB 供电再测一次。我个人的习惯是调试 BLE 广播时尽量使用外部 LDO 供电避免板载 ST-LINK 的电流余量影响射频表现。2.3 时钟与低功耗配置WB55 的 BLE 协议栈对时钟有硬性要求。系统必须提供可用的 32 MHz HSE高频外部晶振用于射频以及 32.768 kHz LSE低频外部晶振用于低功耗时的定时基准。如果你在 CubeMX 里为了省事把时钟源改成内部 HSI16 或者禁用了 LSEM0 核上的协议栈初始化可能不报错但广播始终起不来。另一点是低功耗模式。很多自定义工程会在主循环里调用WFI或者直接进入 STOP 模式来省电但如果没有正确配置 BLE 协处理器的唤醒源M4 核睡着了M0 核的协议栈虽然还在运行但射频活动可能被挂起广播自然停止。调试阶段我建议先关闭所有低功耗优化把系统跑在最高性能模式等确认广播正常后再逐步加入睡眠逻辑。3. 软件与协议栈真正的重灾区排除硬件和扫描端问题后剩下的十有八九是软件配置问题。这部分内容比较绕尤其是第一次接触 STM32WB 双核架构的开发者很容易掉进一些看似玄学的坑里。3.1 全片擦除把 BLE 协议栈擦没了这是我在社区里见过最多的问题自己也踩过一次必须放在最前面说。STM32WB55 是双核芯片Cortex-M4 核运行你的用户代码Cortex-M0 核运行预编译的 BLE 协议栈。蓝牙协议栈不是以库的形式链进你的工程而是以固件形式烧录在 M0 核对应的 Flash 区域里由名为 FUSFirmware Upgrade Services的系统管理。NUCLEO-WB55RG 出厂时厂商已经把 FUS 和 BLE 协议栈都烧好了。但很多人拿到板子后为了清空用户代码直接在 STM32CubeProgrammer 里点了 Full chip erase。这个操作会毫不留情地把 M0 区域的 FUS 和 BLE 协议栈一起擦掉。此后你烧录任何 M4 工程M4 代码能正常跑、LED 能闪、串口能打印但只要程序调用BLE_Init()或hci_init()跟 M0 通信就会失败广播当然也不存在。排查方法打开 STM32CubeProgrammer连接板卡后在STM32WB相关页面查看 FUS 版本是否还存在。如果显示为空或者无法读取说明协议栈区域已经被清空。恢复方案是从 STM32Cube_FW_WB 固件包中获取对应的 FUS 和 BLE 协议栈 bin 文件用 CubeProgrammer 烧写回去。具体操作在不同 SDK 版本里有细微差别我建议严格按照固件包 README 中Firmware upgrade章节的步骤执行不要手动乱填起始地址否则容易把两个区域的地址搞混。3.2 初始化顺序与返回值逐个检查很多人烧完官方示例后能广播但程序一改成自己的工程就失败问题往往出在初始化顺序上。BLE 协议栈的启动不是写一行BLE_Init()就能搞定的它要求一系列调用按顺序执行而且每步都可能返回错误。标准的初始化顺序大致是先配置系统时钟再初始化 BLE HCI 层让 M4 和 M0 建立通信然后初始化 GAP 和 GATT 服务接着设置地址、广播参数、广播数据最后启动广播。每一步我都建议检查返回值不要默认成功。比如aci_gap_set_advertising_configuration()返回非零后面的aci_gap_set_advertising_data()和aci_gap_start_advertising()很可能也不会正常执行但代码不一定会崩溃只是广播没开。我习惯在调试阶段写一个简单的错误打印函数把返回值转到串口上一目了然。这样能快速看到是协议栈没起、还是广播参数配置失败而不是对着手机扫描列表干瞪眼。3.3 别忽略地址类型STM32WB 没有出厂 BLE 地址很多单片机自带厂商标定的唯一 MAC 地址但 STM32WB 系列没有。它的 BLE 地址需要你自己指定要么用静态随机地址Static Random Address要么在系统 Flash 里存一个自己的公共地址。这是官方例程里已经处理好的细节但自己建工程时很容易忽略。如果你使用的是公共地址Public Address但代码里没有写入任何地址协议栈可能返回错误或者生成一个全零地址进行广播。手机端收到全零地址的设备时部分扫描 App 会直接过滤掉。我强烈建议在做最小验证时使用静态随机地址类型具体在aci_gap_set_advertising_configuration()的参数中指定示例代码里经常用RANDOM_STATIC_ADDR。这个类型不需要事先烧录任何地址协议栈会自动生成一个随机地址用于广播简单可靠。另外注意如果在同一块板子上反复烧录不同工程手机里会积累很多旧设备缓存。有时候广播其实已经发出了但手机因为缓存了之前同名的设备显示还是旧的。遇到这种情况清除手机蓝牙缓存或者重启手机蓝牙往往就能搜到了。3.4 广播参数配置的细节广播参数包含广播类型、间隔、信道、过滤策略、广播数据等多个维度。最常用的广播类型是ADV_IND这是可连接无定向广播手机可以搜到也能连接。如果你不小心用了ADV_NONCONN_IND或ADV_SCAN_IND手机虽然能搜到但无法连接在某些应用场景里会让人觉得设备有问题。广播间隔的单位是 0.625ms很多人直接填一个很小的值比如 20ms结果是功耗飙升且广播包过于密集反而容易和环境里其他信号冲突。反过来如果你把间隔设成 1.28 秒以上手机扫描时可能正好错过广播信道表现为偶尔能搜到过一会儿就消失。一般建议开发阶段使用 100ms 到 200ms 之间的间隔兼顾响应速度和稳定性。广播数据的格式也很有讲究。每个广播包由若干 AD Structure 组成每个结构的第一字节是长度第二字节是类型随后是数据。如果长度字段和实际数据不匹配或者把超过 31 字节的数据塞进传统广播包手机端扫描器很可能直接丢弃整个包。BLE 5.0 引入了扩展广播可以传输更长数据但需要 WB55 协议栈和扫描端都支持调试阶段建议先用 31 字节以内的传统广播排错最简单。4. 实际操作从官方例程到最小广播工程理论讲得再多不如直接上板子跑一遍。这一节我给出一个通用的操作路径先用官方例程验证硬件再写一个最小广播工程定位问题最后用日志和抓包确认结论。4.1 不写代码验证官方 P2P Server拿到新板子我建议第一件事不是新建工程而是直接打开 STM32Cube_FW_WB 固件包里的 BLE P2P Server 示例。注意这个示例的 README 里通常会要求先用 STM32CubeProgrammer 烧录 BLE 协议栈固件到 M0再烧录 M4 应用。如果出厂板子没被擦过直接烧 M4 应用也可以跑但如果你不确定板子状态按 README 走一遍完整流程是最稳妥的。烧完官方示例打开手机 nRF Connect扫描列表中应该能看到名为P2P_Server之类设备设备名可能因 SDK 版本不同略有差异。如果你能看到这个设备并能连接说明板卡硬件、射频天线、协议栈都是完好的问题几乎可以锁定在你自己的代码配置上。如果连官方示例都搜不到那就要回到前面第 3.1 节检查协议栈是否还在。这个时候不要急着改代码先把板卡恢复到一个确定能工作的状态再做后续开发否则所有问题都会混在一起。4.2 写一个最小可广播工程在确认官方例程能广播之后我会自己建一个尽量精简的工程只保留点灯和广播功能用来做后续的变量控制实验。代码逻辑大致如下static uint8_t adv_data[] { 0x02, 0x01, 0x06, // Flags: LE General Discoverable 0x09, 0x09, W, B, 5, 5, _, T, e, s, t // Name: WB55_Test }; int8_t BLE_StartAdvertising(void) { int8_t ret; /* 1. 配置广播参数传统可连接广播静态随机地址间隔约100ms */ ret aci_gap_set_advertising_configuration( 0, GAP_ADV_IND, RANDOM_STATIC_ADDR, NULL, 160, /* min interval, 0.625ms * 160 100ms */ 160, /* max interval */ 0x07, /* 37/38/39三个信道全开 */ NO_WHITE_LIST_USE ); if (ret ! 0) return ret; /* 2. 设置广播数据 */ ret aci_gap_set_advertising_data(0, sizeof(adv_data), adv_data); if (ret ! 0) return ret; /* 3. 启动广播 */ ret aci_gap_start_advertising(0, GAP_FAST_ADV, 0); return ret; }这个工程的关键在于每个返回值都打印出来。如果第 1 步就返回错误说明问题在协议栈初始化和地址配置如果第 3 步返回错误问题大概率在广播数据或连接参数。通过这种最小化变量的方式你能非常快地锁定问题层次。4.3 用日志和抓包确认广播软件层面排查完如果一切正常但手机还是搜不到就要借助专业工具做物理层确认。NUCLEO-WB55RG 板载 ST-LINK 的虚拟串口可以输出 HCI 日志打开官方例程默认的日志功能观察协议栈有没有打印广播启动成功的事件。更高阶的做法是抓取空中的无线电包。ST 官方提供基于另一块 STM32WB 开发板的 BLE Sniffer 方案也可以用 nRF52840 Dongle 配 Wireshark 抓 BLE 广播包。抓包时如果能看到 37、38、39 信道上周期性出现的 ADV_IND 数据包那说明射频部分完全正常问题一定在扫描端或手机权限如果只有某个信道有包说明环境干扰严重或者天线方向性导致覆盖面差。我印象最深的一次排查是板卡程序完全正常广播包也能用 Sniffer 抓到但手机就是搜不到。后来发现手机开启了仅限已配对设备的过滤选项把未知广播设备全屏蔽了。这种问题不抓包根本想不到。5. 问题速查表与排查顺序建议把前面所有内容整理成一张速查表遇到问题直接对照。现象可能原因排查动作手机完全搜不到LED 正常闪烁BLE 协议栈被全片擦除检查 FUS 版本重新烧录协议栈手机完全搜不到串口无日志初始化未执行或卡死在 BLE_Init检查是否调用初始化函数确认 M0 协议栈状态所有扫描端都搜不到板卡发热射频开关/GIPO 配置错误检查 RF 路径配置恢复默认电平手机放在 30 厘米内才能搜到发射功率过低或天线被遮挡调高 TX Power清理天线区域广播时有时无间隔不稳定低功耗模式/看门狗复位关闭低功耗检查复位原因寄存器手机能搜到但无法连接广播类型设置错误改用 ADV_IND 可连接广播只有部分手机能搜到扫描端权限或过滤设置检查定位/附近设备权限换 App 验证广播数据超过 31 字节传统广播溢出包被丢弃缩短数据或改用扩展广播推荐的排查顺序是先确认手机权限和 App 设置再用官方例程验证硬件和协议栈接着用最小工程逐个检查初始化返回值然后看串口日志最后才动天线和供电。这个顺序能最大化减少变量避免反复烧录浪费时间。6. 最后分享几个习惯排查 BLE 无广播问题做得多了我有几个固定习惯分享给大家。第一个习惯是拿到新板子后第一件事不是烧自己代码而是先备份 Flash 原始内容。用 STM32CubeProgrammer 的 Read 功能把整片 Flash 读出来存成 bin 文件。这样即使后面误全片擦除也能快速恢复出厂状态不用重新走一遍官方协议栈烧录流程。第二个习惯是永远保留一个最小广播工程模板不依赖厂商例程里的复杂业务逻辑。这个模板只有时钟初始化、协议栈初始化、一个 LED、一个广播启动函数。每次建新项目都从这个模板开始扩展一步验证一步问题范围会小很多。第三个习惯是别忽略串口日志。STM32WB 的 HCI 层会返回非常详细的错误码很多你以为的玄学问题日志里其实写得很明白。花半小时把日志解析熟比在网上查各种没广播怎么办的帖子高效得多。按照这条链路走下来NUCLEO-WB55RG 没有广播的问题基本都能在一个小时内定位到根因。剩下的就是祝你调通之后顺利进入 BLE 连接的下一关。