ESP32 IDF的蓝牙广播demo 说明 - MilkeZhang 的网络笔记

蓝牙广播多种不同类型的广播,其中:1. 1M phy extend adv使用1Mbps的PHY速率,可连接广播。2. 2M phy extend adv使用2MBps的PHY高速广播,可扫描。3. 1M phy legacy adv, ADV_IND1M 高速广播,4. coded phy extend advcoded phy广播,可连接。1. 参数设置首先需要定义发送广播需要的几个参数:定义

ESP32 IDF的蓝牙广播demo 说明

ESP32 IDF的蓝牙广播demo 说明

阅读:267  点赞:0   留言:0


蓝牙广播多种不同类型的广播,其中:

1. 1M phy extend adv

使用1Mbps的PHY速率,可连接广播。

2. 2M phy extend adv

使用2MBps的PHY高速广播,可扫描。

3. 1M phy legacy adv, ADV_IND

1M 高速广播,

4. coded phy extend adv

coded phy广播,可连接。

1. 参数设置

首先需要定义发送广播需要的几个参数:

定义6个字节的地址:

// 定义一个 1M PHY 的地址
uint8_t addr_1m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x01};

定义广播数据AD Structure

// 定义 1M PHY 的扩展广播数据
static uint8_t raw_adv_data_1m[] = {
        0x02, 0x01, 0x06, // 广播标志
        0x02, 0x0a, 0xeb, // 16 位厂商 ID
        0x11, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', // 设备名称
        'D', 'V', '_', '1', 'M'
};

定义启用广播的扩展参数

// 定义 1M PHY 的扩展广播参数
esp_ble_gap_ext_adv_t ext_adv[4] = {
    // 实例,持续时间,间隔
    [0] = {0, 0, 0}
};

定义扩展广播参数

esp_ble_gap_ext_adv_params_t ext_adv_params_1M = {
    .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE, // 广播类型为可连接
    .interval_min = 0x30, // 广播间隔最小值
    .interval_max = 0x30, // 广播间隔最大值
    .channel_map = ADV_CHNL_ALL, // 广播信道
    .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, // 过滤策略
    .primary_phy = ESP_BLE_GAP_PHY_1M, // 主要物理层
    .max_skip = 0, // 最大跳过次数
    .secondary_phy = ESP_BLE_GAP_PHY_1M, // 次要物理层
    .sid = 0, // 广播 ID
    .scan_req_notif = false, // 扫描请求通知
    .own_addr_type = BLE_ADDR_TYPE_RANDOM, // 自身地址类型
    .tx_power = EXT_ADV_TX_PWR_NO_PREFERENCE, // 发射功率
};

定义GAP事件

// 定义 GAP 事件处理函数
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event) {
    case ESP_GAP_BLE_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT:
        // 设置随机地址完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT, status %d", param->ext_adv_set_rand_addr.status);
        break;
    case ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT:
        // 设置参数完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT, status %d", param->ext_adv_set_params.status);
        break;
    case ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT:
        // 设置广播数据完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT, status %d", param->ext_adv_data_set.status);
        break;
    case ESP_GAP_BLE_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT:
        // 设置扫描响应数据完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT, status %d", param->scan_rsp_set.status);
        break;
    case ESP_GAP_BLE_EXT_ADV_START_COMPLETE_EVT:
        // 启动广播完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_START_COMPLETE_EVT, status %d", param->ext_adv_start.status);
        break;
    case ESP_GAP_BLE_EXT_ADV_STOP_COMPLETE_EVT:
        // 停止广播完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_STOP_COMPLETE_EVT, status %d", param->ext_adv_stop.status);
        break;
    default:
        break;
    }
}

2. 启动广播流程

  1. 1.初始化蓝牙适配器
  2. 2.启用蓝牙控制器
  3. 3.初始化蓝牙协议栈
  4. 4.启用蓝牙协议栈
  5. 5.注册GAP事件
  6. 6.设置扩展广播参数
  7. 7.启动广播

3.源代码

/*
 * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Unlicense OR CC0-1.0
 */

/****************************************************************************
*
* 本演示展示了 BLE GATT 服务器。它可以发送广播数据,被客户端连接。
* 运行 gatt_client 演示,客户端演示将自动连接到 gatt_server 演示。
* 客户端演示将在连接后启用 gatt_server 的通知。两个设备将交换数据。
*
****************************************************************************/


#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"

#include "esp_gap_ble_api.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"

#include "sdkconfig.h"

#include "freertos/semphr.h"

