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