前言
学习使用蓝牙芯片进行项目开发,就得先对协议栈的框架结构进行分析,需要对BLE协议栈的框架结构有清晰的理解,因此我尝试简单分析一下BLE协议栈。
协议栈框架
首先,协议栈的意思就是对协议的代码实现,协议栈的框架分层大概可以用下图表示:
控制层可以分为:主控制器(HCI)、链路层(LL)、物理层(PHY);
HCI:控制一般的蓝牙设备行为,负责所有与数据无关的蓝牙系统操作,例如:查询蓝牙状态,连接蓝牙设备或者蓝牙设备被发现和连接;
LL:负责链路控制和链路管理,即创建、维护和释放逻辑链路;
PHY:负责从物理信道传输和接收信息数据包;
主协议层可以分为:通用访问规范(GAP)、通用属性配置文件(GATT)、属性层(ATT)、SMP(安全管理层)、L2CAP(链路控制和适配层);
GAP:GAP是对LL层有效数据包进行解析的方式的一种。GAP简单的对LL层有效数据进行了一些规范和定义,因此GAP主要用来进行广播、扫描和发起连接;
L2CAP:L2CAP对LL层进行了一次简单封装,LL层只关心传输的数据本身,L2CAP就要区分是加密通道还是普通通道,同时还要对连接间隔进行管理;
SMP:SMP用来管理BLE连接的加密和安全,如何保证连接的安全性,同时不影响用户的体验,这些都是SMP要考虑的工作;
扫描二维码关注公众号,回复: 11387978 查看本文章ATT:ATT层用来定义用户命令及命令操作的数据,比如读取某个数据或者写入某个数据;在BLE协议栈中,开发者接触最多的是ATT层;BLE引入attribute(属性)概念,用来描述一条条的数据,attribute除了定义数据外,还定义该数据可以使用的ATT命令;
GATT:GATT层用来规范attribute中的数据内容,并运用group(组)概念对attribute进行分类管理;没有GATT,BLE协议栈也能跑,但是互联互通就会出问题;
应用层:就是根据实际需求添加用户的应用代码,实际上就是添加服务文件;
Tips:
1、GATT定义了服务器(server)和客户端(client)两种角色,一般来说提供数据的设备称为GATT服务器,比如开发板;访问GATT服务器而获得数据的设备为GATT客户端,比如手机;
2、那么BLE蓝牙主机和从机又有什么区别呢?
答:BLE蓝牙的角色有广播者(advertiser)、扫描者(scanner)、从设备(slave)、主设备(master)、发起者(initiator),其中主设备是由发起者、扫描者转化而来,从设备是由广播者转化而来;
代码分析
一般来说,我们基本都是基于官方提供的工程框架来根据需求开发项目(毕竟有现成的就没必要自己造轮子了嘛),所以我们首先就要了解官方工程的基本结构。
基于官方样例工程基本可以把结构分为:
1、协议栈的hex文件目录:工程目录\components\softdevice\s110\hex,根据实际需求在这个目录下找合适的协议栈烧录文件即可;
2、应用app的hex文件目录:工程目录\examples\ble_peripheral\ble_app_template\hex;
3、启动文件/工具链文件目录:工程目录\components\toolchain\arm,根据不同的架构裁剪工程即可;
4、官方的服务例程文件目录:工程目录\components\ble\ble_services,官方提供大量的服务例程,我们可以在这里根据需求裁剪;
5、描述文档目录:documentation;
6、板级支持文件目录:examples\bsp;
我们先分析main函数代码:
/**@brief Function for application main entry.
*/
int main(void)
{
// Initialize.
leds_init(); //非必要
timers_init(); //非必要
buttons_init(); //非必要
ble_stack_init(); //必要
gap_params_init(); //必要
services_init(); //必要
advertising_init(); //必要
conn_params_init(); //视情况而定,如果连接之后不需要协商连接参数,这个函数可以不要
// Start execution.
advertising_start(); //必要
// Enter main loop.
for (;;)
{
power_manage(); //进入睡眠
}
}
其实核心函数也就5个,把非必要的去掉其实也能互联互通。而最后一个死循环函数就是BLE低功耗的关键,因为BLE协议栈是由事件驱动的工作模式,就是说只有事件触发才会执行相应的处理,否者将一直睡眠。
问:协议栈怎么运作的呢?
答:当手机发送链接请求或者数据时,协议栈首先收到这些数据后做一些处理,然后将这些数据打包成一个结构体并附加事件ID,然后通过派发函数将这个结构体上抛给应用层处理。
/**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler. * * @details This function is called from the scheduler in the main loop after a BLE stack * event has been received. * * @param[in] p_ble_evt Bluetooth stack event. */ static void ble_evt_dispatch(ble_evt_t * p_ble_evt) { on_ble_evt(p_ble_evt); ble_conn_params_on_ble_evt(p_ble_evt); ble_lbs_on_ble_evt(&m_lbs, p_ble_evt); ble_nus_on_ble_evt(&m_nus, p_ble_evt); }
总结
到这里我们基本可以简单理解BLE协议栈的工作流程和一些基础知识。