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

八、基于GD32 Embedded Builder开发GD32VW553(蓝牙广播)

前言:

笔者最近使用GD32VW553进行开发时,遇到了很多问题,现在记录下来,供GD32开发者参考。

已有:

GD32 Embedded Builder界面中文化(保姆级教程)-CSDN博客

一、基于GD32 Embedded Builder开发GD32VW553(编译环境搭建)-CSDN博客

二、基于GD32 Embedded Builder开发GD32VW553(点亮一个Led灯)_gd32embeddedbuilder-CSDN博客

三、基于GD32 Embedded Builder开发GD32VW553(裸机开发流程)-CSDN博客

四、基于GD32 Embedded Builder开发GD32VW553(GD32VW553K-START开发板代码烧录)_gd32g553ccu7-CSDN博客

五、基于GD32 Embedded Builder开发GD32VW553(萤火工场 GD32VW553-IOT代码烧录下载)-CSDN博客

六、基于GD32 Embedded Builder开发GD32VW553(基本指令用户指南)-CSDN博客

七、基于GD32 Embedded Builder开发GD32VW553(AT指令)-CSDN博客

本文介绍如何进行蓝牙广播。

一、蓝牙广播

根据gd32vw553 ble开发指南和官方的sdk实现广播的流程。

3个步骤:

1应用层初始化函数,也就是开发指南里面的蓝牙三层架构的最上层app,用户自己创建的函数。

2.事件处理回调函数,当广播被别的设备扫描到时,就调用这个回调函数进行处理。

3广播启动函数。

找到MSDK/app/main.c,然后再主函数的后面把下面的函数粘贴过去,然后在主函数里调用初始函数,在freertos任务里一直恢复ble_stack最底层的蓝牙协议栈。

