4. BLE广播与扫描:广播信道与数据信道、广播包格式、扫描参数优化、连接间隔设置

BLE的广播机制,说白了就是设备在“喊话”。它不关心有没有人在听,只管按固定节奏往外丢数据包。我刚开始做低功耗项目时,总觉得广播嘛,不就是发几个字节吗?结果一测功耗,电池撑了不到三天就趴窝了。后来才明白——广播这玩意儿,用好了是门铃,用不好就是广场舞大喇叭。

4.1 广播信道与数据信道

BLE在2.4GHz频段划分了40个信道,编号0~39。但真正用于广播的只有3个:37、38、39。为什么是这三个?

你想想看,2.4GHz频段上Wi-Fi和蓝牙挤在一起,干扰很严重。BLE的设计者特意选了三个互不重叠的信道——37在2402MHz,38在2426MHz,39在2480MHz。它们避开了Wi-Fi的1、6、11三个主信道,能最大程度降低碰撞概率。

信道分配速查表

信道编号 频率(MHz) 用途 备注
37 2402 广播/扫描 起始信道
38 2426 广播/扫描 中间信道
39 2480 广播/扫描 最高频信道
0~36 2404~2478 数据通信 连接后使用

数据信道则不同。连接建立后,双方会在37个数据信道上跳频通信。跳频序列由连接事件决定,每次收发都换一个信道。我有个项目就因为没处理好跳频同步,导致连接后频繁断连——后来发现是主从设备的信道映射表没对齐。

4.2 广播包格式

广播包的结构其实不复杂。我拆开给你看:

广播包 = 前导码(1字节) + 接入地址(4字节) + PDU(2~39字节) + CRC(3字节)

PDU是核心部分。它又分成两种:

  • ADV_IND:可连接的非定向广播,最常用
  • ADV_NONCONN_IND:不可连接的非定向广播,纯广播场景用
  • ADV_SCAN_IND:可扫描的非定向广播,允许扫描请求
  • ADV_DIRECT_IND:定向广播,指定目标设备

PDU内部结构长这样:

PDU头部(2字节) + 广播地址(6字节) + 广播数据(0~31字节)

广播数据部分采用AD Structure格式:

长度(1字节) + AD Type(1字节) + AD Data(长度-1字节)

我的习惯:广播数据最多31字节,但实际能用的往往更少。我一般把核心信息控制在20字节以内,留出余量给厂商自定义数据。曾经有个项目非要塞满31字节,结果扫描端解析时频繁丢包——广播数据越长,接收成功率越低。

4.3 扫描参数优化

扫描参数直接影响功耗和发现速度。核心参数就两个:

  • 扫描窗口:每次扫描持续的时间
  • 扫描间隔:两次扫描开始之间的时间

扫描器在每个广播信道上监听扫描窗口时长,然后跳到下一个信道。一个完整的扫描周期覆盖37、38、39三个信道。

注意:扫描窗口不能大于扫描间隔。如果窗口=间隔,那就是连续扫描——功耗最高,但发现最快。如果窗口远小于间隔,功耗低,但可能错过广播包。

我常用的经验值:

场景 扫描窗口 扫描间隔 平均功耗
快速发现 30ms 30ms 高
平衡模式 30ms 100ms 中
低功耗 10ms 500ms 低

我曾经做过一个信标项目,要求电池撑一年。扫描端是手机,功耗不是问题。但广播端是纽扣电池设备,广播间隔设了500ms,扫描窗口设了30ms——结果手机经常要等好几秒才能发现设备。后来我把广播间隔降到200ms,扫描窗口提到50ms,发现时间缩短到1秒以内,功耗只多了不到10%。

4.4 连接间隔设置

连接建立后,主从设备按固定间隔交换数据。这个间隔叫连接间隔(Connection Interval),范围是7.5ms~4s,步进1.25ms。

连接间隔的选择是个权衡:

  • 间隔小:延迟低,数据吞吐高,但功耗大
  • 间隔大:功耗低,但延迟高,吞吐低

我一般按这个原则选:

  1. 实时控制类(如遥控器):7.5ms~30ms
  2. 数据采集类(如传感器):50ms~200ms
  3. 低功耗监测类(如温湿度计):500ms~2s

避坑指南:我曾经把连接间隔设成4s,想着省电。结果设备每隔4秒才发一次数据,用户按了遥控器要等4秒才有反应——产品直接被退货。后来改成30ms,功耗虽然高了点,但用户体验完全不一样。

还有一个容易被忽略的参数:从机延迟(Slave Latency)。它允许从设备跳过若干个连接事件,继续睡眠。比如连接间隔100ms,从机延迟设为9,那从设备可以睡1秒才起来收一次数据。这对低功耗非常友好。

但要注意:从机延迟不能太大,否则主设备会认为连接丢失。BLE规范规定,从机延迟最大值为499,但实际芯片往往有更严格的限制。

4.5 广播与扫描的完整流程

我把整个流程画了张图,方便你理解:

BLE广播与扫描流程 广播设备 广播信道(37/38/39) 扫描设备 发送广播包 接收广播包 扫描窗口/间隔 广播间隔 连接间隔 连接建立 → 跳频到数据信道(0~36) 数据通信(按连接间隔周期性收发) 关键参数总结: 广播间隔:决定发现速度 | 扫描窗口/间隔:决定扫描功耗 | 连接间隔:决定通信延迟与功耗 从机延迟:允许跳过连接事件,进一步降低功耗

4.6 实战建议

最后给几个我踩过坑之后总结的经验:

广播间隔别太短:20ms以下的广播间隔会让芯片持续发射,功耗飙升。除非你做的是一对一的快速配对,否则建议100ms起步。

扫描窗口别太大:连续扫描(窗口=间隔)的功耗是间歇扫描的3~5倍。如果不需要实时发现,把扫描窗口降到10ms,间隔拉到500ms以上。