前言
(1)本章節主要是對
BLE
技術進行簡單的介紹,熟悉藍牙技術的發展過程,了解相關術語方便后續的學習。
(2)為了防止單篇博客太長以至于看不下去,因此我基礎概念章節分為兩篇來寫。
(3)疊甲一:本人剛接觸BLE開發不久,文章盡可能的查詢了各方面資料進行學習。如果依舊存在錯誤,愿各位大佬不吝賜教。
(4)疊加二:本文僅用于科普入門,因此講解深度并不是很深,愿周知。
藍牙與BLE關系
藍牙的起源
(1)1994-1997年之間,包括愛立信,英特爾,諾基亞在內的一些科技公司,想要制定一種短距離無線通信協議,用于各種電子設備之間通訊,取代當時的有線通信形式。
(2)可是各個公司都推出了自己的通信協議,不同廠商的設備并不兼容。于是在1997年的一次通信會議上,各個廠商希望制定一種統一的通信協議,使的他們的設備相互兼容。在這場會議中,商定了“Bluetooth
”作為通信協議的名稱。
Bluetooth
是由一位英特爾的工程師 Jim Kardach 推薦的。原因是他當時正在閱讀有關維京人和哈拉爾國王的歷史小說,由于哈拉爾國王以統一了因宗教戰爭和領土爭議而分裂的挪威與丹麥而聞名于世,國王的成就與此次會議的的理念不謀而合,而且傳說哈拉爾國王有一個壞死的牙齒,變成的藍色,所以世人就給他起了個綽號“Bluetooth
”,因此該工程師提議使用哈拉爾國王的綽號“Bluetooth
”作為通信協議的名稱。- 藍牙的圖標也是和這位哈拉爾國王有關。 哈拉爾國王真名拼寫“Harald”,藍牙組織將國王的真名“
Harald
”和綽號“Bluetooth
”的首字母拼合在一起,配以藍牙的底圖,就形成了藍牙圖標。
(3)1998 年 2月,5個跨國大公司,包括愛立信、諾基亞、BM、東芝及 Intel 組成了一個特殊興趣小組(
SIG
),他們共同的目標是建立一個全球性的小范圍無線通信技術,即現在的藍牙。
藍牙發展
(1)1999年,愛立信聯合其他科技公司在制定了藍牙1.0 協議版本。早期的協議版本在兼容性、安全性、傳輸速率等方面都有很多的不足,所以此本并未得到大量應用。此時的藍牙稱為基本碼率,
Basic Rate
,簡稱BR
。
(2)2004年,藍牙2.0的協議版本發布,增加了增強速率模式(EDR
:Enhanced DataRate
),同傳輸速率提升至2-3Mbps.
(3)2009年,引入全新的交替射頻技術(AMP
:Alternate MACIPHY
),推出藍牙3.0+ HS(High Speed)高速藍牙的功能。HS
使得Bluetooth
能利用Wi-Fi
作為傳輸方式進行數據傳輸,允許藍牙協議棧針對任一任務動態地選擇正確射頻,通過瞬間使用消費者設備中已存在的輔助無線電提供更快的吞吐量,使其支持的傳輸速度最高可達24Mbps。
(4)2010年,推出藍牙4.0標準,它是第一個綜合性規范,其加入了全新的藍牙低功耗技術,即藍牙 4.0集三種規格于一體。最重要的特點就是省電,可以使一粒紐扣電池連續工作數年。三種規格如下:
- 傳統藍牙(Classic Bluetooth):適用于高數據傳輸需求的應用,如音頻和視頻流。
- 低功耗藍牙(Bluetooth Low Energy, BLE):適用于低數據傳輸需求且需要長時間運行的設備,如傳感器和可穿戴設備。
- 高速藍牙(High Speed Bluetooth):高速藍牙并不是一種獨立的藍牙類型,而是經典藍牙的一種增強模式。它利用了
Wi-Fi
技術來實現更高的數據傳輸速率。具體來說,高速藍牙允許設備在需要傳輸大量數據時,切換到Wi-Fi
連接,從而實現更快的數據傳輸速度。適用于需要快速傳輸大量數據的場景。(5)2016年,推出藍牙5.0標準。相比較藍牙4.0,具有 2倍的數據速率、4 倍的覆蓋范圍和8倍的廣播能力。新增高精度室內定位的功能,針對
loT
物聯網進行底層優化,力求以更低的功耗和更高的性能為智能家居服務。
關于經典藍牙和高速藍牙的問題
在編程時,通常只會看到選擇
BR/EDR
(經典藍牙)和BLE
(低功耗藍牙)的選項,而看不到關于高速藍牙(High Speed Bluetooth)的內容,主要有以下幾個原因:
- 高速藍牙的實現方式:高速藍牙(High Speed Bluetooth)并不是一種獨立的藍牙模式,而是經典藍牙的一種增強功能。它通過結合
Wi-Fi
技術來實現更高的數據傳輸速率。這意味著高速藍牙的實現依賴于設備同時支持藍牙和Wi-Fi
,并且需要在藍牙協議棧之外進行額外的Wi-Fi
配置和管理。但并不是所有的藍牙設備同時支持藍牙和Wi-Fi
的硬件能力。- 開發工具和庫的支持:大多數藍牙開發工具和庫主要關注經典藍牙(
BR/EDR
)和低功耗藍牙(BLE
),因為這兩種模式是藍牙技術的核心部分,應用最為廣泛。高速藍牙的實現涉及到跨協議的操作(藍牙和Wi-Fi
),這增加了開發的復雜性,因此在標準的藍牙開發工具和庫中通常不會直接提供對高速藍牙的支持。即使進行了相關支持,高速藍牙在編程時通常被歸類到經典藍牙中,因為高速藍牙本質上是經典藍牙(BR/EDR
)與Wi-Fi
技術的結合。- 應用場景的需求:高速藍牙主要用于需要傳輸大量數據的特定應用場景,如大文件傳輸或視頻流傳輸。然而,許多藍牙應用并不需要如此高的數據傳輸速率,經典藍牙和低功耗藍牙已經能夠滿足大多數應用的需求。因此,開發者在編程時通常只需要選擇
BR/EDR
或BLE
即可。綜上所述,在編程時通常只會看到選擇
BR/EDR
和BLE
的選項,而看不到關于高速藍牙的內容,是因為高速藍牙的實現方式復雜,開發工具和庫的支持有限,以及應用場景和硬件支持的限制。而且高速藍牙并非獨立的技術模式,而是經典藍牙的一種特性,因此在編程時通常不會單獨列出高速藍牙的選項,而是集成在經典藍牙(BR/EDR
)中一同使用。
藍牙的三種LOGO和設備類型
三種LOGO
(1)上面我們說了,藍牙4.0是第一個綜合性規范,它集三種規格于一體。但是這三種規格又有不同的應用場景,在某些特定的場景中,我們僅僅只需要一種規范即可滿足任務。因此藍牙興趣小組(
SIG
)規定了如下三種LOGO
用于標識版本之間的區別和兼容性。
(2)這三種LOGO的含義如下:
- Bluetooth Smart Ready:同時支持經典藍牙(
BR/EDR
)和低功耗(BLE
)技術,設備可以與兩種類型的藍牙產品通信。如手機。- 傳統 Bluetooth:僅支持經典藍牙(
BR/EDR
)。如用于傳輸語音的藍牙耳機。- Bluetooth Smart:僅支持低功耗藍牙(
BLE
)技術的設備,主要用于低功耗和低復雜度的應用。如可穿戴設備、健身追蹤器等。
單模與雙模
(1)藍牙4.0以后的版本分為兩種模式,單模藍牙和雙模藍牙。
- 單模設備:只支持低功耗藍牙(
BLE
),如用 nRF51822 開發的藍牙設備即為單模設備,單模設備對低功耗的要求很高。- 雙模設備:既支持經典藍牙(
BR/EDR
)也支持低功耗藍牙(BLE
),這兩種技術使用同一個射頻前端和天線,雙模設備一般都有足夠的供電能力,對低功耗的要求不高。
(3)下圖為單模設備和雙模設備與傳統藍牙設備的兼容性:
- 雙模設備和雙模設備:可以通過LE通信,也可以通過傳統藍牙通信。
- 單模設備和單模設備:通過 LE 通信。
- 傳統藍牙和傳統藍牙:通過傳統藍牙(經典藍牙)通信。
- 雙模設備和單模設備:通過 LE 通信。
- 雙模設備和傳統藍牙:通過傳統藍牙(經典藍牙)通信。
- 單模設備和傳統藍牙:不能通信。
BLE的體系結構
BLE的三層結構
(1)
BLE
體系結構如下(新手百分百看不懂下面的內容,但是還是建議先過一遍,后續會再進一步進行介紹):
<1>控制層(Controller):
- PHY 層(Physicallayer 物理層):
PHY
層用來指定BLE
所用的無線頻段,調制解調方式和方法等。PHY
層還決定了傳輸數據的速度、整個BLE
芯片的功耗、靈敏度以及selectivity
等射頻指標的配置。- LL層(Link Layer 鏈路層):
LL
層是整個BLE
協議棧的核心,也是BLE
協議棧的難點和重點。像Nordic
的BLE
協議棧能同時支持20個link
(連接),就是LL
層的功勞。LL
層要做的事情非常多,比如具體選擇哪個射頻通道進行通信,怎么識別空中數據包,具體在哪個時間點把數據包發送出去,怎么保證數據的完整性,ACK
如何接收,如何進行重傳,負責廣播、掃描、建立和維護連接,以及確保數據包按照正確的方式組織、正確地校驗值和加密序列等等。LL
層只負責把數據發出去或者收回來,對數據進行怎樣的解析則交給上面的GAP
或者GATT
。- 主機控制器接口 HCI(Host controller interface):這個是可選的,在主機(
Host
)和控制器(Controller
) 之間提供一個標準化的接口。該層可以由應用程序接口API
實現或者使用硬件接口UART
、SPI
或USB
來控制。控制器通過HCI
發送數據和事件給主機,主機通過HCI
發送命令和數據給控制器。<2>主協議層(HOST):
- GAP層(Generic access profile):
GAP
是對LL
層payload
(有效數據包)如何進行解析的兩種方式中的一種,而且是最簡單的那一種。GAP
簡單的對LL payload
進行一些規范和定義,因此GAP
能實現的功能極其有限。GAP
目前主要用來進行廣播,掃描和發起連接等。- L2CAP 層(Logic link control and adaptation protocol):
L2CAP
對LL
進行了一次簡單封裝,LL
只關心傳輸的數據本身,L2CAP
就要區分是加密通道還是普通通道,同時還要對連接間隔進行調整。通俗來說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無線通信產品。<3>應用層(Profiles):最上層的
Profiles
層里,包含的公共任務和私有任務。其中公共任務是藍牙協議小組(SIG
)定義的藍牙任務,私有任務是用戶或者企業自定義的藍牙任務。
Controller層拓展解釋
PHY層
(1)前面我們說了:“
PHY
層用來指定BLE
所用的無線頻段,調制解調方式和方法等。PHY
層還決定了傳輸數據的速度、整個BLE
芯片的功耗、靈敏度以及selectivity
等射頻指標的配置。”現在我選取其中三點將盡可能詳細的解釋PHY
的作用:
<1> 無線頻段:
PHY
層決定了BLE
工作在2.4GHz ISM
頻段,頻率范圍為2.400-2.4835 GHz
。- 再將
2.4GHz
頻段劃分為40
個信道,可以有效利用頻譜資源、減少干擾、優化連接建立過程,并提高信號傳輸質量和可靠性。- 其中廣播信道固定為
37
、38
、39
,對應的中心頻率是2402MHz
、2426MHz
、2480MHz
。廣播信道之間至少相差24MHZ
。每次廣播,都會在3
個信道上將廣播數據發送一次,這能有效地避免干擾,即使1
個信道存在干擾,另外的信道也可以很好地工作,而3
個信道同時被干擾的情況極少。- 廣播信道越多,各個信道同時受到干擾的幾率越小,抗干擾性越強。但是廣播信道越多發射數據占用的時間就越長,功耗也就越高。所以,在綜合考慮抗干擾性和功耗的情況下
SIG
將廣播設定為3
個。- 廣播信道的選擇主要是考慮到
WI-FI
接入點的干擾。通過正好避免了三個WI-FI
常用接入點信道的覆蓋,避免了他們的干擾。
<2> 調制解調方式:采用高斯頻移鍵控(
GFSK
),帶寬時間積BT=0.5,調制因子=[0.45-0.55],有效頻率偏移為±185kHz。
<3>靈敏度:芯片的靈敏度是一個重要指標,能夠能大程度上決定芯片傳輸的距離。從專業的術語來解釋的話,接收靈敏度就是對應的芯片能解調的最小的信號能量大小。以人的視力舉例說明:一個圖案,距離人越遠就越難看清楚細節(信號在空中傳播會衰減)。張三能夠在5米之外就能夠看清楚圖案的細節,李四要在3米才能看清細節。這表明張三的視力要比李四好(靈敏度更強)。
LL層
(1)前面說了LL層工作包括了具體選擇哪個射頻通道進行通信,這里就是讓除3個廣播信道以外的其余
37
個數據信道采用自適應跳頻技術。自適應跳頻技術會自動避開受干擾的信道,選擇質量較好的信道進行數據傳輸,能夠減少數據包的丟失和重傳,從而提高通信的穩定性和效率。自適應跳頻通常是基于跳頻擴頻(Frequency-Hopping Spread Spectrum, FHSS)技術,在多個頻率間快速切換,以增加信號的抗干擾能力。
(2)LL層要對鏈路進行管理和控制,負責廣播、掃描、建立和維護連接,以及確保數據包按照正確的方式組織、正確地校驗值和加密序列等。因此,在LL層的設備有如下5種狀態:
- 就緒態(Standby):上電后,鏈路層進入并保持就緒態,直到接收到主機的命令。狀態機的中心狀態,處于其它狀態下都可以進入到此狀態。
- 廣播態(Advertising):發送廣播報文和掃描響應,用于回應主動掃描的設備。可被發現或者可被連接的設備需要處于廣播態。向在一定區域內對其他設備進行廣播數據,也需要處于廣播態。為了成為廣播者,設備必須有發射機,但也可以有接收機。只支持廣播態的設備可以沒有接收機,以降低芯片成本。但是,實際中,出貨量大的收發機芯片往往比出貨量小的單發射機芯片更便宜。廣播態的設備停止廣播后可進入就緒態。在收到發起者的連接請求之后,廣播態的設備也可以進入連接態。
- 掃描態(Scanning):接收廣播信道的報文。掃描態有兩個子狀態:主動掃描和被動掃描。被動掃描僅接收廣播報文。主動掃描則發送掃描請求給廣播態設備,并獲取附加的掃描響應數據。掃描態的設備只能進入就緒態,轉換的條件是停止掃描。
- 發起態(Initialing):發起態設備偵聽自己試圖連接的設備,如果收到了來自該設備的廣播報文,鏈路層會向其發送連接請求并進入連接態,并假設廣播者也進入連接態。如果發起者不再試圖發起連接,也可以進入就緒態。
- 連接態(Connection):唯一一個用到數據信道的狀態,其他狀態均使用廣播信道,兩個設備只有在連接態中才能互相傳送數據。連接態只能通過斷開連接轉換為就緒態,連接態有兩個子狀態:主、從。
(3)前面說了,掃描態(Scanning)有兩個子狀態:主動掃描和被動掃描。
- 被動掃描:設備只能被動地掃描,不能發送任何報文。因此,被動掃描可以在只有接收機的設備中實現。被動掃描主要適用于低功耗場景,因為只進行掃描,不會主動發送任何請求,因此能夠節省電量。簡單的設備發現和監控應用中,只需要獲取設備的基本信息(如MAC地址和廣播數據),被動掃描足以滿足需求。
- 主動掃描:主機不僅監聽廣播信道的數據包,還會發送掃描請求(
SCAN_REQ
)給廣播設備。廣播設備接收到掃描請求后,會返回一個掃描響應包(SCAN_RSP
),提供額外的信息。掃描請求和響應報文都在廣播信道中傳輸。因為就能耗而言,掃描請求、響應這兩個額外的報文使得能耗更高。但是,主動掃描可以獲取更多數據,如設備名稱、服務數據等,因為它能接收額外的掃描響應包。(4)連接態也有兩個子狀態:主和從。下圖為進入主、從兩種狀態的方法。
- 主連接態:主連接態只能從發起態進入。為了成為主設備,它必須發起連接請求,掃描周圍的廣播設備,并選擇一個目標設備進行連接。一旦連接建立,主設備控制連接參數,如連接間隔、超時時間等,確保通信的穩定性。主設備必須定期向從設備發送報文。主設備通過發送數據包或空的PDU(協議數據單元)來維持連接,并可以請求從設備返回數據。
- 從連接態:從連接態只能從廣播態進入。為了成為從設備,它必須進行廣播,一旦接收到連接請求,要進行響應,最終建立連接。從設備沒有主動發送數據的能力,只有當主機發送連接事件后,從機正確接收主設備的報文才能發送數據進行回應。如果從設備有更多的數據需要發送,必須等待主設備發送另外的報文再回復。如果從機沒有數據需要發送,也可以忽略主機的報文,以達到節能作用。但是這個忽略次數是有限制的,由開發人員決定。超過一定次數,即認為斷開連接了,此時將從連接態轉換為就緒態。
HCI層
(1)從上面我們可以知道,
Controller
只實現鏈路層的狀態機,管理連接參數、信道更新、加密等鏈路控制。通俗來說,就是它只管數據收沒收到,至于數據安不安全、有什么含義、不同的設備之間能否兼容都不是由它來管。如果只需要進行點對點的簡單無線數據傳輸,不考慮安全性、兼容性等問題,理論上可以只要Controller
層就可以了。
(2)因為需要保證不同的設備之間具備兼容能力和安全性等問題,于是有了HOST
層來確保BLE
協議棧的上層協議和邏輯,包括設備發現、連接管理、數據傳輸和安全性等功能。
(3)如果HOST
層和Controller
層集成在同一款芯片上,理論上是可以不需要HCI
層的。但是現實情況不是這樣的,在手機這類復雜場景中,手機應用跑在AP
芯片上,然后手機廠商想自己設計一個BLE
協議棧(HOST
層工作)已達到定制的功能,這樣他們就只需要一個Controller
層的芯片。為了降低工作量,手機廠商不可能再去找一個包含Controller
層的AP
芯片,于是就有了如下的設計方案。AP
芯片跑HOST
層,然后外置一個Controller
層的芯片。
(4)但是這又誕生了一個問題,如果手機廠商認為,此時有一個更好的Controller
層芯片了,我要進行替換怎么辦呢?于是,為了降低替換的工作量,SIG
規定了一個HCI
層同一接口規范。
(5)上述方案是手機廠這類有一定藍牙開發能力的公司采取的方案,如果有一些小公司,也想使用藍牙功能,但是對藍牙技術又不太了解怎么辦呢?此時他們就可以買一些外置藍牙模塊,然后通過這些藍牙模塊的
AT
指令實現藍牙傳輸功能。此時需要注意,外置的藍牙模塊內部包含Controller
層和HOST
層,這個外置的藍牙模塊可以沒有HCI
層。
(6) 最后一種方案大多用于消費類電子,集成度很高,調調部參數可以直接使用。這類一般是半導體廠商半開源協議棧,基于特定的編譯器,把藍牙協議棧直接燒寫到藍牙芯片中,例如樂鑫
ESP32
、Nordic NRF51xxx
、TI CC2540
。這類型芯片不但可以直接使用藍牙功能,還能外接一些設備,例如LCD
顯示屏,音頻播放器等。可以做出的產品有藍牙手表,藍牙音頻等。這類型方案的芯片中也是內部包含Controller
層和HOST
層,可以沒有HCI
層。
舉例理解BLE體系結構
(1)通過上面的講解,相信依舊有很大一部分朋友依然搞不明白每一層到底做了什么,有什么意義。這很正常,這些概念和術語首次理解起來確實會很抽象,這里我將會舉一個簡單的例子再次講解說明促進理解。
(2)現在,我們假設手上的藍牙耳機把自己目前的電量狀態83%
(十六進制表示為0x53
)發給手機,應該怎么做?作為應用層開發者,肯定希望越簡單越好,最好可以只需要調用一個API
接口即可完成任務,例如調用Battery_Capacity_Send(0x53)
函數,藍牙耳機就可以將自己當前電量發送給手機。實際上,BLE
協議棧就是這樣做的,上層應用只需要調用一個API
,其余的BLE
協議棧都會幫你處理好。但是呢,從物理層的角度來看,真的是如下圖一樣,只發送了一個0x53
嗎?
(3)我能進行反問,就說明肯定不是這樣的。仔細想想,上面我們說了,
BLE
存在40
個信道,那么現在我們發送數據,到底是將0x53
發送到哪個信道里面呢?毫無疑問,肯定不可能把數據發送到40
個信道里面,那樣會造成信道的擁擠,并且能耗大大增加。為了解決這個問題,此時就需要引入LL層了。上層應用開發者調用Battery_Capacity_Send(0x53)
函數,但是這個函數其實就是LL_Send(Battery_Capacity,2402M)
函數的一次封裝,這樣標識電量數據固定在2402M信道頻率上進行傳輸。
void Battery_Capacity_Send(int Battery_Capacity)
{//假設電量數據固定在2402M信道頻率上/* Battery_Capacity : 電量信息* 2402M : 數據發送信道*/LL_Send(Battery_Capacity,2402M);
}
(4)現在我們知道了電量數據應該發送在哪個信道上了,但是,又需要考慮一個問題。這個數據到底是發送給誰呢?你總不可能一個設備占用一個信道吧,上面也說了,
BLE
存在自適應跳頻技術會不斷調整信道以達到信號的抗干擾能力。于是這里又需要引入另外一個概念 —— 訪問地址(access address
)。訪問地址(access address
)用于表明數據是發送給誰的,其中,0x8E89BED6這個訪問地址(access address
)比較特殊,它表示要發給周邊所有設備,即廣播。如果想讓藍牙耳機數據只被自己的手機收到,自己手機的數據只被自己的藍牙耳機收到,那么就需要生成一個獨特的隨機訪問地址(access address
),用于標識設備之間的連接。接下來,我將以廣播和連接兩種方式進行說明各層的作用。
廣播方式
(1)在廣播模式下,藍牙耳機被稱之為廣播者(
advertiser
),手機被稱為 掃描者(scanner
) 或者 觀察者(observer
)。因為是廣播,所以需要加上廣播地址,因此藍牙耳機的LL
層的API
實際上就應該是如下了:
void Battery_Capacity_Send(int Battery_Capacity)
{//假設電量數據固定在2402M信道頻率上進行廣播/* Battery_Capacity : 電量信息* 2402M : 數據發送信道固定為2402M* 0x8E89BED6 : 表示進行廣播*/LL_Send(Battery_Capacity,2402M,0x8E89BED6);
}
(2)但是,手機此時能夠同時接收到多個設備的廣播信息,為了確保收到的廣播信息是源自于藍牙耳機,此時還應當加上藍牙耳機的訪問地址(
access address
)。那么此刻LL
層的API
應當如下:
void Battery_Capacity_Send(int Battery_Capacity)
{//假設電量數據固定在2402M信道頻率上進行廣播/* Battery_Capacity : 電量信息* 2402M : 數據發送信道固定為2402M* 0x8E89BED6 : 表示進行廣播* 0xE1022AAB753B : 藍牙耳機的訪問地址(access address)*/LL_Send(Battery_Capacity,2402M,0x8E89BED6,0xE1022AAB753B);
}
(3)數據發送似乎沒有問題了,但是我們的LL層還需要考慮到數據在空中傳播過程中沒有被干擾,為此引入了
CRC24
對數據包進行檢驗 (假設為0xB2C78E
) 。那么此刻LL
層的API
應當如下:
void Battery_Capacity_Send(int Battery_Capacity)
{//假設電量數據固定在2402M信道頻率上進行廣播/* Battery_Capacity : 電量信息* 2402M : 數據發送信道固定為2402M* 0x8E89BED6 : 表示進行廣播* 0xE1022AAB753B : 藍牙耳機的訪問地址(access address)* 0xB2C78E : CRC24校驗*/LL_Send(Battery_Capacity,2402M,0x8E89BED6,0xE1022AAB753B,0xB2C78E);
}
(4)同時為了調制解調電路工作更高效,每一個數據包的最前面會加上1個字節的
preamble
(前導幀),preamble
一般為0x55
或者0xAA
,這里取0xAA。那么此刻LL
層的API
應當如下:
void Battery_Capacity_Send(int Battery_Capacity)
{//假設電量數據固定在2402M信道頻率上進行廣播/* 0xAA : 前導幀* Battery_Capacity : 電量信息* 2402M : 數據發送信道固定為2402M* 0x8E89BED6 : 表示進行廣播* 0xE1022AAB753B : 藍牙耳機的訪問地址(access address)* 0xB2C78E : CRC24校驗*/LL_Send(0xAA,Battery_Capacity,2402M,0x8E89BED6,0xE1022AAB753B,0xB2C78E);
}
(5)通過上面的分析我們即可得出數據的空中包如下(空中包用小端模式表示!):
(6)通過上面的封裝,似乎就萬事大吉了。但是,如果實測之后會發現,還有很多問題。
<1>當手機收到AAD6BE898E3B75AB2A02E1538EC7B2
這串數據的時候,它如何知道那個才是自己想要的電量數據呢?因此,我們這里需要在訪問地址(access address
)后面加入兩個字段Advertising Header
和長度字節。Advertising Header
用來表示數據包的LL
類型,包括可連接的無定向廣告(ADV_IND
)、可連接的定向廣告(ADV_DIRECT_IND
)、不可連接的無定向廣告(ADV_NONCONN_IND
)、可掃描的無定向廣告(ADV_SCAN_IND
)等。長度字節用來指明有效載荷(payload
)的長度。
<2>為了保持低功耗,藍牙設備不會一直打開射頻窗口,因此手機應該什么時候開啟設備窗口接收藍牙耳機的數據呢?
- Case1:當藍牙耳機發送數據包的時候,手機將接收窗口關閉,那么此時將無法成功通訊。
- Case2:手機打開接收窗口,但是藍牙耳機沒有發送數據包,顯然此時也將無法成功通訊。
- Case3:只有當手機打開接收窗口,同時藍牙耳機發送數據包,此時才能成功通訊。
綜上所述:
LL
層還必須定義通信時序,并且加入Advertising Header
和長度字節用于表示有效數據位置。
(7)通過上面的封裝,此時手機能夠收到有效數據
0x53
了。但是,各位再思考思考,藍牙耳機總不可能只給手機發送一個電量信息吧,還有其他信息,例如音頻信息。LL
層說了,它只負責收發數據,至于怎么處理,不歸它來負責。因此,現在接力棒來到了GAP
層了。
(8)GAP
層引入了LTV(Length-Type-Value)
結構來定義數據,比如020105
,02
-長度,01
-類型(強制字段,表示廣播flag
,廣播包必須包含該字段),05
-值。
(9)GAP
層并沒有定義電量信息類型數據,因此Type
我們需要設置為0xFF
,表示供應商自定義數據類型即04FF590053
,其中04
表示長度,FF
表示數據類型(自定義數據),0x0059
是供應商ID
(自定義數據中的強制字段),0x53
就是我們的數據(設備雙方約定0x53
就是表示電量)。
(10)因此,最終數據包變成了下圖所示:
<1>AA – 前導幀(preamble)
<2>D6BE898E – 訪問地址(access address),表示進行廣播
<3>60 – LL幀頭字段(LL header),表示非連接無向廣告事件
<4>0E – 有效數據包長度(payload length)
<5>3B75AB2A02E1 – 廣播者設備地址(advertiser address),即藍牙耳機地址
<6>02010504FF590053 – 廣播數據
- 020105 : 強制字段,必須包含,表示設備處于LE Limited Discoverable Mode,并且不支持BR/EDR。
- 04FF590053 :
04
表示長度,FF
表示自定義數據,0x0059
是供應商ID
(自定義數據中的強制字段),0x53
就是我們的數據<7>8EC7B2 – CRC24值
(10)以C代碼方式理解如下:
void GAP_Send(int LTV1, int LTV2,int Battery_Capacity)
{/* 2402M : 數據發送信道固定為2402M* 0xAA : 前導幀* 0xD6BE898E : 表示進行廣播* 0x60 : 表示非連接無向廣告事件* 0x0E : 有效數據包長度(payload length)* 0x3B75AB2A02E1 : 藍牙耳機地址* LTV1 : 廣播數據中的強制字段,表示設備處于LE Limited Discoverable Mode,并且不支持BR/EDR。* LTV2 : 廠商自定義數據,表示電量* Battery_Capacity : 電量信息* 0xB2C78E : CRC24校驗*/LL_Send(2402M,0xAA,0xD6BE898E,0x60,0x0E,0x3B75AB2A02E1LTV1,LTV2,Battery_Capacity,0xB2C78E);
}
void Battery_Capacity_Send(int Battery_Capacity)
{/* 020105 : 強制字段,必須包含,表示設備處于LE Limited Discoverable Mode,并且不支持BR/EDR。* 04FF5900 : 04表示長度,FF表示自定義數據,0x0059是供應商ID* Battery_Capacity : 電量信息*/GAP_Send(020105,04FF5900,Battery_Capacity);
}
(11)總結:
- 在廣播方式中,
LL
層主要負責知道通訊雙方地址,控制數據的狀態信息,確保數據無誤的上傳到HOST
層。GAP
層得到LL
層的數據,并將數據封裝成相應的含義。(12)現在我們再回過頭來看看上面的這個體系結構,是不是就能夠理解
GAP
層為何會貫穿整個HOST
層了呢?原因很簡單,如果進行廣播,只需要LL
層和GAP
層即可,因此GAP
層會貫穿整HOST
層。
連接方式
(1)通過上面廣播的例子,我們理解了
GAP
層和LL
層作用。現在我們看看連接方式是怎么樣的呢。首先,我們需要搞明白,手機和藍牙耳機的連接(connection
)是什么意思。
(2)以有線通訊為例,例如手機通過數據線連接電腦進行通訊,這個過程叫做連接。數據線將兩個設備相連,實際上是讓2個設備有共同的通信媒介,并讓兩者時鐘進行同步。藍牙連接也是同理,手機和藍牙耳機建立藍牙連接,就是讓手機和藍牙耳機兩者一對一的同步成功。其具體包含以下方面:
- 手機和藍牙耳機對接下來要使用的物理信道達成一致。
- 雙方建立一個共同的時間錨點,也就是說,把雙方的時間原點變成同一個點。
- 兩者時鐘同步成功,即雙方都知道對方什么時候發送數據包什么時候接收數據包。
- 連接成功后,手機和藍牙耳機通信流程如下所示:
(3)一旦手機(Master) 和藍牙耳機(Slave) 連接成功,手機(Master) 將會以
CI(connection interval)
這個間隔向藍牙耳機(Slave) 發送數據包,而藍牙耳機(Slave) 也會周期性以CI(connection interval)
為間隔打開射頻窗口來接收手機(Master) 的數據包。同時,按照藍牙規范要求,當藍牙耳機(Slave) 收到手機(Master) 的數據包150us
后,藍牙耳機(Slave) 需要從發送狀態切換為接收狀態,把自己的數據發送給手機(Master) 。同理,手機(Master) 在發送完數據包150us
后,需要從發送狀態轉換為接收狀態。由此可見,連接狀態下,手機(Master) 和藍牙耳機(Slave) 的射頻發送和接收窗口都是周期性地有計劃地開和關,而且開的時間非常短,從而大大降低系統功耗并大大提高系統效率。
(4)明白了連接狀態下手機(Master) 和藍牙耳機(Slave) 的收發方式,那么我們就來看看數據包如何發送。依舊是以藍牙耳機(Slave) 將電量狀態83%
(十六進制表示為0x53
)發送給手機(Master) 。
- 應用層:只需要調用
Battery_Capacity_Send(0x53)
即可將電量信息發送出去。- GATT層:藍牙耳機(Slave) 數據
0x53
發出來了,手機(Master) 不知道這個0x53
是啥意思啊。于是GATT
層就需要定義數據的類型。例如這里創建一個Flag
為0x0013
表示電量這種數據類型,這樣GATT
層把數據打包成130053
(小端模式!)- ATT層:藍牙耳機(Slave) 把電量數據
0x53
發送給手機(Master) 了,但是這樣又存在一個問題。手機(Master) 怎么知道這個數據到底是用來干嘛的呢?比如這個電量數據可以是將手機(Master) 的電量修改為0x53
,或者是只是需要讀到這個數據就可以。ATT
層有讀/寫/notify
/indicate
等等通訊命令,我們這里選擇notify
命令0x1B
,表示發送數據更新,不需要回復。這樣數據包變成了:1B130053
(小端模式!)- L2CAP層:數據包封裝好了之后,問題是現在這個數據包發到哪個邏輯通道里面。這里我們指定邏輯通道編號
0x0004
(表示ATT
命令),最后還需要加上ATT
數據長度0x0004
加在包頭,最終數據就變為:040004001B130053
。- LL層:這一層要干的活上面已經說過了,因此不做贅述。
(5)最終數據包長這樣:
- AA : 前導幀(preamble)
- 0x50655DAB : 訪問地址(access address),即手機地址
- 1E : LL幀頭字段(LL header)
- 08 : 有效數據包長度(payload length)
- 04000400 : ATT數據長度,以及L2CAP通道編號
- 1B : notify command
- 0013 : 電量數據handle
- 53 : 真正要發送的電量數據
- F650D5 : CRC24值
參考
(1)紅旭無線:BLE基礎知識
(2)C站:【低功耗藍牙】① 藍牙廣播數據格式分析
(3)谷雨文檔中心:BLE技術揭秘
(4)TI官方藍牙BLE 低功耗技術教程:藍牙低功耗技術及其特點
(5)C站:藍牙4.0、經典藍牙、BT、BLE的關系與區別
(6)博客園:深入淺出低功耗藍牙(BLE)協議棧
(7)博客園:三種藍牙架構實現方案(藍牙協議棧方案)
(8)知乎:(通信算法系列)藍牙BLE物理層算法詳解—GFSK調制與解調(1)
(9)簡書:BLE 信道和自適應跳頻
(10)C站:一文讓你徹底了解市面藍牙架構,無憂藍牙產品選型
(11)博客園:詳解BLE空口包格式—兼BLE Link layer協議解析
(12)[艾克姆科技教程]nRF52832開發指南.pdf
(13)低功耗藍牙開發權威指南.pdf
(14)劉權-BLE4.0低功耗藍牙協議總結.pdf