先看一下:蓝牙协议栈的分层结构
首先,从大的逻辑上,蓝牙协议栈可以分为三层,分别是APP应用层,Host逻辑链路层和Controller硬件交互层。
APP应用层其实是我们能够看到的各种具体的蓝牙设备,比如实现的蓝牙耳机,蓝牙鼠标,蓝牙键盘等等。
在应用层中,我们的鼠标移动数据,或者键盘的敲击按键数据,要想通过蓝牙传输,就需要调用下一层的API来进行调用,实现数据的传输。
那么,Host层就为APP层提供了上述的传输API,当然Host层本身还提供了很多通用的蓝牙访问文件层,自适应的一些层,链接的安全管理层,属性协议层以及访问配置文件和属性配置文件层。
再下一层就是Controller,它主要负责与硬件层的交互,其中包括了物理层,链路层和主机控制接口层。
我们来分别看一下各个模块的具体内容,我们从下层向上垒一下。
PHY
这一层主要是指的物理层的信道,蓝牙BLE使用无线通信,其频率规定为免费的2.4Ghz,具备2Mbps带宽,自适应跳频GFSK的无线电系统。
LL
LL层是链路层,它负责控制设备的RF状态,一共有五个状态:Standby,Advertising,Scanning,Initiating,Connected。
LL层可以发送广播包和数据包,他会通过定时机制,在主机和从机的连接期间内进行数据发送和接收。
LL层负责自适应调频算法,对于广播包,他会选择在37,38,39三个广播信道上循环发送。
对于数据包,会使用自适应跳频算法,在0~36这37个数据信道中挑选可用的信道。
调频算法在之前的文章中。
HCI
HCI 层负责主机和控制器之间的通信,是 Host 和 Controller 通信之间的接口。定义了特定的格式来控制蓝牙芯片来做相应的动作(比如:inquiry,connect,disconnect)。
HCI 层为上层级提供了一个统一访问 HCI 控制器的接口,其接口为一系列的指令和事件,接口适用于 BR/EDR/LE/AMP 控制器。
HCI 层位于蓝牙高层协议和低层协议之间,其目的是实现主机设备与蓝牙模块之间的互操作,即 HCI 是蓝牙主机与主机控制器间软硬件接口。
HCI 为蓝牙硬件中基带控制器和链接管理器提供了命令接口,从而实现对硬件状态注册器和控制寄存器的访问,提供了对蓝牙基带的统一访问模式。
目前,HCI 的传输层主要有:USB,RS-232,UART 等,早些年很多外挂的蓝牙外设芯片,他们的界面就是基于HCI这一层。
L2CAP
在LL协议中,实现了逻辑连接(logic link)建立,硬件地址寻址,CRC校验等功能。
而在L2CAP层中,通过对LL层建立的逻辑连接进行控制和适配,来实现不同应用。
实现数据传输中对分包、组包、流控、重传等功能需求。
L2CAP主要功能:
1.协议信道复用(protocol/channel multiplexing)
2.分段与重组(segmentation and reassembly SAR)
3.每个信道流控(per-channel flow control)
4.差错控制(error control)
L2CAP为上层,提供了一个可靠的数据收发接口。
SMP
这一层主要定义配对功能和秘钥的分发机制。
GAP
负责访问模式和进程,包括设备发现、建立连接、终止连接、初始化安全特征和设备配置。
GAP(Generic Access Profile, 通用访问规范),该profile保证不同的Bluetooth产品可以互相的发现对方并建立连接。同时描述了设备如何成为广播者和观察者,并且实现无需连接的数据传输。
GAP层还定义了不同类型的地址来实现隐私性和可解析性。
GAP将设备分为四种角色:外围设备(Peripheral),中央设备(Central),播报设备(Broadcast),观察设备(Observer)。
· 外围设备(Peripheral):广播发送者,是可连接的设备,连接后成为从设备
· 中央设备(Central):扫描广播启动连接,连接后成为主设备
· 播报设备(Broadcaster):广播发送者,不是可连接的设备
· 观察设备(Observer):扫描广播启动连接,连接后成为主设备
那么为什么GAP要分为4种角色?
因为蓝牙标准制定的考虑,BLE主打低功耗,所以在BLE体系中,为了更大可能的优化设备,节省功耗,所有层都采用了非对称的设计(主从不同构),对于物理层的无线电装置,可以是以下3种形式:
- 芯片只有发射机:只能发射无线信号,不能接收无线信号,硬件成本低。芯片只有接收机:只能接收无线信号,不能发射无线信号,硬件成本低。芯片同时具有接收机和发射机:既可以接收无线信号,也可发射无线信号,硬件成本较高。
这样,当某个应用只需要在设备之间单向传输数据时,其中一个设备可以作为广播者,采用只有发射机的芯片,另外一个设备可以作为观察者,并且用了尽量少的硬件资源,所以功耗会更低,理论造价也会更低。
当然,我们也可以用同时具有接收机和发射机的设备实现这些功能,实际产品中,用这种方式的更多,但是因为只需实现单项传输,广播者多了用不到的接收机,观察者多了用不上的发射机,这会增加电流的消耗和硬件成本。
所以,蓝牙标准的制定考虑的足够多,从功耗、成本、以及各种应用场景都做了全面的考虑。
GAP层为蓝牙确定了主从关系,以及连接过程中遵循的各种参数,比如链接间隔,广播间隔,广播数据,扫描间隔等等等,他确保了两个设备之间的建立链接过程。
ATT
ATT层是一个非常重要的层,定义了各种属性、属性的操作方法,但是这些属性有什么作用,能给用户提供什么服务,它并不知道,他只是允许设备向其他设备公开某些数据或属性,也就是客户和服务端模型。
Client 和 Server 之间是通过 ATT PDU来通信的,ATT PDU主要包括4类:读,写,notify 和 indicate。
我们举一个生活中的例子来了解ATT的作用:
GATT
GATT层主要用于定义如何使用ATT的服务框架,它是一个通用属性,BLE连接后的通信协议是建立在GAT协议之上的。它定义了两个BLE设备之间,通过Service和Characteristic进行通信。
GATT结构由嵌套的Profile、Service、Characteristics组成。
每个Profile就是预先定义好的Service集合。例如官方的心率Heart Rate Profile就是结合了Heart Rate Service和Device Information Service。
https://btprodspecificationrefs.blob.core.windows.net/gatt-specification-supplement/GATT_Specification_Supplement.pdf
Service就是一个独立的逻辑项,它包含一个或多个Characteristic,每个Service都由唯一的UUID标识,UUID有16位的有128位的,16位的UUID是官方通过认证的,需要花钱购买,128位的可以随便自己定义。
Characteristic是GATT中最小的逻辑数据单元,当然它可能包含一组关联的数据,例如加速度计的 X/Y/Z 三轴值。
在官方心率的例子,可以看到它包含了 3 个 Characteristic:Heart Rate Measurement、Body Sensor Location 和 Heart Rate Control Point,并且定义了只有第一个是必须的,其他是可选实现的。
每个Characteristic对应的value就是对应格式的实际心率数据。中心可以通过读取service、再进一步读取characteristic来获得具体的心率数值。
每个 Characteristic 用 16 bit 或者 128 bit 的 UUID 唯一标识。所有数据交互必须通过明确的UUID确定到service和characteristic。
实际上,和 BLE 外设打交道,主要是通过 Characteristic。
你可以从 Characteristic 读取数据,也可以往 Characteristic 写数据,这样就实现了双向的通信。
所以你可以自己实现一个类似串口(UART)的 Sevice,这个 Service 中包含两个 Characteristic,一个被配置只读的通道(RX),另一个配置为只写的通道(TX),这就是我们常用的透传模块。