BLE 和经典蓝牙不是一回事
很多人一听到蓝牙就想到耳机、音箱,那是经典蓝牙(BR/EDR),要连续传音频,功耗高。BLE(Bluetooth Low Energy,现在叫 Bluetooth Smart)完全是另一种东西:它按"突发小数据包"工作,平时深度睡眠,醒过来几百毫秒发一帧就走。一颗纽扣电池能跑一两年的传感器、手环、Beacon、信标,全靠它。
BLE 的设计目标就是"占空比极低",不是"带宽高"。把它当 WiFi 用是错的,把它当"每隔几秒发一次小报文的无线串口"才是对的。
这篇从协议栈分层讲到 GATT 设计、再到省电和配对,把 BLE 真正做产品要踩的坑走一遍。
协议栈分层与角色
BLE 协议栈从下到上分:PHY(2.4G 射频)、Link Layer(链路层,负责广播与连接)、Host(逻辑链路控制、属性协议 ATT)、GAP(广播/扫描的角色定义)、GATT(服务与特征的应用层模型)。开发板上你通常只跟 Host 以上打交道,PHY 和 Link Layer 由 Nordic nRF52、PHY6222、CH582 这类芯片的协议栈固件替你做了。
- nRF52832/52840Nordic 生态最成熟,资料最多。
- PHY6222国产、便宜、配蓝牙 mesh 不错。
- CH582沁恒国产,RISC-V 内核,性价比高。
- ESP32-C3/C6带 WiFi+BLE,做网关最合适。
角色上,设备要么是 Peripheral(从设备,被手机连),要么是 Central(中心设备,去连别人)。绝大多数传感器是 Peripheral。
广播与扫描:让手机找到你
Peripheral 平时不建连接,只是周期性地在 37、38、39 三个广播信道上"喊":我叫 SHT30-001,我有温度数据。手机 App 在周围扫描,听到广播包,再发起连接。
// 典型广播数据结构(按 ADV 结构组装)
// Flags: 0x06 (LE General Disc, 不支持经典)
// Complete Local Name: "SHT30-001"
// Manufacturer Specific: 0x0059 + 设备 MAC + 电池电压
// 广播间隔 100ms,发射功率 0dBm
adv_interval = MSEC_TO_UNITS(100, UNIT_0_625_MS);
sd_ble_gap_adv_data_set(adv_data, sizeof(adv_data),
scan_rsp, sizeof(scan_rsp));
sd_ble_gap_adv_start(&adv_params);
广播包只有 31 字节,所以通常把"名字"放广播里、复杂数据放扫描响应里,或者干脆连上之后通过 GATT 读。
GATT:服务、特征与 Notify
连上之后,所有数据交换都走 GATT。GATT 是一棵树:Profile → Service → Characteristic → Descriptor。每个 Characteristic 有一个 UUID,可以读、写、Notify。
// 自定义 Service UUID: 0000A000-0000-1000-8000-00805F9B34FB
// Char1 0xA001 温度值 (Read + Notify)
// Char2 0xA002 采样间隔 (Read + Write)
// Char3 0xA003 设备名字 (Read + Write)
// 温度变化时主动 Notify 给手机
uint16_t len = 2;
uint8_t temp[2] = { temp_lo, temp_hi };
sd_ble_gatts_hvx(conn_handle, &(ble_gatts_hvx_params_t){
.type = BLE_GATT_HVX_NOTIFICATION,
.handle = char_temp_handle,
.p_len = &len, .p_data = temp
});
Notify 是 BLE 省电的关键:不用手机轮询,设备温度一变化就推一帧。手机端订阅 Notify 之后,数据是自动上来的。
连接参数与省电设计
BLE 连接建立后,双方按一个"连接间隔"同步醒来交换数据包。间隔越大越省电、但数据延迟越高。工程上常用:
- 配置阶段用 15ms 间隔,快速完成握手。
- 稳定后切到 100ms 或 200ms,兼顾实时与功耗。
- 没人连接时,把广播间隔从 100ms 拉到 1 秒,省一半电。
- 空闲 10 分钟无连接,直接关 BLE,靠外部中断(按键)再唤醒。
- 广播态100ms 间隔约 30~50μA。
- 连接态200ms 间隔约 100~150μA。
- 深睡眠1~2μA,纽扣电池能撑一年。
配对与加密
裸奔的 BLE 谁都能连。产品上必须做配对:Just Works(无加密,方便但不安全)、Passkey(手机弹 6 位数字确认)、LE Secure Connections(带加密)。家庭传感器建议用 Passkey,工业或门锁必须用 LE Secure Connections + 白名单。
绑定之后,手机和设备各自存一份 LTK。下次连接自动加密,未授权设备连不上。
常见坑与调试
BLE 调试最麻烦的是"看不到数据"。常用工具:
// 1. nRF Connect 手机 App:扫广播、连设备、看 GATT、订阅 Notify
// 2. Ellisys / Frontline 协议分析仪:空中包抓包
// 3. 芯片自带日志:串口打印连接事件、参数更新回调
// 4. 常见症状
// - 广播扫不到:确认 37/38/39 信道、广播间隔不小于 20ms
// - 连上就断:连接超时或配对失败,看 on_disconnected 错误码
// - Notify 收不到:手机端未订阅 CCCD,写 0x0001 进去
BLE 写起来不难,难的是把"省电、稳定、能被手机可靠识别"这三件事同时做到。先在 nRF Connect 上跑通,再换自己的 App,最后再优化功耗。
跑通这套流程,下一个产品就是 BLE Beacon、传感器节点或者键盘鼠标,套路都是一样的。