send函数 获得已发送数据长度_蓝牙BLE开发1--起因与回调函数
1 起因
筆者在開發(fā)藍牙芯片CC2540,試圖取實現(xiàn)大量數(shù)據(jù)的BLE透傳功能,在認真學習了藍牙4.0協(xié)議標準以及TI提供的SDK說明,我總結(jié)了兩個發(fā)送函數(shù),以及兩個接收函數(shù)的位置。
兩個發(fā)送函數(shù)包括
1 當我的設備處于主機角色的時候,發(fā)送數(shù)據(jù)給從機的函數(shù),此時采用寫特征值的方法。
void CC2541_send_as_central(uint8 * buf , uint16 len);2 當我的設備處于從機角色的時候,發(fā)送數(shù)據(jù)采用notify方法
void CC2541_send_as_periph(uint8 * buf , uint16 len);理所當然的可以將兩個發(fā)送函數(shù)合并為
CC2541_send(role_t role , uint8* buf , uint16 len);閱讀TI提供的藍牙協(xié)議棧函數(shù),各種機制,函數(shù)回調(diào)非常復雜,但是通過網(wǎng)上其他人的文章我找到了插入位置。
兩個接收的位置
1 做從機的時候,接收數(shù)據(jù)事件發(fā)生在profile里的特征值被修改后發(fā)生。
static void TRANSFERProfileChangeCB(uint8 paramID) {uint8 bBuf[20] = { 0 }; uint8 rltByteNum=0; //...省略部分 TRANSFERProfile_GetParameter(TRANSFERPROFILE_CHAR1, bBuf,&rltByteNum); //通過get函數(shù)獲得值修改后的特征值,存放在bBuf數(shù)組里 //在這里得知了獲取的數(shù)據(jù)bBuf 以及長度 rltByteNum }2 做主機的時候,接收數(shù)據(jù)事件發(fā)生在GATT的MESSAGE事件中,因為作主機的時候,獲得數(shù)據(jù)實際上就是得到了從機的notify。(從機給主機發(fā)數(shù)據(jù)采用notify,類似中斷一樣,強行告訴主機,我有數(shù)據(jù)發(fā)給你,主機還有一個read方法可以訪問從機的數(shù)據(jù),但是不是從機主動發(fā)起的)。
static void simpleBLECentralProcessGATTMsg(gattMsgEvent_t *pMsg) {//...函數(shù)里面包含了各種GATT的消息,通過判斷pMsg->method來判斷這是哪一種消息類型,很明顯simpleBLECentralProcessGATTMsg函數(shù)是一個系統(tǒng)的回調(diào)函數(shù),下文分享筆者對回調(diào)的理解,為文章簡潔,僅復制相關(guān)代碼else if ((pMsg->method == ATT_HANDLE_VALUE_NOTI)) {//檢查profile Handle號,由BTools獲得if (pMsg->msg.handleValueNoti.handle == 0x0025) { //獲得的數(shù)據(jù) pMsg->msg.handleValueNoti.value //獲得數(shù)據(jù)的長度是 pMsg->msg.handleValueNoti.len}}}筆者想實現(xiàn)的功能是 主從一體的藍牙透傳模塊,數(shù)據(jù)由外部經(jīng)過UART傳入藍牙芯片,藍牙芯片通過調(diào)制藍牙信號發(fā)送給另一個藍牙芯片,另一個藍牙芯片經(jīng)過UART傳給終端設備。
因此,筆者還得研究關(guān)于TI提供的UART工具。找到了一個發(fā)送函數(shù),以及一個在回調(diào)函數(shù)中的接收位置。
發(fā)送函數(shù)
void NPI_WriteTransport(uint8* buffer , uint16 len);接收位置
static void simpleBLE_NpiSerialCallback(uint8 port, uint8 events) {if (events & (HAL_UART_RX_TIMEOUT | HAL_UART_RX_FULL)){uint8 numBytes = 0;numBytes = NPI_RxBufLen(); //讀出串口緩沖區(qū)有多少字節(jié)if (numBytes == 0) {return;} else{uint8 *buffer = osal_mem_alloc(numBytes);if (buffer){//數(shù)據(jù)指針是 buffer 長度是 numBytesosal_mem_free(buffer); } }} }回調(diào)函數(shù)的理解
如果你自己也經(jīng)常使用函數(shù)指針,那么對回調(diào)應該很容易理解。
例如我自己是一個非常崇尚代碼完美主義的人,我的main函數(shù)是這樣寫的,寫的很漂亮。
int main(void){ mySystem_init(); Loop: mySystem_handle(); User_handle(); goto Loop; }注意這里mySystem_handle 和 mySystem_init是我寫的代碼,User_handle是我預留給用戶去寫的!
這個main函數(shù)的結(jié)構(gòu)就是由三塊構(gòu)成的,mySystem_init 和 mySystem_handle 以及User_handle ,類比藍牙協(xié)議棧,mySystem_init和mySystem_handle實現(xiàn)了藍牙協(xié)議棧的基本功能,我想絕大多數(shù)人是不愿意修改這部分代碼的,因此不能動這部分代碼。
TI的作者工程師也不希望你修改這段代碼的代碼結(jié)構(gòu)!于是作者們會給你提供User_handle的入口給你。
例如 User_handle會這樣寫
typedef void * function_pointer(void);// 定義函數(shù)指針類型 function_pointer User_app; void User_handle(){ User_app(); } void register_user_app(function_pointer ){ User_app = function_pointer ; }這樣一來,你可以使用register_user_app函數(shù)來修改主函數(shù)的執(zhí)行內(nèi)容,轉(zhuǎn)到你配置的程序流中,但是不修改原有的工程運行結(jié)構(gòu)。
BLE的協(xié)議棧很復雜,一般人不應當輕易的改變他的工程結(jié)構(gòu),所以TI的工程師們選擇把回調(diào)函數(shù)放給開發(fā)者。
上文中的simpleBLECentralProcessGATTMsg等函數(shù)都是回調(diào)函數(shù)。
回調(diào)函數(shù)怎么傳值?
還是以app_handle為例
typedef void * function_pointer(int);// 定義函數(shù)指針類型 function_pointer User_app; void User_handle(){ User_app(100); } void register_user_app(function_pointer ){ User_app = function_pointer ; } void test_task(int a){printf(“得到的數(shù) %d ”,a); } //在主函數(shù)中注冊 register_user_app(test_task);運行原有工程結(jié)構(gòu)后,test_task就獲得了100這個值。
在BLE的SDK中大部分都是依靠這樣的回調(diào)來進行傳值,包括我之前總結(jié)的幾個接收數(shù)據(jù)的位置!
現(xiàn)在遇到的問題是:
1 在回調(diào)函數(shù)中得到的數(shù)據(jù)不完整,舉個例子來說,外部通過UART傳進來的數(shù)據(jù),不止一次的進入回調(diào)函數(shù),每次進入回調(diào)函數(shù)獲得的數(shù)據(jù)長度都不同,但是系統(tǒng)能保證的是不會少數(shù)據(jù),但是每次進入的次數(shù)都不一樣,這給最終的數(shù)據(jù)處理帶來麻煩,因為最終數(shù)據(jù)處理肯定得是一個完整的包。
2 藍牙發(fā)送速度與串口接受速度不一致,有快有慢,會出現(xiàn)數(shù)據(jù)覆蓋的現(xiàn)象。
筆者采用兩種方法解決這個問題,
1 通過超時判斷
2 通過循環(huán)隊列緩存
后面慢慢寫自己解決問題的過程,分享解決的過程給大家
總結(jié)
以上是生活随笔為你收集整理的send函数 获得已发送数据长度_蓝牙BLE开发1--起因与回调函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python编程环境要求_python公
- 下一篇: 异常数据4种剔除方法_数据分析系列 22