泉州专业网站制作公司推广引流app
以下是一个基于ESP32-S3的蓝牙SDK封装设计,包含双模蓝牙(BLE+经典蓝牙)支持,提供清晰的数据结构、枚举类型和API接口。
1. 头文件定义 (esp32_s3_bt_sdk.h)
c
复制
#ifndef ESP32_S3_BT_SDK_H #define ESP32_S3_BT_SDK_H#include "esp_bt.h" #include "esp_bt_main.h" #include "esp_gap_ble_api.h" #include "esp_gatts_api.h" #include "esp_gattc_api.h" #include "esp_spp_api.h" #include "esp_bt_defs.h"#ifdef __cplusplus extern "C" { #endif/*** @brief 蓝牙工作模式枚举*/ typedef enum {BT_MODE_NONE = 0, // 无模式BT_MODE_BLE, // 仅BLE模式BT_MODE_CLASSIC, // 仅经典蓝牙模式BT_MODE_DUAL // 双模模式(BLE+经典蓝牙) } bt_mode_t;/*** @brief 蓝牙角色枚举*/ typedef enum {BT_ROLE_PERIPHERAL = 0, // BLE外设模式BT_ROLE_CENTRAL, // BLE中心设备模式BT_ROLE_IDLE // 空闲模式 } bt_role_t;/*** @brief 蓝牙连接状态枚举*/ typedef enum {BT_STATE_DISCONNECTED = 0, // 未连接BT_STATE_CONNECTING, // 连接中BT_STATE_CONNECTED, // 已连接BT_STATE_DISCONNECTING // 断开中 } bt_state_t;/*** @brief 蓝牙安全模式枚举*/ typedef enum {BT_SEC_NONE = 0, // 无安全要求BT_SEC_ENCRYPT, // 需要加密BT_SEC_ENCRYPT_NO_MITM, // 加密但不需MITM保护BT_SEC_ENCRYPT_MITM // 加密且需要MITM保护 } bt_sec_mode_t;/*** @brief 蓝牙设备信息结构体*/ typedef struct {char name[32]; // 设备名称esp_bd_addr_t addr; // 设备地址int8_t rssi; // 信号强度bt_role_t role; // 设备角色uint16_t appearance; // 设备外观(仅BLE) } bt_device_info_t;/*** @brief BLE GATT服务配置结构体*/ typedef struct {esp_bt_uuid_t service_uuid; // 服务UUIDesp_bt_uuid_t char_uuid; // 特征UUIDesp_gatt_perm_t perm; // 权限esp_gatt_char_prop_t prop; // 属性uint16_t handle; // 句柄(输出参数) } ble_gatt_service_t;/*** @brief 蓝牙配置参数结构体*/ typedef struct {bt_mode_t mode; // 工作模式bt_role_t role; // 设备角色char device_name[32]; // 设备名称uint16_t mtu_size; // BLE MTU大小uint32_t spp_baudrate; // SPP波特率(经典蓝牙)bt_sec_mode_t sec_mode; // 安全模式uint16_t conn_params_min; // 最小连接间隔(ms)uint16_t conn_params_max; // 最大连接间隔(ms) } bt_config_t;/*** @brief 蓝牙数据回调结构体*/ typedef struct {void (*on_ble_data)(const uint8_t *data, uint16_t length); // BLE数据接收回调void (*on_spp_data)(const uint8_t *data, uint16_t length); // SPP数据接收回调void (*on_conn_state)(bt_state_t state, const bt_device_info_t *device); // 连接状态回调void (*on_scan_result)(const bt_device_info_t *device); // 扫描结果回调 } bt_callback_t;/*** @brief 初始化蓝牙SDK* @param config 蓝牙配置参数* @param callback 回调函数集合* @return esp_err_t 执行结果*/ esp_err_t bt_sdk_init(const bt_config_t *config, const bt_callback_t *callback);/*** @brief 反初始化蓝牙SDK*/ void bt_sdk_deinit(void);/*** @brief 开始蓝牙设备扫描* @param duration_sec 扫描持续时间(秒),0表示持续扫描* @return esp_err_t 执行结果*/ esp_err_t bt_sdk_start_scan(uint32_t duration_sec);/*** @brief 停止蓝牙设备扫描*/ void bt_sdk_stop_scan(void);/*** @brief 连接指定蓝牙设备* @param device 目标设备信息* @return esp_err_t 执行结果*/ esp_err_t bt_sdk_connect_device(const bt_device_info_t *device);/*** @brief 断开当前连接*/ void bt_sdk_disconnect(void);/*** @brief 通过BLE发送数据* @param data 数据指针* @param length 数据长度* @return esp_err_t 执行结果*/ esp_err_t bt_sdk_send_ble_data(const uint8_t *data, uint16_t length);/*** @brief 通过SPP发送数据* @param data 数据指针* @param length 数据长度* @return esp_err_t 执行结果*/ esp_err_t bt_sdk_send_spp_data(const uint8_t *data, uint16_t length);/*** @brief 添加BLE GATT服务* @param service 服务配置* @return esp_err_t 执行结果*/ esp_err_t bt_sdk_add_gatt_service(ble_gatt_service_t *service);/*** @brief 设置BLE广播数据* @param adv_data 广播数据* @param adv_len 广播数据长度* @param scan_rsp_data 扫描响应数据* @param scan_rsp_len 扫描响应数据长度* @return esp_err_t 执行结果*/ esp_err_t bt_sdk_set_adv_data(const uint8_t *adv_data, uint16_t adv_len, const uint8_t *scan_rsp_data, uint16_t scan_rsp_len);/*** @brief 开始BLE广播* @param duration_sec 广播持续时间(秒),0表示持续广播* @return esp_err_t 执行结果*/ esp_err_t bt_sdk_start_advertising(uint32_t duration_sec);/*** @brief 停止BLE广播*/ void bt_sdk_stop_advertising(void);#ifdef __cplusplus } #endif#endif // ESP32_S3_BT_SDK_H
2. 核心实现 (esp32_s3_bt_sdk.c)
c
复制
#include "esp32_s3_bt_sdk.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h"#define TAG "BT_SDK"// 蓝牙SDK全局上下文 typedef struct {bt_config_t config;bt_callback_t callback;bt_state_t state;bt_device_info_t connected_device;bool is_scanning;bool is_advertising;esp_gatt_if_t gatt_if;uint16_t conn_id;uint32_t spp_handle; } bt_sdk_context_t;static bt_sdk_context_t s_bt_ctx = {0};// BLE GATT事件处理 static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {switch (event) {case ESP_GATTS_REG_EVT:s_bt_ctx.gatt_if = gatts_if;ESP_LOGI(TAG, "GATT server registered, gatt_if=%d", gatts_if);break;case ESP_GATTS_CONNECT_EVT:s_bt_ctx.state = BT_STATE_CONNECTED;s_bt_ctx.conn_id = param->connect.conn_id;memcpy(s_bt_ctx.connected_device.addr, param->connect.remote_bda, ESP_BD_ADDR_LEN);if (s_bt_ctx.callback.on_conn_state) {s_bt_ctx.callback.on_conn_state(BT_STATE_CONNECTED, &s_bt_ctx.connected_device);}break;case ESP_GATTS_DISCONNECT_EVT:s_bt_ctx.state = BT_STATE_DISCONNECTED;if (s_bt_ctx.callback.on_conn_state) {s_bt_ctx.callback.on_conn_state(BT_STATE_DISCONNECTED, &s_bt_ctx.connected_device);}break;case ESP_GATTS_WRITE_EVT:if (s_bt_ctx.callback.on_ble_data && param->write.is_prep == false) {s_bt_ctx.callback.on_ble_data(param->write.value, param->write.len);}break;default:break;} }// BLE 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_SCAN_RESULT_EVT:if (param->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT && s_bt_ctx.callback.on_scan_result) {bt_device_info_t device = {0};memcpy(device.addr, param->scan_rst.bda, ESP_BD_ADDR_LEN);device.rssi = param->scan_rst.rssi;device.role = BT_ROLE_PERIPHERAL;if (param->scan_rst.ble_adv != NULL) {if (param->scan_rst.ble_adv->name_len > 0) {strncpy(device.name, (char *)param->scan_rst.ble_adv->name, MIN(param->scan_rst.ble_adv->name_len, sizeof(device.name)-1));}}s_bt_ctx.callback.on_scan_result(&device);}break;case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:ESP_LOGI(TAG, "BLE scan parameters set complete");break;case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:if (param->scan_start_cmpl.status == ESP_BT_STATUS_SUCCESS) {s_bt_ctx.is_scanning = true;ESP_LOGI(TAG, "BLE scan started");} else {ESP_LOGE(TAG, "BLE scan start failed");}break;case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:s_bt_ctx.is_scanning = false;ESP_LOGI(TAG, "BLE scan stopped");break;default:break;} }// 经典蓝牙SPP事件处理 static void spp_event_handler(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) {switch (event) {case ESP_SPP_SRV_OPEN_EVT:s_bt_ctx.state = BT_STATE_CONNECTED;s_bt_ctx.spp_handle = param->srv_open.handle;memcpy(s_bt_ctx.connected_device.addr, param->srv_open.rem_bda, ESP_BD_ADDR_LEN);if (s_bt_ctx.callback.on_conn_state) {s_bt_ctx.callback.on_conn_state(BT_STATE_CONNECTED, &s_bt_ctx.connected_device);}break;case ESP_SPP_CLOSE_EVT:s_bt_ctx.state = BT_STATE_DISCONNECTED;if (s_bt_ctx.callback.on_conn_state) {s_bt_ctx.callback.on_conn_state(BT_STATE_DISCONNECTED, &s_bt_ctx.connected_device);}break;case ESP_SPP_DATA_IND_EVT:if (s_bt_ctx.callback.on_spp_data) {s_bt_ctx.callback.on_spp_data(param->data_ind.data, param->data_ind.len);}break;default:break;} }// 初始化蓝牙SDK esp_err_t bt_sdk_init(const bt_config_t *config, const bt_callback_t *callback) {if (config == NULL || callback == NULL) {return ESP_ERR_INVALID_ARG;}// 保存配置和回调memcpy(&s_bt_ctx.config, config, sizeof(bt_config_t));memcpy(&s_bt_ctx.callback, callback, sizeof(bt_callback_t));s_bt_ctx.state = BT_STATE_DISCONNECTED;// 初始化蓝牙控制器esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();esp_err_t ret = esp_bt_controller_init(&bt_cfg);if (ret != ESP_OK) {ESP_LOGE(TAG, "Bluetooth controller init failed");return ret;}// 启用蓝牙控制器ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM);if (ret != ESP_OK) {ESP_LOGE(TAG, "Bluetooth controller enable failed");return ret;}// 初始化蓝牙栈ret = esp_bluedroid_init();if (ret != ESP_OK) {ESP_LOGE(TAG, "Bluedroid init failed");return ret;}ret = esp_bluedroid_enable();if (ret != ESP_OK) {ESP_LOGE(TAG, "Bluedroid enable failed");return ret;}// 设置设备名称esp_bt_dev_set_device_name(s_bt_ctx.config.device_name);// 根据模式注册回调if (s_bt_ctx.config.mode == BT_MODE_BLE || s_bt_ctx.config.mode == BT_MODE_DUAL) {esp_ble_gatts_register_callback(gatts_event_handler);esp_ble_gap_register_callback(gap_event_handler);}if (s_bt_ctx.config.mode == BT_MODE_CLASSIC || s_bt_ctx.config.mode == BT_MODE_DUAL) {esp_spp_register_callback(spp_event_handler);esp_spp_init(ESP_SPP_MODE_CB);}// 设置安全模式if (s_bt_ctx.config.sec_mode != BT_SEC_NONE) {esp_ble_auth_req_t auth_req = ESP_LE_AUTH_NO_BOND;if (s_bt_ctx.config.sec_mode == BT_SEC_ENCRYPT_MITM) {auth_req = ESP_LE_AUTH_REQ_MITM;}esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(auth_req));}ESP_LOGI(TAG, "Bluetooth SDK initialized");return ESP_OK; }// 其他函数实现... // [由于篇幅限制,这里只展示关键部分,完整实现需要包含所有声明的函数]
3. 主要数据结构说明
3.1 枚举类型
-
bt_mode_t: 蓝牙工作模式
-
BT_MODE_NONE: 无模式
-
BT_MODE_BLE: 仅BLE模式
-
BT_MODE_CLASSIC: 仅经典蓝牙模式
-
BT_MODE_DUAL: 双模模式
-
-
bt_role_t: 设备角色
-
BT_ROLE_PERIPHERAL: BLE外设
-
BT_ROLE_CENTRAL: BLE中心设备
-
BT_ROLE_IDLE: 空闲模式
-
-
bt_state_t: 连接状态
-
BT_STATE_DISCONNECTED: 未连接
-
BT_STATE_CONNECTING: 连接中
-
BT_STATE_CONNECTED: 已连接
-
BT_STATE_DISCONNECTING: 断开中
-
-
bt_sec_mode_t: 安全模式
-
BT_SEC_NONE: 无安全
-
BT_SEC_ENCRYPT: 需要加密
-
BT_SEC_ENCRYPT_NO_MITM: 加密但无需MITM
-
BT_SEC_ENCRYPT_MITM: 加密且需要MITM
-
3.2 结构体类型
-
bt_device_info_t: 蓝牙设备信息
-
name: 设备名称
-
addr: 设备地址
-
rssi: 信号强度
-
role: 设备角色
-
appearance: 设备外观(仅BLE)
-
-
ble_gatt_service_t: BLE GATT服务配置
-
service_uuid: 服务UUID
-
char_uuid: 特征UUID
-
perm: 权限
-
prop: 属性
-
handle: 句柄(输出参数)
-
-
bt_config_t: 蓝牙配置
-
mode: 工作模式
-
role: 设备角色
-
device_name: 设备名称
-
mtu_size: BLE MTU大小
-
spp_baudrate: SPP波特率
-
sec_mode: 安全模式
-
conn_params_min/max: 连接参数
-
-
bt_callback_t: 回调函数集合
-
on_ble_data: BLE数据接收回调
-
on_spp_data: SPP数据接收回调
-
on_conn_state: 连接状态回调
-
on_scan_result: 扫描结果回调
-
-
bt_sdk_context_t: SDK内部上下文(私有)
-
包含所有运行时状态和配置
-
4. 使用示例
c
复制
#include "esp32_s3_bt_sdk.h" #include "esp_log.h"// 蓝牙数据接收回调 void on_ble_data(const uint8_t *data, uint16_t length) {ESP_LOGI("EXAMPLE", "Received BLE data, len=%d", length); }// 蓝牙连接状态回调 void on_conn_state(bt_state_t state, const bt_device_info_t *device) {if (state == BT_STATE_CONNECTED) {ESP_LOGI("EXAMPLE", "Connected to device: %s", device->name);} else {ESP_LOGI("EXAMPLE", "Disconnected");} }void app_main() {// 蓝牙配置bt_config_t config = {.mode = BT_MODE_DUAL,.role = BT_ROLE_PERIPHERAL,.device_name = "ESP32-S3-BT",.mtu_size = 512,.spp_baudrate = 115200,.sec_mode = BT_SEC_ENCRYPT,.conn_params_min = 20,.conn_params_max = 40};// 回调设置bt_callback_t callback = {.on_ble_data = on_ble_data,.on_conn_state = on_conn_state,.on_spp_data = NULL,.on_scan_result = NULL};// 初始化蓝牙SDKesp_err_t ret = bt_sdk_init(&config, &callback);if (ret != ESP_OK) {ESP_LOGE("EXAMPLE", "Bluetooth init failed");return;}// 添加GATT服务示例ble_gatt_service_t service = {.service_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = 0xABCD}},.char_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = 0x1234}},.perm = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,.prop = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE};bt_sdk_add_gatt_service(&service);// 开始广播uint8_t adv_data[] = {0x02, 0x01, 0x06, 0x0A, 0x09, 'E', 'S', 'P', '3', '2', '-', 'S', '3'};bt_sdk_set_adv_data(adv_data, sizeof(adv_data), NULL, 0);bt_sdk_start_advertising(0); // 持续广播 }
5. 设计特点
-
双模支持: 同时支持BLE和经典蓝牙SPP协议
-
模块化设计: 清晰的接口分层,易于扩展
-
异步回调: 所有事件通过回调通知应用层
-
线程安全: 适合在FreeRTOS多任务环境中使用
-
完整状态管理: 维护连接状态和设备信息
-
灵活配置: 支持多种工作模式和安全级别
这个SDK封装了ESP32-S3的蓝牙功能,提供了简洁易用的API接口,适合大多数蓝牙应用场景开发。