蓝牙
蓝牙的波段为2400-2483.5MHz(包括防护频带)。这是全球范围内无需取得执照(但定不是无管制的)的工业、科学和医疗用(ISM)波段的2.4GHz短距离无线电频段。
蓝牙使用跳频技术,讲传输的数据分割成数据包,通过79个指定的蓝牙频道分别传输数据包。每个频道的频宽为1MHz。蓝牙4.0使用2 MHz间距,可容纳40个频道。第一个频道始于 2402 MHz,每 1MHz一个频道,至2480MHz 。有了适配跳频(AFH)功能,通常每秒跳1600次。
通讯连接
蓝牙主设备最多可与一个微微网(一个采用蓝牙技术的临时计算机网络)中的七个设备通讯,当然并不是所有设备都能够达到这一最大量。设备之间可通过协议转换角色,从设备也可以转换为主设备(比如,一个头戴式耳机如果向手机发起连接请求,它作为连接的发送者,自然是主设备,但是随后也许会作为从设备运行。)
蓝牙核心规格提供两个或以上的微微网连接以形成分布式网络,让特定的设备在这些薇薇网中自动同时的分别扮演主和从的角色。
数据传输可随时在主设备和其他设备之间进行(应用极少的广播模式除外)。主设备可选择要访问的葱设备;典型的情况是,它可以在设备之间以轮替的方式快速转换。因为是主设备来选择要访问的从设备,理论上从设备就要在接收槽内待命,主设备的负担要比从设备少一些。主设备可以于七个从设备相连接,但是从设备却很难于一个以上的主设备相连。规格对于散射网中的行为要求是模糊的。
蓝牙是一个标准的无限通讯协议,基于设备低成本的收发器芯片,传输距离近、低功耗。由于设备使用无线电(广播)通讯系统,他们并非以实际可见的线相连,然而准光学无线路径则必须是可行的。射程范围取决于功率和类别,但是有效射程范围在实际应用中会各有差异。
有效射程因传输条件,材料覆盖、生产样本的变化、天线配置和电池状态有关。多数蓝牙应用是为室内环境而设计的,由于墙的衰弱和信号反射造成的信号衰落会使得射程远小于蓝牙产品规定的射程范围。多数蓝牙应用是由电池供电的2类设备,无论对方设备是1类或2类,射程差异均不明显,因为射程范围通常取决于低功率的设备。在某些情况下,当2类设备连接到一个敏感度和发射功率都高于典型的2类设备的1类接收器上时,数据链的有效射程可被延长,然而多数情况下,1类设备于2类设备的美感度是相近的。
两个敏感度和发射功率都较高的1类设备相连接,射程可远高于一般水平的100m ,取决于应用所需要的吞吐量。有些设备在开放的环境中的射程能够高达1km 甚至更远。
蓝牙配置文件
要使用蓝牙无线技术,设备必须能够解译某些蓝牙配置文件,蓝牙配置文件定义了可能的应用,并规定了蓝牙设备之间通信的一般行为。这些配置文件包括对通信参数和控制的最初设定。配置文件能够节约在双向链路起效之前重新发送参数的时间。广泛的蓝牙配置文件描述很多不同类型的应用或设备用例。
BLE协议层
-
物理层(PHY)
- 运行在 2.4GHz ISM band
- GFSK 调制方式(高斯频移键控) -40 频道 2MHz 的通道间隙
*3 个固定的广播通道 *37 个自适应自动调频数据通道
LL层、RF控制层
控制芯片工作在 standby(准备)、advertising(广播)、scanning
(监听/扫描),initiating(发起连接)、connected(已连接)这五个状态中的一种。五 种状态的切换描述为:advertising(广播)不需要连接就可以发送数据(告诉所有人, 我来了),scanning(监听/扫描)来自广播的数据,initiator(发起人)将携带 connection request(连接请求)来相应广播者,如果 advertiser(广播者)同意该请求,那么广播 这和发起者都会进入已连接状态,发起连接的设备变为 master(主机),接收连接请求 的设备变为 slave(从机)。HCI层 通信层
向 host 和 controller 提供一个标准化的接口。该层可以由软件 api 实现或 者使用硬件接口 uart、spi、usb 来控制。L2CAP
相当于快递,将数据打包,可以让客户点对点的通信。SM层
安全服务层,提供配对和密钥的分发,实现安全连接和数据交换。ATT层
允许设备向另外一个设备展示一块特定的数据,称之为“属性”,在 ATT 环境中,
展示“属性”的设备称为服务器,与之配对的设备称为客户端。
链路层状态(主机和从 机)与设备的 ATT 角色是相互独立的,也就是说,主机设备可以是 ATT 服务器,也可以 是 ATT 客户端。从机也一样。GATT层
从名字就能看出,GATT 是在 ATT 上面的一层结构,定义了使用 ATT 的服务框架, GATT 规定了配置文件(鼎鼎有名的 profile)的结构,在 BLE 中,所有被 profile 或者服 务用到的数据块都称为“特性,characteristic”两个建立连接的设备之间的所有数据通 信都是通过 GATT 子程序处理,应用程序和 profile 直接使用 GATT 层,在后面具体的代 码中,我们会经常见到 GATT。
蓝牙4.0
蓝牙4.0是2012年最新蓝牙版本,是3.0的升级版本;较3.0版本更省电、成本低、3毫秒低延迟、超长有效连接距离、AES-128加密等;通常用在蓝牙耳机、蓝牙音箱等设备上。
蓝牙中心模式流程
- 建立中心角色
- 扫描外设(discover)
- 连接外设(connect)
- 扫描外设中的服务和特征(discover)
- 获得外设的services服务
- 获取外设的Characteristics,获取Characteristics的值,获取Characteristics的Descriptor和Descriptor的值
- 与外设做数据交互(explore and interact)
- 订阅Characteristic的通知
- 断开链接(disconnect)
蓝牙外设模式流程
- 启动一个Peripheral管理对象
- 本地Peripheral设置服务、特性、描述、权限等等
- Peripheral发送广告
- 设置处理订阅、取消订阅、读characteristic(特性)、写characteristic的委托方法
蓝牙设备状态
- 待机状态(Standby):设备没有传输和发送数据,并且没有连接到任何设备
- 广播状态(Advertiser):周期性广播状态
- 扫描状态(Scanner):主动寻找在广播的设备
- 发起链接状态(Initiator):主动向扫描设备发起连接
- 主设备(Master):作为主设备连接到其他设备
- 从设备(Slave):作为从设备连接到其他设备
蓝牙设备的物种工作状态
- 准备 standby
- 广播 advertising
- 监听扫描 scanning
- 发起连接 initiating
- 已连接 connected
名词解释
GAAT
现在低功耗蓝牙(BLE)连接都是建立在 GATT (Generic Attribute Profile) 协议之上。GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范,这些很短的数据段被称为属性(Attribute)。
蓝牙SIG规定了许多低功耗设备的配置文件。配置文件是设备如何在特定的应用程序中工作的规格说明。注意一个设备可以实现多个配置文件。例如,一个设备可能包括心率监测仪和电量检测。Characteristic 特性
一个characteristic包括一个单一变量和0-n个用来描述characteristic变量的descriptor,characteristic可以被认为是一个类型,类 似于类。Descriptor
Descriptor用来描述characteristic变量的属性。例如,一个descriptor可以规定一个可读的描述,或者一个characteristic变量可接受的范围,或者一个characteristic变量特定的测量单位。Service
service是characteristic的集合。例如,你可能有一个叫“Heart Rate Monitor(心率监测仪)”的service,它包括了很多characteristics,如“heart rate measurement(心率测量)”等
GAP
详细介绍 GATT 之前,需要了解 GAP(Generic Access Profile),它在用来控制设备连接和广播。GAP 使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与合同设备进行交互。例如 Beacon 设备就只是向外广播,不支持连接,小米手环就等设备就可以与中心设备连接。
-
设备角色
GAP给设备定义了若干角色,其中主要就是外围设备(Peripheral)和中心设备(Central)- 外围设备:一般就是非常小活着简单的低功耗设备,用来提供数据,并连接到一个更加相对强大的中心设备,例如小米手环。
- 中心设备:中心设备想对比较强大,用来连接其他外围设备,例如手机。
广播数据
在 GAP 中外围设备通过两种方式向外广播数据: Advertising Data Payload(广播数据)和 Scan Response Data Payload(扫描回复),每种数据最长可以包含 31 byte。这里广播数据是必需的,因为外设必需不停的向外广播,让中心设备知道它的存在。扫描回复是可选的,中心设备可以向外设请求扫描回复,这里包含一些设备额外的信息,例如设备的名字。连接间隔
在两个BLE设备的连接中使用调频机制,两个设备使用特定的信道收发 数据,然后过一段时间后再使用新的信道。(链路层处理信道切换),两设备在信道切换 后收发数据称之为连接事件,即使没有应用数据的收发,两个设备任然会通过交换链路 层数据来维持连接,连接间隔就是两个连接时间之间的时间间隔,连接间隔以 1.25ms 为单位,连接间隔的值为 6(7.5ms)~3200(4s)。
不同的应用可以要求不同的时间间隔,长的时间间隔的优势是显著的节省功耗,因 为设备可以在连接事件之间有较长时间的休眠,坏处是当设备有应用数据需要发送时, 必须要等到下一个连接事件。短的时间间隔优势是两设备连接频发,可以更快的收发数 据,不利之处是设备因连接时间的到来而频繁的唤醒,会有较多的功耗。-
广播流程
外围设备会设定一个广播间隔,每个广播间隔中,它会重新发送自己的广播数据。广播间隔越长,越省电,同时也不太容易扫描到。
大部分情况下,外设通过广播自己来让中心设备发现自己,并建立 GATT 连接,从而进行更多的数据交换。也有些情况是不需要连接的,只要外设广播自己的数据即可。用这种方式主要目的是让外围设备,把自己的信息发送给多个中心设备。因为基于 GATT 连接的方式的,只能是一个外设连接一个中心设备。 使用广播这种方式最典型的应用就是苹果的 iBeacon。广播工作模式下的网络拓扑图如下:
GATT
它定义了两个BLE设备通过较多 Service 和Characteristic 的东西进行通信。GATT 使用了ATT协议 ,ATT 协议把 Service 和Characteristic 以及对应的数据保存在一个查找表中,使用16bit ID 作为每一项的索引。
一旦两个设备建立起了连接,GATT 就开始起作用了,这也意味着,你必须完成前边的 GAP 协议 GATT连接,必须先经过 GAP 协议
注意 GATT 连接是独占的。也就是一个BLE外设同时智能被一个中心设备连接。一旦外设被连接,它就会马上停止广播,这样它就对其他设备不可见了。当设备断开,它又开始广播。中心设备和外设需要双向通信的话,唯一的方法就是建立GATT连接 。
一旦建立起了连接,通信就是双向的了,对比前面的 GAP 广播的网络拓扑,GAP 通信是单向的。如果你要让两个设备外设能通信,就只能通过中心设备中转。
GATT 通信事务
GATT通信的双方是C/S关系。外设作为GATT 服务端 (Server),它维持了ATT查找表以及 service 和characteristic 的定义。
中心设备是GATT 客户端(Client),它向Server 发起请求。
注意:需要注意的是,所有的通信事件,都是由客户端(主设备)发起,并且接收服务端(从设备)的相应。
一旦连接建立,外设将会给中心设备建议一个连接间隔,这样,中心设备就会在每个连接间隔尝试去重新连接,检查是否有新的数据。但是,这个间隔只是一个建议,你在中心设备可能并不会严格按照这个间隔来执行。例如你的中心设备正在忙于连接其他的外设,活着中心设备资源太忙。
下图展示一个外设(GATT 服务端)和中心设备(GATT 客户端)之间的数据交换流程,可以看到的是,每次都是主设备发起请求:
GATT结构
BLE
Profile
Profile 可以理解为一种规范,一个标准的通信协议,Profile 存在于从机中。蓝牙组
织规定了一些列的标准 Profile,例如 HID OVER GATT、防丢器、心率计等。每个 Profile 中会包含多个 Service,每个 Service 代表从机的一种能力。Service
Service 可以理解为一个服务,在 ble 从机中,通过有多个服务,例如电量信息服务、系 统信息服务等,每个 Service 里又包含多个 Characteristic 特征值。每个具体的 Characteristic 特征值,才是 ble 通信的主体。比如当前的电量是 80%,所以会通过电量 的 characteristic 特征值存在从机的 profile 里,这样主机就可以通过这个 characteristic, 来读取 80%这个数据Characteristic
Characteristic 特征值,BLE 主从机的通信均是通过 Characteristic 来实现,可以理解为一 个标签,通过这个标签可以获取或者写入想要的内容。UUID
UUID,统一识别码,我们刚才提到的 Service 和 Characteristic,都需要一个唯一的 UUID 来标识。
每个从机都会有一个叫做 profile 的东西存在,不管是上面的自定义的 simpleProfile,还是标准的防丢器 Profile,他们都是由一些列 Service 组成,然后每个 Service 又包含了多个 Characteristic,主机和从机之间的通信,均是通过 Characteristic 来实现。
数据发送
在BLE 协议栈中进行数据传递氛围两个方面,一个是GATT的client主动向service发送数据,另一个是GAAT的service主动向client发送数据 。简化为从主机向从机发送数据,从机向主机发送发送数据。
- 主机向从机发送数据
发送可以调用 GATT_WriteCharValue 函数实现,该函教会调用协议栈里面与硬件相
关的函数最终将数据通过天线发送出去,这里面涉及对射频模块的操作,例如:打开发 射机,调整发射机的发送功率等内容,这些部分协议栈已经实现了,用户不需要自己写 代码去实现,只需要掌握 GATT_WriteCharValue 函数的使用方法即可。需要发送的数据 填充到 value 中,然后数据长度填充到 len 中。如下图。
- 从机向主机发送数据
从机向主机发送数据,需要调用 GATT_Notification 函数实现,上面的主从机没用使
用到该函数。开发串口透传等项目时,就需要在从机中主动向主机发送数据,需要该函 数来实现。下面的代码是来自我们的串口透传中。需要填充的和 GATT_WriteCharValue 类似,value 和 len。
数据接收
数据接收和数据发送一样,同样分为两个方面。
从机接收主机发来的数据和主机接收来自从机的数据
- 从机接收主机发送来的数据
当从机接收到主机发来的数据后,从机会产生一个 GATT Profile Callback 调用,我们 在这个 callback 中接收主机发送的数据。这个 callback 在从机初始化时向 Profile 注册。
主机通过 BLE 提供的数据发送接口发送数据 后,从机的协议栈收到数据后,做相应处理,取得自己需要的数据即可,其他工作,都 由 BLE 协议栈自动完成了。
扫描回应
当主机扫描从机时,如果从机正在广播,将被扫描到,并且可以看到从机的设备名,发射功率等信息,而这些信息并为出现在刚才的广播数据中,这是为什么呢。
当从机接到主机发来的扫描请求时,会有一个扫描回应 Scan Response ,在这个 response 中,携带了从机设备名,发送功率等信息 。
一个按键服务的底层实现
首先注册按键服务程序
向一个全局变量中赋值自己的任务 ID,从代码中可以看出,只能第一个调用改函数 的任务才能成功注册到按键服务。