原文網址:http://www.deyisupport.com/question_answer/wireless_connectivity/bluetooth/f/103/t/61462.aspx
看了下問題,發現不太會回答了,很久沒弄,全忘記了,只好貼出之前的一些東西,幫助初學者入下門吧:
一、初識BLE
1、藍牙4.0協議:BR/EDR(標准藍牙)+ BLE 目前
CC2540硬件只支持BLE這種單模無線標准,不能夠與4.0以前的版本通信。
2、針對
CC2540
BLE-Stack 重點學習了該協議棧的結構,TI的藍牙平台支持兩種協議棧/應用配置:單一設備配置、網絡處理器配置(application/profile在另外的處理器或者PC上的應用)。
3、重點學習了協議棧最頂層的兩個通用profile:GAP(通用接入規范)、GATT(通用屬性規范)。
4、GAP主要負責處理設備的接入方式以及接入的過程:設備發現、鏈路建立、鏈路終止、啟動安全功能、設備配置(主要是連接參數的配置)。
5、GATT主要完成服務器和客戶端之間通信的相關子過程。
6、BLE支持40個通道的跳頻機制,其中3個通道用於advertise,剩下的用於數據通信;而BR的通道數在80,相比而言BLE的機制更加節電。兩者的跳頻偏移分別為2MHz、1MHz。
7、OS抽象層相關過程學習,如何配置一個新的任務、任務優先級、事件觸發、消息傳遞等。
8、存在的問題:搞不清楚BLE協議內部的GAP、GATT profile與application profile的聯系與區別,是否BLE能夠在app上添加:A2DP(藍牙立體聲音訊傳輸協議)、HID(人機界面規范)等這些規范。
二、開始了解stack
進一步學習GAP,主要扮演四種角色:broadcaster(廣播者)、obseerver(觀察者)、peripheral(外圍)、central(中央)。
1、
BLE-Stack中有每一種角色的Sample程序,且正對不同的示例程序對應的lib也不相同,eg:
CC2540_ble_single_chip_peri.lib 、
CC2540_ble_network_processor_all.lib 等。
2、對於應用程序的profile需要按照規范自己編寫,目前ti提供幾個醫療上使用的profile,對於文件傳輸、音頻傳輸等profile,我的理解是BLE不適用於這些場合(參考wiki網上一些話題討論、BLE_TechDay_2011.pdf、 BLE_
CC2540_DeepDive_Training_2011.pdf 來源於wiki網)。
我理解的classic就是傳統的那種藍牙應用,BLE的應用主要是用於第一幅圖。BLE目前一個數據包支持的最大字節數為20Byte,基本上都是幾個字節的應用,ti例程。
3、在wiki網上找到一個相關的例子:Serial App 通過串口實現兩台PC之間的數據傳輸,打算從這個例子入手,在轉向USB的,初步看了一下這個Serial App,在該頁上能夠下載一個HCI Tester的腳本測試工具,並不是直接通過兩個串口實現數據傳輸,需要上層的profile和HCI Command。
4、Btool工具通過連接usb dongle看了一下軟件的選項,嘗試連接兩個usb dongle,在wiki上看到有人說能夠建立連接,實測無法搜索到設備。
5、初步計划先移植keyfob的程序到dongle上,實現兩個設備之間建立連接,keyfob通過一個按鈕觸發30s的dicoverable狀態,這時候啟動dongle進行scan等一系列操作。
三、摸着石頭過河
1、移植KeyFob例程到USB dongle上面,修改按鍵等宏,刪除了加速度、蜂鳴器程序,該Sample與HostTestApp之間可以建立鏈接並通信,參考wiki地址如下:
存在的問題:
1)KeyFob例程使用按鍵啟動30秒的advertising,此后由Btool通過USB dongle向KeyFob(另外一個dongle模擬的)發送請求鏈接的命令。按鍵使用輪詢的方式能夠正常進入相應事件,使用IO中斷的方式無法進入,檢查了很多遍未找到原因所在。
2)建立鏈接之前USB dongle需要Scan設備,這是在KeyFob發送advertising之后,會存在無法查找到設備,猜測是由於使用了輪詢按鍵的方式導致的。
2、
CC2540的接收發送緩存都為128Byte:
再去看了下之前wiki上看到的關於發送字節不超過20Byte的說法,是限制在10ms以內的。
3、Btool建立連接的狀態:
[25]中表明GAP_EstablishLink Success,在Read/Write選項中通過操作關鍵字、描述符來實現通信中數據的交互,參考1中網址。
eg:通過USB dongle讀取KeyFob電池的電量等,實際讀取錯誤,無效的數據(我想是否需要購買一個keyFob加快開發)
4、想要實現兩台PC之間的通信:
1)如果采用HostTestApp的方式,上位機需要與Btool類似,產生HCI Command讀寫數據也需要相關命令和操作序列。
2)采用單芯片方式(區別於網絡處理器模式,HostTestApp模式),不直接和外界PC或者MCU交互。
最終如何選擇,還需要花時間進一步學習
BLE-stack。
四、站的高一點點
1、基本上搞清楚一個應用程序由哪些部分組成,需要做哪些初始化,App函數的位置,以及各種事件的響應方式。
2、關於
CC2540 RF寄存器的問題:
1)User Guide上面未詳細介紹寄存器的各個位,只有簡單的寄存器說明,查閱E2E確定TI未開放,所以無法編寫RF部分的驅動。
2)TI建議的方式:Note, that OSAL and HAL source is avail, a free sniffer is avail, and RF studio can access RF directly.
3)打開RF Studio
CC2540界面,好好看看有哪些部分,對於測試等等有很大用處的。

