当前位置: 首页 > news >正文

zephyr架构下Bluetooth advertising接口

目录

概述

1 函数接口

2 主要函数介绍

2.1 bt_le_adv_start函数

2.1.1 函数功能介绍

2.1.2 典型使用示例

2.1.3 广播间隔

2.1.4 注意事项

2.2 bt_le_adv_stop 函数

2.2.1  函数功能

 2.2.2 使用方法介绍

2.2.3 实际应用示例

2.2.4 关键注意事项

 2.2.5 常见问题解决

2.2.6 应用总结 

2.3 bt_enable

2.3.1 函数功能

 2.3.2 典型使用模式

2.3.3 关键处理流程

 2.3.4 注意事项

 2.3.5 初始化失败常见原因

2.3.6  实际应用示例

2.3.7 应用总结

2.4 bt_le_adv_update_data函数

2.4.1 函数功能

 2.4.2 典型使用场景

2.4.3 关键特性

 2.4.4 实现原理

2.4.5 注意事项

 2.4.6 错误处理最佳实践

2.4.7 典型应用案例

2.4.8 应用总结


概述

本文主要介绍zephyr架构下Bluetooth advertising一些接口函数的功能和使用方法,这些函数是bluetooth的最重要的一些接口,掌握这些函数的用法是进行蓝牙功能开发的基础。

1 函数接口

基于zephyr OS架构下实现Bluetooth advertising功能其使用的函数接口有如下这些

函数名称功能说明

bt_le_adv_start

实现广播功能BLE模块被使能后,启用该函数进行广播,可通过设置不同的参数,实现不同的广播方式

bt_enable

使能BLE使能BLE的功能,该函数

bt_le_adv_stop

停止广播关闭广播功能,下次要重新广播时,需要调用bt_le_adv_start

bt_le_adv_update_data

更新广播数据

2 主要函数介绍

2.1 bt_le_adv_start函数

2.1.1 函数功能介绍

bt_le_adv_start 是蓝牙低功耗 (BLE) 协议栈中的一个关键 API 函数,用于启动设备的广播(Advertising)功能。这个函数允许 BLE 设备(Peripheral 角色)向周围设备广播自己的存在,并携带相关信息。bt_le_adv_start 是 BLE 设备广播功能的核心 API,合理配置广播参数和数据可以优化设备发现性、连接速度和功耗表现。开发者需要根据具体应用场景(如 Beacon、可连接外设等)选择合适的广播模式和数据结构。

1)功能概述

  • 作用:启动 BLE 设备的广播功能

  • 适用角色:Peripheral(外设)或 Broadcaster(广播者)

  • 广播模式:可配置为可连接广播、不可连接广播、可扫描广播等

  • 广播数据:可携带设备名称、服务 UUID、厂商数据等

2)函数原型:

int bt_le_adv_start(const struct bt_le_adv_param *param,const struct bt_data *ad,size_t ad_len,const struct bt_data *sd,size_t sd_len);

3)参数说明

参数类型说明
parambt_le_adv_param*广播参数配置(广播类型、间隔等)
adbt_data*广播数据(Advertising Data)
ad_lensize_t广播数据项数量
sdbt_data*扫描响应数据(Scan Response Data)
sd_lensize_t扫描响应数据项数量

4)广播参数配置(bt_le_adv_param)

struct bt_le_adv_param {uint8_t  id;        // 广播集 IDuint32_t options;   // 广播选项(如 BT_LE_ADV_OPT_CONNECTABLE)uint16_t interval_min; // 最小广播间隔(单位:0.625ms)uint16_t interval_max; // 最大广播间隔(单位:0.625ms)uint8_t  peer[6];   // 定向广播的目标地址(可选)
};

常用广播选项(options)

  • BT_LE_ADV_OPT_CONNECTABLE - 可连接广播

  • BT_LE_ADV_OPT_USE_NAME - 在广播中包含设备名称

  • BT_LE_ADV_OPT_SCANNABLE - 允许扫描响应

  • BT_LE_ADV_OPT_ONE_TIME - 仅广播一次

 5)广播数据类型(bt_data)

struct bt_data {uint8_t type;  // 数据类型(如 BT_DATA_NAME_COMPLETE)uint8_t data_len;const uint8_t *data;
};

2.1.2 典型使用示例

1)1. 基本可连接广播

static const struct bt_data ad[] = {BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};static const struct bt_le_adv_param *adv_param = BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_USE_NAME,BT_GAP_ADV_FAST_INT_MIN_1,BT_GAP_ADV_FAST_INT_MAX_1,NULL
);bt_le_adv_start(adv_param, ad, ARRAY_SIZE(ad), NULL, 0);