#define LOG_TAG "MULTI_ADV_DEMO"

// 定义一个宏,用于发送消息并等待信号量
#define FUNC_SEND_WAIT_SEM(func, sem) do {        esp_err_t __err_rc = (func);        if (__err_rc != ESP_OK) {             ESP_LOGE(LOG_TAG, "%s, message send fail, error = %d", __func__, __err_rc);         }         xSemaphoreTake(sem, portMAX_DELAY); } while(0);
// 定义一个信号量,用于等待消息发送完成
static SemaphoreHandle_t test_sem = NULL;

// 定义一个 1M PHY 的地址
uint8_t addr_1m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x01};

// 定义一个 1M PHY 的扩展广播参数
esp_ble_gap_ext_adv_params_t ext_adv_params_1M = {
    .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE, // 广播类型为可连接
    .interval_min = 0x30, // 广播间隔最小值
    .interval_max = 0x30, // 广播间隔最大值
    .channel_map = ADV_CHNL_ALL, // 广播信道
    .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, // 过滤策略
    .primary_phy = ESP_BLE_GAP_PHY_1M, // 主要物理层
    .max_skip = 0, // 最大跳过次数
    .secondary_phy = ESP_BLE_GAP_PHY_1M, // 次要物理层
    .sid = 0, // 广播 ID
    .scan_req_notif = false, // 扫描请求通知
    .own_addr_type = BLE_ADDR_TYPE_RANDOM, // 自身地址类型
    .tx_power = EXT_ADV_TX_PWR_NO_PREFERENCE, // 发射功率
};

// 定义 1M PHY 的扩展广播数据
static uint8_t raw_adv_data_1m[] = {
        0x02, 0x01, 0x06, // 广播标志
        0x02, 0x0a, 0xeb, // 16 位厂商 ID
        0x11, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A', // 设备名称
        'D', 'V', '_', '1', 'M'
};

// 定义 1M PHY 的扩展广播参数
esp_ble_gap_ext_adv_t ext_adv[4] = {
    // 实例,持续时间,间隔
    [0] = {0, 0, 0}
};

// 定义 GAP 事件处理函数
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event) {
    case ESP_GAP_BLE_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT:
        // 设置随机地址完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT, status %d", param->ext_adv_set_rand_addr.status);
        break;
    case ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT:
        // 设置参数完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT, status %d", param->ext_adv_set_params.status);
        break;
    case ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT:
        // 设置广播数据完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT, status %d", param->ext_adv_data_set.status);
        break;
    case ESP_GAP_BLE_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT:
        // 设置扫描响应数据完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT, status %d", param->scan_rsp_set.status);
        break;
    case ESP_GAP_BLE_EXT_ADV_START_COMPLETE_EVT:
        // 启动广播完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_START_COMPLETE_EVT, status %d", param->ext_adv_start.status);
        break;
    case ESP_GAP_BLE_EXT_ADV_STOP_COMPLETE_EVT:
        // 停止广播完成事件
        xSemaphoreGive(test_sem);
        ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_EXT_ADV_STOP_COMPLETE_EVT, status %d", param->ext_adv_stop.status);
        break;
    default:
        break;
    }
}

void app_main(void)
{
    esp_err_t ret;

    // 初始化 NVS
    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK( ret );

    // 释放经典蓝牙控制器
    ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));

    // 初始化蓝牙控制器
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    ret = esp_bt_controller_init(&bt_cfg);
    if (ret) {
        ESP_LOGE(LOG_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    // 启用蓝牙控制器
    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
    if (ret) {
        ESP_LOGE(LOG_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    // 初始化蓝牙协议栈
    ret = esp_bluedroid_init();
    if (ret) {
        ESP_LOGE(LOG_TAG, "%s init bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    // 启用蓝牙协议栈
    ret = esp_bluedroid_enable();
    if (ret) {
        ESP_LOGE(LOG_TAG, "%s enable bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    // 注册 GAP 事件处理函数
    ret = esp_ble_gap_register_callback(gap_event_handler);
    if (ret){
        ESP_LOGE(LOG_TAG, "gap register error, error code = %x", ret);
        return;
    }

    vTaskDelay(200 / portTICK_PERIOD_MS);

    // 创建信号量
    test_sem = xSemaphoreCreateBinary();

    // 设置 1M PHY 的扩展广播参数
    FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_params(0, &ext_adv_params_1M), test_sem);

    // 设置 1M PHY 的扩展广播随机地址
    FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_set_rand_addr(0, addr_1m), test_sem);

    // 配置 1M PHY 的扩展广播数据
    FUNC_SEND_WAIT_SEM(esp_ble_gap_config_ext_adv_data_raw(0, sizeof(raw_adv_data_1m), &raw_adv_data_1m[0]), test_sem);

    // 启动所有广播
    FUNC_SEND_WAIT_SEM(esp_ble_gap_ext_adv_start(4, &ext_adv[0]), test_sem);

    return;
}

广播包信息

程序烧写运行后,可以通过手机蓝牙调试APP查看到广播信息

设备Services

连接设备后,可以看到两个默认的Servicecs,它们通用属性配置文件(GATT)服务,该服务用于在BLE设备上发现服务、特征和描述符。

  • 00001801-0000-1000-8000-00805f9b34fb:通用属性配置文件(GATT)服务,用于在 BLE 设备上发现服务、特征和描述符;
  • 00001800-0000-1000-8000-00805f9b34fb:通用访问配置文件(GAP)服务,用于管理 BLE 设备的连接和广播。它包括了设备名称、外观、首选连接参数和广播数据等信息。









编写于:2023/12/13 15:59:22
发布 IP 属地:广东省深圳市

版权声明

本站内容均来自网络转载或网友提供,如有侵权请及时联系我们删除!本站不承担任何争议和法律责任!


艾金森

每一个童年的梦想都值得用青春去捍卫!




用户地图 心情地图 日记地图 笔记地图 时间轴地图 2023年9月27日 星期三 晴 工作交接了,开心~事情不会像我想的那么好,但也不会像我想的那么糟面基2023年10月18日 星期三 雨 母婴护理第11课(结束)2023/9/7 复盘麦冬旭 的日记 2023/09/24 21:20:60第八周周记цитат из "Как Закалялась Сталь"关于朋友2023年11月26日 星期日 晴 休息 社工证综合能力9-10章 志愿者文华书城兄妹日常2021年10月10日2023年11月10日 星期五 雨 产康第9课 刮痧拔罐 第10课 满月发汗 (扶阳罐第7次)兄妹日常2021年6月7日1226兄妹日常2020年12月15日兄妹日常2021年5月5日2023年郑州的第一场大雪LuweitongGenerated by ChatGPT突然而来的小确幸,10年前的今日2023年12月6日 星期三 晴 悦享喜月湾母婴护理晚班第2天兄妹日常2021年5月4日24兄妹日常2020年12月22日betty 的日记 2024/01/20 14:12:21铁蛋儿 的日记 2023/10/23 14:27:26兄妹日常2021年1月31日关于昨天晚上师兄弟喝闷酒2023-09-19 日记【状态不好】兄妹日常2021年7月19日兄妹日常2021年8月3日2月14日,我的减肥日记2023年11月9日 星期四 晴 产康第8课 盆底肌修复key4127 的日记 2023/09/20 22:37:17康康 的日记 2024/01/30 23:21:512024-02-05 日记【春节 - 古灵精怪的哥斯拉】2023年11月23日 星期四 晴 休息 社工证综合能力1-3章兄妹日常2021年3月5日2023/9/12 复盘Generated by ChatGPT2023/10/9 复盘Across the Iron Curtain兄妹日常2021年8月24日Generated by ChatGPTjh1127 的日记 2024/01/17 22:29:24兄妹日常2020年12月1日时薪1.0416666…元人民币Linda's Embarrassing TeachingArya 的日记 2023/12/26 15:46:35兄妹日常2021年2月28日阅读须知,但没那么须今天在公司,下午13:00 还有一小时开播满山的猴子我腚最红 的日记 2023/10/03 08:45:152023.8.23再会兄妹日常2021年8月8日兄妹日常2021年7月17日兄妹日常2021年2月5日2023/9/11 复盘key4127 的日记 2024/01/13 23:12:51为什么爱Generated by ChatGPTdddssssss09-24给足尊重平安夜兄妹日常2021年4月5日Trigonometric Trial兄妹日常2021年8月2日专业见习(4)2023年11月12日 星期日 阴 休息 心理咨询师考试芊. 的日记 2024/02/18 18:05:39Generated by ChatGPT2023年10月10日 星期二 雨 母婴护理第4课 新生儿护理挣扎的一天兄妹日常2021年7月1日2023年11月30日 星期四 晴 休息 志愿者金台寺兄妹日常2021年5月10日兄妹日常2021年2月15日青石巷·异兽笔录(序)2023年12月23日 星期六 雨转晴 第9味馄饨店兼职第3天万事休矣兄妹日常2021年3月25日2023/9/20 复盘Generated by ChatGPT兄妹日常2021年4月11日key4127 的日记 2023/10/07 21:11:182023/08/29--周二2024-01-23 Web开发记录【重构笔记功能 】【数据结构】兄妹日常2020年12月8日地铁2023年12月22日 星期五 晴 悦享喜月湾母婴护理白班第8天Desperated Spatacle兄妹日常2021年10月9日兄妹日常2021年3月7日兄妹日常2021年7月3日隔着眼泪看这个世界,整个世界都在哭新生的萌芽 的日记 2023/10/13 16:17:49那一年,2023的我知乎过去评论的总结整理判断题疑难点43-57 基本办公软件判断题疑难点66-67 图片音频文件笔记本扩展外屏【内存不足】沙茶酱是什么做的OTG与USB线的区别及接线图Matthew H. Kramer:《菲尼斯式的报应主义》节选翻译I满山的猴子我腚最红 的笔记 2023/10/01 19:03:09Godzilla - Eminem低功耗蓝牙广播 说明企业总结判断题疑难点74-78 程序ESP32 IDF的蓝牙广播demo 说明简单了解 新加坡IDMA认证Dylan Moran - Like, Totally 第一部分(02:55)证券短线波段八字基本知识2023120420231207Der Weg zur Quelle【天干】甲【个人笔记】伪需求识别与过滤修车熊市末端持股策略,下跌何时结束。觉着活着没意思的,推荐一个视频。《女人一生的追求》人的不自知【功能介绍】个人信息属性标签【未完成】20231206降压控制器 LM3150 6V至42V宽输入电压范围【鱼露】调味料是什么简单了解 印度WPC认证重读经典的伟大冒险1新生的萌芽 的笔记 2023/10/19 16:57:59重读经典的伟大冒险2OC_角色_乱象《健身先健脑》ESP32 开发环境选择【都不方便】放弃这一次证券股投机,等待3个月之后的机会ESTI EN 300328 无线产品CE认证测试标准朝鲜宣布废除“9·19南北军事协议”如何开始论八字新生的萌芽 的笔记 2023/10/07 17:54:43帅还是呆 的笔记 2023/10/26 11:11:18C to the O C O N ADer Weg zur Quelle 生与死《走遍德国》B2 S106阅读翻译练习Zachary Hoskins: Fair Play, Political Obligation, and Punishment节选翻译判断题疑难点28-34 不常用软件与工具【Datasheet】地平线 旭日X3芯片【梁博-出现又离开】简谱判断题疑难点68-73 操作系统【变动】由于懒得调整,新增【通讯录】按钮,暂时无功能2023.11.30为什么无线信号(RSSI)是负值20231218我抠出来了!!!2014年做的电路板,一个比较淘气的设计CR2032 CR1632 电池规格和性能【用户意见】2023-09-01 移动端体验太差终点也是起点判断题疑难点58-65 数字的表示ESP32C3 BLE 发射功率调整及 RSSI 相关知识整理随笔卡牌游戏玩家目的分析2023-10-03 通过OSS存储网站资源 - 体验简单了解 台湾NCC认证啊?判断题疑难点1-20 python编程相关关于自律即自由的看法c#文件过大,将一个文件拆分成几个部分【小故事】QQ群第一个里程碑 - 50人了我的平行宇宙,是窝在家里的舒适第七天——余华【再一次为生在这个家庭而感到幸运】C# <summary>注释实现换行《战国策》东周策一:秦兴师临周而求九鼎章【Datasheet】Amlogic A311D AI芯片参数规格Android Studio 【SeekBar】基本用法镜启轻力 焕然新动2015年画的电路板,记录一下Android Studio 快捷键大全20231205被破坏的下班心情MSSQL 查询重复数据及删除巴以冲突第49天·休战第1天满山的猴子我腚最红 的笔记 2023/09/21 12:06:39欧盟CE认证之RED无线指令A Choice of Three简单了解 新加坡COC 认证八字基本知识该说不说,必应的圣诞官网做的真不错,我挺喜欢的如何获取浏览器IP与城市,并记录存储【2023年可以用,已解决】塔罗被禁了?!触控屏框贴、全贴合、零贴合工艺解析IEC 60335 国际电工委员会制定的关于家用电器安全性的标准判断题疑难点21-27 压缩与编码八字基本知识回家 近期判断题疑难点35-42 计算机系统相关SolidWorks装配体保存成零件方法