低功耗蓝牙学习笔记-链路层

声明:BLE低功耗蓝牙系列博客来自个人的学习总结,其中肯定会包含很多错误,如果发现欢迎帮忙指正。BLE内容比较多,我现在还没有完全学完,好在其分层设计,所以可以每学完一个部分就可以做相应的总结。需要说明的是该系列博客的大部分内容来自《低功耗蓝牙开发权威指南》这本书,还会包含韦东山蓝牙系列课程的部分内容。该系列博客可以提供些什么?该系列博客是对BLE相关的知识点做归纳总结,注释个人在学习过程中的观点、理解。以后的内容计划有BLE应用的使用和实现过程,尽可能的在博客内容加入协议分析的过程,总之是从作者的学习历程记录BLE学习、理解的过程。通过对BLE低功耗蓝牙的学习弥补了我对无线通讯技术的空白,今后持续学习BLE这项技术,博客也会不断完善,必要时进行调整,修改。 

 

低功耗蓝牙框架

下面这张图就是就是低功耗蓝牙的框架:上半部分为主机部分,下半部分为控制器部分。主机部分主要是软件协议(蓝牙协议栈),控制器部分其实是个带有无线发送/接收模块的MCU。当我们的电脑没有自带蓝牙模块时,需要买个蓝牙适配器(控制器),这时电脑(主机)和蓝牙适配器(控制器)通讯是使用USB接口。

 

本章总结的链路层(LL)其实就是控制器的组成部分,物理层(PHY)如何进行无线信号传输上一章已经讲过了。HCI是英文Host Controller Interface的缩写,上面描述蓝牙适配器的传输媒介是USB,也可以是UART、SDIO。控制器内部如何实现我们不用关心,它是一套标准化的东西,我们只要了解它的工作方式、流程即可(控制器具有一定智能,实现起来还是很复杂的)。上面框架图看不懂也没关系,主机部分由后面涉及。

 

链路层的状态机

无规矩不成方圆,链路层的状态机规定了主/从机工作模式切换过程。如下图:

首先无论主机(发起连接者),从机(被连接者)都是从就绪态开始。一台机器可以选择做主机也可以选择做从机,如果要做从机就得进入到广播态(必须打开发射器)->发送广播->等待连接请求。主机则要进入扫描态(必须打开接收器)->获取广播包->选择要连接的设备,进入发起态->发起连接请求->进入连接态。从机收到连接请求后便可进入连接态,之后主机、从机之间就可以传输数据报文。

上面为链路层的概述,下面详细内容:

如上图链路层包含如下几种状态:就绪态、广播态、扫描态、发起态、连接态;

处于广播态的链路层可以发出广播报文,也可以发出扫描响应,用于回应主动扫描的设备(此时处于广播态的设备同时打开了发射器和接收器)。

处于扫描态的设备能够接受广播通道的报文,扫描态可用于简单侦听哪些设备正在广播。扫描态有两个子状态:被动扫描和主动扫描。被动扫描仅接受广播报文。主动扫描则发送扫描请求给广播态设备,并获取附加的扫描态响应数据。

为了发起连接,链路层需要处于发起态。处于发起态的发起者,其接收机用于侦听自己试图连接的设备。如果收到了来自该设备的广播报文,链路层会向其发送连接请求并进入连接态。

从广播态或发起态均可以进入连接态,两种情况均源于发起者向广播者发送连接请求报文。连接态有两个子状态:主或从。连接态中,两个设备相互传送数据报文。这也是唯一一个用到数据报文的状态。

主连接态:主连接只能从发起态进入,为了成为主设备,它必须向对端设备发起连接。主设备必须定期向向从设备发送报文。从设备只有通过回复这些报文才能发送自己的数据。

从连接态:从连接态只能从广播态进入。为了成为从设备,它必须向对端设备进行广播。对于从设备,只有在正确接收主设备的报文后才能发送。收到从设备的一个报文后,从设备可以发送一个自己的报文。如果从设备想发送更多的数据,则必须等待主设备发送另外的报文再回复。从设备也可以随时忽略主设备已达到节能的目的。这样一来,从设备可以通过“休眠”来节省大量的能量。

上面这段话讲明白了,主从设备间是如何数据传输的。主从设备间都有接收器/发送器的情况下,如果双方都随意向对方发送信息,这时肯定要乱成一锅粥。主从之间通讯过程可以描述为:主机定时向从机发送信息(携带主机发往从机的数据),从机收到消息后响应(携带从机发往主机的数据),如果当主机或从机没有数据要发送给对方时,携带数据长度为0即可。

链路层的报文

下面是报文的基本结构,适用于所有报文。无论是广播报文还是数据报文都遵守该报文结构,BLE无线通讯以该报文结构作为基础。

