BLE 协议栈架构与开发环境搭建
本章从 BLE 协议栈的层次结构出发,帮助读者建立对蓝牙低功耗通信模型的整体认知,并完成硬件选型、SDK 安装与工程模板解读。这是后续所有连接、数据读写和本地持久化实验的基础。
1.1 核心协议层:从物理射频到应用配置
BLE 协议栈从下到上可划分为四层:
- 物理层(PHY):负责 2.4GHz 射频收发,支持 1Mbps、2Mbps 及 Coded PHY(125/500kbps)。
- 链路层(LL):控制射频状态机(待机、广播、扫描、发起、连接),处理时序、重传与加密。
- 主机协议栈(Host):包含 L2CAP(逻辑链路控制与适配协议)、ATT(属性协议)、GATT(通用属性配置文件)、GAP(通用访问配置文件)、SM(安全管理器)。
- 应用层(App):用户代码通过 GATT/GAP API 实现具体业务逻辑。
核心概念:GAP 负责广播、扫描、连接的角色(Central/Peripheral);GATT 负责数据的组织与读写,通过 Service/Characteristic 树形结构暴露数据。
1.2 硬件选型:主流 BLE SoC 对比
选择 SoC 时需综合考虑功耗、RAM/Flash 大小、SDK 成熟度及社区资源。以下为三种常见平台:
| 参数 | Nordic nRF52840 | ESP32-C3 | TI CC2640R2F |
|---|---|---|---|
| 内核 | Cortex-M4F | RISC-V 单核 | Cortex-M3 |
| Flash | 1 MB | 4 MB(外置) | 128 KB |
| RAM | 256 KB | 400 KB | 20 KB(缓存)+ 8 KB SRAM |
| BLE 版本 | 5.4 | 5.0 | 5.0 |
| SDK 工具链 | nRF5 SDK + SES / GCC | ESP-IDF + VSCode | CCS + TI BLE-Stack |
| 典型应用 | 穿戴、传感、Mesh | WiFi+BLE 混合、IoT | 低功耗传感、Beacon |
硬件避坑:若需要同时使用 BLE 与 Flash 持久化,确保 SoC 具有足够 RAM 存放协议栈 + 应用数据 + 文件系统缓存。nRF52840 256KB RAM 通常够用,CC2640R2F 则需谨慎分配。
1.3 SDK 安装(以 nRF5 SDK v17.1.0 为例)
推荐使用 Segger Embedded Studio(SES)或 GCC + Makefile 进行编译。以下为基于 SES 的安装流程:
- 下载 nRF5 SDK 并解压至无空格路径。
- 下载并安装 SES(建议 v5.50 以上)。
- 打开 SDK 中的示例工程(如
examples/ble_peripheral/ble_app_uart)。 - 在 SES 中设置目标芯片(如 nRF52840_xxAA)。
- 编译并烧录。首次烧录需安装 J-Link 驱动。
SDK 关键路径结构:
nRF5_SDK_17.1.0_9b71d5c/
├── components/ # 驱动、协议栈、库
│ ├── ble/ # BLE 协议栈 API
│ ├── boards/ # 板级支持包
│ └── libraries/ # 通用库(FDS、FSTOR等)
├── examples/ # 示例工程
│ └── ble_peripheral/ # 外设示例
│ └── ble_app_uart/
├── external/ # 第三方(FreeRTOS、segger_rtt)
└── integration/ # 构建系统配置
性能优化要点:在工程中关闭不需要的协议栈特性(如 BLE Mesh、多连接)可减少 RAM 占用;使用静态内存分配替代动态 malloc 可避免堆碎片。
1.4 工程模板结构(以 nRF5 SDK 基础示例为例)
一个典型的 BLE 工程包含以下文件:
- main.c:应用入口,初始化硬件、协议栈、定时器,进入主循环。
- ble_
.c/.h :自定义 GATT 服务实现。 - app_scheduler.c(可选):任务调度器,用于非中断上下文事件处理。
- sdk_config.h:协议栈和驱动的宏配置开关。
- Makefile / SES project:编译与链接规则。
代码片段展示 BLE 初始化顺序(仅示意关键调用):
// 1. 初始化 SoftDevice(BLE 协议栈)
nrf_sdh_enable_request();
nrf_sdh_ble_enable(&ram_start);
// 2. 配置 GAP 参数
ble_gap_conn_params_t gap_conn_params = {
.min_conn_interval = MSEC_TO_UNITS(20, UNIT_0_625_MS),
.max_conn_interval = MSEC_TO_UNITS(20, UNIT_0_625_MS),
.slave_latency = 0,
.conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS)
};
sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN);
sd_ble_gap_conn_params_set(&gap_conn_params);
// 3. 添加 GATT 服务
ble_uart_service_init(&m_uart, uart_data_handler);
常见错误:
• 忘记调用
•
• 硬件引脚定义与板级文件冲突,例如 PA08 被同时用于 UART RTS 和 GIPO 输出。
• 忘记调用
nrf_sdh_ble_enable() 导致协议栈未启动,连接失败。•
sdk_config.h 中协议栈 RAM 分配不足导致 HardFault。• 硬件引脚定义与板级文件冲突,例如 PA08 被同时用于 UART RTS 和 GIPO 输出。