日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ESP32 VHCI实现BLE广播,就是这么神奇

發(fā)布時(shí)間:2024/1/1 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ESP32 VHCI实现BLE广播,就是这么神奇 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

零. 聲明


本專欄文章我們會(huì)以連載的方式持續(xù)更新,本專欄計(jì)劃更新內(nèi)容如下:

第一篇:ESP-IDF基本介紹,主要會(huì)涉及模組,芯片,開發(fā)板的介紹,環(huán)境搭建,程序編譯下載,啟動(dòng)流程等一些基本的操作,讓你對(duì)ESP-IDF開發(fā)有一個(gè)總體的認(rèn)識(shí),比我們后續(xù)學(xué)習(xí)打下基礎(chǔ)!

第二篇:ESP32-IDF外設(shè)驅(qū)動(dòng)介紹,主要會(huì)根據(jù)esp-idf現(xiàn)有的driver,提供各個(gè)外設(shè)的驅(qū)動(dòng),比如LED,OLED,SPI LCD,TOUCH,紅外,Codec ic等等,在這一篇中,我們不僅僅來做外設(shè)驅(qū)動(dòng),還會(huì)對(duì)常用的外設(shè)總線做一個(gè)介紹,讓大家知其然又知其所以然!

第三篇:目前比較火熱的GUI LVGL介紹,主要會(huì)設(shè)計(jì)LVGL7.1,LVGL8的移植介紹,并且也會(huì)介紹各個(gè)組件,知道原理后,最后,我們會(huì)推出一款組態(tài)軟件來構(gòu)建我們的GUI,來提升我們的效率!

第四篇:ESP32-藍(lán)牙,熟悉我的,應(yīng)該都知道,我即使從事藍(lán)牙協(xié)議棧的開發(fā)的,所以這個(gè)是我們獨(dú)有的優(yōu)勢(shì),在這一篇章,我們會(huì)提供不僅僅是藍(lán)牙應(yīng)用方法的知識(shí),也會(huì)應(yīng)用結(jié)合藍(lán)牙底層協(xié)議棧的理論,讓你徹底從上到下打通藍(lán)牙任督二脈!

第五篇:Wi-Fi介紹,熟悉我的,應(yīng)該也知道,我們也做過一款sdio wifi的驅(qū)動(dòng)教程板子,所以在wifi這方面我們也是有獨(dú)有的優(yōu)勢(shì),在這一篇章,我們同樣不僅僅提供Wi-Fi應(yīng)用方面的知識(shí),也會(huì)結(jié)合底層理論,讓你對(duì)Wi-Fi有一個(gè)清晰的認(rèn)知!

另外,我們的教程包括但是不局限于以上篇章,為了給你一個(gè)更好的導(dǎo)航,以下信息尤其重要,請(qǐng)?jiān)敿?xì)查看!!

------------------------------------------------------------------------------------------------------------------------------------------

購買開發(fā)板(點(diǎn)擊我)

ESP32系列文章目錄(點(diǎn)擊我)

Github代碼倉庫(點(diǎn)擊我)

藍(lán)牙交流扣扣群:539357317

微信公眾號(hào)↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

????

------------------------------------------------------------------------------------------------------------------------------------------

一. 整體介紹

此文章主要介紹基于ESP32 VHCI的架構(gòu)實(shí)現(xiàn)BLE的搜索,也就是不使用默認(rèn)的Host API,自己編寫一部分代碼來實(shí)現(xiàn)功能,具體ESP32的架構(gòu)如下圖所示:

那我們做的事情是什么呢?我們相當(dāng)于把默認(rèn)的Host拿掉,也就是如圖所示的bluedroid部分,寫Host部分的廣播實(shí)現(xiàn)

此文章算是熟悉一個(gè)VHCI的開發(fā)模式,不管對(duì)于默認(rèn)的Host(Bluedroid/nimble)甚至自己移植進(jìn)來一個(gè)Host都有很大的幫助,我就算起到一個(gè)拋磚引玉的作用吧!

