记录蓝牙学习过程,分享个人理解和资料分享,欢迎各位朋友、前辈交流和指教。持续更新中!
蓝牙协议栈介绍
BLE协议栈可分为Bluetooth Application和Bluetooth Core两大部分,其中Bluetooth Core又包含BLE Controller和BLE Host两部分。下面从下往上进行分析:
1、Physical Layer(物理层)
任何通信系统都需要确定其通信介质,BLE也是一样。在BLE协议中Physical Layer如下描述:
由于BLE属于无线通信,则其通信介质是一定频率范围下的频带资源(Frequency Band);
BLE的市场定位是个体和民用,因此使用的是免费ISM频段(频段范围是2.400~2.4835GHz);
为了同时支持多个设备,将整个频带分为40个信道,每个信道为2MHz。
经过如上定义,BLE的物理通道已经确定了,频点分别为 f=2402+k*2MHz , K=0~39,带宽为2MHz的40个信道。
如果想进一步了解物理层的其他特性,可以深入了解以下几点:
RF发射相关的特性:发射功率、调制方式(高斯频移键控)、杂散、射频频率误差;
RF接收相关的特性:实际灵敏度。
2、Link Layer(链路层)
在Physical Layer中定义了40个传输信道。如何在这些信道上传输和控制RF收发相关的参数就是链路层需要做的事情,但这是其中一部分:
首先,Physical Layer仅仅提供了有限的40个Channel,而BLE中参与通信的实体数量肯定不是这个数量级,Link Layer需要解决Channel的共享问题;
2.1 链路层状态
链路层可以抽象为以下五种状态:
- Standby State
- Advertising State
- Scanning State
- Initiating State
- Connection State
链路层状态机在同一时刻只允许处于一个状态。但链路层可能有多个链路层状态机实例,这就意味着BLE设备在一个状态机保持连接的同时,另一个状态机可以保持广播或者扫描状态,或者多个链路状态机都处于连接状态,这是BLE实现多个连接的基础。
Standby状态是初始状态,即不发送数据,也不接受数据。根据上层实体的命令(如host层的GAP),可由其他任何状态进入,也可切换到除Connection状态外的任何一种状态;
Advertising状态是可以发送广播数据包,由Standby状态进入。广播的数据可以由处于Scanning或Initiating状态的实体接收。上层实体可通过命令将Advertising状态切换回Standby状态。在连接成功后,切换到Connection状态;
Scanning状态可以通过广播通道接收数据的状态,由Standby状态进入。根据Advertiser所广播的数据类型,有些Scanner还可以主动向Advertiser请求一些额外的数据。上层实体可通过命令切换回Standby状态;
Initiating状态和Scanning状态类似,是处于特殊的接收状态,由Standby状态进入,只能接收Advertiser广播的connection数据,并在接收到数据后发送连接请求,以便和Advertiser建立连接。当连接成功后,Initiater和对应的Advertiser都会切换到Connection状态。
Connection状态是和某个实体建立了单独通道的状态,在通道建立之后,由Initiating或Advertising自动切换而来。通道断开连接后,会重新回到Standby状态。
处于已连接状态的双方会分为两种角色:
- 从Initiating State进入的称为Mater(主机);
- 从Advertising State进入的称为Slave(从机)。
2.2蓝牙空中接口数据包组成解析
在状态和角色定义完成后,需要有相应的协议来进行数据交互。主要包括两种情况:第一种是在某一状态下和其他实体对应状态之间的数据交互机制;第二种是根据上层实体指令和当前的实际情况,负责状态之间的切换。在BLE中这部分的协议称为Air Interface Protocol(空中接口协议)。
2.2.1 数据包格式
最短包长为10个字节,最长包长为47个字节。
2.2.1.1 前导码
BLE 4.2 1M的Preamble是8bits
前导码长度为8位,在接收中用于频率同步、数据速率同步和AGC调整。
在广播通道中,访问地址固定为10001110100010011011111011010110b(0x8E89BED6),最低位为0所以,所以广播通道的引导码固定为10101010(0xAA)。
在数据通道中,如果访问地址最低位为1,引导码为01010101(0x55),否则为10101010(0xAA)
BLE 5.0 新增了2M PHY模式,Preamble是16bits
当访问地址的LSB(最低有效位)为1时,引导码为:10101010 10101010
当访问地址的LSB为0时,引导码为:01010101 01010101
2.2.1.2 访问地址
访问地址长32位,广播信道的访问地址固定为0x8E89BED6,数据信道访问地址必须与其它任何已连接信道的访问地址不一样,初始化者在初始化状态产生数据信道的访问地址,并保证满足以下要求:
- 不能有连续超过6个以上的连续0或1
- 不能与广播信道访问地址相同
- 不能与广播信道访问地址只有1位之差
- 数据信道访问地址不能四个字节都相同
- 不能有24位以上的变化
- 高6为必须有超过2位以上的变化
2.2.1.3 PDU
PDU(protocol data unit,协议数据单元,BLE数据传送的基本单元)前两个字节固定为LL Header(1 byte)、payload length(1 byte,其中两个bit为保留位)。
2.2.1.4 CRC
每一个链路层数据包最后是一个 24 位的 CRC,用于校验数据完整性。
2.2.2 广播信道PDU包解析
PDU包前两个字节固定为LL Header(1个字节)和payload Lenght(1个字节),以及payload数据,如图4。
对PDU包再展开,PDU包由Advertising Header、Payload Length、Device Address、Advertising Data组成。如图5所示。
2.2.2.1 Advertising Header
即上述的LL Header,长度为一个字节,其每bit定义如下所示:
-
PDU Type为4bit,具体定义如下
广播PDU类型-
ADV_IND(无目的地广播)
ADV_IND用于可连接非定向广播事件中。数据头中的TxAdd决定了AdvA中的地址是公共地址还是随机地址,AdvData中包含了广播者的数据。
是在链路层通过广播信道发送,发送后可接收扫描者发送的SCAN_REQ PDU,或发起者发送的CONNECT_REQ PDU,在接收后链路层需要在同一个信道上进行扫描者或发起者的应答。当接收的数据没通过广播滤波,要么用下一个广播信道进行广播,要么关闭广播事件。如果接收到的SCAN_REQ PUD通过了滤波,那么广播者需要在同一信道回复SCAN_RSP PDU应答报文的时间一定是150±2μs完成。如果接收到CONNECT_REQ PDU,就进入连接状态,不需要进行应答。
具有以下格式:
-
ADV_DIREC_IND(指定地址广播)
ADV_DIREC_IND用于可连接定向广播事件。数据头中的TxAdd决定了在AdvA中的地址是公共地址还是随机地址,RxAdd决定了InitA的地址类型。
这个广播是为了快速建立连接,报文中包含两个地址,发起设备收到发给自己的定向广播报文后,可以立刻发送连接请求事件作为回应,并进入连接状态。定向广播有特殊的时序要求,广播事件必须没3.75ms内重复一次,这一要求让扫描设备只需扫描3.75ms即可收到定向广播设备的消息。但这么快的发送速度会让周围都充斥着广播信道,使得其他广播事件无法进行广播,所以协议规定定向广播不能持续1.28s以上的时间。如果超出连接还没有建立,或主机没有主动停止,控制器也会自动停止广播。
具有以下格式:
-
ADV_NONCONN_IND(不可连接非定向广播)
ADV_NONCONN_IND用于不可连接非定向广播事件。数据头中的TxAdd决定了AdvA是公共地址还是随机地址,AdvData中包含广播者的数据。
不可连接广播用于向周围的设备周期性的广播特定的信息,附件的设备都可以接收该广播包,但不可以进行连接。一般用于防丢器、beacon等场景。
具有以下格式:
-
ADV_SCAN_IND(可扫描非定向广播)
ADV_SCAN_INDE用于可扫描非定向广播事件。数据头中的TxAdd决定了AdvA是公共地址还是随机地址,AdvData中包含广播者的数据。
可扫描广播用于通知其他设备进行扫描操作,与通用广播的最大区别是不能建立连接,经常用于被动扫描,以便其他设备能够检测并与广播设备建立连接。如蓝牙手表通过ADV_SCAN_IND广播通知周围设备进行扫描,以便他们能够检测到手表并建立连接,从而实现数据传输或控制交互。
有以下格式:
扫描PDU类型
- SCAN_REQ(扫描请求)
由扫描状态的设备发出,被广播状态的设备接收。数据头中的TxAdd指示了扫描者的地址域ScanA是公共地址还是随机地址,RxAdd指示了广播者的地址域AdvA是公共地址还是随机地址。具有以下格式:
-
SCAN_RSP(扫描应答)
由广播状态设备发出,被扫描状态设备接收。数据头中TxAdd指示了广播者的地址域AdvA是公共地址还是随机地址.具有以下格式:
-
-
RFU 为预留占2bit
-
TxAdd/RxAdd,各占1bit,表示随后的Device Address字段代表的蓝牙MAC地址类型,TX代表发送方、RX代表接收方,0代表Public地址,1代表random地址。
2.2.2.2 Payload length
定义如下所示,广播包PDU最长37个字节,最少6个字节(MAC地址)
2.2.2.3 Device Address
设备地址也就是我们常说的MAC地址,其格式为11:22:33:44:55:66的形式。
2.2.2.4 Advertising Data
广播数据在BLE4.0-BLE4.2支持的最大广播payload包长是31字节。在BLE5.0增加了扩展模式,payload大小可支持255字节(但在实际应用中我只试过使用数据包为244个字节,广播暂未验证过)。可参考这篇文章BLE一次能传多少数据(ATT_MTU设置/LE Data扩展) - Jay’s some notes (leconiot.com)
2.2.2 数据信道PDU包解析
数据信道的PDU包括了一个16位的数据头,可变长度的payload,还可能包括一个消息完整性的校验域
对Header展开如下:
其详细定义如下:
当非机密连接及数据信道PDU中payload为0字节的加密连接包中不包括MIC,数据信道PDU中payload不为0的加密连接必须使用MIC。
payload格式由LLID决定,如果LLID = 01b或10b时,数据信道PDU负载是一个LL DATA PDU。如果LLID = 11b时,数据信道PDU负载域是一个LL CONTROL PDU。
数据头的字节长度决定了payload和MIC的长度,范围为0-31,如果存在MIC,则payload长度最大为31-4=27。
2.2.2.1 LL DATA PDU
LL DATA PDU是数据信道PDU中用于发生L2CAP数据,此时LLID需要设置为01b或10b。
如果LLID = 01b,并且数据头的负载长度为0,则这是一个空PDU,主机的连接可能发生一个空PDU给从机,用于允许从机回复任意一个数据信道PDU。
如果LLID = 10b,则数据头的负载长度域不能设置为0。
2.2.2.2 LL CONTROL PDU
LL CONTROL PDU在数据信道PDU中用于控制链路层的连接。格式如下:
所有的LL CONTROL PDU的数据头中的长度域都不能为0,所有LL CONTROL PDU都是固定长度的,长度由Opcode决定,也觉得了LL CONTROL PUD不同的类型和CtrData。
如果接收到的LL CONTROL PDU是不被使用或不支持的,设备将返回LL_UNKNOW_RSP PDU。
如果接收到的LL CONTROL PDU的Opcode是无效的,如设置为预留值,或CtrData域是无效值,设备也将返回LL_UNKNOW_RSP PDU。
附录:(用于记录蓝牙开发中遇到的问题)
1、在已知蓝牙的MAC地址的情况下是否可以不扫描直接进行连接?
答:是不可以的!即使主机知道外设的MAC地址,也需要扫描才知道什么时候发送连接请求,外设什么时候接收连接请求。
参考回答:
https://www.zhihu.com/question/593501174#:~:text=%E5%85%88%E9%BB%98%E8%AE%A4%E4%BD%A0%E8%BF%99%E4%B8%AA%E8%93%9D%E7%89%99,%E7%8E%B0%E6%89%8D%E8%83%BD%E8%BF%9B%E8%A1%8C%E8%BF%9E%E6%8E%A5%E3%80%82
https://zhuanlan.zhihu.com/p/263532072