最近在捣鼓这个ESP32的BLE的SPP功能,把自己的心得体会写下来,如果有什么不对的地方欢迎大家来留言讨论。
首先是乐鑫官方的源码地址:
https://github.com/espressif/espidf/tree/30372f5a4ff2c0dfdaad95f544dc36bcdda30b75/examples/bluetooth/bluedroid/ble/ble_spp_server
这个模式的蓝牙是低功耗蓝牙串口传输,它的工作流程是:
1、初始化蓝牙控制器
ret = esp_bt_controller_init(&bt_cfg);
然后使能蓝牙控制器
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
这个ESP_BTMODE_BLE是使能的模式选择,可以是BLE也可以是BT还可以是两者的共存。
2、初始化蓝牙堆栈
ret = esp_bluedroid_init();
并使能堆栈
ret = esp_bluedroid_enable();
经过以上两个步骤,蓝牙就已经初始化完成了,是不是很简单。
接下来就是一些回调函数了,
这个是GATT的注册回调函数
esp_ble_gatts_register_callback(gatts_event_handler);
这个是GAP的注册回调函数
esp_ble_gap_register_callback(gap_event_handler);
注册应用APP
esp_ble_gatts_app_register(ESP_SPP_APP_ID);
这个函数执行以后蓝牙堆栈会给用户分配一个gatts_if 这个就是我们与蓝牙堆栈的操作端口,这个函数执行以后就会触发esp_ble_gatts_register_callback的ESP_GATTS_REG_EVT事件
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
ESP_LOGI(GATTS_TABLE_TAG, “EVT %d, gatts if %d\n”, event, gatts_if);
//分配一个gatts_if用于和堆栈进行连接
if (event == ESP_GATTS_REG_EVT) {
if (param->reg.status == ESP_GATT_OK) {
spp_profile_tab[SPP_PROFILE_APP_IDX].gatts_if = gatts_if;
} else {
ESP_LOGI(GATTS_TABLE_TAG, “Reg app failed, app_id %04x, status %d\n”,param->reg.app_id, param->reg.status);
return;
}
}
do {
int idx;
for (idx = 0; idx < SPP_PROFILE_NUM; idx++) {
//已经成功的分配一个gatts_if进入到回调函数里面进行操作
if (gatts_if == ESP_GATT_IF_NONE ||
gatts_if == spp_profile_tab[idx].gatts_if) {
if (spp_profile_tab[idx].gatts_cb) {
spp_profile_tab[idx].gatts_cb(event, gatts_if, param);
}
}
}
} while (0);
}
case ESP_GATTS_REG_EVT:
ESP_LOGI(GATTS_TABLE_TAG, “%s %d\n”, func, LINE);
//设置服务器的名字
esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
ESP_LOGI(GATTS_TABLE_TAG, "%s %d\n", __func__, __LINE__);
广播原始数据
esp_ble_gap_config_adv_data_raw((uint8_t *)spp_adv_data, sizeof(spp_adv_data));
ESP_LOGI(GATTS_TABLE_TAG, "%s %d\n", __func__, __LINE__);
创建属性表
esp_ble_gatts_create_attr_tab(spp_gatt_db, gatts_if, SPP_IDX_NB, SPP_SVC_INST_ID);
当执行完这个广播原始数据以后会触发gap的回调函数:
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
//gap开始广播
esp_ble_gap_start_advertising(&spp_adv_params);
break;
这样你的手机就可以搜索到这个设备了。
剩下的就是一些读和写事件了
ESP_GATTS_WRITE_EVT
ESP_GATTS_READ_EVT
这些都没什么好说的就是一些读写操作,它的读写数据都存在一个共用体里面,蓝牙堆栈为每一个事件都定义了一个共用体,到时间需要哪个数据直接操作esp_ble_gatts_cb_param_t这个共用体里面的数据就行了。
这一步的重要的是创建这个属性表,官方的文档是这样解释的:
https://github.com/espressif/esp-idf/blob/30372f5a4/examples/bluetooth/bluedroid/ble/gatt_server_service_table/tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md
这个属性表就是一个结构体数组,定义:
esp_attr_control_t attr_control; //这个变量定义的意思为是你的程序回应还是有蓝牙堆栈自动回应
esp_attr_desc_t att_desc; 这个结构体如下:
uint16_t uuid_length; /UUID的长度 /
uint8_t uuid_p; /!< UUID 的值 /
uint16_t perm; /!< 属性的权限,是读,写还是通知 /
uint16_t max_length; /!<定义最大长度/
uint16_t length; /!< 当前服务的长度/
uint8_t value; /!< 元素值数组*/
经过以上的步骤基本上蓝牙的一些功能就已经实现了,如果想要收到蓝牙的数据要开启通知。
只要把这个属性表弄明白了,其他也就没什么难度了。以上是我对这个的理解,如有不对的地方,欢迎指教。。。。
来源:CSDN
作者:liumengyang1992
链接:https://blog.csdn.net/liumengyang1992/article/details/103728188