二. menuconfig實(shí)現(xiàn)

我們雖然不用ESP32的默認(rèn)Host,但是我們要用他默認(rèn)的Controller,所以還是要配置一下的,一共三個(gè)地方需要特別留意一下,其他保持默認(rèn),如下圖所示:

1.Bluetooth controller mode

2.HCI mode

3.bluetooth Host

三. 程序?qū)崿F(xiàn)

1.初始化NVS

/* Initialize NVS — it is used to store PHY calibration data */ esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init(); } ESP_ERROR_CHECK( ret );

這一段必須要加上,主要是用于存儲(chǔ)PHY的信息,否則無法正常使用controller

2.初始化controller,注冊(cè)Controller的callback函數(shù)實(shí)現(xiàn)

esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();ret = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); if (ret) {ESP_LOGI(TAG, "Bluetooth controller release classic bt memory failed: %s", esp_err_to_name(ret));return; }if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {ESP_LOGI(TAG, "Bluetooth controller initialize failed: %s", esp_err_to_name(ret));return; }if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) {ESP_LOGI(TAG, "Bluetooth controller enable failed: %s", esp_err_to_name(ret));return; }esp_vhci_host_register_callback(&vhci_host_cb);

此段我們?cè)诮榻Besp32 controller api的時(shí)候已經(jīng)詳細(xì)介紹,看API名字也知道主要在做什么事情,沒什么難度,我們來看下注冊(cè)給controller的callback的實(shí)現(xiàn)

static void controller_rcv_pkt_ready(void) {printf("controller rcv pkt ready\n"); }static int host_rcv_pkt(uint8_t *data, uint16_t len) {printf("host rcv pkt: ");for (uint16_t i = 0; i < len; i++) {printf("0x%02x ", data[i]);}printf("\n");return 0; }static esp_vhci_host_callback_t vhci_host_cb = {controller_rcv_pkt_ready,host_rcv_pkt };

以上代碼,我們接受到數(shù)據(jù),并沒有做什么事情,只是打印下數(shù)據(jù)的hex而已!

3.實(shí)現(xiàn)HCI 的廣播

while (1) {bool send_avail = false;vTaskDelay(1000 / portTICK_PERIOD_MS);send_avail = esp_vhci_host_check_send_available();if (send_avail) {switch (cmd_cnt) {case 0: hci_cmd_send_reset(); ++cmd_cnt; break;case 1: hci_cmd_send_ble_set_adv_param(); ++cmd_cnt; break;case 2: hci_cmd_send_ble_set_adv_data(); ++cmd_cnt; break;case 3: hci_cmd_send_ble_adv_start(); ++cmd_cnt; break;}}printf("BLE Advertise, flag_send_avail: %d, cmd_sent: %d\n", send_avail, cmd_cnt); }

在代碼中,我們不去解析hci event的parse,只是一個(gè)個(gè)命令的發(fā)送hci command來實(shí)現(xiàn)廣播,此部分也是我們本文章的重點(diǎn),下面我就來一一詳細(xì)介紹下

3.1 hci廣播的流程

如果不考慮整個(gè)藍(lán)牙Host的健壯性以及可用性,只考慮用ESP32 VHCI架構(gòu)實(shí)現(xiàn)BLE廣播功能,那么其實(shí)4個(gè)步驟就能實(shí)現(xiàn),分別如下:

1) 發(fā)送HCI reset command

2) 發(fā)送ble set adv param,也就是設(shè)置廣播的參數(shù)

3) 發(fā)送ble set adv data,也就是設(shè)置廣播的數(shù)據(jù)

4) 發(fā)送ble adv start command,也就是開啟廣播

在后面的小節(jié)我們?cè)僖灰唤榻B下每個(gè)command的格式以及作用!

3.2 hci command的格式