2)不可连接广播(Beacon 模式)

static const uint8_t beacon_data[] = {0x01, 0x02, 0x03, 0x04, // 厂商特定数据
};static const struct bt_data ad[] = {BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NONCONN_IND),BT_DATA(BT_DATA_MANUFACTURER_DATA, beacon_data, sizeof(beacon_data)),
};bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad), NULL, 0);

2.1.3 广播间隔

BLE 广播间隔以 0.625ms 为单位:

  • 快速广播:20ms - 60ms(BT_GAP_ADV_FAST_INT_MIN_1 = 32 = 20ms)

  • 慢速广播:100ms - 150ms(BT_GAP_ADV_SLOW_INT_MIN = 160 = 100ms)

返回值

  • 0:广播启动成功

  • 负值:错误码(如 -EINVAL 参数错误,-ENOMEM 内存不足)

2.1.4 注意事项

  1. 广播数据总长度不能超过 31 字节

  2. 扫描响应数据也受 31 字节限制

  3. 广播间隔影响功耗和可发现性

  4. 某些广播模式(如定向广播)有额外限制

2.2 bt_le_adv_stop 函数

2.2.1  函数功能

bt_le_adv_stop 是蓝牙低功耗 (BLE) 协议栈中的一个关键 API 函数,用于停止正在进行的广播。它通常与 bt_le_adv_start 配对使用,用于控制 BLE 设备的广播生命周期。

1)核心功能

  • 停止广播:立即终止当前正在进行的 BLE 广播

  • 释放资源:释放与广播相关的协议栈资源

  • 配合广播控制:通常用于动态广播管理场景

 2)函数原型(基于 Zephyr BLE 协议栈)

int bt_le_adv_stop(void);

参数

  • 无参数:直接停止当前活跃的广播

返回值

返回值说明
0停止广播成功
-EALREADY当前没有活跃的广播
其他负值其他错误(如协议栈错误)

 2.2.2 使用方法介绍

1) 基本启停控制

// 启动广播
bt_le_adv_start(...);// 一段时间后停止广播
bt_le_adv_stop();

2)条件性停止广播

if (need_to_stop_advertising) {int err = bt_le_adv_stop();if (err) {printk("Stop failed (err %d)\n", err);}
}

3) 广播模式切换

// 先停止当前广播
bt_le_adv_stop();// 更换参数后重新启动
bt_le_adv_start(new_params, ...);

2.2.3 实际应用示例

场景:温度传感器按需广播

void start_temp_advertising(void) {bt_le_adv_start(..., temp_ad_data, ...);
}void stop_advertising_when_connected(void) {// 当连接建立时自动停止广播// 或手动调用:bt_le_adv_stop();
}void on_button_press(void) {// 按钮按下时重新广播bt_le_adv_stop();  // 先确保停止start_temp_advertising();
}

2.2.4 关键注意事项

  1. 无广播时的调用

    如果没有活跃的广播,调用会返回 -EALREADY(非致命错误)
  2. 线程安全性

    建议在协议栈线程(如 Zephyr 的 Bluetooth 线程)上下文中调用
  3. 与连接的交互

    如果设备已通过广播建立连接,广播会自动停止,此时调用会返回 -EALREADY
  4. 低功耗场景

    停止广播会显著降低功耗(广播是功耗主要来源之一)
  5. 广播集支持

    在支持多广播集的协议栈中(如 Zephyr 2.7+),可能需要指定广播集 ID

 2.2.5 常见问题解决

Q1:停止广播后为什么设备仍可被扫描到?
A1:可能是其他广播实例仍在运行,或广播停止有延迟(检查返回值)

Q2:如何确保广播完全停止?
A2:

do {err = bt_le_adv_stop();
} while (err == 0); // 直到返回-EALREADY

Q3:停止广播会影响已建立的连接吗?
A3:不会,只影响广播行为,不影响现有连接

2.2.6 应用总结 

bt_le_adv_stop 是 BLE 设备广播管理的核心控制点,合理使用可以实现:

  • 精确的广播生命周期控制

  • 动态广播策略切换

  • 有效的功耗管理

在需要频繁切换广播模式或优化功耗的场景中,正确使用该API至关重要。

2.3 bt_enable

2.3.1 函数功能

bt_enable 是蓝牙协议栈中的核心初始化函数,用于启用和初始化蓝牙控制器及协议栈。它是任何蓝牙应用程序的第一个关键调用,为后续所有蓝牙操作建立基础环境。

函数原型(基于Zephyr等常见协议栈)

int bt_enable(bt_ready_cb_t cb);

