第4章 GAP层联调:广播与连接参数的那些坑
GAP层,说白了就是蓝牙设备的“社交礼仪”。设备怎么打招呼、怎么回应、怎么建立长期关系,全归它管。我做了这么多年蓝牙开发,GAP层出的问题至少占联调阶段的一半以上。今天咱们就把广播参数、扫描参数、连接参数、白名单这几个核心模块掰开揉碎聊一聊。
本章核心脉络:广播参数决定“怎么喊” → 扫描参数决定“怎么听” → 连接参数决定“怎么聊” → 白名单决定“跟谁聊”。四个环节环环相扣,任何一个参数配错,联调都可能卡好几天。
4.1 广播参数配置:别让你的设备“喊破嗓子”
广播参数是GAP层最基础、也最容易出问题的地方。我见过太多团队联调时,两边设备明明都在广播,就是互相发现不了。为什么?广播参数没对齐。
4.1.1 广播间隔:快与慢的博弈
广播间隔决定了设备多久发一次广播包。BLE协议规定范围是20ms到10.24s,但实际用起来远没那么简单。
| 场景 | 推荐间隔 | 原因 |
|---|---|---|
| 快速发现(配对/配置) | 20ms - 50ms | 用户等不了,越快越好 |
| 正常广播(信标/设备发现) | 100ms - 500ms | 功耗与发现速度的平衡点 |
| 低功耗广播(电池供电) | 1s - 2s | 省电优先,发现慢点无所谓 |
我曾经踩过的坑:有一次做智能门锁项目,广播间隔设了20ms,结果手机扫描死活搜不到。查了两天才发现——广播间隔太短,信道冲突率飙升,丢包率超过60%。后来改成100ms,问题立刻解决。记住:广播间隔不是越小越好,20ms在实验室环境可能没问题,到了真实场景,干扰一多就完蛋。
4.1.2 广播类型:可连接 vs 不可连接
广播类型有四种,但联调中最常用的是两种:
- 可连接非定向广播:最常用,任何扫描设备都能发起连接
- 不可连接非定向广播:只发数据,不接受连接,信标设备常用
我个人的习惯是:联调初期先用可连接广播,等基本功能调通后再根据需求切换。你想想看,如果一开始就设成不可连接,两边连不上,你都不知道是广播问题还是扫描问题。
4.1.3 广播通道:37/38/39的选择
BLE有三个广播通道:37(2402MHz)、38(2426MHz)、39(2480MHz)。默认情况下三个通道都会发,但有些场景需要调整。
小技巧:如果设备在WiFi密集的环境下工作(比如办公室),建议避开WiFi的Channel 1(2412MHz)和Channel 6(2437MHz)。我一般会保留37和39,关闭38——因为38离WiFi的Channel 6太近了,干扰特别严重。
4.2 扫描参数优化:别让你的设备“听不见”
广播参数配好了,扫描端也得跟上。扫描参数的核心就两个:扫描窗口和扫描间隔。
4.2.1 扫描窗口 vs 扫描间隔
扫描窗口是每次扫描持续的时间,扫描间隔是两次扫描开始之间的时间差。这两个参数决定了扫描的“占空比”。
// 典型的扫描参数配置(以TI CC254x为例)
#define DEFAULT_SCAN_INTERVAL 0x100 // 160ms
#define DEFAULT_SCAN_WINDOW 0x050 // 50ms
// 快速扫描配置(用于配对场景)
#define FAST_SCAN_INTERVAL 0x030 // 30ms
#define FAST_SCAN_WINDOW 0x030 // 30ms // 连续扫描模式
说白了,扫描窗口越接近扫描间隔,扫描越密集,发现设备越快,但功耗也越高。我建议联调时先用连续扫描(窗口=间隔),等确认能发现设备了,再优化参数降低功耗。
4.2.2 被动扫描 vs 主动扫描
这个坑我见过太多次了。被动扫描只收广播包,不发送扫描请求;主动扫描会发扫描请求,获取设备的扫描响应数据。
很多新手把扫描端设成被动扫描,结果收不到设备的完整广播数据,以为是设备没发。其实设备发了,只是扫描端没去“要”而已。
经验之谈:如果你的广播数据超过31字节(需要用到扫描响应),扫描端必须用主动扫描。否则,你只能收到前31字节,后面的数据全丢了。我在做ibeacon项目时就吃过这个亏,调试了两天才发现是扫描模式设错了。
4.3 连接参数协商:最容易被忽略的“隐形杀手”
连接参数协商是GAP层联调中最复杂、也最容易出问题的环节。很多团队广播和扫描都调通了,但一建立连接就断,或者连接后数据传着传着就断了。十有八九是连接参数没谈拢。
4.3.1 连接参数的核心要素
| 参数 | 范围 | 说明 |
|---|---|---|
| 最小连接间隔 | 7.5ms - 4s | 连接间隔的下限,单位1.25ms |
| 最大连接间隔 | 7.5ms - 4s | 连接间隔的上限,单位1.25ms |
| 从机延迟 | 0 - 499 | 从设备可以跳过多少个连接事件 |
| 监督超时 | 100ms - 32s | 超过这个时间没收到包就断连,单位10ms |
4.3.2 参数协商的“潜规则”
连接参数不是主机单方面决定的。从机可以发起参数更新请求,主机可以接受或拒绝。这个协商过程,说白了就是两边讨价还价。
我遇到过最典型的问题:从机要求最小连接间隔7.5ms,但主机芯片不支持这么快的间隔(比如某些低端芯片最小只能到15ms)。结果主机直接拒绝,连接就断了。
避坑指南:从机发起参数更新请求时,一定要查主机芯片的数据手册,确认它支持的最小/最大间隔范围。我曾经在项目中把最小间隔设成7.5ms,结果对方用的是Nordic nRF51系列,最小只能到10ms,协商失败后连接直接断开。后来改成15ms,两边都满意。
4.3.3 从机延迟的“双刃剑”
从机延迟允许从设备在连续几个连接事件中不回复数据,从而省电。但延迟设得太大,会导致数据延迟增加。
举个例子:连接间隔30ms,从机延迟设成9。那么从设备最多可以跳过9个连接事件,也就是270ms不回复。如果主机发了数据,从机要等270ms才能收到。这对实时性要求高的场景(比如音频、遥控)是致命的。
我的建议:数据量大的场景,从机延迟设成0;省电场景,从机延迟不要超过3。超过3之后,用户体验会明显变差。
4.3.4 监督超时的“安全网”
监督超时是连接的最后一道防线。如果超过这个时间没收到任何包,双方都会认为连接已断开。
公式很简单:监督超时 > 连接间隔 × (1 + 从机延迟) × 2
为什么?因为从机最多可以跳过(从机延迟)个连接事件,再加上主机可能丢包,所以至少要留两倍的余量。
// 举个例子
连接间隔 = 50ms
从机延迟 = 5
最小监督超时 = 50ms × (1 + 5) × 2 = 600ms
// 实际配置建议留30%余量
推荐监督超时 = 600ms × 1.3 = 780ms → 取整为800ms
4.4 白名单与绑定:只跟“认识的人”说话
白名单和绑定是GAP层安全机制的核心。白名单决定谁可以扫描/连接我,绑定决定谁可以跟我建立加密连接。
4.4.1 白名单的两种模式
- 扫描白名单:只允许白名单内的设备扫描到我
- 连接白名单:只允许白名单内的设备连接我
这两个可以独立配置。我一般建议联调初期先关掉白名单,等基本功能调通后再开启。否则两边设备互相找不到,你都不知道是白名单的问题还是广播的问题。
4.4.2 绑定流程的“握手”细节
绑定不是自动发生的。它需要主机发起绑定请求,从机确认,然后交换密钥。这个过程中,任何一个步骤超时或失败,绑定就断了。
我遇到过最坑的问题:从机在绑定过程中突然进入低功耗模式,导致绑定请求超时。后来在绑定期间强制从机不休眠,问题解决。
关键提醒:绑定过程中,不要做任何其他操作(比如同时进行数据传输)。绑定本身就需要交换多个包,如果中间插了其他数据,很容易导致绑定失败。我习惯在绑定前先暂停所有业务数据,绑定完成后再恢复。
4.4.3 白名单与绑定的配合
绑定成功后,设备地址会自动加入白名单。但有个细节:绑定用的是“长期密钥”,白名单用的是“设备地址”。如果设备地址变了(比如用了随机地址),白名单就失效了。
所以,如果你用了随机地址,绑定后一定要把当前的随机地址加入白名单,而不是用静态地址。这个坑我踩过两次,第一次排查了整整一天。
4.5 联调实战:一个完整的GAP层调试流程
说了这么多理论,咱们来点实际的。下面是我个人总结的GAP层联调标准流程:
- 第一步:确认广播。用手机APP(比如nRF Connect)扫描,看能不能发现设备。如果发现不了,检查广播间隔、通道、发射功率。
- 第二步:确认扫描。用设备扫描手机(手机模拟广播),看设备能不能发现手机。如果发现不了,检查扫描窗口和扫描模式。
- 第三步:建立连接。两边都能互相发现了,尝试建立连接。如果连不上,检查连接参数是否在双方支持的范围内。
- 第四步:测试稳定性。连接建立后,持续传输数据30分钟以上,看会不会断连。如果断连,检查监督超时和从机延迟。
- 第五步:开启安全机制。最后再开启白名单和绑定,确认安全功能正常。
最后提醒一句:GAP层联调最忌讳“一把抓”。每次只改一个参数,改完测试,确认没问题再改下一个。我见过太多人一次性改了广播间隔、扫描窗口、连接参数三个地方,结果出了问题根本不知道是哪个参数导致的。记住:控制变量法是联调的第一原则。