我們知道了步驟,并且知道了發(fā)送哪些command,但是command的格式是什么呢?那么這個(gè)算是一個(gè)比較大的話題,牽扯到藍(lán)牙core spec hci章節(jié)的內(nèi)容,我們本章本著應(yīng)用文章,此部門我們簡單的一筆帶過,如果想徹底了解內(nèi)部原理,那么我建議你看下這兩篇文章:

藍(lán)牙HCI command/event/acl/sco格式介紹_Wireless_Link的博客-CSDN博客

藍(lán)牙傳輸介質(zhì)Transport UART H4(RS232)介紹_Wireless_Link的博客-CSDN博客_藍(lán)牙通過什么介質(zhì)傳輸

以上兩篇文章,分別介紹H4以及HCI的格式,好了,我們回歸主題來介紹下HCI command的格式。

Opcode:每個(gè)命令被分配一個(gè)2字節(jié)的操作碼(opcode),用來唯一地識(shí)別不同類型的命令,操作碼(opcode)參數(shù)分為兩個(gè)字段,稱為操作碼組字段(Opcode Group Field, OGF)和操作碼命令字段(Opcode Command Field, OCF)。其中OGF占用高6bit字節(jié),OCF占用低10bit字節(jié)。

一共有以下幾組OGF:

1)Link Control commands, the OGF is defined as 0x01.鏈路控制OGF,也就是控制藍(lán)牙芯片跟remote溝通的命令

2)Link Policy commands, the OGF is defined as 0x02,鏈路策略O(shè)GF,也就是寫一些Policy,比如轉(zhuǎn)換角色等

3)HCI Control and Baseband commands, the OGF is defined as 0x03,控制本地芯片跟基帶的OGF。比如reset本地芯片等。

4)Informational Parameters commands, the OGF is defined as 0x04。讀取信息的OGF,比如讀取本地芯片的LMP版本呢,支持的command,藍(lán)牙地址等,

5)status parameters commands, the OGF is defined as 0x05,狀態(tài)參數(shù)OGF,比如讀取RSSI等。

6)Testing commands, the OGF is defined as 0x06,測(cè)試命令的OGF,比如讓芯片進(jìn)入測(cè)試模式(DUT,device under test)

7)LE Controller commands, the OGF code is defined as 0x08,BLE 的comand

8)vendor-specific debug commands,the OGF code is defined as 0x3F,此部分是vendor定義的,也就是芯片廠商為了擴(kuò)展core文檔的HCI command定義

OCF眾多,在每個(gè)OGF下都有一堆的OCF定義

Parameter Total Length:后續(xù)參數(shù)的長度

Parameter:每個(gè)command的para不同

3.3 hci reset命令

hci command的命令如下:

OGF是0x03,OCF是0x03

hci reset作用如下:

The HCI_Reset command willreset the Controller and the Link Manager on the BR/EDR Controller or the Link Layer on an LE Controller. If the Controller supports both BR/EDR and LEthen the HCI_Reset command shall reset the Link Manager, Baseband and Link Layer. The HCI_Reset command shall not affect the used HCI transport layer since the HCI transport layers may have reset mechanisms of their own. After the reset is completed, the current operational state will be lost, the Controller will enter standby mode and the Controller will automatically revert to the default values for the parameters for which default values are defined in the specification.

Note: The HCI_Reset command will not necessarily perform a hardware reset. This is implementation defined.

The Host shall not send additional HCI commands before the HCI_Command_Complete event related to the HCI_Reset command has been received。

函數(shù)實(shí)現(xiàn)如下:

/* HCI Command Opcode group Field (OGF) */ #define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10) /* 0x0C00 */ #define HCI_GRP_BLE_CMDS (0x08 << 10)/* HCI Command Opcode Command Field (OCF) */ #define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)uint16_t make_cmd_reset(uint8_t *buf) {UINT8_TO_STREAM (buf, H4_TYPE_COMMAND);UINT16_TO_STREAM (buf, HCI_RESET);UINT8_TO_STREAM (buf, 0);return HCI_H4_CMD_PREAMBLE_SIZE; } static void hci_cmd_send_reset(void) {uint16_t sz = make_cmd_reset (hci_cmd_buf);esp_vhci_host_send_packet(hci_cmd_buf, sz); }

組成的數(shù)據(jù)格式是:0x01 ,0x03 0x0c 0x00

3.4 hci set adv param命令

hci command的格式如下:

OGF=0x08,OCF=0x06

我們來看下這個(gè)command的格式:

這個(gè)命令是設(shè)置廣播的參數(shù),其中參數(shù)如下:

Advertising_Interval_Min:廣播的最小間隔

Advertising_Interval_Max:廣播的最大間隔

設(shè)備每次廣播時(shí),會(huì)在3個(gè)廣播信道上(根據(jù)設(shè)置的channel map而決定哪個(gè)信道)發(fā)送相同的報(bào)文。這些報(bào)文被稱為一個(gè)廣播事件。除了定向報(bào)文以外,其他廣播事件均可以選擇“20ms ~ 10.24s”不等的間隔。兩個(gè)相鄰廣播事件之間的時(shí)間稱為廣播間隔。

但是,設(shè)備周期性的發(fā)送廣播會(huì)有一個(gè)問題:由于設(shè)備間的時(shí)鐘會(huì)不同程度的漂移,兩個(gè)設(shè)備可能在很長一段時(shí)間同時(shí)廣播而造成干擾。為防止這一情況的發(fā)生,除定向廣播之外的其他廣播類型,發(fā)送時(shí)間均會(huì)被擾動(dòng)。實(shí)現(xiàn)該擾動(dòng)的方式為,在上一次廣播事件后加入“0 ~ 10ms”的隨機(jī)延時(shí)。這意味著,即使兩個(gè)設(shè)備廣播間隔相同,并在相同信道及時(shí)間點(diǎn)上發(fā)送造成了沖突,但它們發(fā)送下一個(gè)廣播事件時(shí)也會(huì)有很大可能不再?zèng)_突。

所以,兩個(gè)相鄰的廣播事件的之間的時(shí)間間隔(T_advEvent)為:T_AdvEvent = advInterval + advDelay

其中,advInterval 必須是“0.625ms”的整數(shù)倍,范圍是“20ms ~ 10.24s”之間。對(duì)于可掃描非定向廣播和不可連接非定向廣播這兩種廣播類型,該值最好不小于100ms,即(160個(gè)0.625ms)。advDelay是Link Layer(鏈接層)分配的一個(gè)偽隨機(jī)數(shù),它的范圍為“0 ~ 10ms”。

廣播包的截圖如下:

當(dāng)然,實(shí)際設(shè)置過程中沒有廣播間隔參數(shù),而是設(shè)置Advertising_Interval_Min(最小廣播間隔)和Advertising_Interval_Max(最大廣播間隔)這兩個(gè)參數(shù)來調(diào)整廣播間隔,它們都是以“0.625ms”為單位,如果要固定廣播間隔為某一個(gè)值,只需要將這兩個(gè)參數(shù)設(shè)置為同一個(gè)有效數(shù)值即可。

Advertising_Type:廣播類型

一共分為四種廣播類型:

1)可連接的非定向廣播(Connectable Undirected Event Type):這是一種用途最廣的廣播類型,包括廣播數(shù)據(jù)和掃描響應(yīng)數(shù)據(jù),它表示當(dāng)前設(shè)備可以接受其他任何設(shè)備的連接請(qǐng)求。

鑒于此種廣播類型用的最多,下面我們來討論一下此類型下廣播事件中廣播包的發(fā)送情況,另外要注意在一個(gè)廣播事件中,前一個(gè)“ADV_IND PDUs”的開始到相鄰的下一個(gè)“ADV_IND PDUs”的開始處的時(shí)間要小于等于 10ms :

第一種情況:僅僅有廣播 PDUs 。截圖顯示如下:

第二種情況:在廣播事件的中間有“SCAN_REQ”和“SCAN_RSP PDUs”。截圖顯示如下:

第三種情況:在廣播事件的結(jié)尾有“SCAN_REQ”和“SCAN_RSP PDUs”。截圖顯示如下:

第四種情況:在廣播事件的中間接收到“CONNECT_REQ PDU”的情況。截圖顯示如下:

此情況下,廣播事件會(huì)關(guān)閉,不會(huì)繼續(xù)在下一個(gè)信道上廣播。

2)可連接的定向廣播(Connectable Directed Event Type):定向廣播類型是為了盡可能快的建立連接。這種報(bào)文包含兩個(gè)地址:廣播者的地址和發(fā)起者的地址。發(fā)起者收到發(fā)給自己的定向廣播報(bào)文之后,可以立即發(fā)送連接請(qǐng)求作為回應(yīng)。

定向廣播類型有特殊的時(shí)序要求。完整的廣播事件必須每3.75ms重復(fù)一次。這一要求使得掃描設(shè)備只需掃描3.75ms便可以收到定向廣播設(shè)備的消息。

當(dāng)然,如此快的發(fā)送會(huì)讓報(bào)文充斥著廣播信道,進(jìn)而導(dǎo)致該區(qū)域內(nèi)的其他設(shè)備無法進(jìn)行廣播。因此,定向廣播不可以持續(xù)1.28s以上的時(shí)間。如果主機(jī)沒有主動(dòng)要求停止,或者連接沒有建立,控制器都會(huì)自動(dòng)停止廣播。一旦到了1.28s,主機(jī)便只能使用間隔長得多的可連接非定向廣播讓其他設(shè)備來連接。

當(dāng)使用定向廣播時(shí),設(shè)備不能被主動(dòng)掃描。此外,定向廣播報(bào)文的凈荷中也不能帶有其他附加數(shù)據(jù)。該凈荷只能包含兩個(gè)必須的地址。

3)不可連接的非定向廣播(Non-connectable Undirected Event Type):僅僅發(fā)送廣播數(shù)據(jù)。

4)可掃描的非定向廣播(Scannable Undirected Event Type):這種廣播不能用于發(fā)起連接,但允許其他設(shè)備掃描該廣播設(shè)備。這意味著該設(shè)備可以被發(fā)現(xiàn),既可以發(fā)送廣播數(shù)據(jù),也可以響應(yīng)掃描發(fā)送掃描回應(yīng)數(shù)據(jù),但不能建立連接。這是一種適用于廣播數(shù)據(jù)的廣播形式,動(dòng)態(tài)數(shù)據(jù)可以包含于廣播數(shù)據(jù)之中,而靜態(tài)數(shù)據(jù)可以包含于掃描響應(yīng)數(shù)據(jù)之中。

注意:所謂的定向和非定向針對(duì)的是廣播的對(duì)象,如果是針對(duì)特定的對(duì)象進(jìn)行廣播(在廣播包PDU中會(huì)包含目標(biāo)對(duì)象的MAC)就是定向廣播,反之就是非定向??蛇B接和不可連接是指是否接受連接請(qǐng)求,如果是不可連接的廣播類型,它將不回應(yīng)連接請(qǐng)求。可掃描廣播類型是指回應(yīng)掃描請(qǐng)求。

不同的廣播類型對(duì)掃描請(qǐng)求和連接請(qǐng)求的不同結(jié)果如下圖:

Own_Address_Type:本地地址類型

Peer_Address_Type:對(duì)端地址類型

Public Device Addrss:公有設(shè)備地址是設(shè)備所特有的并且是不可改變的。類似網(wǎng)絡(luò)設(shè)備的MAC地址,它的長度為48位。由兩部分組成:

Ramdom Device Address:隨機(jī)設(shè)備地址(私有設(shè)備地址),它也是48位。組成如下所示:

