
BLE協(xié)議棧主要由如下幾部分組成:?
PHY層(Physical layer物理層)
PHY層用來(lái)指定BLE所用的無(wú)線頻段,調(diào)制解調(diào)方式和方法等。PHY層做得好不好,直接決定整個(gè)BLE芯片的功耗,靈敏度以及selectivity等射頻指標(biāo)。
LL層(Link Layer鏈路層)。
LL層是整個(gè)BLE協(xié)議棧的核心,也是BLE協(xié)議棧的難點(diǎn)和重點(diǎn)。像Nordic的BLE協(xié)議棧能同時(shí)支持20個(gè)link(連接),就是LL層的功勞。
LL層要做的事情非常多,比如具體選擇哪個(gè)射頻通道進(jìn)行通信,怎么識(shí)別空中數(shù)據(jù)包,具體在哪個(gè)時(shí)間點(diǎn)把數(shù)據(jù)包發(fā)送出去,怎么保證數(shù)據(jù)的完整性,ACK如何接收,如何進(jìn)行重傳,以及如何對(duì)鏈路進(jìn)行管理和控制等等。LL層只負(fù)責(zé)把數(shù)據(jù)發(fā)出去或者收回來(lái),對(duì)數(shù)據(jù)進(jìn)行怎樣的解析則交給上面的GAP或者GATT。
HCI(Host controller interface)
HCI是可選的(具體請(qǐng)參考文章:三種藍(lán)牙架構(gòu)實(shí)現(xiàn)方案(藍(lán)牙協(xié)議棧方案)),HCI主要用于2顆芯片實(shí)現(xiàn)BLE協(xié)議棧的場(chǎng)合,用來(lái)規(guī)范兩者之間的通信協(xié)議和通信命令等。
GAP層(Generic access profile)
GAP是對(duì)LL層payload(有效數(shù)據(jù)包)如何進(jìn)行解析的兩種方式中的一種,而且是最簡(jiǎn)單的那一種。GAP簡(jiǎn)單的對(duì)LL payload進(jìn)行一些規(guī)范和定義,因此GAP能實(shí)現(xiàn)的功能極其有限。GAP目前主要用來(lái)進(jìn)行廣播,掃描和發(fā)起連接等。
L2CAP層(Logic link control and adaptation protocol)
L2CAP對(duì)LL進(jìn)行了一次簡(jiǎn)單封裝,LL只關(guān)心傳輸?shù)臄?shù)據(jù)本身,L2CAP就要區(qū)分是加密通道還是普通通道,同時(shí)還要對(duì)連接間隔進(jìn)行管理。
SMP(Secure manager protocol)
SMP用來(lái)管理BLE連接的加密和安全的,如何保證連接的安全性,同時(shí)不影響用戶的體驗(yàn),這些都是SMP要考慮的工作。
ATT(Attribute protocol)。
簡(jiǎn)單來(lái)說(shuō),ATT層用來(lái)定義用戶命令及命令操作的數(shù)據(jù),比如讀取某個(gè)數(shù)據(jù)或者寫(xiě)某個(gè)數(shù)據(jù)。BLE協(xié)議棧中,開(kāi)發(fā)者接觸最多的就是ATT。BLE引入了attribute概念,用來(lái)描述一條一條的數(shù)據(jù)。Attribute除了定義數(shù)據(jù),同時(shí)定義該數(shù)據(jù)可以使用的ATT命令,因此這一層被稱為ATT層。
GATT(Generic attribute profile)
GATT用來(lái)規(guī)范attribute中的數(shù)據(jù)內(nèi)容,并運(yùn)用group(分組)的概念對(duì)attribute進(jìn)行分類管理。沒(méi)有GATT,BLE協(xié)議棧也能跑,但互聯(lián)互通就會(huì)出問(wèn)題,也正是因?yàn)橛辛薌ATT和各種各樣的應(yīng)用profile,BLE擺脫了ZigBee等無(wú)線協(xié)議的兼容性困境,成了出貨量最大的2.4G無(wú)線通信產(chǎn)品?
BLE引入access address概念,用來(lái)指明接收者身份
0x8E89BED6這個(gè)access address比較特殊,它表示要發(fā)給周邊所有設(shè)備,即廣播。
如果你要一對(duì)一的進(jìn)行通信(BLE協(xié)議將其稱為連接),即設(shè)備A的數(shù)據(jù)包只能設(shè)備B接收,同樣設(shè)備B 的數(shù)據(jù)包只能設(shè)備A接收,那么就必須生成一個(gè)獨(dú)特的隨機(jī)access address以標(biāo)識(shí)設(shè)備A和設(shè)備B兩者之間的連接。?
廣播情況
設(shè)備A叫advertiser(廣播者),設(shè)備B叫scanner或者observer(掃描者)。廣播狀態(tài)下設(shè)備A的LL層API將變成send_LL(0x53,2402M, 0x8E89BED6)。
由于設(shè)備B可以同時(shí)接收到很多設(shè)備的廣播,因此數(shù)據(jù)包還必須包含設(shè)備A的 device address(0xE1022AAB753B)以確認(rèn)該廣播包來(lái)自設(shè)備A,為此send_LL參數(shù)需要變成(0x53,2402M, 0x8E89BED6, 0xE1022AAB753B)。
設(shè)備A和設(shè)備B建立藍(lán)牙連接
指設(shè)備A和設(shè)備B兩者一對(duì)一“同步”成功,其具體包含以下幾方面:?
設(shè)備A和設(shè)備B對(duì)接下來(lái)要使用的物理信道達(dá)成一致
設(shè)備A和設(shè)備B雙方建立一個(gè)共同的時(shí)間錨點(diǎn),也就是說(shuō),把雙方的時(shí)間原點(diǎn)變成同一個(gè)點(diǎn)
設(shè)備A和設(shè)備B兩者時(shí)鐘同步成功,即雙方都知道對(duì)方什么時(shí)候發(fā)送數(shù)據(jù)包什么時(shí)候接收數(shù)據(jù)包
設(shè)備A和設(shè)備B通信流程

