ESP32蓝牙开发笔记(十四)

在 ESP32 的 BLE 开发中,esp_ble_gatts_add_char 是用于向 GATT 服务中添加特征(Characteristic)的核心函数。以下是该函数的详细说明、参数解析及示例代码:


函数原型

cpp 复制代码
esp_err_t esp_ble_gatts_add_char(
    uint16_t service_handle,                  // 服务句柄(由添加服务时返回)
    esp_bt_uuid_t *char_uuid,                  // 特征的 UUID
    esp_gatt_perm_t perm,                      // 特征的访问权限
    esp_gatt_char_prop_t property,             // 特征的属性(可读、可写等)
    esp_attr_value_t *char_val,                // 特征的初始值(可选)
    esp_attr_control_t *control                // 特征的属性控制(安全模式等)
);

参数详解

1. service_handle(服务句柄)
  • 来源 :由 esp_ble_gatts_create_serviceesp_ble_gatts_add_service 创建服务后返回的句柄。
  • 作用:指定特征所属的服务。
2. char_uuid(特征 UUID)
  • 类型esp_bt_uuid_t,可以是 16-bit、32-bit 或 128-bit UUID。

  • 示例

    cpp 复制代码
    // 16-bit UUID(例如心率测量特征)
    esp_bt_uuid_t char_uuid = {
        .len = ESP_UUID_LEN_16,
        .uuid = {.uuid16 = 0x2A37}
    };
3. perm(权限)
  • 类型esp_gatt_perm_t,定义客户端对特征的访问权限。
  • 常用值
    • ESP_GATT_PERM_READ:允许读
    • ESP_GATT_PERM_WRITE:允许写
    • ESP_GATT_PERM_READ_ENCRYPTED:需要加密读
    • ESP_GATT_PERM_WRITE_ENCRYPTED:需要加密写
4. property(属性)
  • 类型esp_gatt_char_prop_t,定义特征支持的操作类型。
  • 常用值 (按位或组合):
    • ESP_GATT_CHAR_PROP_BIT_READ:可读
    • ESP_GATT_CHAR_PROP_BIT_WRITE:可写(无响应)
    • ESP_GATT_CHAR_PROP_BIT_WRITE_NR:可写(有响应)
    • ESP_GATT_CHAR_PROP_BIT_NOTIFY:支持通知
    • ESP_GATT_CHAR_PROP_BIT_INDICATE:支持指示
5. char_val(特征初始值)
  • 类型esp_attr_value_t,可选参数。如果设为 NULL,特征值初始为空。

  • 示例

    cpp 复制代码
    esp_attr_value_t char_val = {
        .attr_max_len = 10,  // 最大长度
        .attr_len = 4,       // 初始值长度
        .attr_value = {0x01, 0x02, 0x03, 0x04} // 初始值
    };
6. control(属性控制)
  • 类型esp_attr_control_t,通常用于配置安全模式。如果不需要特殊配置,可设为 NULL

  • 示例

    cpp 复制代码
    esp_attr_control_t control = {
        .auto_rsp = ESP_GATT_AUTO_RSP  // 自动响应读/写请求
    };

返回值

  • ESP_OK:特征添加成功。
  • 其他错误码:失败(如无效句柄、内存不足等)。

示例代码

步骤 1:创建服务
cpp 复制代码
esp_bt_uuid_t service_uuid = {
    .len = ESP_UUID_LEN_16,
    .uuid = {.uuid16 = 0x180D} // 心率服务
};
uint16_t service_handle;
esp_ble_gatts_create_service(&service_uuid, 0, 5, &service_handle);
步骤 2:添加特征
cpp 复制代码
// 定义特征 UUID(心率测量)
esp_bt_uuid_t char_uuid = {
    .len = ESP_UUID_LEN_16,
    .uuid = {.uuid16 = 0x2A37}
};

// 特征权限和属性
esp_gatt_perm_t perm = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE;
esp_gatt_char_prop_t property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY;

// 添加特征
esp_err_t ret = esp_ble_gatts_add_char(
    service_handle,
    &char_uuid,
    perm,
    property,
    NULL,  // 初始值为空
    NULL   // 使用默认控制
);

if (ret != ESP_OK) {
    ESP_LOGE("GATTS", "添加特征失败: %s", esp_err_to_name(ret));
}
步骤 3:启动服务
cpp 复制代码
esp_ble_gatts_start_service(service_handle);

关键注意事项

  1. 特征描述符 (如 CCCD):
    • 若特征支持通知或指示,需手动添加客户端特征配置描述符(CCCD),使用 esp_ble_gatts_add_char_descr
  2. 回调处理
    • 特征的操作(读/写)会触发 ESP_GATTS_READ_EVTESP_GATTS_WRITE_EVT,需在 esp_ble_gatts_register_callback 中处理。
  3. 动态值更新
    • 使用 esp_ble_gatts_set_attr_value 可动态更新特征值。

错误排查

  • 无效句柄 :确保 service_handle 来自已成功创建的服务。
  • 权限冲突propertyperm 需匹配(例如,若 property 包含 ESP_GATT_CHAR_PROP_BIT_READ,则 perm 必须包含 ESP_GATT_PERM_READ)。
  • 内存不足 :检查 ESP32 的堆内存(heap_caps_get_free_size())。

完整流程示意图

cpp 复制代码
创建服务 (esp_ble_gatts_create_service)
   |
   v
添加特征 (esp_ble_gatts_add_char)
   |
   v
(可选)添加描述符 (esp_ble_gatts_add_char_descr)
   |
   v
启动服务 (esp_ble_gatts_start_service)
   |
   v
处理读写事件 (ESP_GATTS_READ_EVT / WRITE_EVT)

通过合理使用 esp_ble_gatts_add_char,可以构建符合 BLE 标准的 GATT 服务,实现数据交互。

相关推荐
摇滚侠19 分钟前
Spring Boot 3零基础教程,WEB 开发 自定义静态资源目录 笔记31
spring boot·笔记·后端·spring
摇滚侠20 分钟前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 遍历 笔记40
spring boot·笔记·thymeleaf
Chloeis Syntax1 小时前
接10月12日---队列笔记
java·数据结构·笔记·队列
QT 小鲜肉1 小时前
【个人成长笔记】Qt 中 SkipEmptyParts 编译错误解决方案及版本兼容性指南
数据库·c++·笔记·qt·学习·学习方法
Cathy Bryant2 小时前
矩阵乘以向量?向量乘以向量?
笔记·神经网络·考研·机器学习·数学建模
递归不收敛3 小时前
Conda 常用命令汇总(新手入门笔记)
笔记·conda
前端橙一陈4 小时前
Salesforce Developer Edition(开发者版) 搭建测试环境
经验分享·笔记·其他
电子小子洋酱4 小时前
BearPi小熊派 鸿蒙入门开发笔记(4)
笔记·华为·harmonyos
摇滚侠5 小时前
Spring Boot 3零基础教程,WEB 开发 通过配置类代码方式修改静态资源配置 笔记32
java·spring boot·笔记
聪明的笨猪猪6 小时前
Java JVM “内存(1)”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试