参数说明

参数类型说明
cbbt_ready_cb_t蓝牙初始化完成后的回调函数(可设为NULL)

 回调函数类型定义:

typedef void (*bt_ready_cb_t)(int err);

核心功能

  1. 硬件初始化

    • 初始化蓝牙射频控制器(Radio)

    • 配置底层硬件(如时钟、电源等)

  2. 协议栈加载

    • 加载HCI层、L2CAP、ATT/GATT等协议栈组件

    • 初始化安全管理器(SM)

  3. 默认配置应用

    • 设置默认蓝牙MAC地址

    • 应用编译时配置的默认参数

  4. 状态切换

    • 将蓝牙控制器从OFF状态切换到READY状态

返回值

返回值说明
0初始化流程成功启动(注意:实际结果通过回调返回)
-EALREADY蓝牙协议栈已启用
-ENOMEM内存不足
-EIO硬件初始化失败

 2.3.2 典型使用模式

1) 同步初始化(无回调)

int err = bt_enable(NULL);
if (err) {printk("Bluetooth init failed (err %d)\n", err);return;
}
// 继续其他蓝牙操作

2)异步初始化(带回调)

void bt_ready(int err) {if (err) {printk("Bluetooth init failed (err %d)\n", err);return;}printk("Bluetooth initialized\n");// 在这里启动广播/扫描等操作
}void main(void) {int err = bt_enable(bt_ready);if (err) {printk("Bluetooth enable failed (err %d)\n", err);}
}

2.3.3 关键处理流程

 2.3.4 注意事项

  1. 单次调用限制

    • 多数实现要求全局只调用一次

    • 重复调用需先调用bt_disable()

  2. 回调上下文

    • 回调函数通常在蓝牙线程执行

    • 避免在回调中进行阻塞操作

  3. 依赖关系

    • 必须在所有其他蓝牙API前调用

    • 通常应在系统初始化完成后调用

  4. 调试支持

    • 可通过CONFIG_BT_DEBUG等选项启用调试日志

 2.3.5 初始化失败常见原因

  1. 硬件问题

    • 蓝牙芯片未正确供电

    • 射频电路故障

  2. 配置冲突

    • 与其他无线服务(如WiFi)共用资源

    • 错误的时钟配置

  3. 资源不足

    • 内存池大小不足(检查CONFIG_BT_*_TX_COUNT等配置)

    • 中断冲突

2.3.6  实际应用示例

1) 简单外设初始化

void main(void) 
{bt_enable(NULL); // 同步初始化bt_le_adv_start(...); // 立即开始广播
}

2)带错误恢复的初始化

void bt_retry_init(int err)
{if (err) {k_sleep(K_SECONDS(1));bt_enable(bt_retry_init); // 重试初始化}
}void main(void) 
{bt_enable(bt_retry_init);
}

2.3.7 应用总结

bt_enable 是蓝牙开发的第一个关键调用,其核心价值在于:

  • 建立蓝牙操作的基础环境

  • 提供同步/异步两种初始化模式

  • 协调硬件和协议栈的启动

正确使用该API需要注意:

  1. 调用时机(早于其他蓝牙操作)

  2. 错误处理机制

  3. 特定协议栈的特殊要求

在复杂应用中,建议使用异步回调模式,以便在初始化完成后自动执行后续蓝牙操作流程。

2.4 bt_le_adv_update_data函数

2.4.1 函数功能

bt_le_adv_update_data 是蓝牙低功耗 (BLE) 协议栈中的一个关键 API 函数,用于动态更新正在进行的广播数据或扫描响应数据,而无需停止并重新启动广播。

核心功能

  • 动态更新广播数据:修改广播包(Advertising Data)或扫描响应包(Scan Response Data)内容

  • 无需重启广播:保持广播持续进行,避免广播中断导致的设备不可见期

  • 实时数据刷新:适用于需要频繁更新广播信息的场景(如传感器数据变化)

 函数原型(基于Zephyr等常见协议栈)

int bt_le_adv_update_data(const struct bt_data *ad, size_t ad_len,const struct bt_data *sd,size_t sd_len);

参数说明

参数类型说明
adbt_data*新的广播数据数组
ad_lensize_t广播数据项数量
sdbt_data*新的扫描响应数据数组
sd_lensize_t扫描响应数据项数量

返回值

返回值说明
0数据更新成功
-EINVAL参数无效(如数据长度超限)
-ENOMEM内存不足
-EAGAIN协议栈繁忙,需重试
-ENOTCONN当前未进行广播

 2.4.2 典型使用场景

1) 传感器数据实时更新

