Zephyr RTOS低功耗蓝牙开发全流程记录
在IoT可穿戴与传感器节点中,低功耗蓝牙(Bluetooth Low Energy, BLE) 是首选无线协议。Zephyr RTOS原生集成BlueZ-hosted BT stack(Host + Controller可选),支持Peripheral/Central/Observer等角色,且对Nordic nRF52、ST WB系列有直接驱动支持。本文将按真实Bring-up顺序,记录从环境搭建到GATT服务的完整开发流程。
一、环境与板卡准备
• Host机:Ubuntu 22.04 + west (Zephyr meta-tool)
• Target:nRF52840 DK(PCA10056)或 nRF5340 DK
- Zephyr版本:v3.5 LTS(示例命令兼容新版)
• 工具链:arm-none-eabi-gcc,west已安装并zephyr-sdk-0.16.x设好环境变量
初始化工作空间(若未做):
west init ~/zephyrproject
cd ~/zephyrproject
west update
west zephyr-export
确认板子被识别:
west boards | grep nrf52840dk
二、创建BLE Peripheral示例工程
Zephyr自带samples/bluetooth/peripheral_hr(心率计)与peripheral(自定义GATT),我们以最简Peripheral为例。
1. 拷贝示例并配置
cp -r zephyr/samples/bluetooth/peripheral my_ble_periph
cd my_ble_periph
prj.conf 最小BLE Peripheral配置:
# 启用BLE协议栈
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Zephyr_BLE"
CONFIG_BT_DEVICE_APPEARANCE=833 # Generic Heart Rate Sensor
# 使能GATT服务(示例自带Heart Rate Service)
CONFIG_BT_GATT_SERVICE=y
CONFIG_BT_GATT_DIS=y # Device Information Service
# 日志
CONFIG_BT_DEBUG_LOG=y
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
# 低功耗(可选)
CONFIG_PM=y
CONFIG_BT_CTLR_SLEEP_BETWEEN_PREAMBLES=y
2. 设备树 overlay(如需自定义广播间隔)
/ {
chosen {
zephyr,bt-enable = &bt_ctlr;
};
};
三、编译与烧录
# 编译(nRF52840 DK)
west build -b nrf52840dk_nrf52840 -p auto
# 烧录(J-Link / CMSIS-DAP)
west flash
# 查看RTT/串口日志
west espressif monitor # 或 minicom @ 115200
上电后串口应打印:
[00:00:00.010,000] bt_hci_core: Bluetooth initialized
[00:00:00.012,000] peripheral: Advertising started
手机端用nRF Connect可扫描到 Zephyr_BLE 并发现 Heart Rate Service (0x180D)。
四、添加自定义GATT Service(核心实战)
真实产品通常需要自定义特征值,下面演示添加一个只读设备状态特征。
1. 定义UUID(可随机生成)
/* my_service.h */
#define MY_SVC_UUID BT_UUID_DECLARE_128( \
0x12,0x34,0x56,0x78,0x90,0xAB,0xCD,0xEF, \
0xFE,0xDC,0xBA,0x09,0x87,0x65,0x43,0x21)
#define MY_CHAR_STATUS_UUID BT_UUID_DECLARE_16(0xFF01)
2. 实现GATT Service回调
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/uuid.h>
#include "my_service.h"
static uint8_t dev_status = 0x55; // 示例:电池+工作状态
static ssize_t read_status(struct bt_conn *conn,
const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{
return bt_gatt_attr_read(conn, attr, buf, len, offset,
&dev_status, sizeof(dev_status));
}
/* GATT Attribute Table */
BT_GATT_SERVICE_DEFINE(my_svc,
BT_GATT_PRIMARY_SERVICE(MY_SVC_UUID),
BT_GATT_CHARACTERISTIC(MY_CHAR_STATUS_UUID,
BT_GATT_CHRC_READ,
BT_GATT_PERM_READ,
read_status, NULL, NULL)
);
/* 在main中启用 */
void ble_adv_start(void)
{
struct bt_le_adv_param *param = BT_LE_ADV_CONN;
bt_le_adv_start(param, ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd));
}
在main.c初始化顺序:
void main(void)
{
int err = bt_enable(NULL);
if (err) printk("Bluetooth init failed (%d)\n", err);
/* 可选:注册GAP回调 */
bt_conn_cb_register(&conn_callbacks);
ble_adv_start();
}
重新编译烧录后,nRF Connect可看到自定义Service并读取0x55。
五、低功耗相关配置与验证
BLE Peripheral在广播间隙与连接空闲可进低功耗:
# prj.conf 追加
CONFIG_PM=y
CONFIG_BT_CTLR_LOW_LATENCY_DISABLE=y # 允许controller休眠
CONFIG_SYS_POWER_MANAGEMENT=y
CONFIG_TICKLESS_KERNEL=y
用电流表测nRF52840:
• 广播态(ADV_IND 20ms间隔):≈ 20 µA 平均(含栈处理)
• 连接空闲(7.5ms Conn Interval):≈ 5–8 µA
- 深度休眠(未广播,挂起):≈ 0.8 µA
注意:若打开了CONFIG_BT_DEBUG_LOG,日志UART会阻止深睡,实测电流显著升高——发布版务必关调试日志。
六、常见坑排查
现象 原因 解决
编译报 undefined reference to bt_enable 未开 CONFIG_BT=y 或链接zephyr.elf时缺lib 确认prj.conf包含 CONFIG_BT=y
手机搜不到设备 广播数据(ad/sd)未含Flags字段 示例中已含 BT_DATA_FLAGS(BT_LE_AD_GENERAL_DISC)
写特征值返回 BT_ATT_ERR_ATTRIBUTE_NOT_FOUND UUID不匹配或Characteristic未注册 检查 BT_GATT_SERVICE_DEFINE 宏是否被执行(需全局对象)
功耗异常高 LOG_UART活跃 / 未开Tickless 关闭CONFIG_BT_DEBUG_LOG,确认CONFIG_TICKLESS_KERNEL=y
七、结语
Zephyr RTOS提供了一套从Controller到GATT Service的完整BLE协议栈。通过west构建、最小prj.conf启用BT、用BT_GATT_SERVICE_DEFINE挂自定义服务,配合低功耗Kconfig选项,即可在nRF等平台快速实现符合规范的BLE Peripheral。对Central / Observer 角色,流程相似,只需切换CONFIG_BT_CENTRAL=y并调用bt_le_scan_start()。





