3、BLE基础与协议栈:理解BLE 5.0/5.1的核心概念(GAP、GATT、广播、连接、服务与特征),以及nRF协议栈(SoftDevice)的架构与配置

在nRF智能穿戴项目中,BLE(Bluetooth Low Energy)是连接设备与手机App、云端的核心桥梁。无论是心率数据的实时上传,还是动作传感器(如加速度计、陀螺仪)的配置下发,都依赖于对BLE协议栈的深刻理解。本章将系统梳理BLE 5.0/5.1的核心概念,包括GAP、GATT、广播、连接、服务与特征,并深入解析Nordic Semiconductor的SoftDevice协议栈架构与配置方法。掌握这些内容,是后续实现心率采集、动作识别与数据同步业务的基础。

nRF智能穿戴BLE协议栈架构与数据流 应用层(App Layer) 心率采集 / 动作识别 / 业务逻辑 / 数据同步 SoftDevice 协议栈(Nordic) GAP(通用访问规范) 广播 / 扫描 / 连接管理 GATT(通用属性规范) 服务 / 特征 / 属性操作 L2CAP / ATT / SM 数据封装 / 属性协议 / 安全管理 链路层(Link Layer) 物理信道 / 数据包 / 重传 / 跳频 BLE 5.0/5.1 物理层(2.4GHz ISM频段,2Mbps / Coded PHY / 测向) 事件回调 / 数据上报 协议栈事件 关键点:应用层通过SoftDevice API与协议栈交互,不直接操作硬件寄存器 GAP负责设备发现与连接,GATT负责连接后的数据读写与通知

3.1 BLE 5.0/5.1核心概念:GAP与GATT

3.1.1 核心原理:GAP与GATT的分工

BLE协议栈从逻辑上分为两大规范:GAP(Generic Access Profile,通用访问规范)和GATT(Generic Attribute Profile,通用属性规范)。GAP定义了设备如何被发现、如何建立连接,以及设备在系统中的角色(广播者、扫描者、主机、从机)。GATT则定义了连接建立后,数据如何以“服务”和“特征”的形式进行结构化传输。简单来说,GAP负责“握手”,GATT负责“对话”。

在nRF智能穿戴项目中,手表或手环通常作为GATT Server(从机),手机App作为GATT Client(主机)。设备通过GAP广播自身的存在,手机扫描到广播后发起连接请求。连接建立后,手机通过GATT发现设备上的服务(如心率服务、电池服务),并订阅特征值以接收实时数据。

3.1.2 判断方法:角色与连接状态机

在开发中,首先要明确设备角色。nRF52832/52840等芯片既可作为外围设备(Peripheral),也可作为中央设备(Central)。对于智能穿戴项目,设备通常作为Peripheral。连接状态机包括:Standby(待机)、Advertising(广播)、Scanning(扫描)、Initiating(发起连接)、Connected(已连接)。开发者需要根据业务需求设计状态切换逻辑,例如在未连接时进入低功耗广播模式,连接后切换为高速数据传输模式。

状态角色典型应用场景功耗
Advertising广播者设备待配对、寻找手机低(可配置间隔)
Scanning扫描者手机搜索设备中
Connected主/从数据同步、实时心率传输中高
Standby-深度睡眠、省电模式极低

3.1.3 案例拆解:心率服务的数据交互

以典型的心率监测为例:设备端在GATT Server中定义Heart Rate Service(0x180D),包含Heart Rate Measurement特征(0x2A37)。手机App作为Client,连接后执行以下操作:

  1. 发现服务:通过GATT Discover Services找到0x180D。
  2. 发现特征:找到0x2A37,并读取其属性(支持Notify)。
  3. 配置通知:写入Client Characteristic Configuration Descriptor(CCCD,0x2902)为0x0001,使能Notify。
  4. 接收数据:设备端每次测量到心率后,主动通过Notify发送数据包(格式:Flags + 心率值)。

这个过程中,GAP负责连接建立,GATT负责服务发现与数据交互。如果设备端没有正确配置CCCD,手机将无法收到任何数据,这是最常见的开发错误之一。

经验提醒:在nRF SDK中,使用sd_ble_gatts_hvx()函数发送Notify数据。务必在连接事件(BLE_GAP_EVT_CONNECTED)后,检查客户端是否已使能CCCD,否则数据会被协议栈丢弃。

3.2 广播、连接与安全机制

3.2.1 核心原理:广播数据包与连接参数

广播是BLE设备被发现的唯一途径。广播数据包(Advertising Data)最大31字节,可包含设备名称、服务UUID、厂商自定义数据等。在nRF智能穿戴中,广播包通常包含设备名称和心率服务UUID,以便手机App快速识别。连接参数包括连接间隔(Connection Interval)、从机延迟(Slave Latency)和超时时间(Supervision Timeout)。连接间隔越短,数据实时性越高,但功耗越大。

