3、链路层状态机:Standby、Advertising、Scanning、Initiating、Connection 状态,以及 Idle 与 Sleep 的区分
链路层状态机,说白了就是 BLE 设备在底层到底在干什么。我刚开始啃 BLE 协议栈时,觉得这五个状态绕来绕去,后来自己画了一张图,才真正理清楚。
这五个状态分别是:Standby、Advertising、Scanning、Initiating、Connection。另外还有两个容易混淆的概念:Idle 和 Sleep。咱们一个一个说。
核心要点:链路层状态机是 BLE 协议栈的底层调度核心。所有无线活动,都在这五个状态之间切换。理解状态机,你就理解了 BLE 的“心跳”。
3.1 五个核心状态
先看一张我手绘的状态机图,你跟着箭头走一遍,基本就懂了。
3.2 逐个拆解
Standby(待机态)
这是所有状态的起点和终点。设备上电后,默认就在 Standby。此时射频关闭,不发送也不接收任何数据。说白了,就是“啥也不干”。
我个人习惯把 Standby 比作“宿舍里的床”——你可以随时躺上去,也可以随时爬起来干活。从 Standby 可以跳到 Advertising、Scanning 或 Initiating,反过来这三个状态也能回到 Standby。
Advertising(广播态)
设备在广播态时,会周期性地在三个广播信道(37/38/39)上发送广播包。广播包分两种:
- 可连接广播:允许其他设备发起连接。这是外设(Peripheral)的典型行为。
- 不可连接广播:只发不收,常用于 Beacon 类应用。
我在项目中遇到过一个问题:广播间隔设得太短,导致功耗飙升。你想想看,每 20ms 发一次包,和每 100ms 发一次包,电流差距可不是一星半点。
经验之谈:广播间隔建议设为 100ms 以上。除非你的应用对连接速度有硬性要求,否则别为了快那几百毫秒,把电池寿命搭进去。
Scanning(扫描态)
扫描态的设备在监听广播信道。它不主动发数据,只是“听”。扫描分两种模式:
- 被动扫描:只听,不发任何包。
- 主动扫描:听到广播后,会发一个扫描请求,获取更多信息。
嗯,这里要注意:主动扫描会多一次交互,功耗自然更高。如果你只是想知道周围有没有设备,被动扫描就够了。
Initiating(发起态)
这个状态比较特殊。它本质上是一种“定向扫描”——设备在扫描时,如果发现某个特定的广播地址,就会立即发送连接请求。发起态只能从 Scanning 进入,而且只能针对可连接广播。
我曾经调试过一个 Bug:设备明明扫描到了广播,但就是连不上。后来发现是发起态的超时时间设得太短,还没来得及发连接请求就超时了。这种坑,踩过一次就记住了。
Connection(连接态)
连接建立后,双方进入 Connection 状态。此时设备角色分为 Master(主设备)和 Slave(从设备)。连接态下,双方按照约定的连接间隔(Connection Interval)定期交换数据。
连接态是 BLE 休眠唤醒机制的主战场。后面几章会详细展开,这里先记住:连接态不等于一直收发,它内部还有更细的休眠策略。
3.3 Idle 与 Sleep 的区分
这两个概念经常被混为一谈,但它们在 BLE 协议栈里是完全不同的东西。
| 概念 | 所属层级 | 含义 | 射频状态 | 典型场景 |
|---|---|---|---|---|
| Idle | 链路层状态机 | 设备处于 Standby 状态,无任何无线活动 | 关闭 | 设备刚上电、广播/扫描结束后 |
| Sleep | 主机控制器接口(HCI)/ 芯片级 | 芯片进入低功耗模式,CPU 时钟停止或降频 | 关闭 | 连接间隔之间的空闲时段 |
说白了,Idle 是状态机里的一个“位置”,而 Sleep 是芯片的一种“工作模式”。设备可以在 Idle 状态下不 Sleep(比如 CPU 还在跑),也可以在 Connection 状态下进入 Sleep(比如两个连接事件之间)。
避坑指南:我曾经把 Idle 和 Sleep 当成一回事,结果在调试低功耗时,发现设备明明进入了 Standby,电流却居高不下。后来才意识到:Standby 只是链路层不干活了,但 CPU 还在全速运行。要让芯片真正省电,必须主动调用 Sleep 接口。
3.4 状态切换的实际流程
咱们用一个实际例子串一遍:
- 设备上电,进入 Standby(Idle 状态)。
- 应用层要求开始广播,链路层切换到 Advertising。
- 另一个设备开始 Scanning,发现了这个广播。
- 扫描设备决定连接,进入 Initiating,发送连接请求。
- 双方握手成功,进入 Connection。
- 连接断开后,双方回到 Standby。
你看,整个流程就是一条清晰的路径。每个状态之间的切换,都由特定的事件触发——比如定时器超时、收到数据包、应用层指令等。
3.5 小结
链路层状态机是 BLE 协议栈的骨架。Standby 是起点,Advertising 和 Scanning 是发现阶段,Initiating 是连接前的最后一步,Connection 是数据交换的主战场。而 Idle 和 Sleep 的区别,说白了就是“状态”和“模式”的区别——一个是逻辑上的空闲,一个是物理上的休眠。