Peer_Address:對(duì)端藍(lán)牙地址

Advertising_Channel_Map:廣播信道表

決定在哪個(gè)信道上廣播,如果0x07就是在廣播全信道(37,38,39)

Advertising_Filter_Policy:過濾策略

對(duì)應(yīng)上圖的內(nèi)容解釋如下:

接受任何設(shè)備的掃描請(qǐng)求或連接請(qǐng)求。(Value:0x00)

僅僅接受白名單中的特定設(shè)備的掃描請(qǐng)求,但是接受任何設(shè)備的連接請(qǐng)求。(Value:0x01)

接受任何設(shè)備的掃描請(qǐng)求,但僅僅接受白名單中的特定設(shè)備的連接請(qǐng)求。(Value:0x02)

僅僅接受白名單中的特定設(shè)備的掃描請(qǐng)求和連接請(qǐng)求。(Value:0x03)

整個(gè)實(shí)現(xiàn)的代碼如下:

/* HCI Command Opcode group Field (OGF) */ #define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10) /* 0x0C00 */ #define HCI_GRP_BLE_CMDS (0x08 << 10)/* HCI Command Opcode Command Field (OCF) */ #define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) /* Advertising Commands. */ #define HCI_BLE_WRITE_ADV_ENABLE (0x000A | HCI_GRP_BLE_CMDS) #define HCI_BLE_WRITE_ADV_DATA (0x0008 | HCI_GRP_BLE_CMDS) #define HCI_BLE_WRITE_ADV_PARAMS (0x0006 | HCI_GRP_BLE_CMDS)/* HCI Command length. */ #define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE 1 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS 15 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA 31uint16_t make_cmd_ble_set_adv_param (uint8_t *buf, uint16_t adv_int_min, uint16_t adv_int_max,uint8_t adv_type, uint8_t addr_type_own,uint8_t addr_type_dir, bd_addr_t direct_bda,uint8_t channel_map, uint8_t adv_filter_policy) {UINT8_TO_STREAM (buf, H4_TYPE_COMMAND);UINT16_TO_STREAM (buf, HCI_BLE_WRITE_ADV_PARAMS);UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS );UINT16_TO_STREAM (buf, adv_int_min);UINT16_TO_STREAM (buf, adv_int_max);UINT8_TO_STREAM (buf, adv_type);UINT8_TO_STREAM (buf, addr_type_own);UINT8_TO_STREAM (buf, addr_type_dir);BDADDR_TO_STREAM (buf, direct_bda);UINT8_TO_STREAM (buf, channel_map);UINT8_TO_STREAM (buf, adv_filter_policy);return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS; } static void hci_cmd_send_ble_set_adv_param(void) {uint16_t adv_intv_min = 256; // 160msuint16_t adv_intv_max = 256; // 160msuint8_t adv_type = 0; // connectable undirected advertising (ADV_IND)uint8_t own_addr_type = 0; // Public Device Addressuint8_t peer_addr_type = 0; // Public Device Addressuint8_t peer_addr[6] = {0};uint8_t adv_chn_map = 0x07; // 37, 38, 39uint8_t adv_filter_policy = 0; // Process All Conn and Scanuint16_t sz = make_cmd_ble_set_adv_param(hci_cmd_buf,adv_intv_min,adv_intv_max,adv_type,own_addr_type,peer_addr_type,peer_addr,adv_chn_map,adv_filter_policy);esp_vhci_host_send_packet(hci_cmd_buf, sz); }

3.5 hci set adv data命令

hci command的格式如下:

OGF=0x08,OCF=0x08

我們來看下這個(gè)command的格式:

Advertising_Data_Length:廣播數(shù)據(jù)長度,最長是31個(gè)字節(jié)

Advertising_Data:廣播數(shù)據(jù)

廣播參數(shù)格式如下:

一個(gè)1byte的length,n byte的type,后面跟的是這個(gè)item的廣播數(shù)據(jù),符合L T V格式

L:length T:Type V:value

其中Type跟HCI EIR基本一樣,在文檔CSS_V9中,想詳細(xì)看的可以看下

說不講原理,又忍不住給你們講解原理了,就此打住,想看廣播數(shù)據(jù)的,可以看下我這篇文章:

低功耗藍(lán)牙搜索廣播的實(shí)現(xiàn)流流程介紹 /BLE?scan flow ----- 藍(lán)牙低功耗協(xié)議棧_Wireless_Link的博客-CSDN博客

在上述文章步驟6)解析BLE廣播event的數(shù)據(jù)包 有廣播數(shù)據(jù)類型,格式等

我們看下代碼實(shí)現(xiàn)

/* HCI Command Opcode group Field (OGF) */ #define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10) /* 0x0C00 */ #define HCI_GRP_BLE_CMDS (0x08 << 10)/* HCI Command Opcode Command Field (OCF) */ #define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) /* Advertising Commands. */ #define HCI_BLE_WRITE_ADV_ENABLE (0x000A | HCI_GRP_BLE_CMDS) #define HCI_BLE_WRITE_ADV_DATA (0x0008 | HCI_GRP_BLE_CMDS) #define HCI_BLE_WRITE_ADV_PARAMS (0x0006 | HCI_GRP_BLE_CMDS)/* HCI Command length. */ #define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE 1 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS 15 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA 31 uint16_t make_cmd_ble_set_adv_enable (uint8_t *buf, uint8_t adv_enable) {UINT8_TO_STREAM (buf, H4_TYPE_COMMAND);UINT16_TO_STREAM (buf, HCI_BLE_WRITE_ADV_ENABLE);UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_WRITE_ADV_ENABLE);UINT8_TO_STREAM (buf, adv_enable);return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_ADV_ENABLE; } static void hci_cmd_send_ble_adv_start(void) {uint16_t sz = make_cmd_ble_set_adv_enable (hci_cmd_buf, 1);esp_vhci_host_send_packet(hci_cmd_buf, sz); }

3.6 hci send ble adv start命令

hci command的格式如下:

OGF=0x08,OCF=0x0a

我們來看下這個(gè)command的格式:

Advertising_Enable:停止或者關(guān)閉BLE廣播

代碼如下:

/* HCI Command Opcode group Field (OGF) */ #define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10) /* 0x0C00 */ #define HCI_GRP_BLE_CMDS (0x08 << 10)/* HCI Command Opcode Command Field (OCF) */ #define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) /* Advertising Commands. */ #define HCI_BLE_WRITE_ADV_ENABLE (0x000A | HCI_GRP_BLE_CMDS) #define HCI_BLE_WRITE_ADV_DATA (0x0008 | HCI_GRP_BLE_CMDS) #define HCI_BLE_WRITE_ADV_PARAMS (0x0006 | HCI_GRP_BLE_CMDS)/* HCI Command length. */ #define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE 1 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS 15 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA 31 uint16_t make_cmd_ble_set_adv_enable (uint8_t *buf, uint8_t adv_enable) {UINT8_TO_STREAM (buf, H4_TYPE_COMMAND);UINT16_TO_STREAM (buf, HCI_BLE_WRITE_ADV_ENABLE);UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_WRITE_ADV_ENABLE);UINT8_TO_STREAM (buf, adv_enable);return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_ADV_ENABLE; } static void hci_cmd_send_ble_adv_start(void) {uint16_t sz = make_cmd_ble_set_adv_enable (hci_cmd_buf, 1);esp_vhci_host_send_packet(hci_cmd_buf, sz); }

四.程序效果

整個(gè)代碼運(yùn)行效果就是我們可以搜索到我們的設(shè)備,但是不能連接哈,因?yàn)槲覀冏约簩懙倪@部分代碼不是完整的Host代碼

總結(jié)

以上是生活随笔為你收集整理的ESP32 VHCI实现BLE广播,就是这么神奇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。