1. BLE协议栈全景与开发环境搭建
1.1 协议栈分层结构
BLE协议栈由控制器(Controller)和主机(Host)两部分构成,分别对应物理层/链路层与上层应用功能。典型分层模型如下表:
| 层名 | 英文 | 职责 |
|---|---|---|
| 物理层 | PHY | 2.4GHz ISM频段射频收发,支持1M/2M/125kbps(LE Coded) |
| 链路层 | LL | 广播、扫描、连接建立、数据包重传、加密状态机 |
| 主机控制接口 | HCI | Controller与Host之间的命令/事件/数据通道(UART/SPI/USB) |
| 逻辑链路控制与适配协议 | L2CAP | 协议多路复用、分段重组、MTU协商 |
| 安全管理 | SM | 配对、认证、密钥分发、加密 |
| 属性协议 | ATT | 客户端-服务器属性读写、通知、指示 |
| 通用属性配置文件 | GATT | 基于ATT的服务/特征/描述符定义 |
| 通用访问配置文件 | GAP | 广播模式、连接角色、设备发现 |
理解要点:应用开发者主要与GAP/GATT打交道,但广播工程直接涉及LL+GAP。底层HCI和L2CAP由SDK封装,调试时偶需关注MTU和连接间隔。
1.2 开发板与SDK选择
主流BLE SoC及对应的SDK对比如下:
| 芯片厂商 | 代表性型号 | SDK | 推荐工具链 |
|---|---|---|---|
| Nordic | nRF52840 / nRF5340 | nRF5 SDK / nRF Connect SDK (Zephyr) | SEGGER Embedded Studio / VS Code + nRF Command Line Tools |
| Espressif | ESP32-C3 / ESP32-S3 | ESP-IDF (BLE组件) | VS Code + ESP-IDF插件 |
| TI | CC2640R2 / CC2652 | SimpleLink CC13x2/CC26x2 SDK | CCS / IAR |
| Dialog | DA1469x | SmartSnippets SDK | Keil / GCC |
课程选型:优先使用Nordic nRF52840 DK + nRF5 SDK 17.1.0(原生BLE协议栈SoftDevice S140)作为主示例;同时提供ESP32-DevKitC + ESP-IDF v5.0备选方案。
1.3 开发环境搭建(Nordic nRF52840)
步骤一:安装工具链
- 下载安装SEGGER Embedded Studio(免费商用版本可用于nRF5 SDK)。
- 下载nRF Command Line Tools(含JLink驱动、mergehex、nrfjprog)。
- 安装GNU Arm Embedded Toolchain(版本 10.3-2021.10)。
步骤二:获取SDK和SoftDevice
# 下载 nRF5 SDK 17.1.0(约500MB)
wget https://www.nordicsemi.com/eng/nordic/downloads/.../nRF5_SDK_17.1.0_ddde560.zip
unzip nRF5_SDK_17.1.0_ddde560.zip -d ~/nRF5_SDK_17.1.0
# SDK内部包含SoftDevice hex文件
# 位置:components/softdevice/s140/hex/s140_nrf52_7.3.0_softdevice.hex
步骤三:第一个BLE广播工程(模板)
使用nRF5_SDK/examples/ble_peripheral/ble_app_beacon作为起点,修改main.c设定广播数据:
// main.c 核心片段
static void advertising_init(void)
{
ret_code_t err_code;
ble_advdata_t advdata;
uint8_t flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
// 构建广播数据(iBeacon示例)
ble_advdata_manuf_data_t manuf_specific_data;
manuf_specific_data.company_identifier = 0x004C; // Apple
manuf_specific_data.data.p_data = (uint8_t[]){0x02,0x15,0xE2,0x0A,0x39,0xF4,...};
manuf_specific_data.data.size = 25;
memset(&advdata, 0, sizeof(advdata));
advdata.name_type = BLE_ADVDATA_NO_NAME;
advdata.flags = flags;
advdata.p_manuf_specific_data = &manuf_specific_data;
ble_gap_adv_params_t adv_params;
memset(&adv_params, 0, sizeof(adv_params));
adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND;
adv_params.p_peer_addr = NULL; // 向所有设备广播
adv_params.fp = BLE_GAP_ADV_FP_ANY;
adv_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS);
adv_params.timeout = 0; // 持续广播
err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &advdata, &adv_params);
APP_ERROR_CHECK(err_code);
}
常见错误:SoftDevice未烧录时调用任何BLE API会返回
NRF_ERROR_INVALID_STATE。务必先使用nrfjprog --program s140_nrf52_7.3.0_softdevice.hex --sectorerase写入SoftDevice。1.4 ESP32-C3 备选环境配置
# 安装 ESP-IDF(推荐 v5.0 及以上)
git clone -b v5.0 --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh esp32c3
. ./export.sh
# 打开示例
cp -r examples/bluetooth/bluedroid/ble/ble_ibeacon ~/my_ble_beacon
cd ~/my_ble_beacon
idf.py set-target esp32c3
idf.py menuconfig # 配置广播参数(UUID, Major, Minor)
idf.py build flash monitor
ESP32-C3使用Bluedroid协议栈(基于蓝牙双模规范),广播API在esp_ble_gap_config_adv_data()中设置。
1.5 调试与日志验证
nRF5调试:串口UART输出日志(波特率115200),Segger RTT可实时查看。典型广播启动日志:
00:00:00.000 <info> app: SoftDevice S140 7.3.0 initialized
00:00:00.100 <info> app: Starting advertising...
00:00:00.200 <info> app: Advertising interval = 100.00 ms
00:00:00.250 <info> app: Advertising started, handle 0x0001
ESP32调试:使用idf.py monitor查看蓝牙事件:
I (452) BT_INIT: BT controller initialized
I (462) BLE_IBEACON: Advertising data set successfully
I (472) BLE_IBEACON: Advertising started
1.6 性能调优建议
- 广播间隔:100ms(10Hz)是功耗与发现速度的平衡点。间隔越小(20ms)温升越快,间隔越大(1s)省电但扫描端响应慢。
- 广播通道:默认使用37/38/39三个通道。若需降低干扰,可强制使用单一通道(如只发CH37)。
- 广播数据长度:最多31字节(传统广播)或255字节(扩展广播)。缩短数据可减少片上处理时间。
首次成功原则:先让LED闪烁工程跑通,再烧录SoftDevice,最后编译运行广播工程。分步验证可以快速定位环境问题。