藍牙是一種短距的無線通訊技術,可實作固定裝置、移動裝置之間的資料交換。一般将藍牙3.0之前的BR/EDR藍牙稱為傳統藍牙,而将藍牙4.0規範下的LE藍牙稱為低功耗藍牙。
很多人對藍牙的認識還很局限于手機領域,其實藍牙的應用已經遠遠不止于此。過去幾年裡,藍牙的增長量就達到了80%,當然,低功耗藍牙的出現也起到關鍵的作用,相信未來藍牙會開創一個可互動的物聯世界。

藍牙4.0标準包括傳統藍牙子產品部分和低功耗藍牙子產品部分,是一個雙模标準。低功耗藍牙也是建立在傳統藍牙基礎之上發展起來的,并差別于傳統子產品,最大的特點就是成本和功耗降低,應用于實時性要求比較高。
BLE(Bluetooh Low Energy)藍牙低能耗技術是短距離、低成本、可互操作性的無線技術,它利用許多智能手段最大限度地降低功耗。
BLE技術的工作模式非常适合用于從微型無線傳感器(每半秒交換一次資料)或使用完全異步通信的遙控器等其它外設傳送資料。這些裝置發送的資料量非常少(通常幾個位元組),而且發送次數也很少(例如每秒幾次到每分鐘一次,甚至更少)。
1、協定有兩個部分組成:Controller和Host
2、Profiles和應用總是基于GAP和GATT之上
3、在單晶片方案中,Controller和Host,profiles,和應用層都在同一片晶片中
4、在網絡控制器模式中,Host和Controller是在一起運作的,但是應用和profiles在另外一個器件上,比如PC或者其他微控制器,可以通過UART,USB進行操作
5、在雙晶片模式中,Controller運作在一個控制器,而應用層,profiles和Host是運作在另外一個控制器上
如上圖所述,要實作一個BLE應用,首先需要一個支援BLE射頻的晶片,然後還需要提供一個與此晶片配套的BLE協定棧,最後在協定棧上開發自己的應用。可以看出BLE協定棧是連接配接晶片和應用的橋梁,是實作整個BLE應用的關鍵。那BLE協定棧具體包含哪些功能呢?簡單來說,BLE協定棧主要用來對你的應用資料進行層層封包,以生成一個滿足BLE協定的空中資料包,也就是說,把應用資料包裹在一系列的幀頭(header)和幀尾(tail)中。具體來說,BLE協定棧主要由如下幾部分組成:
PHY層(Physical layer實體層)。
PHY層用來指定BLE所用的無線頻段,調制解調方式和方法等。PHY層做得好不好,直接決定整個BLE晶片的功耗,靈敏度以及selectivity等射頻名額。
LL層(Link Layer鍊路層)。
LL層是整個BLE協定棧的核心,也是BLE協定棧的難點和重點。像Nordic的BLE協定棧能同時支援20個link(連接配接),就是LL層的功勞。LL層要做的事情非常多,比如具體選擇哪個射頻通道進行通信,怎麼識别空中資料包,具體在哪個時間點把資料包發送出去,怎麼保證資料的完整性,ACK如何接收,如何進行重傳,以及如何對鍊路進行管理和控制等等。LL層隻負責把資料發出去或者收回來,對資料進行怎樣的解析則交給上面的GAP或者ATT。
HCI(Host controller interface)。
HCI是可選的,HCI主要用于2顆晶片實作BLE協定棧的場合,用來規範兩者之間的通信協定和通信指令等。
GAP層(Generic access profile)。
GAP是對LL層payload(有效資料包)如何進行解析的兩種方式中的一種,而且是最簡單的那一種。GAP簡單的對LL payload進行一些規範和定義,是以GAP能實作的功能極其有限。GAP目前主要用來進行廣播,掃描和發起連接配接等。
L2CAP層(Logic link control and adaptation protocol)。
L2CAP對LL進行了一次簡單封裝,LL隻關心傳輸的資料本身,L2CAP就要區分是加密通道還是普通通道,同時還要對連接配接間隔進行管理。
SMP(Secure manager protocol)。
SMP用來管理BLE連接配接的加密和安全的,如何保證連接配接的安全性,同時不影響使用者的體驗,這些都是SMP要考慮的工作。
ATT(Attribute protocol)。
簡單來說,ATT層用來定義使用者指令及指令操作的資料,比如讀取某個資料或者寫某個資料。BLE協定棧中,開發者接觸最多的就是ATT。BLE引入了attribute概念,用來描述一條一條的資料。Attribute除了定義資料,同時定義該資料可以使用的ATT指令,是以這一層被稱為ATT層。
GATT(Generic attribute profile )。
GATT用來規範attribute中的資料内容,并運用group(分組)的概念對attribute進行分類管理。沒有GATT,BLE協定棧也能跑,但互聯互通就會出問題,也正是因為有了GATT和各種各樣的應用profile,BLE擺脫了ZigBee等無線協定的相容性困境,成了出貨量最大的2.4G無線通信産品。
移動擴充裝置
汽車電子裝置
健康醫療用品:心跳帶、血壓計等
定位應用:室内定位、井下定位等
近距離資料采集:無線抄表、無線遙測等
資料傳輸:智能家房間内控制、藍牙調光、列印機等
所謂協定,即将指定的位元組按照一定的順序排列起來,以便他人使用自己的裝置時,能通過該協定同其他裝置進行通信。協定一特點,就是有固定的幀格式,通過該格式發送,接收者通過解讀幀格式,進而得到新息内容;
一般通信協定,一類通信是直接發生資料,當裝置接送到資料時,直接對資料進行解析,當接受到的資料合法時,即為有效資料,該類型的通信協定,主要用在有線通信協定中,比如Modbus,Can通常采用的即為該類型的通信方式。
另一類通信協定,則需要建立立連接配接,當雙方連接配接建立成功了方可通信,例如TCP、BLE;BLE協定在需要進行通信時,即需要向外發送廣播信号,告訴接收者,即将和它進行通信,接受者接收到廣播内容後,确認是與自己通信,于是向廣播者發送一響應資訊,這樣當廣播者和接受者都有了對方的身份資訊時,即表示雙方連接配接成功。
是以,在連接配接過程中,必定有相應的廣播幀格式。在BLE通信過程中,假設裝置A需要連其他裝置假設為B,則A需要不斷地發送廣播信号(此過程一般有一個時間間隔,在沒發送廣播資料時間内,晶片處于低功耗狀态),每發送一次廣播包,稱之為一次廣播事件。
前導:
是一個8比特的交替序列
接入位址的第一個比特為0:01010101
接入位址的第一個比特為1:10101010
接入位址:廣播幀為固定位址:0x8E89BED6(低位元組在前)
廣播封包的報頭:
包含4bit廣播封包類型、2bit保留位、1bit發送位址類型和1bit接收位址類型。
廣播封包類型:
發送位址類型:
0: 公共位址
1:随機位址
長度:廣播封包的長度域包含8個比特,有效值的範圍是6~37
資料: 廣播者位址(6個位元組)+廣播資料(31個位元組)
校驗: 3個位元組,為CRC校驗。
廣播資料: 分為有效資料和無效資料
有效資料部分:
包含N個AD Structure,每個AD Structure由Length,AD Type和AD Data組成。其中:
Length: AD Type和AD Data的長度。
AD Type: 訓示AD Data資料的含義。
詳見https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/
注:圖中M代表手機,S代表裝置B,M->S表示手機将資料包發給裝置B,即手機開啟Tx視窗,裝置B開啟Rx視窗;S->M正好相反,表示裝置B将資料包發給手機,即裝置B開啟Tx視窗,手機開啟Rx視窗。
如圖所示,手機在收到A1廣播包ADV_IND後,以此為初始錨點(這個錨點不是連接配接的錨點),T_IFS時間後給Advertiser發送一個connection request指令,即A2資料包,告訴advertiser我将要過來連你,請做好準備。Advertiser根據connect_req指令資訊做好接收準備,connect_req包含如下關鍵資訊:
Transmit window offset,定義如上圖示
Transmit window size,定義如上圖所示
connect_req資料包完整定義如下所示
connect_req其實是在告訴advertiser,手機将在Transmit Window期間發送第一個同步包(P1)給你,請在這段時間裡把你的射頻接收視窗打開。裝置B收到P1後,T_IFS時間後将給手機回複資料包P2(ACK包)。
一旦手機收到資料包P2,連接配接即可認為建立成功。當然,實際情況會比較複雜,手機有可能收不到P2,這個時候手機将持續發送同步包直到逾時時間(supervision timeout)到,在此期間隻要裝置B回過一次ACK包,連接配接即算成功。是以一旦P1包發出,主機(手機)即認為連接配接成功,而不管有沒有收到裝置的ACK包。
這也是為什麼在Android或者iOS系統中,應用經常收到連接配接成功的回調事件(該回調事件就是基于P1包有沒有發出,隻要P1包發出,手機即認為連接配接成功,而不管有沒有收到裝置的ACK包),但實際上手機和裝置并沒有成功建立連接配接。
後續手機将以P1為錨點(原點),Connection Interval為周期,周期性地給裝置B發送資料包(Packet),Packet除了充當資料傳送功能,它還有如下兩個非常重要的功能:
同步手機和裝置的時鐘,也就是說,裝置每收到手機發來的一個包,都會把自己的時序原點重新設定,以跟手機同步。
告訴裝置你現在可以傳資料給我了。連接配接成功後,BLE通信将變成主從模式,是以把連接配接發起者(手機)稱為Master或者Central,把被連接配接者(之前的Advertiser)稱為Slave或者Peripheral。
BLE通信之是以為主從模式,是因為Slave不能“随性”給Master發資訊,它隻有等到Master給它發了一個packet後,然後才能在規定的時間把自己的資料回傳給Master。
有如下幾種典型的連接配接失敗情況:
如步驟2圖所示,如果slave在transmit window期間沒有收到master發過來的P1,那麼連接配接将會失敗。此時應該排查master那邊的問題,看看master為什麼沒有在約定的時間把P1發出來。
如果master在transmit window期間把P1發出來了,也就是說master按照connect_req約定的時序把P1發出來了,但slave沒有把P2回過去或者沒有在逾時時間内把P2回過去,那麼連接配接也會失敗。此時應該排查slave這邊的問題,看一看slave為什麼沒有把P2回過去
如果master把P1發出來了,slave也把P2回過去了,此時主機或者從機還是報連接配接失敗,這種情況有可能是軟體有問題,需要仔細排查master或者slave的軟體。
還有一種比較常見的連接配接失敗情況:空中射頻幹擾太大。此時應該找一個幹淨的環境,比如屏蔽室,排除幹擾後再去測試連接配接是否正常。
封包的基礎是資料鍊路層的封包,其它封包都是從此展開的,BLE資料鍊路層資料格式如下:
在最新的core spec 5.2中,有1M PHY和2M的PHY,對應前導符變為1-2個位元組。前導符用于頻率同步、時序評估和自動增益控制訓練。前導符第一bit應該與接入位址的LSB相同。
字段解析:
封包類型(低 4 個 bit): ADV_IND(0000) ——通用廣播 ADV_DIRECT_IND(0001) ——定向連接配接廣播 ADV_NONCONN_IND(0010) ——不可連接配接廣播 ADV_SCAN_IND(0110) ——可掃描廣播 SCAN_REQ( 0011) ——主動掃描請求 SCAN_RSP( 0100) ——主動掃描應答 CONNECT_REQ( 0101) ——連接配接請求
發送位址( TXADD)和接收位址( RXADD): 當此位為“1”時表示 Random Add(随機位址),當此位為“0”時表示 Public Add(公共位址)。 這個位址指的是資料淨荷中最初的幾個位址位元組。
淨荷長度: 這個長度是指在 PDU 中的資料除去報頭和長度之外的有效淨荷數 據長度。
廣播通道的 PDU 格式:
發送位址( TXADD)和接收位址( RXADD): 當此位為“1”時表示 Random Add (随機位址),當此位為“0”時表示 Public Add(公共位址)。 這個位址指的是資料淨荷中最初的幾個位址位元組。
淨荷長度: 這個長度是指在 PDU 中的資料除去報頭和長度之外的有效淨荷資料長度。
資料通道的 PDU 格式:
字段釋義:
LLID:
表示此包資料是 LL Date PDU 還是 LL Control PDU
00b: Reserved 01b: LL Date PDU:Continuation fragment of L2CAP message, or an Empty PDU. 10b: LL Date PDU:Start of an L2CAP message or a complete L2CAP message with no fragmentation. 11b: LL Control PDU
MIC( Message Integrity Check):
資訊完整性檢測。涉及到加密操作,上圖中是用虛線表示的,并不是一定要有此項。
MD:
這個标志位是用來通知對方裝置自己還有其他資料準備發送。0 表示沒有更多資料發送, 1 表示有更多資料準備發送。這樣,隻要還有資料需要發送,連接配接事件會自動擴充。一旦不再有資料發送,連接配接事件立即關閉。
Note:如何區分是确定包、新包還是重發包?
SN:
隻有一個 bit 位,是以值是在 0 和 1 之間進行切換。如果序列号與之前的一樣,則為重傳封包,如果序列号和之間的不同,則為新封包。
NESN:
預期序列号,它是接收方希望接到的下一包的序列号,也就是資料包的确認标志。當裝置接收到序列(SN)為 0 的封包後,在發送給對方的資料包中,應将 NESN 設為 1,這樣對方接收到這個包後,會發送一個新的資料包過來,否則就會重發上一次序列号為 0 的包。這個标志可以用來判斷資料包是否被正确接收還是需要重傳。
(1) AD type
(2) AD data 簡述
Flags:
SERVICE:
Local Name:
TX Power Level:
本例以OSAL下BLE代碼為例做講解。
什麼是OSAL?
OSAL為:Operating System Abstraction Layer,即作業系統抽象層,支援多任務運作,它并不是一個傳統意義上的作業系統,但是實作了部分類似作業系統的功能。
OSAL概念是由TI公司在ZIGBEE協定棧引入,他的意思是”模拟作業系統”,此OS,并非一個真正的OS,而是模拟OS的一些方法為廣大程式設計者提供一種寫MCU程式的方法。當有一個事件發生的時候,OSAL負責将此事件配置設定給能夠處理此事件的任務,然後此任務判斷事件的類型,調用相應的事件處理程式進行處理。
實驗平台
1、藍牙協定棧:1.3.2 2、軟體平台:IAR For 8051 8.10.3 3、硬體平台:Smart RF開發闆(從機),Android_Lightblue(主機)
代碼解析
int main(void)
osal_init_system()
osalInitTasks()
GAPRole_Init( taskID++ )
SimpleBLEPeripheral_Init
SimpleBLEPeripheral_ProcessEvent
GAPRole_StartDevice
gapRole_SetupGAP
GAP_DeviceInit
當GAP_DeviceInit初始化完成後,将産生GAP_DEVICE_INIT_DONE_EVENT事件;
uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events ) //鍊路處理事件
static void gapRole_ProcessOSALMsg( osal_event_hdr_t *pMsg ) //鍊路系統消息事件
gapRole_ProcessGAPMsg
stat=GAP_UpdateAdvertisingData( gapRole_TaskID,TRUE, gapRole_AdvertDataLen, gapRole_AdvertData );//更新廣播資料後,将産生GAP_ADV_DATA_UPDATE_DONE_EVENT事件;
執行廣播事件
處理GAP_MakeDiscoverable消息事件
這時候底層已經使能硬體在廣播了,要麼廣播逾時産生一個GAP_END_DISCOVERABLE_DONE_EVENT消息,要麼被連接配接事件 GAP_LINK_ESTABLISHED_EVENT;
廣播逾時産生一個GAP_END_DISCOVERABLE_DONE_EVENT消息
廣播時産生一個GAP_LINK_ESTABLISHED_EVENT消息