基于NXP QN9080 BLE 框架浅谈(一)

 一、前言

首先,要实现一个 BLE 应用,首先需要一个支持 BLE 射频的芯片以及具备与此芯片配套的 BLE 协议栈,最后在此基础上开发自己的应用。我们可以把 BLE 协议栈当成是连接芯片与应用的桥梁,是实现整个 BLE 应用的关键。本文以 NXP QN9080 平台为例子给大家进行讲解。


二、环境搭建

2.1 SDK 及软件下载

本文基于NXP QN9080 IC,SDK 和软件可在NXP 官网 https://mcuxpresso.nxp.com 下载。

2.2 硬件

本文基于 QN9080 官方板进行开发,官方板如图 2.2 所示:

图 2.2



2.3 开发软件

SDK 支持 IAR、Keil、MCUXpreeso IDE 三种开发软件、本文以 IAR 为开发环境作为介绍。

 三、BLE 协议栈解析

BLE 架构:

BLE 协议栈主要是用来对你的应用数据进行层层封包,以生成一个满足 BLE 协议的空中数据包。

BLE 协议栈主要包含以下部分:

  • PHY 层(Physical Layer物理层):PHY 层用来指定 BLE 所用的无线频段,调制解调方式和方法等。所以,整个 BLE 芯片的功耗、灵敏度、以及选择性等射频指标都取决于 PHY 层的功能优劣。
  • LL 层(Link Layer 链路层):BLE 协议栈的核心之重以及难点之处。BLE协议栈能同时支持多少个连接直接取决于 LL 层。它的具体功能体现在:选择哪个射频 Channel 进行通信、怎么识别空中数据包、在哪个具体时间点发送数据包、如何保证数据完整性、如何接收 ACK ,如何进行重传以及如何对链路进行控制和管理等。LL 层只负责如何发送以及接收数据包,对数据包进行解析则要交给上层的 GAP 或 GATT 。用于控制设备的射频状态,设备将处于五种状态之一:等待、广告、扫描、初始化、连接。在 QN9080 的 BLE 应用代码中,,可以从下图中看出,有详细的代码表示连接过程的每个状态,将连接过程中的状态打印出来,可以得知设备连接到哪个步骤以及连接错误提示。广播设备不需要建立连接就能发送数据,扫描设备(如电脑设备)接收广播设备发送的数据;发起连接的设备通过发送连接请求(如输入密码、或者无密码确认连接,在上位机中实现)回应广播设备,如果广播设备接受连接请求,那么两个设备之间将进入连接状态。发起连接和接收连接请求的设备之间呈主从机关系。
  • HCI (Host Controller Interface 主机控制器接口):HCI 是可选的,可以参考网址:

https://www.cnblogs.com/iini/p/8834970.htm

HCI 主要用来规范广播者和扫描者之间的通信协议和通信命令,这一层可以是软件或者硬件接口,在此不多做介绍。

  • GAP 层(Generic Access Profile 通用访问配置文件):GAP 层是对 LL 层有效数据包如何进行解析的两种方式之一,且是最简单的。GAP 层能实现的功能极其有限,能简单地对 LL 层有效数据包进行一些规范和定义。目前这一层主要是用来进行广播、扫描、发起连接等。
  • L2CAP 层(Logic Link Control And Adaptation Protocol 逻辑链路控制与适应协议):L2CAP 对 LL 层进行一次简单封装,后者只关心传输的数据本身,前者就要区分是加密通道还是普通通道,与此同时还要对连接间隔进行管理。
  • SMP(Secure Manager Protocol 安全管理协议):SMP 用来管理 BLE 连接的加密和安全,它要考虑的是如何保证 BLE 连接的安全性且同时不影响用户的体验。在 QN9080 中,我们可以从下图得知 QN9080 的SMP 数据修改,如何设置配对模式和等级,在配对的密钥交换阶段,SMP需要交换的密钥标志。

 











SMP定义的I/O能力:通过这几个数可以设置电脑端是否有显示和密码输入,其中gIoNone_c 属于无密码连接设置的一部分。

gapSmpKeys_t 中包含配对过程中交换的SMP信息的结构,包含了加密密钥大小、长期密钥、ID 解决关键、连接签名解析密钥、RAND 的大小(通常等于 gcMaxRandSize_d)、识别LTK 的 RAND 值、以及公开地址或随机地址等等。

下图为安全模式和级别的可选择类型:

