Bluetooth LE Exploer(微軟提供的)能夠讀取BLE藍牙設備,能夠讀寫它的值。本篇博客將使用BTStack寫出一個精簡版的Bluetooth LE Exploer。windows
涉及文件:數組
btstack-master\example\le_data_channel_client.c函數
btstack-master\example\Makefile.inc測試
注意:在PC上使用軟件Bluetooth LE Exploer來操做藍牙模塊時,使用系統自帶的驅動;spa
使用btstack來操做藍牙模塊時,使用winusb驅動(使用zadig-2.4.exe安裝此驅動)設計
在手機上使用藍牙時,過程以下:ip
1. 掃描周邊的藍牙設備ci
2. 選擇某個設備,鏈接它get
3. 使用該設備回調函數
1、程序效果:
咱們寫的藍牙程序也包含這3個過程,我設計出4個菜單:
1.主菜單:
********* Main Menu *********
[s] show scan menu
[c] show connect menu
[t] show test menu
能夠在主菜單中:
輸入s進入「Scan Menu」,
輸入c進入「Connect Menu」,
輸入t進入「Test Menu」。
2. 掃描菜單:
********* Scan Menu *********
[s] scan ble devices
[t] stop scan ble devices
[l] list ble devices
[q] Back to main menu
能夠在掃描菜單中:
輸入s開始掃描周邊設備,掃描結果會打印出來,並在程序中保存起來;
輸入t中止掃描;
輸入l列出掃描到的設備;
輸入q退回到主菜單。
3. 鏈接菜單:
********* Connect Menu *********
List devices have beenn scanned
[0] 100ASK
[1] Mi Band 2
[?] Enter the device's number to connect
[d] Disconnet
[q] Back to main menu
在鏈接菜單的前面,會首先列出以前掃描到的設備。
在鏈接菜單中,
輸入所列設備的序號,就會鏈接它;
輸入d則斷開鏈接;
輸入q退回到主菜單。
4. 測試菜單:
********* Test Menu *********
[r] read att handle 42
[w] write att handle 42
[q] back to main menu
在測試菜單中,
輸入r則會讀取handle等於42的屬性的值;
輸入w則寫handle等於42的屬性的值;
輸入q退回到主菜單。
注意:
之因此固定讀寫handle 42是爲了簡化程序,
42這個值是事先使用軟件Bluetooth LE Explorer鏈接設備後肯定的,你的設備可能有所不一樣。
2、程序演示:
啓動MSYS2 MinGW 64-bit,進入btstack-master/port/windows-winusb目錄:
1. 執行 make 命令編譯程序
2. 執行如下命令啓動程序:
winpty ./le_data_channel_client.exe
注意:在MSYS2下Windows的stdin沒法使用,必須經過winpty來啓動程序。
3. 在主菜單中:輸入s進入掃描菜單
4. 在掃描菜單中:輸入s開始掃描設備
在手機上,啓動「Bluetooth LE Peripheral」,選擇「100ASK」,點擊「START」按鈕。
這時在MSYS2中能夠看到不斷打印以下信息(這表示不斷收到手機發來的廣播信號):
advertisement_report_gets_name get 100ASK
5. 在掃描菜單中:輸入t中止掃描設備
6. 在掃描菜單中:輸入q退回到主菜單
7. 在主菜單中:輸入c進入鏈接菜單
8. 在鏈接菜單中:輸入0表示鏈接第掃描到的第0個設備
9. 在鏈接菜單中:輸入q退回到主菜單
10. 在主菜單中:輸入t進入測試菜單
11. 在測試菜單中:輸入w寫數值
觀察手機上「Bluetooth LE Peripheral」的Service-1中收到的值。
不斷輸入w,能夠觀察到手機上收到的值不斷加1。
12. 在測試菜單中:輸入r讀取數值
13. 在測試菜單中:輸入q退回到主菜單
14. 在主菜單中:輸入c進入鏈接菜單
15. 在鏈接菜單中:輸入d斷開鏈接
3、主要函數:
本程序主要源文件是btstack-master\example\le_data_channel_client.c,我在上面作了大量的修改。
1.要用鍵盤來控制程序,須要給程序增長一個「數據源」,即btstack_data_source_t結構體。
這個數據源從stdin得到數據,根據這些數據進行菜單操做。
使用以下代碼增長數據源:
btstack_stdin_setup(stdin_process);
stdin_process是咱們編寫的處理函數。
2. 啓動掃描:
printf("Start scanning!\n");
state = TC_W4_SCAN_RESULT;
gap_set_scan_parameters(0,0x0030, 0x0030);
gap_start_scan();
3. 記錄打描結果:
掃描到的設備會上報3種信息:MAC地址、地址類型、名。咱們要從上報的信息中取出這些信息,記錄起來。
使用函數gap_event_advertising_report_get_address得到地址;
使用函數gap_event_advertising_report_get_address_type得到地址類型;
使用函數advertisement_report_gets_name得到名字(這函數是我從advertisement_report_contains_name改出來的)。
這3個信息會保存在ble_devs結構體數組中。
4. 鏈接設備:
gap_connect(ble_devs[i].le_data_channel_addr, ble_devs[i].le_data_channel_addr_type);
gap_connect函數只須要2個參數:MAC地址、地址類型。
鏈接成功後會返回一個hci_con_handle_t,也就是一個16位的整數。
一箇中央設備能夠鏈接多個外設,每個鏈接都用一個hci_con_handle_t來分辨。
5. 斷開鏈接:
gap_disconnect(connection_handle);
6. 寫數據:
gatt_client_write_value_of_characteristic_without_response(connection_handle, 42, 1, &g_value);
第1個參數表示要寫哪個設備,用connection_handle 來表示(哪個鏈接對應的設備);
第2個參數表示要寫哪個屬性,每個屬性也都有一個標號即handle;
第3個參數表示要寫多少字節的數據;
第4個參數表示數據的buffer。
7. 讀數據:
gatt_client_read_value_of_characteristic_using_value_handle(handle_gatt_client_event,connection_handle, 42);
第2個參數表示要寫哪個設備,用connection_handle 來表示(哪個鏈接對應的設備);
第3個參數表示要寫哪個屬性,每個屬性也都有一個標號即handle;
第1個參數比較特殊:讀數據時,要先向外設備發出無線信號,過一會收到對方發回到信號後,才能夠解析出數據。因此讀函數不可能馬上返回結果,咱們須要提供一個回調函數。第1個參數就是一個回調函數。
在回調函數中,咱們去解析數據,從中取出咱們關注的數值。
回調函數handle_gatt_client_event源自btstack-master\test\pts\Ble_central_test.c,我作了一些精簡。