ESP32S3基础7-蓝牙通信-Uniapp与ESP32开发板数据交互

张开发
2026/5/11 6:34:49 15 分钟阅读

分享文章

ESP32S3基础7-蓝牙通信-Uniapp与ESP32开发板数据交互
1.ESP32的蓝牙概念1.1.蓝牙的区分GATT用来规范 attribute 中的数据内容,并运用 group(分组)的概念对 attribute 进行分类管理。为主从设备交互数据提供 Profile、Service、Characteristic 等概念的抽象、管理。所以在这个示例程序中,关于GATT的示例是非常多的。除此之外,包括我们经常能见到的蓝牙串口透传,使用的就是 SPP协议。蓝牙Ibeacon 模式,是作为信标用于蓝牙定位的一种协议。鼠标键盘,其他外设HID设备的延时,也提供了对应的例子。1.2.ESP32的蓝牙参考案例的说明使用ESP32的官方例子-gatt_server_service_table1.2.1.重点函数讲解- gap_event_handler作用:处理蓝牙 GAP(Generic Access Profile)层的事件,主要与广播的配置和启动相关。参数1:event:GAP 事件类型(如 ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT)。参数2:param:指向事件参数结构体的指针,包含具体事件的数据。说明:该函数在 GAP 回调中根据事件类型执行相应操作。例如,当广播数据设置完成后,检查是否所有配置完成,若是则开始广播;当广播启动完成时,打印状态信息。- example_prepare_write_event_env作用:处理 GATT 服务器的“准备写”事件(Prepare Write),用于支持长特性值的写入(将数据分片写入)。参数1:gatts_if:GATT 服务器接口号。参数2:prepare_write_env:指向 prepare_type_env_t 结构体的指针,用于保存准备写数据的缓冲区及长度。参数3:param:指向事件参数结构体的指针,包含写入的数据、偏移量、句柄等信息。说明:当客户端执行准备写操作时,该函数会分配缓冲区(若未分配),检查偏移量和长度是否合法,并根据需要发送响应。数据会被暂存到 prepare_write_env-prepare_buf 中。- example_exec_write_event_env作用:处理 GATT 服务器的“执行写”事件(Exec Write),完成长写入操作。参数1:prepare_write_env:指向 prepare_type_env_t 结构体的指针,包含之前暂存的数据。参数2:param:指向事件参数结构体的指针,指示是执行还是取消写入。说明:当客户端发送执行写请求时,该函数根据标志决定是将暂存的数据真正写入(打印数据)还是取消写入(丢弃数据),最后释放缓冲区。- gatts_profile_event_handler作用:处理特定 GATT 配置文件(Profile)的事件,例如注册、读、写、MTU 更新、连接、断开等参数1:event:GATT 服务器事件类型(如 ESP_GATTS_REG_EVT、ESP_GATTS_WRITE_EVT)。参数2:gatts_if:GATT 服务器接口号。参数3:param:指向事件参数结构体的指针。说明:该函数是示例中核心的事件处理逻辑:ESP_GATTS_REG_EVT:注册应用后设置设备名、配置广播数据、创建属性表。ESP_GATTS_WRITE_EVT:处理普通写和准备写(区分 is_prep),对于 CCC 描述符的写入,根据值使能通知或指示,并发送数据。ESP_GATTS_EXEC_WRITE_EVT:调用 example_exec_write_event_env 完成长写入。ESP_GATTS_CONNECT_EVT:连接后更新连接参数。ESP_GATTS_DISCONNECT_EVT:断开后重新开始广播。ESP_GATTS_CREAT_ATTR_TAB_EVT:属性表创建完成后保存句柄并启动服务。其他事件如读、MTU、确认等仅打印日志。- gatts_event_handler作用:全局 GATT 服务器事件处理函数,将事件分发到各个注册的配置文件(Profile)。参数1:event:GATT 服务器事件类型。参数2:gatts_if:GATT 服务器接口号。参数3:param:指向事件参数结构体的指针。说明:首先处理注册事件,保存对应 profile 的 gatts_if。然后遍历所有 profile,若当前 gatts_if 与 profile 的接口匹配(或为 ESP_GATT_IF_NONE),则调用该 profile 的回调函数 gatts_cb(此处为 gatts_profile_event_handler)。- app_main作用:应用程序入口,完成系统初始化和 BLE 协议栈的启动。参数:无。说明:初始化 NVS 闪存。释放经典蓝牙内存(仅使用 BLE)。初始化并启用蓝牙控制器(BLE 模式)。初始化并启用 Bluedroid 协议栈。注册 GATT 服务器回调函数 gatts_event_handler。注册 GAP 回调函数 gap_event_handler。注册 GATT 应用程序(esp_ble_gatts_app_register),应用 ID 为 ESP_APP_ID。设置本地 MTU 大小为 500 字节。2.1.蓝牙小菜通过对比手机端读取到的信息,进行了简单的数据读写测试,了解了程序的设计框架,也算是入门了 ESP-IDF 的蓝牙 GATT 开发。2.2.ESP32S3的开发板上报数据、Uniapp接受2.2.1.功能简述2.2.2.ESP32的代码gatts_table_creat_demo.c/* * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 * * Modified to support 4 buttons sending notifications 1-4 via BLE. */#include"freertos/FreeRTOS.h"#include"freertos/task.h"#include"freertos/event_groups.h"#include"esp_system.h"#include"esp_log.h"#include"nvs_flash.h"#include"esp_bt.h"#include"esp_gap_ble_api.h"#include"esp_gatts_api.h"#include"esp_bt_main.h"#include"gatts_table_creat_demo.h"#include"esp_gatt_common_api.h"#include"driver/gpio.h"// 新增:GPIO 操作#defineGATTS_TABLE_TAG"GATTS_TABLE_DEMO"#definePROFILE_NUM1#definePROFILE_APP_IDX0#defineESP_APP_ID0x55#defineSAMPLE_DEVICE_NAME"POLYPLAY_POINT"// 可修改为其他名称#defineSVC_INST_ID0/* The max length of characteristic value. When the GATT client performs a write or prepare write operation, * the data length must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX. */#defineGATTS_DEMO_CHAR_VAL_LEN_MAX500#definePREPARE_BUF_MAX_SIZE1024#defineCHAR_DECLARATION_SIZE(sizeof(uint8_t))#defineADV_CONFIG_FLAG(10)#defineSCAN_RSP_CONFIG_FLAG(11)staticuint8_tadv_config_done=0;uint16_theart_rate_handle_table[HRS_IDX_NB];typedefstruct{uint8_t*prepare_buf;intprepare_len;}prepare_type_env_t;staticprepare_type_env_tprepare_write_env;// 新增:用于保存通知相关状态staticuint16_tnotify_gatts_if=ESP_GATT_IF_NONE;staticuint16_tnotify_conn_id=0;staticbool notify_enabled=false;// 手机是否已使能特征 F 的通知#defineCONFIG_SET_RAW_ADV_DATA#ifdefCONFIG_SET_RAW_ADV_DATA// 定义广播包staticuint8_traw_adv_data[]={/* flags */0x02,0x01,0x06,/* tx power 0a 是蓝牙发射功率的强度*/0x02,0x0a,0xeb,/* service uuid */0x03,0x03,0xFF,0x00,/* device name 第一个0f是这个全部字段的长度值*/0x0f,0x09,'P','O','L','Y','P','L','A','Y','_','P','O','I','N','T'};// 定义广播应答包staticuint8_traw_scan_rsp_data[]={/* flags */0x02,0x01,0x06,/* tx power */0x02,0x0a,0xeb,/* service uuid */0x03,0x03,0xFF,0x00};#else// ... 省略其他配置(未使用)#endif/* CONFIG_SET_RAW_ADV_DATA */staticesp_ble_adv_params_tadv_params={.adv_int_min=0x20,.adv_int_max=0x40,.adv_type=ADV_TYPE_IND,.own_addr_type=BLE_ADDR_TYPE_PUBLIC,.channel_map=ADV_CHNL_ALL,.adv_filter_policy=ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,};structgatts_profile_inst{esp_gatts_cb_tgatts_cb;uint16_tgatts_if;uint16_tapp_id;uint16_tconn_id;uint16_tservice_handle;esp_gatt_srvc_id_tservice_id;uint16_tchar_handle;esp_bt_uuid_tchar_uuid;esp_gatt_perm_tperm;esp_gatt_char_prop_tproperty;uint16_tdescr_handle;esp_bt_uuid_tdescr_uuid;};staticvoidgatts_profile_event_handler(esp_gatts_cb_event_tevent,esp_gatt_if_tgatts_if,esp_ble_gatts_cb_param_t*param);/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */staticstructgatts_profile_instheart_rate_profile_tab[PROFILE_NUM]={[PROFILE_APP_IDX]={.gatts_cb=gatts_profile_event_handler,.gatts_if=ESP_GATT_IF_NONE,/* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */},};/* Service */staticconstuint16_tGATTS_SERVICE_UUID_TEST=0x00FF;staticconstuint16_tGATTS_CHAR_UUID_TEST_A=0xFF01;staticconstuint16_tGATTS_CHAR_UUID_TEST_B=0xFF02;staticconstuint16_tGATTS_CHAR_UUID_TEST_C=0xFF03;staticconstuint16_tGATTS_CHAR_UUID_TEST_D=0xFF04;staticconstuint16_tGATTS_CHAR_UUID_TEST_E=0xFF05;staticconstuint16_tGATTS_CHAR_UUID_TEST_F=0xFF06;// 我们将使用此特征发送通知staticconstuint16_tprimary_service_uuid=ESP_GATT_UUID_PRI_SERVICE;staticconstuint16_tcharacter_declaration_uuid=ESP_GATT_UUID_CHAR_DECLARE;staticconstuint16_tcharacter_client_config_uuid=ESP_GATT_UUID_CHAR_CLIENT_CONFIG;staticconstuint8_tchar_prop_read=ESP_GATT_CHAR_PROP_BIT_READ;staticconstuint8_tchar_prop_write=ESP_GATT_CHAR_PROP_BIT_WRITE;staticconstuint8_tchar_prop_read_write_notify=ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY;staticconstuint8_theart_measurement_ccc[2]={0x00,0x00};staticconstuint8_tchar_value[4]={0x11,0x22,0x33,0x44};staticconstuint8_ttest_value[4]={0xaa,0xbb,0xcc,0xdd};/* Full Database Description - Used to add attributes into the database */staticconstesp_gatts_attr_db_tgatt_db[HRS_IDX_NB]={// Service Declaration[IDX_SVC]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)primary_service_uuid,ESP_GATT_PERM_READ,sizeof(uint16_t),sizeof(GATTS_SERVICE_UUID_TEST),(uint8_t*)GATTS_SERVICE_UUID_TEST}},/* Characteristic Declaration */[IDX_CHAR_A]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)character_declaration_uuid,ESP_GATT_PERM_READ,CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE,(uint8_t*)char_prop_read_write_notify}},/* Characteristic Value */[IDX_CHAR_VAL_A]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)GATTS_CHAR_UUID_TEST_A,ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,GATTS_DEMO_CHAR_VAL_LEN_MAX,sizeof(char_value),(uint8_t*)char_value}},/* Client Characteristic Configuration Descriptor */[IDX_CHAR_CFG_A]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)character_client_config_uuid,ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,sizeof(uint16_t),sizeof(heart_measurement_ccc),(uint8_t*)heart_measurement_ccc}},/* Characteristic Declaration */[IDX_CHAR_B]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)character_declaration_uuid,ESP_GATT_PERM_READ,CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE,(uint8_t*)char_prop_read}},/* Characteristic Value */[IDX_CHAR_VAL_B]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)GATTS_CHAR_UUID_TEST_B,ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,GATTS_DEMO_CHAR_VAL_LEN_MAX,sizeof(char_value),(uint8_t*)char_value}},/* Characteristic Declaration */[IDX_CHAR_C]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)character_declaration_uuid,ESP_GATT_PERM_READ,CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE,(uint8_t*)char_prop_write}},/* Characteristic Value */[IDX_CHAR_VAL_C]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)GATTS_CHAR_UUID_TEST_C,ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,GATTS_DEMO_CHAR_VAL_LEN_MAX,sizeof(char_value),(uint8_t*)char_value}},/* 自定义特征值 GATTS_CHAR_UUID_TEST_D 功能为只读 */[IDX_CHAR_D]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)character_declaration_uuid,ESP_GATT_PERM_READ,CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE,(uint8_t*)char_prop_read}},[IDX_CHAR_VAL_D]={{ESP_GATT_AUTO_RSP},{ESP_UUID_LEN_16,(uint8_t*)GATTS_CHAR_UUID_TEST_D,ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,GATTS_DEMO_CHAR_VAL_LEN_MAX,sizeof(test_value),

更多文章