// 前向声明函数
static void app_adv_evt_handler(ble_adv_evt_t evt, void *p_data, void *p_ctx);
static void app_adv_start(uint8_t adv_idx);/*** 广播上下文结构体* 用于在回调函数中保存当前广播的索引和状态*/
static struct {uint8_t   idx;     // 广播实例索引uint8_t   state;   // 当前广播状态
} s_adv_ctx;/*** 应用层初始化函数 - 在main()中调用* 功能:初始化BLE协议栈并创建广播实例*/
void ble_adv_app_init(void) {ble_status_t ret;/* 1. 初始化BLE协议栈 */// 恢复BLE协议栈任务ble_stack_task_resume(false);//   ble_app_task_resume(false); // 未使用应用任务/* 2. 直接创建广告,不再调用ble_adv_init */ble_adv_param_t param = {0};// 配置广播参数param.param.type          = BLE_GAP_ADV_TYPE_LEGACY;             // 使用传统广播类型param.param.prop          = BLE_GAP_ADV_PROP_UNDIR_CONN;         // 可连接可扫描的未定向广播param.param.own_addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;             // 使用公网地址param.param.adv_intv_min  = 160;                                   // 最小广播间隔100ms (160 * 0.625ms)param.param.adv_intv_max  = 160;                                   // 最大广播间隔100msparam.param.primary_phy   = BLE_GAP_PHY_1MBPS;                    // 使用1Mbps PHYparam.param.ch_map        = BLE_GAP_ADV_CHANN_37;                 // 仅使用37信道// 创建广播实例并注册事件回调函数ret = ble_adv_create(&param, app_adv_evt_handler, &s_adv_ctx);if (ret != BLE_ERR_NO_ERROR) {dbg_print(ERR, "ble_adv_create fail! 0x%04X\r\n", ret);return;}dbg_print(NOTICE, "ble_adv_create triggered\r\n");
}/*** 广播事件回调函数* 功能:处理各种广播相关事件*/
static void app_adv_evt_handler(ble_adv_evt_t evt, void *p_data, void *p_ctx) {(void)p_ctx;  // 未使用上下文参数switch (evt) {case BLE_ADV_EVT_STATE_CHG: {// 广播状态变化事件ble_adv_state_chg_t *chg = (ble_adv_state_chg_t*)p_data;dbg_print(NOTICE,"ADV state 0x%02X->0x%02X reason=0x%04X\r\n",s_adv_ctx.state, chg->state, chg->reason);// 更新上下文状态和索引s_adv_ctx.state = chg->state;s_adv_ctx.idx   = chg->adv_idx;/* 创建完成后启动广播 */if (chg->state == BLE_ADV_STATE_CREATE) {app_adv_start(chg->adv_idx);}break;}case BLE_ADV_EVT_DATA_UPDATE_INFO: {// 广播数据更新事件ble_adv_data_update_info_t *info = (ble_adv_data_update_info_t*)p_data;dbg_print(NOTICE,"ADV data update idx=%d type=%d status=0x%04X\r\n",info->adv_idx, info->type, info->status);break;}case BLE_ADV_EVT_SCAN_REQ_RCV: {// 接收到扫描请求事件ble_adv_scan_req_rcv_t *req = (ble_adv_scan_req_rcv_t*)p_data;dbg_print(NOTICE,"ScanReq from %02X:%02X:%02X:%02X:%02X:%02X\r\n",req->peer_addr.addr[5], req->peer_addr.addr[4],req->peer_addr.addr[3], req->peer_addr.addr[2],req->peer_addr.addr[1], req->peer_addr.addr[0]);break;}default:break;}
}/*** 启动广播函数* 功能:配置广播数据并启动广播*/
static void app_adv_start(uint8_t adv_idx) {/* 构造广播包:Flags + 完整本地名 */static uint8_t adv_payload[] = {0x02, 0x01, 0x06,            /* Flags字段: LE General Discoverable Mode + BR/EDR Not Supported */0x0A, 0x09,                  /* 完整本地名字段: 长度=10, 类型=0x09 */'G','D','3','2','-','B','L','E'  /* 设备名称: GD32-BLE */};// 配置广播数据ble_data_t raw = {.p_data = adv_payload,.len    = sizeof(adv_payload),};ble_adv_data_set_t adv_set = {.data_force        = true,          // 强制设置数据.data.p_data_force = &raw            // 指向广播数据};// 启动广播ble_status_t ret = ble_adv_start(adv_idx, &adv_set, NULL, NULL);if (ret != BLE_ERR_NO_ERROR) {dbg_print(ERR, "ble_adv_start fail! 0x%04X\r\n", ret);} else {dbg_print(NOTICE, "ble_adv_start OK\r\n");}
}
/* 启动广播示例 */ble_adv_app_init();void *task_handle = sys_task_create(NULL,                   // 静态任务控制块,这里使用动态分配(const uint8_t *)"PA0_Control_Task",  // 任务名称NULL,                   // 栈基地址,这里使用动态分配128,                    // 栈大小,单位为字(4字节)0,                      // 消息队列大小0,                      // 消息队列项大小1,                      // 任务优先级pa0_control_task,       // 任务入口函数NULL                    // 任务参数);if (task_handle == NULL) {// 任务创建失败dbg_print(ERR, "task_handle init failed\r\n");}sys_os_start();void pa0_control_task(void *pvParameters)
{while (1) {// 置高PA0gpio_bit_set(GPIOA, GPIO_PIN_0);//
//        // 置低PA0
//        gpio_bit_reset(GPIOA, GPIO_PIN_0);
//        sys_us_delay(500000);  // 延时500msble_stack_task_resume(false);sys_us_delay(500000);  // 延时500ms//   sys_us_delay(100000);}
}

设置广播扫描响应数据,总体是按照广播数据进行设置的。

在 BLE 广播中,扫描响应(Scan Response)是对扫描请求(Scan Request)的回复,可携带额外信息(如设备名称、服务 UUID 等)。下面详细解析ble_adv_start函数中扫描响应参数的可选配置:

1、扫描响应的作用与限制

作用:广播包(Advertising Data)受 31 字节限制,扫描响应可扩展数据传输。当其他设备主动扫描本设备时,本设备会发送扫描响应(类似 “一问一答”)。

格式:与广播数据相同,采用 AD Structure 格式:[长度(1B)][类型(1B)][数据(nB)],总长度≤31 字节。

2、扫描响应的常用 AD Type(数据类型)

AD Type
名称
说明
0x01
Flags
设备发现模式和功能标志(如是否支持 BLE 和 BR/EDR)
0x02
Incomplete List of 16-bit Service Class UUIDs
部分 16 位服务 UUID 列表(若超过 31 字节)
0x03
Complete List of 16-bit Service Class UUIDs
完整 16 位服务 UUID 列表
0x04
Incomplete List of 32-bit Service Class UUIDs
部分 32 位服务 UUID 列表
0x05
Complete List of 32-bit Service Class UUIDs
完整 32 位服务 UUID 列表
0x06
Incomplete List of 128-bit Service Class UUIDs
部分 128 位服务 UUID 列表
0x07
Complete List of 128-bit Service Class UUIDs
完整 128 位服务 UUID 列表
0x08
Shortened Local Name
短设备名称(截断版,如 “GD32”)
0x09
Complete Local Name
完整设备名称(如 “GD32-BLE”)
0x0A
TX Power Level
发送功率(如 0dBm、-4dBm 等,用于估算距离)
0x10
Device ID
设备标识符(如序列号、产品 ID)
0x16
Service Data - 16-bit UUID
基于 16 位 UUID 的服务数据(自定义数据)
0xFF
Manufacturer Specific Data
厂商自定义数据(如电池电量、温度等)
最后编译,然后烧录进gd32vw553中,使用"BLE调试宝"等手机上的蓝牙调试软件,便可以发现名称“GD32-BLE”,点击连接,便可接受到gd32vw553蓝牙广播发送的消息。

总结:蓝牙广播主要是流程,然后需要查阅大量的相关的源文件,找到函数定义。

http://www.dtcms.com/a/319512.html

相关文章:

  • 复杂光照场景漏检率↓76%!陌讯多模态融合算法在打电话识别的边缘部署优化
  • 使用Puppeteer轻松自动化浏览器操作
  • PYLON交叉编译:Ubuntu是x86,编译出arm64上运行的程序
  • 无人机航拍数据集|第8期 无人机海上目标检测YOLO数据集3641张yolov11/yolov8/yolov5可训练
  • 下载 | Windows Server 2016最新原版ISO映像!(集成7月更新、标准版、数据中心版、14393.8246)
  • 基于 C 语言的多态机制的驱动架构
  • 十八、k8s细粒度流量管理:服务网格
  • UiPath Studio介绍
  • CS231n2017 Assignment3 RNN、LSTM部分
  • 仁懋高压MOSFET在新能源汽车充电领域的应用
  • Java并发与数据库锁机制:悲观锁、乐观锁、隐式锁与显式锁
  • Java基础学习1(Java语言概述)
  • 音视频时间戳获取与同步原理详解
  • 如何为WordPress启用LiteSpeed缓存
  • --- Eureka 服务注册发现 ---
  • 安卓Handler和Looper的学习记录
  • 计算机视觉-OpenCV
  • GPT-5 将在周五凌晨1点正式发布,王炸模型将免费使用??
  • Android 之 Kotlin 扩展库KTX
  • 突破距离桎梏:5G 高清视频终端如何延伸无人机图传边界
  • RK3568项目(十三)--linux驱动开发之基础通讯接口(下)
  • 闪迪 SN8100 旗舰固态评测:读 14.9GB/s,写 14.0GB/s 的性能怪兽
  • 8.结构健康监测选自动化:实时数据 + 智能分析,远超人工
  • 深度学习中主要库的使用:(一)pandas,读取 excel 文件,支持主流的 .xlsx/.xls 格式
  • Flink-1.19.0-核心源码详解
  • 网站IP被劫持?三步自建防护盾
  • 【中微半导体】BAT32G139 逆变器,中微半导体pack包安装使用说明(参考例程获取DemoCode)
  • 51c大模型~合集165
  • 【动态规划 | 完全背包】动态规划经典应用:完全背包问题详解
  • 【CS创世SD NAND征文】额贴式睡眠监测仪的数据守护者:存储芯片如何实现7×24小时安眠状态下的全时稳定记录