3.2.2 操作流程:配置广播与连接参数

在nRF SDK中,配置广播需要填充ble_advdata_t结构体,并调用sd_ble_gap_adv_set_configure()。连接参数则通过sd_ble_gap_conn_param_update()请求更新。以下是一个典型的广播配置代码片段:

ble_advdata_t advdata;
memset(&advdata, 0, sizeof(advdata));
advdata.name_type = BLE_ADVDATA_FULL_NAME;
advdata.include_appearance = true;
advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
ble_advdata_service_data_t service_data;
service_data.service_uuid = BLE_UUID_HEART_RATE_SERVICE;
service_data.data.p_data = (uint8_t*)hr_data;
service_data.data.len = sizeof(hr_data);
advdata.p_service_data = &service_data;
sd_ble_gap_adv_set_configure(&adv_handle, &advdata, NULL, BLE_GAP_ADV_FLAG_CONNECTABLE);

3.2.3 安全机制:配对与绑定

BLE 5.0/5.1支持LE Legacy Pairing和LE Secure Connections(基于ECDH P-256)。对于穿戴设备,通常使用Just Works配对方式(无需输入PIN码),但需要开启加密和绑定(Bonding),以便后续重连时无需重新配对。在nRF中,通过sd_ble_gap_sec_params_reply()响应安全请求。

风险提示:如果配对后未正确保存绑定信息(Bonding Information),设备重启后可能需要重新配对,影响用户体验。务必在BLE_GAP_EVT_SEC_PARAMS_REQUEST事件中正确处理,并将绑定信息写入Flash。

3.3 nRF SoftDevice协议栈架构与配置

3.3.1 核心原理:SoftDevice的分层设计

SoftDevice是Nordic提供的预编译BLE协议栈,以二进制库形式与应用程序链接。它运行在特权模式,应用程序运行在非特权模式,通过Supervisor Call(SVC)指令调用协议栈API。SoftDevice负责链路层、L2CAP、ATT、SM、GAP和GATT的实现,应用程序只需调用API并处理回调事件。这种架构隔离了协议栈与业务代码,提高了稳定性和安全性。

3.3.2 配置方法:内存布局与中断优先级

使用SoftDevice需要配置内存布局。nRF52832的Flash为512KB,SoftDevice(如S132)占用约152KB,应用程序从0x26000开始。RAM方面,SoftDevice占用约4.7KB,应用程序从0x20002C00开始。在Keil或GCC工程中,需设置链接脚本(.icf或.ld)的起始地址。中断优先级方面,SoftDevice要求所有外设中断优先级不得高于协议栈中断(即数值必须大于等于协议栈设定的阈值,通常为4)。

资源SoftDevice S132占用应用程序可用说明
Flash152KB360KB从0x26000开始
RAM4.7KB60KB+从0x20002C00开始
中断优先级0-34-15协议栈使用最高优先级

3.3.3 实战场景:初始化SoftDevice与事件调度

在main函数中,初始化顺序至关重要:先初始化时钟(sd_softdevice_enable()),再初始化协议栈(softdevice_handler_init()),最后注册GAP/GATT回调。事件通过softdevice_evt_schedule()进入主循环处理。以下是一个标准初始化流程:

// 1. 使能SoftDevice
nrf_clock_lf_cfg_t clock_lf_cfg = {.source = NRF_CLOCK_LF_SRC_RC, .rc_ctiv = 16, .rc_temp_ctiv = 2};
sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler);
// 2. 初始化协议栈事件处理
softdevice_handler_init(NRF_CLOCK_LFCLKSRC_RC_CTIV_16, NULL, NULL, NULL);
// 3. 注册BLE事件回调
ble_evt_dispatch(ble_evt_handler);
// 4. 启动主循环
while (1) { app_sched_execute(); }

3.3.4 常见误区与复盘

  • 误区一:在中断服务函数(ISR)中直接调用SoftDevice API。正确做法是将事件通过调度器(app_sched)放入队列,在主循环中处理。
  • 误区二:忽略协议栈对RAM起始地址的要求,导致内存冲突。务必检查链接脚本的RAM起始地址是否与SoftDevice占用区域重叠。
  • 误区三:在未连接时频繁发送数据。协议栈会返回BLE_ERROR_INVALID_STATE,应检查连接状态。
复盘总结:BLE开发的核心是理解GAP/GATT的角色分工,以及SoftDevice的事件驱动模型。在nRF智能穿戴项目中,建议先使用Nordic提供的ble_app_hrs示例工程跑通心率服务,再逐步添加动作传感器和自定义服务。调试时,使用nRF Connect App可以快速查看广播包、服务列表和特征值,极大提升开发效率。