zephyr设置BLE广播数据实例

news2024/11/13 9:48:48

目录

  • 实例1:静态开启广播数据
  • 实例2:动态更改广播数据
  • 实例3:创建可连接的广播

实例1:静态开启广播数据

新建一个hello world的工程模板。
在这里插入图片描述

  1. 在prj.conf中开启蓝牙
CONFIG_BT=y

这个宏,默认会开启广播支持 ( BT_BROADCASTER) ,使用softDevice控制器 ( BT_LL_CHOICE= BT_LL_SOFTDEVICE),发射功率为0dBm( BT_CTLR_TX_PWR = BT_CTLR_TX_PWR_0)。

  1. 设置设备名称
    添加以下行prj.conf:
 CONFIG_BT_DEVICE_NAME="Nordic_Beacon"
  1. 设置广播数据
/* STEP 4.1.1 - Declare the advertising packet */
static const struct bt_data ad[] = {
	/* STEP 4.1.2 - Set the advertising flags */
	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
	/* STEP 4.1.3 - Set the advertising packet data  */
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),

};
  1. 设置扫描响应数据
/* STEP 4.2.2 - Declare the URL data to include in the scan response */
static unsigned char url_data[] = {
	0x17, '/', '/', 'b', 'a', 'i', 'd', 'u', '.',
	'c', 'o', 'm'};

/* STEP 4.2.1 - Declare the scan response packet */
static const struct bt_data sd[] = {
	/* 4.2.3 Include the URL data in the scan response packet*/
	BT_DATA(BT_DATA_URI, url_data, sizeof(url_data)),
};
  1. 使能蓝牙协议栈
	err = bt_enable(NULL);
	if (err)
	{
		LOG_ERR("Bluetooth init failed (err %d)\n", err);
		return -1;
	}
  1. 开启蓝牙广播
	err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
	if (err)
	{
		LOG_ERR("Advertising failed to start (err %d)\n", err);
		return -1;
	}

运行和测试
在这里插入图片描述在这里插入图片描述
开启广播就是这么简单就行。
完整的代码

实例2:动态更改广播数据

这个实例将重点关注广播参数、制造商特定数据以及动态更新广播数据。

广播参数的控制,广播参数放在bt_le_adv_param变量里面。由于此变量需要初始化内容太多,因此使用宏 BT_LE_ADV_PARAM()来帮助初始化
在这里插入图片描述

options:用于配置广告选项的特定宏。例如,选择在哪个频道(373839)上投放广告。有 19 个选项可用,可在此处找到。
最小广告间隔:(N * 0.625 毫秒):小于或等于最大广告间隔。N 的允许范围是 3216384,相当于 20 毫秒到 10.24 秒。API 具有用于广告间隔的预定义值。
最大广告间隔:(N * 0.625 毫秒):大于或等于最小广告间隔。N 的允许范围是 3216384,相当于 20 毫秒到 10.24 秒。API 具有用于广告间隔的预定义值。
对等地址:如果使用定向广告则包含。否则,设置为 NULL

代码实现如下

  1. 使用自带的LED和BUTTON库,在prj.conf加入如下。
# Button and LED library
CONFIG_DK_LIBRARY=y

2.在main.c加入头文件

#include <dk_buttons_and_leds.h>

3.定义广播参数

static struct bt_le_adv_param *adv_param =
	BT_LE_ADV_PARAM(BT_LE_ADV_OPT_NONE,
	800,
	801,
	NULL);

4.定义自定义数据

#define COMPANY_ID_CODE            0x0059

5.定义动态数据存放的变量,这里定义个结构体,方便管理

typedef struct adv_mfg_data {
	uint16_t company_code;	    /* Company Identifier Code. */
	uint16_t number_press;      /* Number of times Button 1 is pressed*/
} adv_mfg_data_type;

初始化

static adv_mfg_data_type adv_mfg_data = {COMPANY_ID_CODE,0x00};

6.将自定义数据包含到广播包里面

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
	BT_DATA(BT_DATA_MANUFACTURER_DATA, (unsigned char *)&adv_mfg_data, sizeof(adv_mfg_data)), // 添加自定义数据
};

7.添加按钮初始化代码,和注册按钮回调函数

static void button_changed(uint32_t button_state, uint32_t has_changed)
{
	if (has_changed & button_state & USER_BUTTON) {
	adv_mfg_data.number_press += 1;
	bt_le_adv_update_data(ad, ARRAY_SIZE(ad),
			      sd, ARRAY_SIZE(sd)); //这里是动态更新广播数据的地方
	}
}

static int init_button(void)
{
	int err;

	err = dk_buttons_init(button_changed);
	if (err) {
		printk("Cannot init buttons (err: %d)\n", err);
	}

	return err;
}

8.在main函数调用按钮初始化

static void button_changed(uint32_t button_state, uint32_t has_changed)
{
	if (has_changed & button_state & USER_BUTTON) {
	adv_mfg_data.number_press += 1;
	bt_le_adv_update_data(ad, ARRAY_SIZE(ad),
			      sd, ARRAY_SIZE(sd));
	}
}

