Zephyr NRF7002 实现AppleJuice

BLE的基础知识

在这里插入图片描述

ble的信道和BR/EDR的信道是完全不一样的。但是范围是相同的,差不多也都是2.4Ghz的频道。可以简单理解为空中有40个信道0~39信道。两个设备在相同的信道里面可以进行相互通信。

而这些信道SIG又重新编号:

../../_images/adv_channel2.png

这个编号就是把37 38 39。 3个信道抽出来,作为广播信道,其他都是数据信道。这篇文章主要讲广播,所以基本数据信息都是围绕37 38 39这三个信道上面的通信来讲的。

我们可以看到这3个信道是分散排列的。大家可以思考下为什么。

其实看下面一张图就知道了。

../../_images/wifi_channel.png

数据广播

广播组成部分

广播分为如下几个部分:

  • 广播
  • 扫描请求
  • 扫描响应

在这里插入图片描述

广播的报文格式

在这里插入图片描述

{"AD1":{"Length":12,"Data":{"AD_Type":12,"AD_Data":"123123"}},"AD2":{"Length":12,"Data":{"AD_Type":12,"AD_Data":"123123"}}
}

记忆要点

每个元素里面有两个要素:1. 长度(length), 2. 数据(data)

  • 每个数据里面又包含两个元素:1. 类型(type), 2. 数据(data)

  • 总结一下就是一个L T V模型(length, type, data)

  • 这个length代表的是后面数据有多长,不包含length的长度。

  • 总的Len一般不超过31字节

参考:

2. BLE 广播和扫描 — bluetoothlover_wiki 0.0.1 文档 (supperthomas-wiki.readthedocs.io)

AD_Type 官方定义

抓包参考:

在这里插入图片描述

APPLE JUICE功能实现

在这里插入图片描述

1.流程梳理

主要需要实现如下功能点:

  • ble 广播开启和关闭
  • ble GAP层各种参数的设置
  • ble MAC地址动态修改

2.Zephyr 中相关接口:

功能接口:

接口名功能描述备注
bt_enable开启BLE功能
bt_le_adv_start开启BLE广播
bt_le_adv_update_data更新BLE广播内容此接口是否实时?未找到对应生效CallBack
bt_le_adv_stop关闭BLE广播
bt_id_create更新广播随机地址

注:

上述接口在执行完成后均会抛出回调:

/*
参数回调注册
*/
void bt_conn_cb_register(struct bt_conn_cb *cb);struct bt_conn_cb {//已建立新连接void (*connected)(struct bt_conn *conn, uint8_t err);//连接已断开void (*disconnected)(struct bt_conn *conn, uint8_t reason);//LE 连接参数更新请求bool (*le_param_req)(struct bt_conn *conn,struct bt_le_conn_param *param);//LE 连接的参数已更新void (*le_param_updated)(struct bt_conn *conn, uint16_t interval,uint16_t latency, uint16_t timeout);
#if defined(CONFIG_BT_SMP)//远程身份地址通过void (*identity_resolved)(struct bt_conn *conn,const bt_addr_le_t *rpa,const bt_addr_le_t *identity);
#endif /* CONFIG_BT_SMP */
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)//连接的安全级别已更改void (*security_changed)(struct bt_conn *conn, bt_security_t level,enum bt_security_err err);
#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */#if defined(CONFIG_BT_REMOTE_INFO)//远程信息程序已完成void (*remote_info_available)(struct bt_conn *conn,struct bt_conn_remote_info *remote_info);
#endif /* defined(CONFIG_BT_REMOTE_INFO) */#if defined(CONFIG_BT_USER_PHY_UPDATE)//连接的 PHY 已更改void (*le_phy_updated)(struct bt_conn *conn,struct bt_conn_le_phy_info *param);
#endif /* defined(CONFIG_BT_USER_PHY_UPDATE) */#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)//连接的数据长度参数已更改void (*le_data_len_updated)(struct bt_conn *conn,struct bt_conn_le_data_len_info *info);
#endif /* defined(CONFIG_BT_USER_DATA_LEN_UPDATE) */#if defined(CONFIG_BT_DF_CONNECTION_CTE_RX)void (*cte_report_cb)(struct bt_conn *conn,const struct bt_df_conn_iq_samples_report *iq_report);
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */#if defined(CONFIG_BT_TRANSMIT_POWER_CONTROL)void (*tx_power_report)(struct bt_conn *conn,const struct bt_conn_le_tx_power_report *report);
#endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */struct bt_conn_cb *_next;
};

