(四)BLE的广播及连接-通俗易懂
BLE的广播及连接
1、通信过程(广播及连接)
将一个复杂的任务进行拆分小的任务,也是从蓝牙协议栈分层设计中学的方法(关于蓝牙分层设计也可参考这个博客)。那将蓝牙通信也拆分三步学习,让我们由浅入深地来探索蓝牙广播和连接的奥秘。
-
第一步:蓝牙通信是如何“打包”数据的?
我们会从一个简单的问题开始:为什么设备不能直接把数据发送出去?看看蓝牙协议栈是如何像打包快递一样,一步步给原始数据穿上“外衣”的。 -
第二步:什么是蓝牙广播(Advertising)?
这就像是在广场上喊话。我们会学习设备如何通过广播“介绍”自己,让周围的设备发现它。 -
第三步:如何建立蓝牙连接(Connection)?
从“广场喊话”到“一对一私聊”。我们会看看两个设备是如何约定好时间、频道,并建立一个稳定、高效的专属通信渠道的。
2、第一步:蓝牙通信是如何“打包”数据的?
想象一下,你的智能手环想告诉手机它现在的电量是 50%(用十六进制表示就是 0x32)。如果它直接在空中发送一个 0x32,手机会一头雾水。这就像你把一张写着“50”的纸条扔出窗外,谁知道这是给谁的?谁写的?它代表什么意思呢?

所以,为了让通信有效,BLE 协议栈必须像打包一个精美的快递包裹一样,给 0x32 这个核心数据加上很多额外信息:
- 前导码 (Preamble): 像快递员在门口喊“有你的快递!”,它告诉接收设备:“注意,我要开始发数据啦!” 这能帮助接收方同步时钟,准备接收。
- 访问地址 (Access Address): 这就是收件人地址。有一个特殊的地址 0x8E89BED6,意思是“发给周围所有人”,这就是广播。而在一对一的连接中,会生成一个独一无二的地址,确保只有指定的设备能收。
- LL 帧头和长度 (LL Header & Length): 这部分说明了这个数据包的类型(是广播包还是连接包?),以及包裹里到底有多长的数据。
- 广播者地址 (Advertiser Address): 这是发件人地址,告诉大家这个数据包是谁发出的。
- 广播数据 (Advertising Data): 这才是我们的“货物”!但为了让对方看懂,我们不能只放一个 0x32。蓝牙使用一种叫 LTV (Length-Type-Value) 的结构来组织数据。比如,它可能会打包成 04FF590032,这里面包含了长度(04)、类型(FF, 表示自定义数据)、厂商ID(5900)和我们真正的数据(32)。这样手机才知道 0x32 代表的是电量,而不是别的。
- CRC 校验码 (CRC): 这是包裹的“防伪码”或“密封条”。接收方收到数据后会用同样的方法计算一遍 CRC,如果结果和发来的一致,就说明数据在传输过程中没有损坏或被篡改。
所以,一个简单的电量数据0x32,经过蓝牙协议栈的层层打包,最终在空中传输的可能是一长串复杂的数据,比如:AAD6BE898E600E2B852B2A02E802010504FF5900327C8D9E。
虽然看起来复杂,但这样做既保证了通信的可靠性。(如果不知道LL层、GAP层可以先参考BLE协议栈分层。)
扩展:前导码的作用
BLE(Bluetooth Low Energy)协议中的前导码,是指在数据报文的开头添加的一些比特(bit)序列。它的主要作用是帮助接收端(接收器)计算每个比特的时钟边沿位置,从而正确解码传输的数据。具体作用如下:
-
时钟同步:BLE协议采用 GFSK 调制方式进行数据传输,其调制波形中包含连续的过渡区域,用于传输正负两个不同频率的信号。但由于传输中可能存在抖动或时钟漂移等问题,接收器的时钟可能无法精确跟随发送器的时钟。在这种情况下,前导码可以帮助接收器对接收到的数据进行正确的时钟同步。
-
帧同步:BLE协议的数据传输采用分帧方式,每个数据包(packet)由不同的帧(frame)组成。前导码可以作为帧的起始标志,帮助接收器正确识别帧的起始位置和帧的边界。
-
消除直流分量:BLE协议的数据传输中,由于调制波形的特性,可能会产生直流分量。前导码中的比特序列可以通过交替出现1和0的方式,消除直流分量。
因此,BLE协议中的前导码是确保数据传输可靠性的重要组成部分,它可以对数据进行时钟同步、帧同步和消除直流分量等处理,从而保证接收器能够正确解码传输的数据。
3、第二步:什么是蓝牙广播?
现在我们已经理解了数据是如何被精心打包的,接下来就看看第一种通信方式——广播 (Advertising)。
你可以把广播想象成一个设备(比如你的蓝牙耳机)站在一个热闹的广场上,用大喇叭向周围所有人喊话:“嘿!我是一个XX牌的耳机,名叫‘MyMusic’,我在这里,可以被连接哦!” 听到这个喊话并关心‘MyMusic’就会去准备关联它。这种情况下,我们把蓝牙耳机叫Advertiser(广播者),关心喊话者叫Scanner或者Observer(扫描者)。
3.1、这种通信方式有几个鲜明的特点:
- 一对多通信:一个设备(称为 广播者 Advertiser)发送信息,周围所有在监听的设备(称为 扫描者 Scanner 或 观察者 Observer)都能收到。
- 单向通信:通常情况下,只有广播者在说话,扫描者只负责听。
- 周期性进行:广播者不会一直不停地喊话,那样太耗电了。它会每隔一段时间(这个间隔叫 广播间隔 Advertising Interval)喊一次。每一次喊话的行为,我们称之为一次 广播事件 (Advertising Event)。在不广播的时候,芯片就进入低功耗的“打盹”状态。
- 多频道广播:为了避免“堵车”和增加被听到的概率,广播者在每一次广播事件中,会依次在3个固定的广播信道(37、38、39号频道)上把同样的内容各发送一遍。