原則上能夠進行數據包的收發測試。
3、查閱相關TI Bluetooth的器件,簡單對比如下:

五、開始搞起了
通過對TI_BLE_Vendor_Specific_HCI_Guide.pdf 和e2e上相關討論的學習,總結如下;
1、可以通過HIC Command對
CC2540進行相關操作,總體描述見下圖。
2、關於
CC2540 Production Test Mode參考網址:
3、創建
CC2540測試工程文件,主要是刪除協議部分的和某些無關的OSAL初始化程序。
uint16 UserApp_ProcessEvent( uint8 task_id, uint16 events )
{
if ( events & USER_START_DEVICE_EVT )
{
HCI_EXT_SetTxPowerCmd (HCI_EXT_TX_POWER_4_DBM);
HCI_EXT_ModemTestTxCmd (HCI_EXT_TX_MODULATED_CARRIER,37);
//HCI_EXT_ModemHopTestTxCmd ();
//HCI_EXT_ModemTestRxCmd (37) ;
//HCI_EXT_EndModemTestCmd ();
return ( events ^ USER_START_DEVICE_EVT );
}
return 0;
}
主要涉及的函數:
HCI_EXT_SetTxPowerCmd 設置發射功率
HCI_EXT_ModemTestTxCmd 開始連續的發送測試,需要指定信道和是否調制
HCI_EXT_ModemHopTestTxCmd 開始連續的發送測試,發送37Byte 數據包(偽隨機數),且信道從0-39遞增
HCI_EXT_ModemTestRxCmd 開始接收測試,需要指定信道
HCI_EXT_EndModemTestCmd 停止Modem測試
六、簡單分析
1、以Central、Peripheral之間通信為例,學習BLE-stack設備之間的數據通信:
1)Peripheral 通過GATT_Notification函數實現數據發送,這種情況下外圍設備扮演Seriver(注1)。
2)Central 通過GATT_MSG_EVENT事件觸發任讀取 gattMsgEvent_t 結構體中的 msg對應的 Indication and Notification messages(參考程序中相關結構體)實現數據接收,這種情況下中央設備扮演Client(注2)。
注1:
static attHandleValueNoti_t *pReport= NULL;
if ( GATT_Notification( 0, pRepor, FALSE )==SUCCESS)
{
//用戶可在這里進行發送成功后的相關操作,pRepor為待發送的Notification
}
/**
* Handle Value Notification format.
*/
typedef struct
{
uint16 handle; //!< Handle of the attribute that has been changed (must be first field)
uint8 len; //!< Length of value
uint8 value[ATT_MTU_SIZE-3]; //!< New value of the attribute
} attHandleValueNoti_t;
注2:
if ( pMsg->method == ATT_HANDLE_VALUE_NOTI ||pMsg->method == ATT_HANDLE_VALUE_IND )
{
attHandleValueNoti_t noti;
dataCount = dataCount+ 1;
LCD_WRITE_STRING_VALUE( "Data Cnt: ", dataCount, 10, HAL_LCD_LINE_1 );
noti.handle = pMsg->msg.handleValueNoti.handle;
noti.len = pMsg->msg.handleValueNoti.len;
osal_memcpy(¬i.value, &pMsg->msg.handleValueNoti.value,noti.len);
//用戶可在這里操作¬i,通過串口發送或者USB發送出去等等
}
2、建立連接的某些細節函數還未搞清楚,發送數據所能夠被用戶看到的最底層函數如1中描述。
3、進一步計划:
1)通過Central、Peripheral之間通信為基本模板先實現設備之間建立連接,然后使用1中方式實現數據交換。
2)在1)的基礎上加入串口通信實現串口之間的通信,並能夠通過串口控制設備建立連接的過程等。
3)使用Dongle實現USB功能,主要是將HostTestApp中的CDC類USB程序提取出來,實現Dongle與PC間數據通信,不涉及
BLE-stack協議棧相關只是一個USB程序。
4)由於CDC類的USB相對而言要簡單一些,上位機編程可以使用串口,在3)的基礎上再去實現HID,具體關於這一部分USB驅動和上位機等還沒有很清晰的思路。
4、需要做的事情:
1)使用購買的
CC2540驗證鏈接建立數據交互的功能。
2)實現
CC2540的UART與PC通信的功能。
3)使用Dongle實現CDC類USB與PC通信的功能。
4)使用Dongle實現HID類USB與PC通信的功能。
附件:

GATT_Notification、GATT_Indication函數的說明,不能夠獨立運行需要在建立連接的基礎上。
七、換個硬件看看
1、使用購買的CC2540模塊實驗,修改了Debug接口,能夠采用TI的CCDebug下載光盤自帶的程序測試正常。
光盤例程使用
BLE-Stack 1.1修改,分別下載KebFob和HostAppTest。
2、下載BLE-Stack 1.21中例程KebFob和HostAppTest測試連接過程也正常。
圖1:測試UUID讀取關鍵字成功,KeyFob的電量(百分比)

圖2:測試Adv.Commands 讀取RSSI值

3、使用BLE-Stack 1.1例程中的虛擬鍵盤,測試連接失敗(光盤和協議棧原始例程都測試了),用HostAppTest測試搜索到的設備地址與待綁定的地址是匹配的。
待做的事情:
1)搞清楚3連接過程中出現的問題。
2)花時間去熟悉API函數以及相關的結構體。
八、開始做硬件了
1、參考《CC2540EM_discrete_schematic.pdf 》繪制CC2540無線模塊原理圖。
1)引出P0(8pin)、P1(8pin)、P2(3pin)、電源(2pin)、USB(2pin)、RESET(1pin)共計24pin。
2)不知引腳排列是否合理,目前的排列有利於模塊布線。
見附件:
CC2540_BLE_RF.pdf
1)添加低功耗加速度傳感器CMA3000(用於計步等,可缺省不焊接)。
2)添加CP2102用於USB轉串口,通過UART打印字符便於調試等。
3)可選USB供電、CCdebug供電、CR2032紐扣電池供電。
4)設計中多處采用0R電阻,便於二次修改。
見附件:
CC2540 Board.pdf
3、閱讀BLE的宣傳資料,覺得不適合在底板上添加傳統的傳感器,不知道是否需要添加傳感器?
見附件:TI BLE @ CES.pdf
九、閑置階段,隨便玩玩
1、原理圖修改、檢查:
1)添加PCB天線和外置天線。
2)添加OLED顯示、電源指示燈、添加撥碼開關。
2、OLED選擇了一款內置升壓電路的型號與之前的像素一致:
1)選取內置升壓的OLED省去了升壓電路的設計。
2)實際經過調研科選擇
TPS61040作為升壓芯片,滿足需求(考慮到電感、續流二極管等物料不好采購的問題)。
3、確定底板上物料在ERP中的型號,主要的器件目前都已經確定、包括接插件。
4、調試CC2540的UART,調試OK能夠打印信息:
1)發現在Advertising過程中會出錯(測試了多種發送情況,確認是Advertising時RF引起的)。
2)使用DMA、ISR都是同樣的情況。

