BLE協(xié)議棧主要由如下幾部分組成:?
PHY層(Physical layer物理層)
PHY層用來指定BLE所用的無線頻段途事,調(diào)制解調(diào)方式和方法等验懊。PHY層做得好不好,直接決定整個BLE芯片的功耗尸变,靈敏度以及selectivity等射頻指標(biāo)义图。
LL層(Link Layer鏈路層)。
LL層是整個BLE協(xié)議棧的核心召烂,也是BLE協(xié)議棧的難點(diǎn)和重點(diǎn)碱工。像Nordic的BLE協(xié)議棧能同時支持20個link(連接),就是LL層的功勞。
LL層要做的事情非常多怕篷,比如具體選擇哪個射頻通道進(jìn)行通信历筝,怎么識別空中數(shù)據(jù)包,具體在哪個時間點(diǎn)把數(shù)據(jù)包發(fā)送出去廊谓,怎么保證數(shù)據(jù)的完整性梳猪,ACK如何接收,如何進(jìn)行重傳蒸痹,以及如何對鏈路進(jìn)行管理和控制等等春弥。LL層只負(fù)責(zé)把數(shù)據(jù)發(fā)出去或者收回來,對數(shù)據(jù)進(jìn)行怎樣的解析則交給上面的GAP或者GATT电抚。
HCI(Host controller interface)
HCI是可選的(具體請參考文章:三種藍(lán)牙架構(gòu)實(shí)現(xiàn)方案(藍(lán)牙協(xié)議棧方案))惕稻,HCI主要用于2顆芯片實(shí)現(xiàn)BLE協(xié)議棧的場合竖共,用來規(guī)范兩者之間的通信協(xié)議和通信命令等碳锈。
GAP層(Generic access profile)
GAP是對LL層payload(有效數(shù)據(jù)包)如何進(jìn)行解析的兩種方式中的一種焕数,而且是最簡單的那一種。GAP簡單的對LL payload進(jìn)行一些規(guī)范和定義,因此GAP能實(shí)現(xiàn)的功能極其有限飞涂。GAP目前主要用來進(jìn)行廣播,掃描和發(fā)起連接等澜驮。
L2CAP層(Logic link control and adaptation protocol)
L2CAP對LL進(jìn)行了一次簡單封裝菠发,LL只關(guān)心傳輸?shù)臄?shù)據(jù)本身,L2CAP就要區(qū)分是加密通道還是普通通道腿准,同時還要對連接間隔進(jìn)行管理际起。
SMP(Secure manager protocol)
SMP用來管理BLE連接的加密和安全的,如何保證連接的安全性吐葱,同時不影響用戶的體驗(yàn)街望,這些都是SMP要考慮的工作。
ATT(Attribute protocol)弟跑。
簡單來說灾前,ATT層用來定義用戶命令及命令操作的數(shù)據(jù),比如讀取某個數(shù)據(jù)或者寫某個數(shù)據(jù)孟辑。BLE協(xié)議棧中哎甲,開發(fā)者接觸最多的就是ATT。BLE引入了attribute概念饲嗽,用來描述一條一條的數(shù)據(jù)炭玫。Attribute除了定義數(shù)據(jù),同時定義該數(shù)據(jù)可以使用的ATT命令貌虾,因此這一層被稱為ATT層吞加。
GATT(Generic attribute profile)
GATT用來規(guī)范attribute中的數(shù)據(jù)內(nèi)容,并運(yùn)用group(分組)的概念對attribute進(jìn)行分類管理。沒有GATT榴鼎,BLE協(xié)議棧也能跑伯诬,但互聯(lián)互通就會出問題,也正是因?yàn)橛辛薌ATT和各種各樣的應(yīng)用profile巫财,BLE擺脫了ZigBee等無線協(xié)議的兼容性困境盗似,成了出貨量最大的2.4G無線通信產(chǎn)品?
BLE引入access address概念,用來指明接收者身份
0x8E89BED6這個access address比較特殊平项,它表示要發(fā)給周邊所有設(shè)備赫舒,即廣播。
如果你要一對一的進(jìn)行通信(BLE協(xié)議將其稱為連接)闽瓢,即設(shè)備A的數(shù)據(jù)包只能設(shè)備B接收接癌,同樣設(shè)備B 的數(shù)據(jù)包只能設(shè)備A接收,那么就必須生成一個獨(dú)特的隨機(jī)access address以標(biāo)識設(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ù)據(jù)包還必須包含設(shè)備A的 device address(0xE1022AAB753B)以確認(rèn)該廣播包來自設(shè)備A,為此send_LL參數(shù)需要變成(0x53,2402M, 0x8E89BED6, 0xE1022AAB753B)销钝。
設(shè)備A和設(shè)備B建立藍(lán)牙連接
指設(shè)備A和設(shè)備B兩者一對一“同步”成功有咨,其具體包含以下幾方面:?
設(shè)備A和設(shè)備B對接下來要使用的物理信道達(dá)成一致
設(shè)備A和設(shè)備B雙方建立一個共同的時間錨點(diǎn),也就是說蒸健,把雙方的時間原點(diǎn)變成同一個點(diǎn)
設(shè)備A和設(shè)備B兩者時鐘同步成功座享,即雙方都知道對方什么時候發(fā)送數(shù)據(jù)包什么時候接收數(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為間隔打開射頻接收窗口以接收設(shè)備A的數(shù)據(jù)包
同時按照藍(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ā)過來的數(shù)據(jù)。
由此可見挽唉,連接狀態(tài)下滤祖,設(shè)備A和設(shè)備B的射頻發(fā)送和接收窗口都是周期性地有計劃地開和關(guān),而且開的時間非常短瓶籽,從而大大降低系統(tǒng)功耗并大大提高系統(tǒng)效率匠童。
連接狀態(tài)下是如何把數(shù)據(jù) 0x53發(fā)送出去的
對開發(fā)者來說,很簡單塑顺,他只需要調(diào)用send(0x53)
- GATT層定義數(shù)據(jù)的類型和分組汤求,方便起見俏险,我們用0x0013表示電量這種數(shù)據(jù)類型,這樣GATT層把數(shù)據(jù)打包成130053(小端模式Q镄鳌)
- ATT層用來選擇具體的通信命令竖独,比如讀/寫/notify/indicate等,這里選擇notify命令0x1B挤牛,這樣數(shù)據(jù)包變成了:1B130053
- L2CAP用來指定connection interval(連接間隔)莹痢,比如每10ms同步一次(CI不體現(xiàn)在數(shù)據(jù)包中),同時指定邏輯通道編號0004(表示ATT命令)墓赴,最后把ATT數(shù)據(jù)長度0x0004加在包頭竞膳,這樣數(shù)據(jù)就變?yōu)椋?40004001B130053
- LL層要做的工作很多
? ? ?首先LL層需要指定用哪個物理信道進(jìn)行傳輸(物理信道不體現(xiàn)在數(shù)據(jù)包中)
? ? ?然后再給此連接分配一個Access address(0x50655DAB)以標(biāo)識此連接只為設(shè)備A 和設(shè)備B 直連服務(wù),然后加上LL header和payload length字段诫硕,LL header標(biāo)識此packet為數(shù)據(jù)packet坦辟,而不是control packet等,payload length為整個L2CAP字段的長度章办,
? ? ? 加上CRC24字段锉走,以保證整個packet的數(shù)據(jù)完整性,所以數(shù)據(jù)包最后變成:
o??AAAB5D65501E08040004001B130053D550F6? ??
???????????o??AA – 前導(dǎo)幀(preamble)
? ? ? ? ? ?o??0x50655DAB – 訪問地址(access address)
? ? ? ? ? ?o??1E – LL幀頭字段(LL header)
? ? ? ? ? ?o??08 – 有效數(shù)據(jù)包長度(payload length)
? ? ? ? ? ?o??04000400 – ATT數(shù)據(jù)長度纲菌,以及L2CAP通道編號
? ? ? ? ? ?o??1B – notify command
? ? ? ? ? ?o??0x0013 – 電量數(shù)據(jù)handle
? ? ? ? ? ?o??0x53 – 真正要發(fā)送的電量數(shù)據(jù)
? ? ? ? ? ?o??0xF650D5 – CRC24值
雖然開發(fā)者只調(diào)用了 send(0x53)挠日,但由于低功耗藍(lán)牙協(xié)議棧層層打包,最后空中實(shí)際傳輸?shù)臄?shù)據(jù)將變成下圖所示的模樣翰舌,這就既滿足了低功耗藍(lán)牙通信的需求,又讓用戶API變得簡單冬骚,可謂一箭雙雕椅贱!