进行BLE 应用开发,我们会经常听说到连个词汇“协议栈”和“协议”。那他 们之间有什么关系和区别呢。
协议定义的是一系列的通信标准,通信双方需要共同按照规定好的标准进行正常的数据收发。
举个例子来说两个人想要进行交流必须要说同一种语言,这就是协议。
协议栈是协议的具体实现形式,通俗理解为用代码实现的函数库,以便于开发人员调用。 蓝牙 4.0 BLE 协议栈就是将各个层定义的协议都集合在一起,以函数的形式实现,并提供一 些应用层 API 供用户调用。
下面来看一下BLE基本协议层
蓝牙核心规格中说明了蓝牙核心系统组成包含主机部分和控制器部分(一个主控制器和一 个或多个二级控制器)。主机和控制器的分离追溯到蓝牙 BR/EDR 设备时期,控制器和主机 通常分开实现。
主机部分:所有非核心配置文件以下和主机控制接口以上层。 控制器部分:主机控制接口以下层。
ti公司的cc2540的结构,将ble协议栈的各个部分进行了详细的区分,这个结构对我们来说过于复杂。
TI 公司(CC2540)精简一下,大致分可分为以下几层。 所有 Profile (配置文件层)和应用都建构在 GAP 或 GATT 之上。TI 的 CC2540 器件可以单芯片实现 BLE 蓝牙协议栈结构图的所有组件,包括应用程序。
下面我们简单了解一下蓝牙协议栈的分层
下面解释一下我们会涉及到的一些专业名词:
物理层(Physical Layer):1Mbps 自适应跳频 GFSK(高斯频移键控调制),运行在免征的 2.4GHz 频段。
链路层(Link Layer):此层为 RF 控制器,用于控制设备的射频状态,控制设备会处于 5 种状态之一:待机(Standby)、广播、监听/扫描(Scan)、初始化、连接。广播设备不需 要建立连接就可以发送数据;而扫描设备监听广播数据。发起设备响应一个连接请求给广播 设备。如果广播设备接受连接请求,发起者设备和广播设备将会进入连接状态。此时两个设 备的角色变了:主机和从机。发起连接的设备叫做主机,接受连接请求的设备称为从机。
主机控制接口层(Host Controller Interface):为主机和控制器之间提供一个标准通信接 口。这一层可以通过软件 API 或硬件接口实现,例如 UART、SPI、USB。
逻辑链路控制及自适应协议层(Logical link Control and Adaptation Protocol):为上层提 供数据封装服务,允许逻辑上的点对多点数据通信。
安全管理层(Security Manager):定义了配对和密钥分配方式。并为协议栈的其它层和 其它设备之间的安全连接和交换数据提供服务。
通用访问配置文件层(Generic Access Profile):GAP 是直接与应用程序或配置文件 (profiles)通信的接口,处理设备发现和连接相关服务。另外还处理安全特性的初始化。对 上级,提供应用程序接口;对下级,管理各级智能部门,尤其是指示 LL 层控制器 5 种状态 切换。
属性协议层(Attribute Protocol):允许设备向其它设备展示一块特定的数据,称之为“属 性”。在 ATT 环境中,展示“属性”的设备称之为服务器,与之配对的设备称之为客户端。 链路层状态(主机和从机)与设备的 ATT 角色是相互独立的。例如,主机设备既可以是 ATT 服务器,也可以是 ATT 客户端。从机设备可以是 ATT 客户端,也可以是 ATT 服务端。
通用属性配置文件层(Generic Attribute Profile):定义了使用 ATT 的服务框架。GATT 规定了配置文件(profiles)的结构。在 BLE 中,所有被 profile 或服务器用到的数据块都称之 为“特征”。两个建立连接的设备之间的所有数据通信都是通过 GATT 子程序处理。应用程 序和 profiles 直接使用 GATT 层。GATT 负责处理向上与应用打交道,其关键工作是为检索工 作提供合适的 profile 结构,而 profile 由检索关键词(characteristics)组成。
再需要介绍的就是协议栈顶层的配置文件层
蓝牙 4.0BLE 协议栈配置文件层包括 GAP/安全配置文件、GATT 配置文件两部分,处于 协议栈的顶层部分,配置文件将协议栈和应用紧密地联系在一起。这使得开发者即使对协议 栈底层的原理没有深入的了解。也可以方便地进行应用的开发。
通用属性配置文件层(Generic Attribute Profile):定义了使用 ATT 的服务框架。GATT 规定了配置文件(profiles)的结构。在 BLE 中,所有被 profile 或服务器用到的数据块都称之 为“特征”。两个建立连接的设备之间的所有数据通信都是通过 GATT 子程序处理。应用程 序和 profiles 直接使用 GATT 层。GATT 负责处理向上与应用打交道,其关键工作是为检索工 作提供合适的 profile 结构,而 profile 由检索关键词(characteristics)组成。
刚才也说到了新的蓝牙规格采用基于属性协议(ATT)的服务结构,所有低功耗数据通信都是通过 通用属性配置文件(GATT)运行。从 GATT 角度来看,当连个设备建立连接后,他们处于 两个状态――GATT 服务器和 GATT 客户端。如果应用或另一个配置文件使用 GATT 配置文 件,那么客户端和服务器可以有序的方式进行互动。
GATT 服务器――它是为 GATT 客户端提供读写数据服务的设备。
GATT 客户端――它是从 GATT 服务器读写应用数据的设备。
特别注意的是,GATT 角色中的客户端和服务器与链路层角色的主机和从机是两个完全 独立的概念,与 GAP 的外设和集中器也是完全独立的。一个从机可以是 GATT 客户端或 GATT 服务器;主机也可以是 GATT 客户端和 GATT 服务器。
服务器包含一个或多个 GATT 服务,GATT 服务是完成特定功能的一系列数据的集合。 而 GATT 配置文件定义如何利用属性协议发现、读取、编写和获取指示。这些功能支持基于 服务的结构。所采用的服务在配置文件规格中有所界定。GATT 使你能了解配置文件规格所 界定的服务和特征。
GATT 结构使创建和实施新的配置文件更加容易。许多新的配置文件仍在开发过程中, 因为这一优势继续扩大。配置文件实施十分简单,有助应用和支持这些配置文件的嵌入式设 备迅速增加。
在 TI 公司的示例工程 SimpleBLEPeripheral 应用中,有三个服务:
强制的 GAP 服务――这一服务包含设备和访问信息,例如,设备名、供应商和产品 标示,它是 BLE 协议栈的一部分,是 BLE 规范对每一个 BLE 设备必须强制要求的, 这部分源码并没有提供,而是编译到协议栈库中了。
强制的 GATT 服务――这一服务包含 GATT 服务器的信息,是协议栈的一部分。是 BLE 规范对每一个 GATT 服务器设备的必须要求。这部分源码并不提供,而是编译 到协议栈库中。
SimpleGATTProfile 服务――这个服务是一个示例配置文件进行测试和示范。所有的 源码程序在 simpleGATTProfile.c 和 simpleGATTProfile.h 文件中。这个服务包含应用 数据的信息,与应用数据的传递密切相关。读者可以按照上面示例特定的格式编写 自己的 GATT 服务。
“特性”是服务用到的值,以及其内容和配置信息,GATT 定义了 BLE 连接中发现、读 取、写入属性的子过程。GATT 服务上的特性值,及其内容和配置信息(即描述符)存储于 属性表中。属性表是一个数据库,包含了小块数据被称之为属性。除了值本身,每个属性都 有与之相关的以下属性。
句柄——属性在表中的地址,每个属性有唯一的句柄。
类型——这表明数据所代表的含义,通常由 Bluetooth SIG 规定或用户自定义的 “UUID”(universal unique identifier)。
权限——规定了 GATT 客户端设备对属性的访问权限,包括是否能访问和怎样访问。
GATT 定义了 GATT 服务器和客户端之间通信的若干个子进程。
下面是一些子进程:
l 读特性值——客户端设备请求读取特定句柄处的特性值,服务器将此值回应为客户端 (假设属性为可读权限)。
l 使用特性的 UUID 读——客户端请求一个特定类型的所有特性值,服务端将所有相匹 配类型的特性的句柄和值回应给客户端(假定属性有读权限)。客户端不需要知道 这些特性的句柄。
l 读多个特性值——客户端一次请求读取多个句柄的特性值,服务器将这些特性值回 应给客户端(假定属性有读权限),客户端需要知道如何解析这些不同特性值的数 据。
l 读特性描述符——客户端请求读取特殊句柄的特性描述符,服务器将特性描述符的值 回应为客户端(假定属性有读权限)。
l UUID 发现特性值——客户端通过发送“特性”的类型(UUID)来请求发现这个“特 性”的句柄,服务器将特性的声明回应给客户端,其中包括特性值的句柄以及特性 的权限。
l 写特性值——客户端请求向服务器特定的句柄写入特性值,服务器将数据是否写入成 功的信息反馈给客户端。
l 写特性描述符——客户端请求向服务器特定的句柄写入特性描述符,服务器将数据是 否写入成功的信息反馈给客户端。
l 特性值通知——服务器将一个特性值通知给客户端。这个客户端无需向服务器请求这 个数据,当客户端接收到通知数据后 3,也不需要回应服务器。但必须首先配置特性 使能通知服务,profile 定义了什么时候服务器应该发送这个数据。
每个 profile 初始化其相应的服务并内在的通过 GATT 服务注册服务。GATT 服务添加整 个服务向属性列表,并给每个属性分配唯一句柄。
GATT 属性列表中有一些特殊属性类型,其值有蓝牙技术联盟技术定义:
GATT_PRIMARY_SERVICE_UUID——表示新服务的开始和提供的服务类型。
GATT_CHARACTER_UUID——称之为“特性声明”,表示紧跟其后的是 GATT 特 性值。
GATT_CLIENT_CHAR_CFG_UUID——这个属性代表特性描述符,它与属性表中它 前面近的句柄处的特征值相关,它允许 GATT 客户端设备使能特性值通知。
GATT_CHAR_USER_DESC_UUID——这个属性代表特性描述符,它与属性表中它前 面近的句柄处的特性值相关,包含一个 ASCII 字符串,是对相关特性的描述。
这些特定属性类型在 BLE 规范中包括,更多其他的详细属性类型请参考文档 BLE_API_Guide_main.htm。
下面是已经采用的基于 GATT 的蓝牙配置文件和服务:
基于 GATT 的规格 服务
(可进行资格认证)
已采纳 版本
ANP 警报通知配置文件
1.0
ANS 警报通知服务
1.0
CTS 当前时间服务
1.0
DIS 设备信息服务
1.0
FMP Find Me 配置文件
1.0
HTP 健康体温计配置文件
1.0
HTS 健康体温计服务
1.0
HRP 心率配置文件
1.0
HRS 心率服务
1.0
IAS 即时警报服务
1.0
LLS 链路丢失服务
1.0
NDCS 下个日光节约时间更改服务
1.0
PASP 电话警报状态配置文件
1.0
PASS 电话警报状态服务
1.0
PXP 近距传感配置文件
1.0
RTUS 参考时间更新服务
1.0
TIP 时间配置文件
1.0
TPS 发射功率服务
1.0
通用访问配置文件(Generic Access Profile)
BLE 协议栈中的 GAP 层负责处理设备访问模式和程序。包括设备发现、建立连接、终止
连接、初始化安全特写和设备配置。
GAP 层总是作为下面四种角色之一:
(1) 广播者------不可连续广播设备;
(2) 观察者------扫描广播,但不发起建立连接;
(3) 外部设备------可连接的广播设备,可以在单个链路层连接中作为从机;
(4) 集中器------扫描广播设备并发起连接,在单链路层或多链路层作为主机,目前,TI 的 BLE 协议栈支持一个集中器连接 3 个外设。
BLE 规范说明允许特性的的多个角色组合。简单外设实例默认仅支持外设角色,可以通 过添加源码程序使工程同时指出外设和广播角色。当然在编译广播源码时,需禁止编译外设 源码。
在典型低功耗蓝牙系统中,外部设备广播特定数据为了是集中器知道它是一个可连接设备。广播包包含:设备地址、以及一些额外的数据,例如设备名。集中器接收到广播包,会向外部设备发送一个扫描请求,这个外部设备响应一个响应信号,被称之“扫描回应”。因此集中器选择意识到外部设备,知道是可以连接的设备,这就是发现设备的过程。此时,集中器向外部设备发送请求建立连接。一个连接请求包含许多连接参数:
连接时间间隔(Connection Interval)
两个 BLE 设备连接使用跳频机制,两个设备发送和接收数据使用特定的信道,一段时间 后使用心得信道(链路层处理信道切换),两设备在切换设备之后收发数据称之为连接事件。 即使没有应用数据收发,两设备也一直通过交换链路层数据位置连接状态。连接间隔就是两 个连接时间的间隔。连接间隔以 1.25ms 为单位。连接间隔的范围:6(7.5ms)~ 3200(4s)。
不同的应用可能要求不同的连接间隔。长时间连接间隔的优势是节省功耗。因为设备在连接过程中有大量的睡眠时间,不好之处是设备发送数据后,需要等待哦下一个连接设备。
短的连接间隔好处是设备收发数据机会多,因为两个之间连接的频率高。不好之处是耗能较高,因为设备频繁被连接事件唤醒。
n从机延时(Slave Latency) 这项参数可以使从机(外设)跳过几项连接事件,使从机设备更灵活。如果没有数据发
送时,可以选择跳过连接事件和休眠,以至于更省电。这个是由从机(外设)决定。
从机延时值就是可以跳过大的连接事件个数。其值的范围:0 ~ 499,0 表示不跳过任 何连接事件。然而大有效间隔时间不能大于 16s。
监视超时(Supervision Timeout)
两个成功连接事件之间的大允许间隔。如果超过了这个大时间而没有成功的连接事 件,设备被认为丢失连接,返回没有连接状态。参数值以 10ms 为单位。监视超时值的范围 从 10(100Ms) ~ 3200(32s)。另外,超时值必须大于有效连接间隔。
有效间隔时间等于连个连接事件按之间的时间。假设从机跳过可能事件的大数量被从 机延时允许(如果从机延时被设置为 0,测有效连接间隔等于真实连接事件)。下面是运算 公式:
这就是告诉我们,在这种情况下,从机向主机没有数据发送时,从机仅仅是每个 500ms 传输一次连接事件。
许多应用中,从机设置跳过连接事件大个数。因此,在选择连接参数时,需要考虑有 效连接间隔。选择正确的连接参数对 BLE 设备的功耗优化启到重要作用。先列表在连接参数 设置上给出一个通用概述:
减少连接间隔: u增加设备功耗
增加双向传输数据量
降低设备之间数据传输所用的时间 增加连接间隔:
降低设备的功耗 u降低设备传输数据量 u提高设备之间数据传输所用的时间
减少从机延时(或这个为 0): u提高从机设备的功耗 u降低从机设备接收集中器数据的时间。
降低从机延时: u外围设备没有数据发送集中器期间降低了功耗。、
Effective Connection Interval = (Connection Interval) * ( 1 + (Slave Latency) )
Take the following example: Connection Interval: 80 (100ms) Slave Latency: 4
Effective Connection Interval: (100ms) * ( 1 + 4 ) = 500ms
提高集中器发送给外围设备的数据时间。
在某些情况,集中器向外设请求一个连接参数包,对外设也是不容易的。在其他情况, 一个外设可能期望改变连接中的参数,以外设应用为基础。外设可以通过向集中器发送“连 接参数参数更新请求”来改变连接设置,这个请求由协议栈的 L2CAP 层处理。这个 请求包 括 4 个参数:小连接间隔、大连接间隔、从机延时和超时连接。这些参数值代表外设所 要求的连接参数。集中器接收请求后可以选择接收或拒绝这些新的参数。
连接可以被主机和从机以任何原因自动终止。一方发起终止,并且另一方必须响应,因此两个设备都退出连接状态。
GAP 层也处理 BLE 连接中安全特性的初始化,只有在已认证连接中,特定的数据才能被 读写。一旦连接建立,两个设备进行配对。当配对完之后,形成加密和认证链接的秘钥。典 型案例中,外设请求集中器提供秘钥来完成配对工作。秘钥可能是一个固定值,例如“000000”, 也可以是一个随机产生的值提供给使用者。当集中器发送正确的秘钥后,两个设备交换安全 秘钥并加密和认证链接。
在许多情况下,同一对集中器和外设会不时地连接和断开,BLE 有一个安全特性在配对 时,提供一个长期的安全秘钥信息。这种特性叫做绑定。它允许两个设备重新连接后快速完 成加密和认证,并且不需要每次连接执行配对过程,只需要两个之间存储这个长期秘钥信息。
参考 SimpleBLEPeripheral 应用,GAP 部分由 GAP 配置文件处理,并且绑定信息管理由 GAP 安全配置文件(security profile)处理,更多的信息在 TI 的 CC2540/41 BLE 协议栈的 GAP 配置文件头文件
链路层规格
借助先进的省电和加密功能,链路层将提供超低耗能的闲置模式运行、简单的设备发现 以及可靠的点对多点数据传输。
使用 GAP 和 GATT 的堆栈 API
应用程序和配置文件直接调用 GAP 和 GATT API 功能来实现 BLE 相关功能,例如,广
播、连接、读写“特性” 。
APIs 中有不同层的 BLE 协议栈的详细信息。可以在 HTML 指导中咨询,更多其他的详
细信息请参考 BLE_API_Guide_main.htm 文档。 使用 GAP 和 GATT 的 API 功能一般步骤如下: (1) 使用适当的参数调用 API 功能;
(2) 协议栈执行特定的操作并返回;
(3) 操作完成后,或者任何时候堆栈有消息需要报告给调用 API 功能的任务,堆栈发送 一条 OSAL 纤细给调用 API 的任务。
(4) 调用 API 任务接收和处理相应地消息;
(5) 调用 API 的任务释放消息;
从 GAP 从机角色 profile 可以看到一个过程的示例(peripheral.c)。
(1) Profile 调用 GAP API 函数 GAP_DeviceInit 初始化设备;、
(2) GAP 进行初始化并返回 SUCCESS(0x00);
(3) 初始化之完成后,BLE 协议栈发送 OSAL 消息,外围角色 profile 的头事件值为 GAP_MSG_EVENT,并且操作码为 GAP_DEVICE_INIT_DONE_EVENT;
(4) Profile 任务接收 SYS_EVENT_MSG 事件,表明它是一个消息,Profile 接收到这个 消息并查看消息头和操作码的值。基于这些,Profile 知道将消息数据归类到相应的类型 (gapDeviceInitDoneEvent_t)并处理。这种情况下,Profile 将生成密钥存储到 Flash 存储器, 并在本地保存设备地址;
(5) Profile 释放消息并返回;
这是另外一个示例,如果 GATT 客户端向共同体 GATT 服务器请求一个 GATT 读请求,
它是可能存在的。
(1) 应用调用 GATT 子程序 API 功能,连接通过,特性句柄(包含数据类型),它自己
的任务 ID 作为参数。
(2) GATT 处理请求,并返回 SUCCESS;
(3) 在下次连接事件协议栈发送读请求,远处的设备接收到读请求,协议栈发送一个包含 读响应的 OSAL 消息给应用,消息包括头事件值为 GATT_MSG_EVENT,操作码为 ATT_READ_RSP;
(4) 应用任务接收到 SYS_EVENT_MSG 事件,表示它是一个消息,Profile 接收到这个消 息并查看消息头和操作码。基于这些,Profile 知道将消息归类到相应的类型(attReadRsp_t), 检索在读响应中接收的数据。
(5) Profile 释放消息并返回;
GATT 的 Profile 层次结构
为了实现用户的应用,profile 通常有一个或者多个“Services”组成。
一个 service 或许包含某个特征值“characteristic values”,(例如,在一个温度采集设备 中,通常会包含一个温度的特征值) 每一个特征值必须有占用一个特征申明结构,其中包括他的其他特性,它是服务端和客 户端共享的读写空间
这个特征值可以包含一个可选的描述(descriptor 字串),来只是这个特征值的含义。