bt_data接口

Zephyr 封装好了部分gap填充接口,在编写广播数据(bt_data)数组的时候可以通过以下宏来辅助:


/*** @brief Construct a new bt data object* * 	_type: GAP字段的类型* 	_data: GAP RAW 数据* 	_data_len: RAW数据长度*/
#define BT_DATA(_type, _data, _data_len) \{ \.type = (_type), \.data_len = (_data_len), \.data = (const uint8_t *)(_data), \}/*** @brief Construct a new bt data object* * 	_type: GAP字段的类型* 	_bytes: GAP RAW 数据*/    
#define BT_DATA_BYTES(_type, _bytes...) \BT_DATA(_type, ((uint8_t []) { _bytes }), \sizeof((uint8_t []) { _bytes }))

参考:

5. BLE — BL_MCU_SDK 开发指南 0.3 文档 (gitee.io)

Zephyr API文档:通用访问配置文件(GAP) (zephyrproject.org)

3. 广播数据填充

AD_Data字段:

static const struct bt_data ad[] = {BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA,0x4c, 0x00, 0x07, 0x19, 0x07, 0x0a, 0x20,0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45,0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00)};

开启广播的时候将ad传入,即可完成广播数据设置。

4.随机地址切换

Apple对于相同MAC地址的设备仅会进行一次弹窗,因此如果想要让手机不断的弹出设备提示框就需要定期修改BLE的MAC地址,代码如下:

bt_addr_le_t local_mac_addr;size_t localmac_size = 1;static bt_addr_le_t myaddr = {.type = BT_ADDR_LE_RANDOM,/* fixed MAC addres */.a = {.val = {0x01, 0x02, 0x03, 0x04, 0x05, 0xc6},},};printk("bt_id_create\r\n");err = bt_id_create(&myaddr, NULL);if (err < 0){printk("bt_id_create err!\r\n");}

小思考:这里思考了下苹果的设计美学,以AirPods为例。通常情况下设备为了节约电池电量并不会一直进行BLE广播,而是在每次打开电池仓时才唤醒ble芯片,关闭电池仓之后进入超低功耗模式。BLE设备的程序在每次唤醒的时候程序会从新启动,所以MAC地址发生改变。

效果演示

在这里插入图片描述

问题和解决方法

  • 问题描述:使用7002DK开发板运行时出现如下问题。
    在这里插入图片描述

  • 原因分析:默认情况下adv字段允许的最大长度为31字节, 当数据填充超出会出现上述报警。

  • 解决方法:可以开启ble的拓展广播功能来增加最大数据长度。相关配置可以参考Demo periodic_adv,相关Menuconfig修改点如下图所示:

在这里插入图片描述
在这里插入图片描述

完整代码:

/*** @file main.c* @author Argon* @brief  BLE Apple * @version 0.1* @date 2024-01-20* * @copyright Copyright (c) 2024* */
#include <zephyr/types.h>
#include <stddef.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>//扫描数据段
static const struct bt_data ad[] = {BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA,0x4c, 0x00, 0x07, 0x19, 0x07, 0x0a, 0x20,0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45,0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00)};//扫描响应数据段
static const struct bt_data sd[] = {BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),BT_DATA_BYTES(BT_DATA_PERIPHERAL_INT_RANGE, 0x20, 0x00, 0x40, 0x00),BT_DATA_BYTES(BT_DATA_TX_POWER, 0x09),
};//设备名
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)int main(void)
{int err;printk("BLE Starting\n");/* Initialize the Bluetooth Subsystem */err = bt_enable(NULL);if (err){printk("Ble init failed (err %d)\n", err);return 0;}printk("Ble initialized\n");do{//开启广播printk("Ble adv start\r\n");err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad),sd, ARRAY_SIZE(sd));if (err){printk("Advertising failed to start (err %d)\n", err);return 0;}k_sleep(K_SECONDS(4));//广播广播printk("Ble adv stop\r\n");err = bt_le_adv_stop();if (err){printk("Advertising failed to stop (err %d)\n", err);return 0;}//更新MACbt_addr_le_t local_mac_addr;static bt_addr_le_t myaddr = {.type = BT_ADDR_LE_RANDOM,/* fixed MAC addres */.a = {.val = {0x01, 0x02, 0x03, 0x04, 0x05, 0xc6},},};printk("Ble update MAC address\r\n");err = bt_id_create(&myaddr, NULL);if (err < 0){printk("bt_id_create err!\r\n");}k_sleep(K_SECONDS(4));} while (1);return 0;
}

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

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

相关文章

Vue源码解读

一、Vue源码解析–响应式原理 1、课程目标 Vue.js的静态成员和实例成员初始化过程​ 首次渲染的过程数据响应式原理 2、准备工作 Vue源码的获取 项目地址&#xff1a;https://github.com/vuejs/vue 为什么分析Vue2.6? 新的版本发布后&#xff0c;现有项目不会升级到3.0,…

杨中科 配置系统

1、配置系统入门 说明 1、传统Web.config配置的缺点&#xff0c;之前DI讲到过 2、为了兼容&#xff0c;仍然可以使用Web.config和ConfigurationManager类&#xff0c;但不推荐。 3、.NET 中的配置系统支持丰富的配置源&#xff0c;包括文件(json、xml、ini等)、注册表、环境变…

序列化和反序列化、pytest-DDT数据驱动

序列化 序列化就是将对象转化成文件 python转成json import jsondata {"数字": [1, 1.1, -1],"字符串": ["aaaa", bbbb],"布尔值": [True, False],"空值": None,"列表": [[1, 2, 3], [4, 5, 6], [7, 8, 9]],&…

OpenCV/C++:点线面相关计算(二)

接续&#xff0c;继续更新 OpenCV/C:点线面相关计算_线面相交的点 代码计算-CSDN博客文章浏览阅读1.6k次&#xff0c;点赞2次&#xff0c;收藏12次。OpenCV处理点线面的常用操作_线面相交的点 代码计算https://blog.csdn.net/cd_yourheart/article/details/125626239 目录 1、…

git的奇特知识点

展示帮助信息 git help -gThe common Git guides are:attributes Defining attributes per pathcli Git command-line interface and conventionscore-tutorial A Git core tutorial for developerscvs-migration Git for CVS usersdiff…

Unity_修改天空球

Unity_修改天空球 Unity循序渐进的深入会发现可以改变的其实很多&#xff0c;剖开代码逻辑&#xff0c;可视化的表现对于吸引客户的眼球是很重要的。尤其对于知之甚少的客户&#xff0c;代码一般很难说服客户&#xff0c;然表现确很容易。 非代码色彩通才&#xff0c;持续学习…

《Docker极简教程》--Docker基础--Docker的基本概念

在这篇文章中我们先大致的了解以下Docker的基本概念&#xff0c;在后续的文章中我们会详细的讲解这些概念以及使用。 一、容器(Container) 1.1 容器的定义和特点 容器的定义 容器是一种轻量级、可移植的软件打包技术&#xff0c;用于打包应用及其依赖项和运行环境&#xff0c…

[英语学习][27][Word Power Made Easy]的精读与翻译优化

[序言] 译者的这次翻译非常好. 对what与从句的嵌套用法&#xff0c; 进行了精准的翻译. 这次的记录, 也是对我自己的一次翻译经验的提升. 但是唯一遗憾的是"derivation"没有翻译好. [英文学习的目标] 提升自身的英语水平, 对日后编程技能的提升有很大帮助. 希望大家…

STM32F1 引脚重映射功能

STM32 端口引脚重映射 文章目录 STM32 端口引脚重映射前言1、查阅芯片数据手册1.1 串口引脚重映射描述 2、代码部分2.1 核心代码部分 3、实验现象4、总结 前言 在写程序时遇到想要的端口功能&#xff0c;而这个引脚又被其它的功能占用了无法删除掉或直接使用&#xff0c;这种情…

蓝桥杯----凑算式

这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。 比如: 68/3952/714 就是一种解法, 53/1972/486 是另一种解法. 这个算式一共有多少种解法? 注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。

Leetcode—42. 接雨水【困难】

2024每日刷题&#xff08;112&#xff09; Leetcode—42. 接雨水 空间复杂度为O(n)的算法思想 实现代码 class Solution { public:int trap(vector<int>& height) {int ans 0;int n height.size();vector<int> l(n);vector<int> r(n);for(int i 0; …

javaEE - 24( 20000 字 Servlet 入门 -2 )

一&#xff1a; Servlet API 详解 1.1 HttpServletResponse Servlet 中的 doXXX 方法的目的就是根据请求计算得到相应, 然后把响应的数据设置到HttpServletResponse 对象中. 然后 Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式, 转成一个字符串, 并通过S…

2024数据分析管理、数字经济与教育国际学术会议(ICDAMDEE2024)

会议简介 2024年数据分析管理、数字经济和教育国际学术会议&#xff08;ICDAMDEE 2024&#xff09;将在武汉举行。会议不仅展示了来自世界各地的研究专家围绕数据分析管理、数字经济和教育的最新科研成果&#xff0c;还为来自不同地区的代表们提供了面对面的交流意见和实验经验…

[C++] opencv + qt 创建带滚动条的图像显示窗口代替imshow

在OpenCV中&#xff0c;imshow函数默认情况下是不支持滚动条的。如果想要显示滚动条&#xff0c;可以考虑使用其他库或方法来进行实现。 一种方法是使用Qt库&#xff0c;使用该库可以创建一个带有滚动条的窗口&#xff0c;并在其中显示图像。具体步骤如下&#xff1a; 1&…

ES6扩展运算符——三个点(...)用法详解

目录 1 含义 2 替代数组的 apply 方法 3 扩展运算符的应用 &#xff08; 1 &#xff09;合并数组 &#xff08; 2 &#xff09;与解构赋值结合 &#xff08; 3 &#xff09;函数的返回值 &#xff08; 4 &#xff09;字符串 &#xff08; 5 &#xff09;实现了 Iter…

耳机空间音频头部相关传递函数(HRTF)设计方法与空间音频渲染

加我微信hezkz17可以申请加入数字音频系统研究开发交流答疑群,加群附加赠送车载DSP音频项目核心开发资料(包含声场,最佳听音位),TWS降噪蓝牙耳机项目资料,空间音频源码 在空间音频的应用里最常见的一种就是“听音辨位”。比如在很多射击游戏中,我们能够通过耳机中目标的…

Java实现教学过程管理系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 教师端2.2 学生端2.3 微信小程序端2.3.1 教师功能如下2.3.2 学生功能如下 三、系统展示 四、核心代码4.1 查询签到4.2 签到4.3 查询任务4.4 查询课程4.5 生成课程成绩 六、免责说明 一、摘要 1.1 项目介绍 基于JAVAVu…

Python学习路线 - Python高阶技巧 - PySpark案例实战

Python学习路线 - Python高阶技巧 - PySpark案例实战 前言介绍Spark是什么Python On SparkPySparkWhy PySpark 基础准备PySpark库的安装构建PySpark执行环境入口对象PySpark的编程模型 数据输入RDD对象Python数据容器转RDD对象读取文件转RDD对象 数据计算map方法flatMap方法red…

数据结构高级算法

目录 最小生成树 Kruskal(克鲁斯卡尔)(以边为核心) 9) 不相交集合(并查集合) 基础 Union By Size 图-相关题目 4.2 Greedy Algorithm 1) 贪心例子 Dijkstra Prim Kruskal 最优解(零钱兑换)- 穷举法 Leetcode 322 最优解(零钱兑换)- 贪心法 Leetcode 322 3)…

opensuse安装百度Linux输入法

前言 Linux下有输入法&#xff0c;拼音&#xff0c;百度的都有&#xff0c;但是用起来总感觉不如在windows下与安卓中顺手。 目前搜狗与百度都出了Linux的输入法&#xff0c;但是没有针对OpenSUSE的&#xff0c;只有ubuntu/deepin/UOS的安装包。 本文主要讲的如何把百度Linux输…