十、開始玩弄她吧
1、CC2540通信建立過程調試:
1)找到UART在advertising過程中發送數據亂碼的問題,使能低功耗(PWRMGR_BATTERY)會伴隨主時鍾的切換,導致波特率不穩定照成的,關閉低功耗數據正常,有待進步一學習,暫時不做深入研究。
2)在調通串口的基礎上實現基本的通信建立過程調試,主要是通過peripheral、central的例子,實現了PC通過串口向peripheral設備發送數據通過無線被central設備接收再通過串口傳輸至另一台PC。
Peripheral(Send):
01 82 fe 07 00 05 11 11 11 11 11
01 82 fe 07 00 05 22 22 22 22 22
Central(Receive):
04 FF 0D 1B 05 00 01 00 07 07 00 11 11 11 11 11
04 FF 0D 1B 05 00 01 00 07 07 00 22 22 22 22 22
以上參考:附件一、附件二。
2、Blood Pressure例程測試:
1)在新版本BLE-Stack1.21中未提供BP的Collector,只有一個BP Sensor,所以還需要花點時間建立Collector的工程。
2)在TI Wiki上找到了關於BLE-Stack1.1關於BP演示的說明,需要一個BleHealthDemo(C#開發)上位機的配合,Collector是工作在Network Process模式下。
測試效果參考:附件三。
3、開會提出的問題小結:
1)為什么要有Proflie?
A:Profile由藍牙SIG發布,描述了不同設備使用藍牙協議棧時的差異性和統一性。比如一個血壓計,大家都按照這個BP Profile、BP Service來進行規范定義,那么一個BP收集器就能夠收集不同廠家生產的BP Sensor測量的血壓值等。如果沒有Profile關有協議那么大家都只能閉門造車,我生產的手機帶藍牙功能,那么你使用的藍牙耳機就必須是我生產的,因為那些數據格式、設備描述等只有我知道,所以才有音頻Profile(A2DP)之后大家按照這個規范去嚴格定義自己的設備就可以了。
2)BT流行版本的Profile比較:
我所理解的在BT2.0、BT2.1、BT3.0這些版本能夠使用傳統Profile,而4.0之后會多出一部分GATT-Basic規范Profile。
這里我們需要理解的是:
BT2.0 = Core Version2.0 +EDR
BT2.1 = Core Version2.1 +EDR
BT3.0 = Core Version3.0 +HS
BT4.0 = Core Version4.0 +BLE = BR/EDR + BLE(這里和以往不同,V4.0有兩個核心,
CC2540只有BLE)
對於血壓計:
V4.0 版本使用BP Profile(Blood Pressure Profile)+ BP Service
V4.0 之前版本使用HD Profile(Human Device Profile)
HD Profile(健康規范)包括 BP Profile(血壓規范) + HT Profile(溫度規范)+ ……
這些規范可以從官方網站查看:
以上參考:附件四、附件五。
3、附件:
附件一

附件二

附件三

附件四

附件五

十一、血壓計分析
1、Blood Pressure示例程序占用資源(256K Flash + 8K RAM):

2、Blood Pressure Profile規定的數據格式:
3、Profile 定義了數據格式、過程、服務的UUID等:
以上這些會在協議屬性表中體現,而這個屬性表會通過相關API將他作為參數傳給協議棧。
static gattAttribute_t bloodPressureAttrTbl[] =
{
// BloodPressure Service
{
{ ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
GATT_PERMIT_READ, /* permissions */
0, /* handle */
(uint8 *)&bloodPressureService /* pValue */
},
// 1. Characteristic Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&bloodPressureTempProps
},
// 2. Characteristic Value
{
{ ATT_BT_UUID_SIZE, bloodPressureTempUUID },
0, //return READ_NOT_PERMITTED
0,
&bloodPressureTemp
},
// 3.Characteristic Configuration
{
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *)&bloodPressureMeasConfig
},
// 4.Presentation Format
{
{ ATT_BT_UUID_SIZE, charFormatUUID },
GATT_PERMIT_READ,
0,
(uint8 *)&bloodPressureTempFormat
},
//////////////////////////////////////////////
// IMMEDIATE MEASUREMENT
//////////////////////////////////////////////
// 5.Characteristic Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&bloodPressureImeasProps
},
// 6.Characteristic Value
{
{ ATT_BT_UUID_SIZE, bloodPressureImeasUUID },
0, //return READ_NOT_PERMITTED
0,
&bloodPressureImeas
},
// 7.Characteristic Configuration
{
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *)&bloodPressureIMeasConfig
},
//////////////////////////////////////////////
// FEATURE
//////////////////////////////////////////////
// 8.Characteristic Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&bpFeatureProps
},
// 9.Characteristic Value
{
{ ATT_BT_UUID_SIZE, bpFeatureUUID },
GATT_PERMIT_READ,
0,
(uint8 *)&bpFeature
},
};
好吧,第一章分享到這里結束了,只是簡簡單單的幫助初學者入門,權當玩玩,專業開發者請忽略。不排除自己理解和排版造成的問題,請自行判斷,謝謝。
后續會上傳代碼和相關文檔,並繼續開貼說第二章
哈,希望ti能給個包包硬盤啥的,鼓勵一下。