在第7步,函数是动态更新广播数据
在这里插入图片描述
编译和测试
在这里插入图片描述
可以点击数据,选择显示数据的格式
在这里插入图片描述

完整代码

开启蓝牙后,建议将栈的空间加大到2048

CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_MAIN_STACK_SIZE=2048

实例3:创建可连接的广播

  1. 配置蓝牙BLE的角色,配置为外设角色
CONFIG_BT_PERIPHERAL=y
  1. 修改蓝牙名称,这样可以方便区分
CONFIG_BT_DEVICE_NAME="Nordic_Peripheral"

3.修改广播的内容,主要是修改flag的内容,

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),
};

扫描响应包添加UUID,比如添加一个LBS的UUID

#include <zephyr/bluetooth/uuid.h>

static const struct bt_data sd[] = {
	// BT_DATA(BT_DATA_URI, url_data, sizeof(url_data)),
	BT_DATA_BYTES(BT_DATA_UUID128_ALL,BT_UUID_128_ENCODE(0x00001523, 0x1212, 0xefde, 0x1523, 0x785feabcd123)),
};

4.设置随机静态地址。

#include <zephyr/bluetooth/addr.h>

    bt_addr_le_t addr;
    err = bt_addr_le_from_str("FF:EE:DD:CC:BB:AA", "random", &addr);
    if (err) {
        printk("Invalid BT address (err %d)\n", err);
    }

    err = bt_id_create(&addr, NULL);
    if (err < 0) {
        printk("Creating new ID failed (err %d)\n", err);
    }

在这里插入图片描述修改广播参数为可连接

static struct bt_le_adv_param *adv_param = BT_LE_ADV_PARAM((BT_LE_ADV_OPT_CONNECTABLE|BT_LE_ADV_OPT_USE_IDENTITY), 
                800, /*Min Advertising Interval 500ms (800*0.625ms) */
                801, /*Max Advertising Interval 500.625ms (801*0.625ms)*/
                NULL); /* Set to NULL for undirected advertising*/

完整代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1931014.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1448.统计二叉树中的好节点数目

给你一棵根为 root 的二叉树&#xff0c;请你返回二叉树中好节点的数目。 「好节点」 X 定义为&#xff1a;从根到该节点 X 所经过的节点中&#xff0c;没有任何节点的值大于 X 的值。 示例 1&#xff1a; 输入&#xff1a;root [3,1,4,3,null,1,5] 输出&#xff1a;4 解释&am…

【算法】LRU缓存

难度&#xff1a;中等 题目&#xff1a; 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;…

【人工智能新纪元】机器学习算法:探索智能背后的奥秘与常见利器

在这个日新月异的科技时代&#xff0c;人工智能&#xff08;AI&#xff09;如同一股不可阻挡的洪流&#xff0c;正深刻地改变着我们的世界。作为AI领域的核心驱动力之一&#xff0c;机器学习算法以其独特的魅力&#xff0c;引领着智能技术的飞速发展。今天&#xff0c;就让我们…

【学习】美国虚拟信用卡申请流程

WildCard 官方网址&#xff1a;https://bewildcard.com/i/PEACEFUL &#xff08;使用邀请码“PEACEFUL”可以享受开卡88 折优惠&#xff0c;注册时提示填写邀请码就可以填写&#xff09;

Vue3 组件向下通信 祖孙组件的通信 provide与inject

介绍 当父子间通信可以使用props&#xff0c;祖孙使用provide&#xff08;传递&#xff09;或inject&#xff08;接收&#xff09;&#xff0c; 这时不管组件套的多深都可以向下传递。 例子 现在有一个需求&#xff0c;把App.vue的数据传递到MusciPlay.vue里。 App.vue …

跟李沐学AI:模型选择、过拟合和欠拟合

目录 训练误差和泛化误差 验证数据集和测试数据集 K-则交叉验证 模型总结 过拟合和欠拟合 模型容量 模型容量的影响 估计模型容量 数据复杂度 拟合总结 训练误差和泛化误差 训练误差&#xff1a;模型在训练数据上的误差 泛化误差&#xff1a;模型在新数据上的误差 …

移掉 K 位数字

题目链接 移掉 K 位数字 题目描述 注意点 1 < k < num.length < 10^5num 仅由若干位数字&#xff08;0 - 9&#xff09;组成除了 0 本身之外&#xff0c;num 不含任何前导零 解答思路 关键是怎样移掉K位数字保证移除后的数字是最小的。观察规律可得&#xff0c;为…

基于LSTM及其变体的回归预测

1 所用模型 代码中用到了以下模型&#xff1a; 1. LSTM&#xff08;Long Short-Term Memory&#xff09;&#xff1a;长短时记忆网络&#xff0c;是一种特殊的RNN&#xff08;循环神经网络&#xff09;&#xff0c;能够解决传统RNN在处理长序列时出现的梯度消失或爆炸的问题。L…

