ESP32蓝牙开发笔记(十四)
在 ESP32 的 BLE 开发中,esp_ble_gatts_add_char 是用于向 GATT 服务中添加特征(Characteristic)的核心函数。以下是该函数的详细说明、参数解析及示例代码:
函数原型
esp_err_t esp_ble_gatts_add_char(uint16_t service_handle,                  // 服务句柄(由添加服务时返回)esp_bt_uuid_t *char_uuid,                  // 特征的 UUIDesp_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_service或esp_ble_gatts_add_service创建服务后返回的句柄。 - 作用:指定特征所属的服务。
 
2. char_uuid(特征 UUID)
 
- 类型:
esp_bt_uuid_t,可以是 16-bit、32-bit 或 128-bit UUID。 - 示例: 
// 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,特征值初始为空。 - 示例: 
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。 - 示例: 
esp_attr_control_t control = {.auto_rsp = ESP_GATT_AUTO_RSP // 自动响应读/写请求 }; 
返回值
ESP_OK:特征添加成功。- 其他错误码:失败(如无效句柄、内存不足等)。
 
示例代码
步骤 1:创建服务
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:添加特征
// 定义特征 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:启动服务
esp_ble_gatts_start_service(service_handle); 
关键注意事项
- 特征描述符(如 CCCD): 
- 若特征支持通知或指示,需手动添加客户端特征配置描述符(CCCD),使用 
esp_ble_gatts_add_char_descr。 
 - 若特征支持通知或指示,需手动添加客户端特征配置描述符(CCCD),使用 
 - 回调处理: 
- 特征的操作(读/写)会触发 
ESP_GATTS_READ_EVT或ESP_GATTS_WRITE_EVT,需在esp_ble_gatts_register_callback中处理。 
 - 特征的操作(读/写)会触发 
 - 动态值更新: 
- 使用 
esp_ble_gatts_set_attr_value可动态更新特征值。 
 - 使用 
 
错误排查
- 无效句柄:确保 
service_handle来自已成功创建的服务。 - 权限冲突:
property和perm需匹配(例如,若property包含ESP_GATT_CHAR_PROP_BIT_READ,则perm必须包含ESP_GATT_PERM_READ)。 - 内存不足:检查 ESP32 的堆内存(
heap_caps_get_free_size())。 
完整流程示意图
创建服务 (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 服务,实现数据交互。