設(shè)備A稱為Master或者Central,把設(shè)備B 稱為?Slave或者?Peripheral
設(shè)備A將周期性以CI(connection interval)為間隔向設(shè)備B發(fā)送數(shù)據(jù)包,而設(shè)備B也周期性地以CI為間隔打開(kāi)射頻接收窗口以接收設(shè)備A的數(shù)據(jù)包
同時(shí)按照藍(lán)牙spec要求,設(shè)備B 收到設(shè)備A數(shù)據(jù)包150us后,設(shè)備B切換到發(fā)送狀態(tài),把自己的數(shù)據(jù)發(fā)給設(shè)備A
設(shè)備A則切換到接收狀態(tài),接收設(shè)備B發(fā)過(guò)來(lái)的數(shù)據(jù)。
由此可見(jiàn),連接狀態(tài)下,設(shè)備A和設(shè)備B的射頻發(fā)送和接收窗口都是周期性地有計(jì)劃地開(kāi)和關(guān),而且開(kāi)的時(shí)間非常短,從而大大降低系統(tǒng)功耗并大大提高系統(tǒng)效率。
連接狀態(tài)下是如何把數(shù)據(jù) 0x53發(fā)送出去的
對(duì)開(kāi)發(fā)者來(lái)說(shuō),很簡(jiǎn)單,他只需要調(diào)用send(0x53)
- GATT層定義數(shù)據(jù)的類型和分組,方便起見(jiàn),我們用0x0013表示電量這種數(shù)據(jù)類型,這樣GATT層把數(shù)據(jù)打包成130053(小端模式?。?/p>
- ATT層用來(lái)選擇具體的通信命令,比如讀/寫(xiě)/notify/indicate等,這里選擇notify命令0x1B,這樣數(shù)據(jù)包變成了:1B130053
- L2CAP用來(lái)指定connection interval(連接間隔),比如每10ms同步一次(CI不體現(xiàn)在數(shù)據(jù)包中),同時(shí)指定邏輯通道編號(hào)0004(表示ATT命令),最后把ATT數(shù)據(jù)長(zhǎng)度0x0004加在包頭,這樣數(shù)據(jù)就變?yōu)椋?40004001B130053
- LL層要做的工作很多
? ? ?首先LL層需要指定用哪個(gè)物理信道進(jìn)行傳輸(物理信道不體現(xiàn)在數(shù)據(jù)包中)
? ? ?然后再給此連接分配一個(gè)Access address(0x50655DAB)以標(biāo)識(shí)此連接只為設(shè)備A 和設(shè)備B 直連服務(wù),然后加上LL header和payload length字段,LL header標(biāo)識(shí)此packet為數(shù)據(jù)packet,而不是control packet等,payload length為整個(gè)L2CAP字段的長(zhǎng)度,
? ? ? 加上CRC24字段,以保證整個(gè)packet的數(shù)據(jù)完整性,所以數(shù)據(jù)包最后變成:
o??AAAB5D65501E08040004001B130053D550F6? ??
???????????o??AA – 前導(dǎo)幀(preamble)
? ? ? ? ? ?o??0x50655DAB – 訪問(wèn)地址(access address)
? ? ? ? ? ?o??1E – LL幀頭字段(LL header)
? ? ? ? ? ?o??08 – 有效數(shù)據(jù)包長(zhǎng)度(payload length)
? ? ? ? ? ?o??04000400 – ATT數(shù)據(jù)長(zhǎng)度,以及L2CAP通道編號(hào)
? ? ? ? ? ?o??1B – notify command
? ? ? ? ? ?o??0x0013 – 電量數(shù)據(jù)handle
? ? ? ? ? ?o??0x53 – 真正要發(fā)送的電量數(shù)據(jù)
? ? ? ? ? ?o??0xF650D5 – CRC24值
雖然開(kāi)發(fā)者只調(diào)用了 send(0x53),但由于低功耗藍(lán)牙協(xié)議棧層層打包,最后空中實(shí)際傳輸?shù)臄?shù)據(jù)將變成下圖所示的模樣,這就既滿足了低功耗藍(lán)牙通信的需求,又讓用戶API變得簡(jiǎn)單,可謂一箭雙雕!
