娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

ESP32學習筆記(32)——BLE GAP主機端連接

發布者:EnchantedDreams最新更新時間:2025-02-27 來源: jianshu關鍵字:ESP32  BLE  GAP 手機看文章 掃描二維碼
隨時隨地手機看文章

一、背景

1.1 低功耗藍牙(BLE)協議棧



鏈路層(LL) 控制設備的射頻狀態,有五個設備狀態:待機、廣播、掃描、初始化和連接。


廣播 為廣播數據包,而 掃描 則是監聽廣播。

GAP通信中角色,中心設備(Central - 主機) 用來掃描和連接 外圍設備(Peripheral - 從機)。

1.2 BLE從初始化到建立連接的過程

  1. 外圍設備開始廣播,發送完一個廣播包后T_IFS,開啟射頻Rx窗口接收來自中心設備的數據包

  2. 中心設備掃描到廣播,在收取此廣播T_IFS后如果開啟了中心設備的掃描回復,中心設備將向外設發送回復

  3. 外設收取到中心設備的回復,做好接收準備,并返回ACK包

  4. 如果ACK包未被中心設備接收到,中心設備將一直發送回復直到超時,此期間內只要外設返回過一次ACK包就算連接成功

  5. 開始建立通信,后續中心設備將以收取到外設廣播的時間為原點,以Connection Interval為周期向外設發送數據包,數據包將具有兩個作用:同步兩設備時鐘和建立主從模式通信

外設每收到中心設備的一個包,就會把自己的時序原點重新設置,以和中心設備同步(Service向Client同步)

BLE通信在建立成功后變為主從模式,中心設備Central變為Master,外設Peripheral變為Slave,Slave只能在Master向它發送了一個包以后才能在規定的時間內把自己的數據回傳給Master

  1. 連接建立成功

  2. 外設自動停止廣播,其他設備無法再查找到該外設

  3. 按照以下時序進行通信,在中心設備發送包的間隔內,外設可以發送多個包

  1. 需要連接斷開時只需要中心設備停止連接(停止發送包)即可

  2. 中心設備可以將外設的addr寫入Flash或SRAM等存儲器件,保持監聽此addr,當再次收到外設廣播時就可以建立通信。BLE Server設備為了省電,當一段時間內沒有數據要發送時,可以不再發送包,雙方就會因為連接超時(connection timeout)斷開,這時需要中心設備啟動監聽,這樣,當BLE Server設備需要發送數據時,就可以再次連接

1.3 ESP32藍牙應用結構

藍牙是?種短距通信系統,其關鍵特性包括魯棒性、低功耗、低成本等。藍牙系統分為兩種不同的技術:經典藍牙 (Classic Bluetooth) 和藍牙低功耗 (Bluetooth Low Energy)。
ESP32 支持雙模藍牙,即同時支持經典藍牙和藍牙低功耗。

從整體結構上,藍牙可分為控制器 (Controller) 和主機 (Host) 兩?部分:控制器包括了 PHY、Baseband、Link Controller、Link Manager、Device Manager、HCI 等模塊,用于硬件接?管理、鏈路管理等等;主機則包括了 L2CAP、SMP、SDP、ATT、GATT、GAP 以及各種規范,構建了向應用層提供接口的基礎,方便應用層對藍牙系統的訪問。主機可以與控制器運行在同?個宿主上,也可以分布在不同的宿主上。ESP32 可以支持上述兩種方式。

1.4 Bluedroid主機架構

在 ESP-IDF 中,使用經過大量修改后的 BLUEDROID 作為藍牙主機 (Classic BT + BLE)。BLUEDROID 擁有較為完善的功能,?持常用的規范和架構設計,同時也較為復雜。經過大量修改后,BLUEDROID 保留了大多數 BTA 層以下的代碼,幾乎完全刪去了 BTIF 層的代碼,使用了較為精簡的 BTC 層作為內置規范及 Misc 控制層。修改后的 BLUEDROID 及其與控制器之間的關系如下圖:

二、API說明

以下控制器和虛擬 HCI 接口位于 bt/include/esp32/include/esp_bt.h。

2.1 esp_bt_controller_mem_release

2.2 esp_bt_controller_init

2.3 esp_bt_controller_enable



以下 GAP 接口位于 bt/host/bluedroid/api/include/api/esp_bt_main.h 和 bt/host/bluedroid/api/include/api/esp_gap_ble_api.h。


2.4 esp_bluedroid_init

2.5 esp_bluedroid_enable

2.6 esp_ble_gap_register_callback

2.7 esp_ble_gap_set_scan_params

2.8 esp_ble_gap_start_scanning

2.9 esp_ble_gap_stop_scanning

2.10 esp_ble_resolve_adv_data

2.11 esp_ble_gap_disconnect

以下 GATT 接口位于 bt/host/bluedroid/api/include/api/esp_gattc_api.h

2.12 esp_ble_gattc_open

2.13 esp_ble_gattc_close

三、BT控制器和協議棧初始化

使用 esp-idfexamplesbluetoothbluedroidblegatt_client 中的例程


.........//esp_bt_controller_config_t是藍牙控制器配置結構體,這里使用了一個默認的參數

    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();

    //初始化藍牙控制器,此函數只能被調用一次,且必須在其他藍牙功能被調用之前調用

    ret = esp_bt_controller_init(&bt_cfg);

    if (ret) {

        ESP_LOGE(GATTC_TAG, '%s initialize controller failed: %sn', __func__, esp_err_to_name(ret));

        return;

    }


    //使能藍牙控制器,mode是藍牙模式,如果想要動態改變藍牙模式不能直接調用該函數,

    //應該先用disable關閉藍牙再使用該API來改變藍牙模式

    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);

    if (ret) {

        ESP_LOGE(GATTC_TAG, '%s enable controller failed: %sn', __func__, esp_err_to_name(ret));

        return;

    }

    //初始化藍牙并分配系統資源,它應該被第一個調用

    /*

    藍牙棧bluedroid stack包括了BT和BLE使用的基本的define和API

    初始化藍牙棧以后并不能直接使用藍牙功能,

    還需要用FSM管理藍牙連接情況

    */

    ret = esp_bluedroid_init();

    if (ret) {

        ESP_LOGE(GATTC_TAG, '%s init bluetooth failed: %sn', __func__, esp_err_to_name(ret));

        return;

    }

    //使能藍牙棧

    ret = esp_bluedroid_enable();

    if (ret) {

        ESP_LOGE(GATTC_TAG, '%s enable bluetooth failed: %sn', __func__, esp_err_to_name(ret));

        return;

    }


    //建立藍牙的FSM(有限狀態機

    //這里使用回調函數來控制每個狀態下的響應,需要將其在GATT和GAP層的回調函數注冊

    /*esp_gattc_cb和esp_gap_cb處理藍牙棧可能發生的所有情況,達到FSM的效果*/

    ret = esp_ble_gap_register_callback(esp_gap_cb);

    if (ret){

        ESP_LOGE(GATTC_TAG, '%s gap register failed, error code = %xn', __func__, ret);

        return;

    }

    ret = esp_ble_gattc_register_callback(esp_gattc_cb);

    if(ret){

        ESP_LOGE(GATTC_TAG, '%s gattc register failed, error code = %xn', __func__, ret);

        return;

    }


    //下面創建了BLE GATT服務A,相當于1個獨立的應用程序

    ret = esp_ble_gattc_app_register(PROFILE_A_APP_ID);

    if (ret){

        ESP_LOGE(GATTC_TAG, '%s gattc app register failed, error code = %xn', __func__, ret);

    }

    /*

    設置了MTU的值(經過MTU交換,從而設置一個PDU中最大能夠交換的數據量)。

    例如:主設備發出一個1000字節的MTU請求,但是從設備回應的MTU是500字節,那么今后雙方要以較小的值500字節作為以后的MTU。

    即主從雙方每次在做數據傳輸時不超過這個最大數據單元。

    */

    esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500);

    if (local_mtu_ret){

        ESP_LOGE(GATTC_TAG, 'set local  MTU failed, error code = %x', local_mtu_ret);

    }.......

四、應用程序配置文件

應用程序配置文件是為一個或多個服務器應用程序設計的功能進行分組的一種方法。例如,可以將應用程序配置文件連接到心率傳感器,并將另一個應用程序配置文件連接到溫度傳感器。每個應用程序配置文件創建一個GATT接口以連接到其他設備。代碼中的應用程序配置文件是gattc_profile_inst結構的實例,其定義如下:


struct gattc_profile_inst {

    esp_gattc_cb_t gattc_cb;

    uint16_t gattc_if;

    uint16_t app_id;

    uint16_t conn_id;

    uint16_t service_start_handle;

    uint16_t service_end_handle;

    uint16_t char_handle;

    esp_bd_addr_t remote_bda;};

結構包括:


gattc_cb:GATT客戶端回調函數


gattc_if:此配置文件的GATT客戶端接口號


app_id:應用程序配置文件ID號


conn_id:連接ID號


service_start_handle:服務頭部句柄


service_end_handle:服務末尾句柄


char_handle:特征句柄


remote_bda:連接到此客戶端的遠程設備地址


本例中有一個應用程序配置文件,其ID定義為:


#define PROFILE_NUM 1#define PROFILE_A_APP_ID 0

應用程序配置文件存儲在gl_profile_tab數組中,并分配相應的回調函數gattc_profile_a_event_handler()。GATT 客戶端上的不同應用程序使用不同的接口,由 gattc_if 參數表示。對于初始化,此參數設置為ESP_GATT_IF_NONE,這意味著應用程序配置文件尚未鏈接到任何服務端。


/* One gatt-based profile one app_id and one gattc_if, this array will store the gattc_if returned by ESP_GATTS_REG_EVT */static struct gattc_profile_inst gl_profile_tab[PROFILE_NUM] = {

        [PROFILE_A_APP_ID] = {.gattc_cb = gattc_profile_event_handler,

                                  .gattc_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */

    },};

應用程序配置文件注冊觸發ESP_GATTC_REG_EVT事件,該事件由esp_gattc_cb()事件處理程序處理。處理程序獲取事件返回的GATT接口,并將其存儲在profile表中:


static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param){

    ESP_LOGI(GATTC_TAG, 'EVT %d, gattc if %d', event, gattc_if);


    /* If event is register event, store the gattc_if for each profile */

    if (event == ESP_GATTC_REG_EVT) {

        if (param->reg.status == ESP_GATT_OK) {

            gl_profile_tab[param->reg.app_id].gattc_if = gattc_if;

        } else {

            ESP_LOGI(GATTC_TAG, 'reg app failed, app_id %04x, status %d',

                    param->reg.app_id,

                    param->reg.status);

            return;

        }

    }…

最后,回調函數調用gl_profile_tab表中每個配置文件的相應事件處理程序。


…/* If the gattc_if equal to profile A, call profile A cb handler,

     * so here call each profile's callback */

    do {

        int idx;

        for (idx = 0; idx < PROFILE_NUM; idx++) {

            if (gattc_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */

                    gattc_if == gl_profile_tab[idx].gattc_if) {

                if (gl_profile_tab[idx].gattc_cb) {

                    gl_profile_tab[idx].gattc_cb(event, gattc_if, param);

                }

            }

        }

    } while (0);}


五、獲取掃描結果

啟動掃描吼,掃描結果在到達ESP_GAP_BLE_SCAN_RESULT_EVT事件時立即顯示,該事件包括以下參數:


    /**

     * @brief ESP_GAP_BLE_SCAN_RESULT_EVT

     */

    struct ble_scan_result_evt_param {

        esp_gap_search_evt_t search_evt;            /*!< Search event type */

        esp_bd_addr_t bda;                          /*!< Bluetooth device address which has been searched */

        esp_bt_dev_type_t dev_type;                 /*!< Device type */

        esp_ble_addr_type_t ble_addr_type;          /*!< Ble device address type */

        esp_ble_evt_type_t ble_evt_type;            /*!< Ble scan result event type */

        int rssi;                                   /*!< Searched device's RSSI */

        uint8_t  ble_adv[ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX]; /*!< Received EIR */

        int flag;                                   /*!< Advertising data flag bit */

        int num_resps;                              /*!< Scan result number */

        uint8_t adv_data_len;                       /*!< Adv data length */

[1] [2]
關鍵字:ESP32  BLE  GAP 引用地址:ESP32學習筆記(32)——BLE GAP主機端連接

上一篇:ESP32學習筆記(33)——BLE GATT客戶端發現服務和讀寫特征值
下一篇:ESP32學習筆記(31)——BLE帶有屬性表的GATT服務

推薦閱讀最新更新時間:2025-06-09 10:39

ESP32玩轉MicroPython(一) 燒入固件, 初識
一. 下載ESP32的Flash工具 https://www.espressif.com/zh-hans/support/download/other-tools 二. 下載esp32的micropython固件 http://www.micropython.org/download/esp32/ 請下載: esp32-idf3-20180511-v1.9.4.bin這個版本 三. 將固件燒入flash中 參數設置如下: 擦除flash 擦除完成后點擊start下載固件 四. 下載esplorer https://esp8266.ru/esplorer/ (官方英文版) https://blog.csdn.n
[單片機]
ESP32學習筆記(36)——BluFi(藍牙配網)接口使用
一、簡介 ESP32 的 BluFi 是通過藍牙通道的 Wi-Fi 網絡配置功能。它提供了一個安全協議來將 Wi-Fi 配置和憑據傳遞給 ESP32。使用這些信息,ESP32 可以連接到一個 AP 或建立一個 SoftAP。 BluFi 層中的分片、數據加密、校驗和驗證是此過程的關鍵要素。 您可以自定義對稱加密、非對稱加密和校驗和支持自定義。這里我們使用DH算法進行密鑰協商,128-AES算法進行數據加密,CRC16算法進行校驗和驗證。 二、BluFi流程 將 ESP32 設置為 GATT Server 模式,然后它將發送帶有特定廣告數據的廣播。您可以根據需要自定義此廣播,這不是 BluFi 配置文件的一部分。 使用安
[單片機]
ESP32、GD32、STM32MCU的區別
01 前言 STM32:意法半導體在 2007 年 6 月 11 日發布的產品,32位單片機。 GD32:兆易創新 2013 年發布的產品,在芯片開發、配置、命名上基本模仿 STM32,甚至 GPIO 和 STM32 都是 pin to pin 的,封裝不改焊上去直接用。有時候 STM32 的源碼不修改,重新編譯燒寫到 GD32 上就可以跑。當然也有很多不同,比如串口驅動、USB 、庫文件等。 ESP32:樂鑫公司 2017 年開發的產品,和 STM32、GD32 不同,ESP32 主要面向物聯網領域,支持功能很多,但引出 GPIO pin 腳很少,因此大多數 GPIO 都有很多復用功能。出廠就集成藍牙、WiFi 等物聯網必備功
[單片機]
<font color='red'>ESP32</font>、GD32、STM32MCU的區別
賽普拉斯PSoC 6 BLE以低功耗,高靈活性獲得IoT技術創新獎
專為IoT產品設計的雙核處理平臺PSoC 6 BLE是當前業內功耗最低、靈活性最高且內置安全功能的MCU 日前,以“新物聯 智世界”為主題的2019年度第六屆中國IoT大會在深圳落下帷幕。大會由電子科技領域專業媒體電子發燒友主辦,匯聚物聯網領域業界精英,共話產業創新機遇。會上同期揭曉了第四屆中國IoT創新獎的評選結果。其中,賽普拉斯半導體技術有限公司 憑借專為IoT產品設計的雙核處理平臺PSoC 6 BLE一舉摘獲IoT技術創新獎。 據悉,此次IoT技術創新獎評選綜合考量參評產品在物聯網相關產品市場的創新價值,與同行友商類似產品相比的競爭優勢,以及對提升用戶產品關鍵指標、改善用戶服務質量的作用。通過網絡實名投票與專家評審相
[嵌入式]
賽普拉斯PSoC 6 <font color='red'>BLE</font>以低功耗,高靈活性獲得IoT技術創新獎
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 土默特左旗| 西贡区| 嘉定区| 三门峡市| 壤塘县| 安阳市| 宜城市| 朝阳县| 潞城市| 临武县| 武川县| 乌什县| 新乡县| 宣恩县| 天津市| 抚远县| 迁安市| 长治县| 山东| 阜城县| 微山县| 葵青区| 阿勒泰市| 逊克县| 无极县| 彩票| 乌什县| 盐津县| 黔南| 长武县| 社旗县| 汝南县| 滦平县| 清水河县| 彰化县| 榆林市| 天峨县| 含山县| 阳高县| 武鸣县| 宝应县|