广播参数相关扩展一:广播事件及广播间隔:
广播是指从机每经过一个时间间隔发送一次广播数据包,这个时间间隔称为广播间隔,这个广播动作叫做广播事件,只有当从机处于广播状态时,主机才能发现该从机。在每个广播事件中,广播包会分别在37,38和39三个信道上依次广播,如下图所示。
那广播间隔怎么计算的呢?具体计算入下图所示:
T_advEvent = advInterval + advDelay
T_advEvent 也就是图中蓝色部分 ;advInterval 是 0.625ms 的倍数,在 20ms~10.24s 之间。如果广播类型是非定向扫描事件或者非定向不可连接广播事件,这个值不能小于 100ms。如果广播事件类型是非定向可连接事件,这个是只需大于20ms 即可;
advDelay 是一个随机数,在 0ms~10ms 之间,在每一个广播事件中都有。 由于设备间的时钟会有不同程度的漂移,所以这个随机延时的作用不但能消除设备之间时钟漂移,还能避免相同信道及时间点上的冲突。
广播参数相关扩展二:广播类型:
广播的类型一般分为四种,分别是:
1.可连接的非定向广播(Connectable UndirectedEvent Type)。
这是一种用途最广的广播类型,包括广播数据和扫描响应数据,它表示当前设备可以接受其他任何设备的连接请求。这个报文发送之后可以接收由扫描者发送的(SCAN_REQ PDU)扫描 请求,或者由发起者发送的(CONNECT_REQ PDU)连接请求。而接收后 链路层需要早同一个信道上进行扫描者或者发起者的应答。当接收的 数据报文没能通过广播滤波政策,要么就用下一个广播信道进行广播 要么就关闭广播事件。
2.可连接的定向广播(Connectable DirectedEvent Type)。
定向广播类型是为了尽可能快的建立连接。**这种报文包含两个地址:广播者的地址和发起者的地址。**发起者收到发给自己的定向广播报文之后,可以立即发送连接请求作为回应。
定向广播类型有特殊的时序要求。完整的广播事件必须每3.75ms重复一次。这一要求使得扫描设备只需扫描3.75ms便可以收到定向广播设备的消息。
当然,如此快的发送会让报文充斥着广播信道,进而导致该区域内的其他设备无法进行广播。因此,定向广播不可以持续1.28s以上的时间。如果主机没有主动要求停止,或者连接没有建立,控制器都会自动停止广播。一旦到了1.28s,主机便只能使用间隔长得多的可连接非定向广播让其他设备来连接。
当使用定向广播时,设备不能被主动扫描。此外,定向广播报文的净荷中也不能带有其他附加数据。该净荷只能包含两个必须的地址。
3.不可连接的非定向广播(Non-connectableUndirected Event Type)。
仅仅发送广播数据。
4.可扫描的非定向广播(Scannable UndirectedEvent Type)。
这种广播不能用于发起连接,但允许其他设备扫描该广播设备。这意味着该设备可以被发现,既可以发送广播数据,也可以响应扫描发送扫描回应数据,但不能建立连接。这是一种适用于广播数据的广播形式,动态数据可以包含于广播数据之中,而静态数据可以包含于扫描响应数据之中。
注意:所谓的定向和非定向针对的是广播的对象,如果是针对特定的对象进行广播(在广播包PDU中会包含目标对象的MAC)就是定向广播,反之就是非定向。可连接和不可连接是指是否接受连接请求,如果是不可连接的广播类型,它将不回应连接请求。可扫描广播类型是指回应扫描请求。
3.2、广播里喊了些什么?
-
广播包里能携带的数据很有限(蓝牙4.x标准里最多31个字节) 。通常包含一些基本信息,比如:
-
设备名称:例如 “MyMusic”。
-
设备功能:例如声明自己支持BLE、是否可被连接等。
-
服务UUID:告诉别人它能提供什么服务,比如心率监测服务、电量服务等。
注意提示:蓝牙4.x,广播有效载荷最多是31个字节。而在蓝牙5.0中,通过添加额外的广播信道和新的广播PDU,将有效载荷增加到了255个字。
3.3、广播的局限性:
虽然广播对于设备发现非常重要,但它就像广场喊话一样,存在一些缺点:
- 无法双向交流:扫描者没法直接回应。
- 传输数据量小:31字节装不下太多东西。
- 不可靠:广播者只管发,并不知道有没有人收到,也不会重发。
- 扫描端功耗高:扫描者为了不错过广播,需要长时间、多频道地开启接收窗口,比较耗电。
为了解决这些问题,就需要更高级的通信方式——连接!
4、第三步:如何建立蓝牙连接(Connection)?
当你的手机(扫描者)在广播中“听”到了智能门锁的“喊话”,并决定要和它通信(比如开锁)时,就需要建立连接。这个过程就像下面这样:
-
发起连接请求 (Connection Request)
- 手机不再仅仅是倾听,它会变成一个 发起者 (Initiator)。
- 它会抓住门锁广播后短暂的监听窗口,发送一个名为 CONNECT_REQ 的连接请求包。这个请求就像是在说:“嘿,门锁!我想和你单独聊聊!”
-
约定通信规则
这个 CONNECT_REQ 包里包含了接下来“私聊”的所有规则 ,比如:-
连接间隔 (Connection Interval):我们每隔多久通信一次?可以是从几毫秒到几秒。
-
信道图 (Channel Map):我们接下来用哪些数据信道来聊天,避开那些拥挤的信道。
-
访问地址 (Access Address):生成一个这次通信专用的“门牌号”,以后只有我们俩的通信才用它。
-
-
连接成功,角色转变
一旦门锁收到了这个请求并做好了准备,连接就建立了。此时,它们的角色也发生了变化:- 手机(主动发起连接的一方)变成了 主设备 (Master/Central)。
- 门锁(被连接的一方)变成了 从设备 (Slave/Peripheral)。
-
连接后的通信
连接成功后,通信变得非常规律和高效,就像跳双人舞一样:- 主设备先行:在每个连接间隔的开始,总是由主设备(手机)先给从设备(门锁)发送一个数据包。
- 从设备回应:从设备在收到主设备的数据包后,必须在极短的时间内(150微秒)回复一个自己的数据包。
- 轮流休眠:在两次通信间隔之间,主从设备都可以关闭射频天线去“睡觉”,从而极大地节省了电量。只有在连接事件 (Connection Event) 发生时,它们才会醒来工作。
这种主从模式、周期性通信的方式,完美地解决了广播的几大痛点,实现了可靠、双向、低功耗的一对一通信!
4.1、抽象类比
根据上面的例子,我们大概了解了什么时连接,下面再进行抽象类比一下:
到底什么叫连接(connection)?像串口UART,很容易理解,就是用线(Rx和Tx等)把设备A和设备B相连。用“线”把两个设备相连,实际是让2个设备有共同的通信媒介,并让两者时钟同步起来。进行类比蓝牙连接也是这个道理,所谓设备A和设备B建立蓝牙连接,就是指设备A和设备B两者一对一“同步”成功,其具体包含以下几方面:
-
设备A和设备B对接下来要使用的物理信道达成一致
-
设备A和设备B双方建立一个共同的时间锚点,也就是说,把双方的时间原点变成同一个点
-
设备A和设备B两者时钟同步成功,即双方都知道对方什么时候发送数据包什么时候接收数据包
-
连接成功后,设备A和设备B通信流程如下所示:

如上图所示,一旦设备A和设备B连接成功(此种情况下,我们把设备A称为Master或者Central,把设备B称为Slave或者Peripheral),设备A将周期性以Connection Interval (CI)为间隔向设备B发送数据包,而设备B也周期性地以CI为间隔打开射频接收窗口以接收设备A的数据包。同时按照蓝牙Spec要求,设备B收到设备A数据包150us后,设备B切换到发送状态,把自己的数据发给设备A;设备A则切换到接收状态,接收设备B发过来的数据。由此可见,连接状态下,设备A和设备B的射频发送和接收窗口都是周期性地有计划地开和关,而且开的时间非常短,从而大大降低系统功耗并大大提高系统效率。
5、广播实际抓包分析
下面看一个ADV_IND例子,如下图展示了一个完整的普通广播数据包(这个图借鉴图,来源不好意思忘了,后续更新掉,谢谢)。
依次点击左侧描述,在右侧可以看到对应的数值。
(1) PDU Type为0000b,表示广播包类型为ADV_IND,如图所示。

(2) ChSel字段为0b,表示不支持通道选择,如图2-5所示。

(3) TxAdd字段为0b,表示广播设备地址类型是public,如图2-6所示。

(4) Length地段为0x23(35),表示广播数据包净荷长度为35个字节,如图2-7所示。

(5) AdvA字段为0xa4c1382e6f3c,是广播设备的地址,如图2-8所示。

一般AdvData都会包含“Device Name”、“Flags”、“Appearance”、“UUID”,在图2-3中可以看到这些元素。设备名就是我们搜索设备时看到的名字;Flags是标识发现模式和是否使用BR/EDR的;外观是定义该产品的类型,如键盘、鼠标、遥控器等等;UUID一般用来标识设备使用哪些属性。
(6) AdvData字段为广播地址后面的29个字节,是广播包携带的信息,如图2-9所示。

上面是我一家之言,同主题对比阅读,才能更好理解。如有错误请指出,谢谢。
更多推荐


所有评论(0)