前导:报文最开始的8比特是01010101或者10101010序列。这是很简单的交替序列。接收机可以用它来配置自动增益控制,以及确定“0”、“1”比特所使用的频率。

接入地址:接入地址的第一个比特决定了前导是01010101还是10101010,如果接入地址的第一个比特为“0”,则使用01010101序列;如果是“1”,则使用10101010序列。这保证了任一报文的前9个比特都是交替的。32比特的接入地址有两种类型:

  • 广播接入地址
  • 数据接入地址

广播接入地址在广播数据,或是广播、扫描、发起连接时使用。数据接入地址在连接建立之后的两个设备间使用。

链路层也不知道其它设备什么时候会发送报文,因此只能保留最近40us接收到的比特,并在新的比特移入到寄存器的时候检查序列是否满足前导和接入地址。这一过程描述为接入地址求相关。

对于广播信道,接入地址是固定值0x8E89BED6。对于数据通道,接入地址是一个随机值。

报头:报头的内容取决于该报文是广播报文还是数据报文

对于广播报文,报头包含了广播报文的类型以及一些标记位,这些标记位指出了报文使用的公共地址还是随机地址。广播报文类型共有7种,每种类型都具有不同的净荷格式及行为:

ADV_IND                           通用广播指示

ADV_DIRECT_IND             定向连接指示

ADV_NONCONN_IND       不可连接指示

ADV_SCAN_IND                可扫描指示

SCAN_REQ                        主动扫描请求

SCAN_RSP                        主动扫描响应

CONNECT_REQ                连接请求 

长度:对于广播报文,长度域包含6个比特,有效值范围是6~37。对于数据报文,长度域包含5个比特,有效值范围是0~31。长度域之后是净荷,其长度是长度域指出的字节数。这里要注意的是,如果报文被加密,则需要包含4字节的消息完整性检查域,实际的净荷数据将被减少到最多27个字节。为了使得链路层设计得到简化,未加密报文的净荷也不允许超过27个字节的限制。

净荷:净荷是所传输的“真实”数据,可以是关于设备的广播数据,或者发给一定区域内所有设备的服务数据;可以是主动扫描响应的附加数据,如设备名称,实现的服务;可以是建立或保持连接所需要的信息,可以是从一个设备到另一个设备的应用层数据。

循环冗余校验:报文的最后3个字节的CRC,CRC对报头、长度域、以及净荷域进行计算。

链路层的信道

低功耗蓝牙共有3个广播信道和37个数据信道,3个信道分散在不同的频段,可避免同时受到干扰

跳频:跳频算法用于数据连接中,数据信道有37个,跳频算法的公式如下(hop是一个5~16范围内的值):

下图给出的是hop值为13的情况:

 

设备发现

共有四种不同类型的广播:通用的、定向的、不可连接的、以及可发现的。设备每次广播时,会在3个广播信道发送相同的报文。这些报文被称为一次广播事件。

除定向报文外,其它广播事件均可以选择20ms~10.28s不等的间隔。广播事件之间的时间被称为广播间隔。主机可以控制该间隔。

但设备周期性的发送广播会有一个问题:多个设备可能在很长一段时间内同时广播而造成干扰。为了防止这一情况,除定向广播之外的其他广播事件,会在上一次事件发生后加入0~10ms的随机延时。

  • 通用广播

通用广播是用途最广的广播方式

  • 定向广播

有时,设备间需要快速建立连接,定向广播事件就是为了尽可能快的建立连接。这种报文包含两个地址:广播者的地址和发起者的地址。发起设备收到发给自己的定向广播报文后,可以立即发送连接请求作为回应。定向广播也有特殊的时序要求。完整的广播事件必须3.75ms重复一次。如此快的发送会让报文充斥着广播信道,所以定向广播不可以持续1.28以上的时间。如果主机没有主动要求停止,或者连接没有建立,控制器都会自动停止广播。

  • 不可连接广播

不想被连接的设备使用不可连接广播事件。这种广播的典型应用包括设备只想广播数据,而不想被扫描或者连接。这也是唯一可用于只有发射机而没有接收机设备的广播类型。

  • 可发现广播

这种广播不能用于发起连接,但允许其他设备扫描该广播设备

下面为通用广播数据报文内容:

 

通用广播数据报文,头部数据内容:

 

通用广播数据报文,广播数据内容:

广播数据域格式为:长度域(1字节):类型(1字节):数据。

长度域的值为类型和数据的长度和。

广播数据的接收无法被确认,必须认为广播是一种不可靠的操作。

建立连接

两个设备建立连接的过程如下:

发起连接请求设备处于发起态(广播报文),下面为发起连接请求的报文:

如上所示,连接请求包含了连接开始时需要的所有信息,包括:

连接时使用的接入地址:连接使用的接入地址总是由主设备来提供的,地址通过随机生成(需要遵循一些规则)。接入地址主从设备共同使用,如果一个主设备对应多个从设备,则主设备会为每次从设备选择不同的随机地址。

CRC初始值:CRC初始值是另一个由主设备提供的随机数。随机数的意义在于,即使接入地址相同的概率很低,万一相同则可以比较CRC。

发送窗口大小

在这个时间段内,接收器持续监听,窗口大小小于连接间隔。

发送窗口偏移

发送连接请求多久后,主设备会发起第一个连接事件。

连接间隔

如上,连接间隔为24(30ms)

从设备延迟

如上,设备延迟为4,可以忽略4个连接事件

监控超时

如上,监控超时为720ms

自适应跳频信道图

自适应跳频信道图是数据通道的位掩码,用来标记信道的好坏。由于共有37个数据信道,信道图的长度于是设为37位。如果某一位被设置为1,表明该信道良好。0表示信道很糟,不适合用于通讯。

跳频算法增量

跳频算法的跳数值是在5~16之间的随机数

休眠时钟精度

时钟精度可以帮助从设备消除连接事件的不确定性

一旦收到或发出连接请求报文,设备既建立了连接,数据交换随即开始,如建立连接过程所示,建立连接后第一个数据报文有主设备发出(对于从设备,只有在正确接收主设备的报文后才能发送)。

连接事件

一个连接事件是指主设备和从设备之间相互发送数据包的过程,可能有多次数据交互,每次数据包发送需要间隔150us。

当主设备发送连接请求后,有哪些情况可能发生:

发送完连接请求后,主设备就认为自己已经建立了连接,紧接着是"发送窗口偏移",从设备收到连接请求的话可在此时启动接收器,在发送窗口时间内,主设备需要发起一个连接事件(数据包),否则从设备将进入超时处理(停止侦听,并会在一个连接间隔后再次尝试)

如果一切正常,连接事件的进行将始终位于一个频率,这个频率由连接间隔来决定,连接间隔的意思就是说,主设备多久会发起下一次连接事件。连接间隔必须是1.25ms的整数倍。连接事件定期发生,但从设备可以不每个连接事件都响应,已达到省电的目的,这里引入了设备延迟这个参数,设备延迟表示从设备在必须侦听之前可以忽略多少个连接事件。监控超时是指总的超时时间不能超过这个值。

一般建议至少给从设备留出6次侦听的机会。上面连接间隔为4,从设备必须侦听第五个连接事件。换个说法是从设备至少需要在120ms内侦听一次,所以监控超时最少需要比120ms多一点,上面的超时时间为720,这样一来,链路在最终断开前从设备至少会有6次侦听机会。

发送数据

第一次连接事件,主设备发给从设备的数据报文如下:

数据报文的净荷可以为0~31字节不等,无论加密层加密与否,传给控制器的数据包最多只能携带27个字节数据。

数据报文的头部如上所示。

逻辑链路标示符(LLID):用于判断数据报文属于下列哪种类型

11    链路层控制报文,用于管理连接,链路层之间的报文不会上传到主机,用于链路层与链路层之间的管理。

主机能够发送大于27字节的数据,但由于无法放入单个链路层的数据包,因此必须支持分段。具体的做法是把数据贴上“高层报文开始”,“高层报文延续”的标签。下图给出了一个例子,三个数据报文属于同一连接事件。

10    高层报文开始,也可以用于一个完整报文(提醒一下:上面报文LLID是......01,是大端格式)

01    高层报文延续

序列号(SN)、下一个预期的序列号(NESN)

建立连接后,第一个数据包的序列号为0,每一次发送新的数据包时,其序号与上个数据包的序列号不同。这使得接收装置能否判断接收的数据包的性质:如果序列号与之前一样,则为重传报文,如果序列号与之前的不同,则为新报文。

如果从设备成功接收序列号为0的报文,在其确认报文中,应将下一个预期序列号设为1,否则序列号为0的数据包将被重传。下一个预期的序列号由从设备设置。

更多数据位

用来通知对端设备自己还有其他的数据准备发送。如果收到设置了更多数据位的数据包,应该在当前连接事件中继续与对端设备通讯。一旦不再有数据发送,连接事件会迅速关闭。

下图,讲述了关于序列号、下一个预期序列号和更多数据位的例子。下面有两个连接事件。

发布了18 篇原创文章 · 获赞 6 · 访问量 6355

猜你喜欢

转载自blog.csdn.net/lewanhah01/article/details/103847906
今日推荐