// 初始广播
bt_le_adv_start(..., initial_ad, ...);// 当温度变化时更新数据
void update_temp_data(float new_temp) 
{uint8_t temp_encoded = (uint8_t)(new_temp * 2);struct bt_data new_ad[] = {BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_GENERAL),BT_DATA(BT_DATA_MANUFACTURER_DATA, &temp_encoded, 1)};bt_le_adv_update_data(new_ad, ARRAY_SIZE(new_ad), NULL, 0);
}

2) 动态切换广播模式

// 从普通广播切换到信标模式
struct bt_data beacon_ad[] = 
{BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NONCONN_IND),BT_DATA(BT_DATA_MANUFACTURER_DATA, beacon_payload, sizeof(beacon_payload))
};bt_le_adv_update_data(beacon_ad, ARRAY_SIZE(beacon_ad), NULL, 0);

2.4.3 关键特性

原子性更新

1)数据更新在单个广播间隔内完 ;
 2)接收端不会看到部分更新的数据


广播连续

1)保持现有广播间隔不变;
2)避免传统"停止-修改-重启"方式导致的 ~300ms 广播中断


数据限制

1)仍需遵守31字节的广播数据长度限制; 
2)数据类型需符合蓝牙规范(不能动态修改AD Type)

 2.4.4 实现原理

2.4.5 注意事项

广播必须处于活跃状态


1)需在bt_le_adv_start之后调用

2)已连接的设备会自动停止广播

数据一致性


1)更新期间应避免修改原始数据缓冲区

2)建议使用静态或全局数据数组


性能考量


1)频繁更新(如每秒多次)可能影响射频稳定性

2)建议合并更新(如每200ms批量更新一次)

厂商限制


1)某些低端蓝牙芯片可能不支持实时更新

2)需要检查协议栈实现是否支持该功能

 2.4.6 错误处理最佳实践

int err = bt_le_adv_update_data(new_ad, ad_len, NULL, 0);
if (err == -ENOTCONN) 
{// 广播未激活,重新启动bt_le_adv_start(...);
} 
else if (err){printk("Update failed (err %d), retrying...\n", err);k_sleep(K_MSEC(100));// 重试逻辑}

2.4.7 典型应用案例

  1. 电子价签系统

    • 不建立连接,通过广播更新价格信息

    • 每15分钟更新一次广播数据

  2. 运动传感器

    • 实时广播心率/步数变化

    • 保持低功耗的同时更新数据

  3. 智能信标

    • 动态调整广播内容(如店铺促销信息)

    • 基于位置切换广播UUID

2.4.8 应用总结

bt_le_adv_update_data 提供了高效的广播数据动态更新机制,特别适合:

  • 需要保持持续广播可见性的场景

  • 实时数据传输但无需建立连接的用例

  • 低功耗设备的数据更新需求

正确使用该API可以避免传统重启广播方式带来的连接中断风险,同时保证数据更新的实时性和可靠性。开发者应注意目标平台的协议栈实现差异,并进行充分的错误场景测试。

相关文章:

  • Ubuntu20.04部署Ragflow(Docker方式)
  • Android studio学习之路(八)---Fragment碎片化页面的使用
  • MCP 协议解读:STDIO 高效通信与 JSON-RPC 实战
  • Dify + Mermaid 实现自然语言转图表
  • 第十六届蓝桥杯大赛软件赛省赛第二场 C/C++ 大学 A 组
  • Python 实现从 MP4 视频文件中平均提取指定数量的帧
  • 大端存储与小端存储:数据存储的镜像世界探秘
  • 【昇腾】PaddleOCR转om推理
  • 二分类任务中,统计置信区间
  • Linux下终端命令行安装常见字体示例
  • Unity任务系统笔记
  • springboot入门-业务逻辑核心service层
  • Python-MCPServerStdio开发
  • Unity之基于MVC的UI框架-含案例
  • Linux——动静态库
  • 解决conda虚拟环境安装包却依旧安装到base环境下
  • 模板引擎语法-算术运算
  • springboot集成MyBatis Generator快速开发
  • 河南联通光猫超级管理员账号设置
  • 利用 functools.lru_cache 优化递归算法
  • 5145篇报道中的上海车展:40年,什么变了?
  • 特朗普将举行集会庆祝重返白宫执政百日,美媒:时机不当
  • 特朗普承认“24小时结束俄乌冲突”是玩笑:大家都知道
  • 最高法知产庭年度报告:民事案件二审发回重审率持续下降
  • 深圳大学传播学院院长巢乃鹏已任深圳大学副校长
  • 无视规范开“远端”、企业云端被窃密,国安部:莫让运维成运“危”