GB35114国密算法-GMSSL

C有个三方库-GMSSL是可以进行GB35114所需要的SM2、SM3、SM4等加解密算法的&#xff0c;但是使用国密算法是需要申请报备的 GmSSL是由北京大学自主开发的国产商用密码开源库&#xff0c;实现了对国密算法、标准和安全通信协议的全面功能覆盖&#xff0c;支持包括移动端在内的主流…

SpringBoot整合Swagger报错:Failed to start bean ‘documentationPluginsBootstrapper

文章目录 1 问题背景2 问题原因3 修改SpringBoot配置文件 application.properties参考 1 问题背景 Swagger是SpringBoot中常用的API文档工具&#xff0c;在刚接触使用的时候&#xff0c;按照通用的代码进行配置&#xff0c;发现报错了 [main] ERROR org.springframework.boot…

【ARM AMBA AXI 入门 5.1 - QoS是什么?QoS是怎么工作的? 】

请阅读【ARM AMBA AXI 总线 文章专栏导读】 转自&#xff1a;揭秘数通知识&#xff1a;QoS是什么&#xff1f;QoS是怎么工作的&#xff1f;&#xff08;一&#xff09; 文章目录 QoS 概述综合服务和差分服务 QoS 工具报文分类报文标记流量监管和整形工具拥塞管理工具拥塞避免工…

JuiceFS缓存特性

缓存 对于一个由对象存储和数据库组合驱动的文件系统&#xff0c;缓存是本地客户端与远端服务之间高效交互的重要纽带。读写的数据可以提前或者异步载入缓存&#xff0c;再由客户端在后台与远端服务交互执行异步上传或预取数据。相比直接与远端服务交互&#xff0c;采用缓存技…

Linux 线程初步解析

1.线程概念 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列。在linux中&#xff0c;由于线程和进程都具有id,都需要调度等等相似性&#xff0c;因此都可以用PCB来描述和控制,线程含有PCB&am…

[RuoYi-Vue] - 5. 部分代码分析

文章目录 &#x1f374;1. 后端部分代码分析1.1 BaseController1.2 TableDataInfo1.3 AjaxResult1.4 BaseEntity &#x1f378;2. 权限注解&#x1f37a;3. 前后端交互3.1 跨域问题 &#x1f374;1. 后端部分代码分析 1.1 BaseController 1.2 TableDataInfo 分页查询统一返回对…

如何用个人电脑搭建一台本地服务器,并部署云原生开发工具TitanIDE到服务器详细教程

服务器是一种高性能计算机&#xff0c;作为网络的节点&#xff0c;它存储、处理网络上80%的数据、信息&#xff0c;因此也被称为网络的灵魂。与普通计算机相比&#xff0c;服务器具有高速CPU运算能力、长时间可靠运行、强大I/O外部数据吞吐能力以及更好的扩展性。 服务器的主要…

Day07-ES集群加密,kibana的RBAC实战,zookeeper集群搭建,zookeeper基本管理及kafka单点部署实战

Day07-ES集群加密&#xff0c;kibana的RBAC实战&#xff0c;zookeeper集群搭建&#xff0c;zookeeper基本管理及kafka单点部署实战 0、昨日内容回顾:1、基于nginx的反向代理控制访问kibana2、配置ES集群TSL认证:3、配置kibana连接ES集群4、配置filebeat连接ES集群5、配置logsta…

自建Web网站部署——案例分析

作者主页: 知孤云出岫 目录 作者主页:如何自建一个Web网站一、引言二、需求分析三、技术选型四、开发步骤1. 项目初始化初始化前端初始化后端 2. 前端开发目录结构示例代码App.jsHome.js 3. 后端开发目录结构示例代码app.jsproductRoutes.jsProduct.js 4. 前后端连接安装axio…

ospf复习综合小实验

实验要求&#xff1a; 1&#xff0c;R4为ISP&#xff0c;其上只能配置IP地址&#xff1b;R4与其他所有直连设备间均使用公有IP 2&#xff0c;R3-R5/6/7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3&#xff0c;整个OSPF环境IP基于172.16.0.0/16划分&#xff1b; 4&#…

redis其他类型和配置文件

很多博客只讲了五大基本类型&#xff0c;确实&#xff0c;是最常用的&#xff0c;而且百分之九十的程序员对于Redis只限于了解String这种最常用的。但是我个人认为&#xff0c;既然Redis官方提供了其他的数据类型&#xff0c;肯定是有相应的考量的&#xff0c;在某些特殊的业务…

1.MQ介绍

MQ 消息队列&#xff0c;本质是一个队列&#xff0c;先进先出&#xff0c;只不过队列中存放的内容是message而已。 为啥学习MQ 1.流量消峰 如果一个订单系统最多每秒能处理一万次订单&#xff0c;正常情况下我们下单1秒后就能返回结果。但是在高峰期&#xff0c;如果有两万…