下面主要是在上位机中进行连接的一些属性,这些定义都在app_preinclude.h 的文件中,包含很多的宏定义,如此应用程序能支持的最大连接数、支持的基于信用的渠道数量、启用/禁用绑定功能、启用/禁用配对过程、启用/禁用隐私的使用、六位数密码的修改等等。

 

 

  • ATT (AttributeProtocol属性协议):简单说来,这一层是用来定义用户命令及命令操作的数据,比如读取某个数据或写某个数据。在 BLE协议栈中,开发应用者接触最多的就是 ATT。BLE 引入了属性概念,可用来描述一条一条的数据。除了定义数据还可同时定义该数据可使用的 ATT 命令,因此这一层被称为 ATT 层。
  • GATT(Generic Attribute Profile 通用属性文件):GATT 用来规范属性中的数据内容,并应用分组的概念对属性进行分类管理,GATT 规定了配置文件的结构。即使没有 GATT ,BLE 协议栈也能跑,但是互联互通就会出现问题。也正因为有了 GATT 和各种各样的应用文件,才能摆脱无线协议中常见的兼容性困境。GATT 定义了使用 ATT 的服务框架,两个建立连接的设备之间的所有数据通信都是通过 GATT 子程序处理。GATT层用于已连接的蓝牙设备之间的数据通信,应用程序和profile直接使用GATT层。当两个设备建立连接之后,它们就处于下面两种角色之一:GATT服务器:为GATT客户端提供数据服务的设备。GATT客户端:从GATT服务器读写应用数据的设备。

下图是连接成功之后,上位机中显示的设备名称为NXP_BLE_HOD 以及特征值等。

 

 

 

 

 

下图中第二个红框中的 0x2A50 是 UUID,在一个BLE 应用中只能有唯一的一个 UUID。第三个红框是 设备的描述符修改,SDK 中是鼠标的描述符,不包含滚轮的功能,只有鼠标左中右按键、光标的低八位 X、Y值等。在本图中我把描述符改成鼠标 + 键盘的组合体,亲测可用。如果需要更多的功能可以继续在此基础上添加。第四、第五个红框是鼠标和键盘发送的数据量,还可在这个文件中直接设置鼠标和键盘的 Report ID ,这样在数据打包、发送的函数中就不需要再次添加 ID了。



 

通过上面的讲解,我们会对 BLE 的框架和流程会有一个初步的了解,但是还不够深入,如果要加深理解,必须从应用着手,并且对每一部分的函数功能和作用以及整个框架都了如指掌。

接下来我们来讲解一下 hid_device.c 文件中的重要部分:这个文件包含了很多关键的部分,比如 BLE 发送的实际数据包、广播的开启、回报率的设置、电量的上报、扫描的定时器时间设置、鼠标应用数据的结构体变量定义、GATT 与 ATT 的回调函数、BLE 的初始化函数、键盘时间的处理(上位机连接)、处理广播定时器回调函数、以及鼠标事件的回调函数、无线发送 HID 报告函数等。

首先是电池电量上报、BLE 鼠标数据发送以及定时器扫描的时间间隔设置。下面是我在方案中的时间间隔设置:



定时器有分钟/秒/毫秒类型选择,由下图可知。



每个定时器要分配它们的唯一 ID:

 

在分配 ID 之后,不要忘了还要分配它们的定时器,如下图所示:

 

 

这个是 BLE 的广播函数,广播连接可以设置自动回连,有白名单广播和快速广播模式:

 

在BleApp_Config 函数中,我们在BLE 初始化完成的时候,打开这些我们需要的定时器,开启这些任务,定时器的其他参数的具体设置可以在 SDK 中进行查询。最后在末尾我们加上一个 BLE 初始化完成的标志位作为判断。



最后,我们在这些定时器里面调用这些回调函数来产生事件:比如第一个红框中滚轮的扫描要设置成 1ms 时间间隔发生一次,第二个红框中首先要判断 BLE 是否已经初始化完成了,完成后才能进行下面的数据扫描和发送部分。


在数据都打包完成后,要进行数据发送,我们就要调用到下面这个 SendReport 函数了,它的参数是我们所要发送的数据,后面两个方框定义了发送的数据量大小,sizeof 中就是我们之前讲到的鼠标的结构体变量。这个函数还不是最终的,后面还会进行特征处理、更新特征值并发出通知等操作。

 

通过以上学习,相信大家对 BLE 有了更深一些的了解了,或许能让你对 BLE 更加感兴趣一些。后续我还会给大家推出NXP QN9080 BLE 框架浅谈后续文章以及更多关于 BLE 、鼠标、键盘方面的博文,扩大大家的知识面,欢迎订阅关注我的博文。

 四、参考资料

【1】《 QN908x user manual 》

【2】深入浅出理解 BLE 协议栈

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论