ESP32的BLE_SPP

最近在捣鼓这个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; 这个结构体如下:
//表示 UUID 的⻓长度,分 16-bit、 32-bit、 128-bit 三种。这是由于属性UUID 是通过指针进⾏行行传递的,因此需要说明⻓长度。
uint16_t uuid_length;
//表示当前属性的 UUID 的指针,⽤用户根据上⾯面的 UUID ⻓长度,从指针⾥里里⾯面读取指定⻓长度的 UUID 值。
uint8_t *uuid_p;
//表示当前属性的读写许可。该变量量为按位操作,每个⽐比特表示⼀一个特定的读写属性,对不不同⽐比特做或操作,可以表示多种读写属性。例例如PERM_READ | PERM_WRITE 表示这个属性既可读⼜又可写。
uint16_t perm;
//表示当前属性值的最⼤长度,协议栈主要根据这个变量量为该属性分配内存。如果对方写入的属性值超过这里定义的最⼤长度,即回复写错误,错误原因是写⻓度超出数据最⼤长度
uint16_t max_length;
//表示当前属性的当前实际⻓长度。
uint16_t length;
//表示当前属性的属性值初始化值。由于这个参数为指针格式,因此需要从上⾯面的 Length 获取该值的实际⻓长度,从而从指针⾥获得正确的值。
uint8_t *value;
经过以上的步骤基本上蓝牙的一些功能就已经实现了,如果想要收到蓝牙的数据要开启通知。
只要把这个属性表弄明白了,其他也就没什么难度了。以上是我对这个的理解,如有不对的地方,欢迎指教。。。。

你可能感兴趣的:(ESP32的BLE_SPP)