怎么理解BLE“连接”,如何通过无线发送一个数据包?一文简单概述

继上一篇,相信还是很多人不懂BLE协议栈的工作原理,那么本篇就以如何发送一个数据包为例来讲解BLE协议栈各层是如何紧密配合,以完成发送任务的。

如何通过无线发送一个数据包

假设有设备A和设备B,设备A要把自己目前的电量状态83%(十六进制表示为0x53)发给设备B,该怎么做呢?作为一个开发者,他希望越简单越好,对他而言,他希望调用一个简单的API就能完成这件事,比如send(0x53),实际上我们的BLE协议栈就是这样设计的,开发者只需调用send(0x53)就可以把数据发送出去了,其余的事情BLE协议栈帮你搞定。很多人会想,BLE协议栈是不是直接在物理层就把0x53发出去,就如下图所示:

怎么理解BLE“连接”,如何通过无线发送一个数据包?一文简单概述

这种方式初看起来挺美的,但由于很多细节没有考虑到,实际是不可行的。首先,它没有考虑用哪一个射频信道来进行传输,在不更改API的情况下,我们只能对协议栈进行分层,为此引入LL层,开发者还是调用send(0x53),send(0x53)再调用send_LL(0x53,2402M)(注:2402M为信道频率)。这里还有一个问题,设备B怎么知道这个数据包是发给自己的还是其他人的,为此BLE引入*access address概念,用来指明接收者身份*,其中,0x8E89BED6这个access address比较特殊,它表示要发给周边所有设备,即广播。如果你要一对一的进行通信(BLE协议将其称为*连接*),即设备A的数据包只能设备B接收,同样设备B的数据包只能设备A接收,那么就必须生成一个独特的*随机*access address以标识设备A和设备B两者之间的连接。

广播方式

我们先来看一下简单的广播情况,这种情况下,我们把设备A叫*advertiser*(广播者),设备B叫*scanner*或者*observer*(扫描者)。广播状态下设备A的LL层API将变成send_LL(0x53,2402M, 0x8E89BED6)。由于设备B可以同时接收到很多设备的广播,因此数据包还必须包含设备A的device address(0xE1022AAB753B)以确认该广播包来自设备A,为此send_LL参数需要变成(0x53,2402M, 0x8E89BED6,0xE1022AAB753B)。LL层还要检查数据的完整性,即数据在传输过程中有没有发生窜改,为此引入CRC24对数据包进行检验 (假设为0xB2C78E) 。同时为了调制解调电路工作更高效,每一个数据包的最前面会加上1个字节的preamble(前导帧),preamble一般为0x55或者0xAA。这样,整个空中包就变成(注:*空中包用小端模式表示!*):

怎么理解BLE“连接”,如何通过无线发送一个数据包?一文简单概述

连接方式

到底什么叫连接(connection)?像有线UART,很容易理解,就是用线(Rx和Tx等)把设备A和设备B相连,即为连接。用“线”把两个设备相连,实际是让2个设备有共同的通信媒介,并让两者时钟同步起来。蓝牙连接有何尝不是这个道理,*所谓设备A和设备B建立蓝牙连接,就是指设备A和设备B两者“同步”成功*,其具体包含以下几方面:

* 设备A和设备B对接下来要使用的物理信道达成一致

* 设备A和设备B双方建立一个共同的时间锚点,也就是说,把双方的时间原点变成同一个点

* 设备A和设备B两者时钟同步成功,即双方都知道对方什么时候发送数据包什么时候接收数据包

* 连接成功后,设备A和设备B通信流程如下所示:

怎么理解BLE“连接”,如何通过无线发送一个数据包?一文简单概述

如上图所示,一旦设备A和设备B连接成功(此种情况下,我们把设备A称为*Master*或者*Central*,把设备B称为*Slave*或者*Peripheral*),设备A将周期性以CI(connection interval)为间隔向设备B发送数据包,而设备B也周期性地以CI为间隔打开射频接收窗口以接收设备A的数据包。同时按照蓝牙spec要求,设备B收到设备A数据包*150us后*,设备B切换到发送状态,把自己的数据发给设备A;设备A则切换到接收状态,接收设备B发过来的数据。由此可见,连接状态下,设备A和设备B的射频发送和接收窗口都是周期性地有计划地开和关,而且开的时间非常短,从而大大减低系统功耗并大大提高系统效率。


分享到:


相關文章: