怎麼理解BLE「連接」,如何通過無線發送一個數據包?一文簡單概述

繼上一篇,相信還是很多人不懂BLE協議棧的工作原理,那麼本篇就以如何發送一個數據包為例來講解BLE協議棧各層是如何緊密配合,以完成發送任務的。

如何通過無線發送一個數據包

假設有設備A和設備B,設備A要把自己目前的電量狀態83%(十六進制表示為0x53)發給設備B,該怎麼做呢?作為一個開發者,他希望越簡單越好,對他而言,他希望調用一個簡單的API就能完成這件事,比如send(0x53),實際上我們的BLE協議棧就是這樣設計的,開發者只需調用send(0x53)就可以把數據發送出去了,其餘的事情BLE協議棧幫你搞定。很多人會想,BLE協議棧是不是直接在物理層就把0x53發出去,就如下圖所示:

怎麼理解BLE“連接”,如何通過無線發送一個數據包?一文簡單概述

這種方式初看起來挺美的,但由於很多細節沒有考慮到,實際是不可行的。首先,它沒有考慮用哪一個射頻信道來進行傳輸,在不更改API的情況下,我們只能對協議棧進行分層,為此引入LL層,開發者還是調用send(0x53),send(0x53)再調用send_LL(0x53,2402M)(注:2402M為信道頻率)。這裡還有一個問題,設備B怎麼知道這個數據包是發給自己的還是其他人的,為此BLE引入*access address概念,用來指明接收者身份*,其中,0x8E89BED6這個access address比較特殊,它表示要發給周邊所有設備,即廣播。如果你要一對一的進行通信(BLE協議將其稱為*連接*),即設備A的數據包只能設備B接收,同樣設備B的數據包只能設備A接收,那麼就必須生成一個獨特的*隨機*access address以標識設備A和設備B兩者之間的連接。

廣播方式

我們先來看一下簡單的廣播情況,這種情況下,我們把設備A叫*advertiser*(廣播者),設備B叫*scanner*或者*observer*(掃描者)。廣播狀態下設備A的LL層API將變成send_LL(0x53,2402M, 0x8E89BED6)。由於設備B可以同時接收到很多設備的廣播,因此數據包還必須包含設備A的device address(0xE1022AAB753B)以確認該廣播包來自設備A,為此send_LL參數需要變成(0x53,2402M, 0x8E89BED6,0xE1022AAB753B)。LL層還要檢查數據的完整性,即數據在傳輸過程中有沒有發生竄改,為此引入CRC24對數據包進行檢驗 (假設為0xB2C78E) 。同時為了調製解調電路工作更高效,每一個數據包的最前面會加上1個字節的preamble(前導幀),preamble一般為0x55或者0xAA。這樣,整個空中包就變成(注:*空中包用小端模式表示!*):

怎麼理解BLE“連接”,如何通過無線發送一個數據包?一文簡單概述

連接方式

到底什麼叫連接(connection)?像有線UART,很容易理解,就是用線(Rx和Tx等)把設備A和設備B相連,即為連接。用“線”把兩個設備相連,實際是讓2個設備有共同的通信媒介,並讓兩者時鐘同步起來。藍牙連接有何嘗不是這個道理,*所謂設備A和設備B建立藍牙連接,就是指設備A和設備B兩者“同步”成功*,其具體包含以下幾方面:

* 設備A和設備B對接下來要使用的物理信道達成一致

* 設備A和設備B雙方建立一個共同的時間錨點,也就是說,把雙方的時間原點變成同一個點

* 設備A和設備B兩者時鐘同步成功,即雙方都知道對方什麼時候發送數據包什麼時候接收數據包

* 連接成功後,設備A和設備B通信流程如下所示:

怎麼理解BLE“連接”,如何通過無線發送一個數據包?一文簡單概述

如上圖所示,一旦設備A和設備B連接成功(此種情況下,我們把設備A稱為*Master*或者*Central*,把設備B稱為*Slave*或者*Peripheral*),設備A將週期性以CI(connection interval)為間隔向設備B發送數據包,而設備B也週期性地以CI為間隔打開射頻接收窗口以接收設備A的數據包。同時按照藍牙spec要求,設備B收到設備A數據包*150us後*,設備B切換到發送狀態,把自己的數據發給設備A;設備A則切換到接收狀態,接收設備B發過來的數據。由此可見,連接狀態下,設備A和設備B的射頻發送和接收窗口都是週期性地有計劃地開和關,而且開的時間非常短,從而大大減低系統功耗並大大提高系統效率。


分享到:


相關文章: