最近在使用芯海的藍牙芯片開發(fā)一個小項目,功能其實很簡單,類似于防丟器,只不過這個項目中的主機也是藍牙芯片,而不是手機。這就不得不去學(xué)習(xí)更多的協(xié)議棧相關(guān)的東西。然而,最讓人頭疼的并不是藍牙協(xié)議本身的學(xué)習(xí),畢竟這是SIG發(fā)布的通行的一套協(xié)議棧,無論誰家的藍牙都應(yīng)遵守。最讓人頭疼的是,每一家做藍牙芯片的廠家,都有一套自己實現(xiàn)SIG BLE協(xié)議棧的源代碼,這時候可是真的看出條條大路通羅馬了。
用硬件來比喻的話,就相當(dāng)于SIG 出了一個原理圖,各家廠家按照原理圖畫了各自的線路板,學(xué)藍牙開發(fā)就像是看那個亂七八糟PCB gerber圖紙,各家都不一樣。
我最早接觸藍牙用的是nordic,天天纏著FAE折騰了一個月才熟悉了它的那套代碼,后來還直接把它的DFU重構(gòu)了一下,適應(yīng)了自己公司的OTA協(xié)議。后來開發(fā)泰凌微,又是一套新東西,不但整套源代碼框架不同,就連IDE也是換了,用起來就像從現(xiàn)代文明一下進入刀耕火種一樣。以至于從那以后,但凡有人給我推薦藍牙,我都先問問能不能在MDK上開發(fā),工具還是用順手的好,已經(jīng)不是調(diào)戲各種工具的年紀(jì)了。
還有一個點,就是這些藍牙的協(xié)議棧都需要跑在一個小型的操作系統(tǒng)上,嚴(yán)格意義上來說,這只是一個稍微復(fù)雜的調(diào)度系統(tǒng),這又是一個非標(biāo)的東西,所以各家系統(tǒng)層的接口又不一樣,比如磐啟微的藍牙是基于一個開源的Zephyr系統(tǒng),我剛一拿到廠家的SDK都不知道從哪入手,第一個函數(shù)去哪里找都費勁,所以說為啥MDK用的人多,即便是企業(yè)用盜版的都不愿用那些開源的五花八門的東西,簡單意味著綜合成本低。
昂瑞微的藍牙和nordic有點類似,杰里的開發(fā)起來工具就又得費點勁兒了,現(xiàn)在我弄得這個芯海的藍牙,不確定是借鑒的哪一家的協(xié)議棧,log信息雖然很多,也是繞了一個星期才將將繞明白從開機啟動到廣播,再從發(fā)起Connect到向從機發(fā)數(shù)據(jù),真的是繞來繞去,一會處理osal的message,一會有處理某一個應(yīng)用的message,都是從底層一個消息隊里取出來的,不同的地方都有相同的事件,再在回調(diào)函數(shù)里面處理一遍,真的暈。所以,藍牙這東西,選擇兩三個平臺就足夠折騰了。去年我在推廣方案的時候,銷售的同事三天能給整倆藍牙進來,根本學(xué)不過來,關(guān)鍵在于學(xué)習(xí)這些不重樣的個性協(xié)議棧沒啥意義,我本身更想關(guān)注的是應(yīng)用怎么寫。
這么看來,當(dāng)年GD把寄存器地址設(shè)計成和ST一模一樣真的是有遠見,從推廣上來說,這起到了決定性作用。但是藍牙沒辦法,這個行業(yè)沒有一家獨大的的情況,即便是Nordic,TI,賽普拉斯,NXP等在市場上也只能算是平分秋色吧。回到應(yīng)用開發(fā)上,協(xié)議棧真的是折騰的我眼花繚亂,整得我整個人都不好了,基本沒心情好好寫應(yīng)用。這不,RSSI數(shù)據(jù)又出問題了,本來都在-30dbm左右,中間總是突然竄出一個-90來,這必須得加一個濾波才行。思來想去選擇了滑動窗口濾波器,在窗口內(nèi)把最大最小值去掉。原來寫過,根本不想去翻了(我必須自己寫一個算法庫,可以隨手拖到工程就能用的那種),正著急的時候,想起來GPT,現(xiàn)在還是不太習(xí)慣身邊有這么個大神啊。我便向他請教:
#include <stdio.h> #include <limits.h> #define WINDOW_SIZE 10 int window[WINDOW_SIZE]; int num_elements = 0; void update_window(int new_value) { if (num_elements < WINDOW_SIZE) { window[num_elements++] = new_value; } else { // 窗口已滿,滑動窗口,丟棄最舊的值 for (int i = 1; i < WINDOW_SIZE; i++) { window[i-1] = window[i]; } window[WINDOW_SIZE-1] = new_value; } } double compute_filtered_output() { if (num_elements == 0) return 0.0; // 沒有數(shù)據(jù) int max = INT_MIN; int min = INT_MAX; int sum = 0; for (int i = 0; i < num_elements; i++) { if (window[i] > max) max = window[i]; if (window[i] < min) min = window[i]; sum += window[i]; } // 減去最大值和最小值,再計算平均 sum -= (max + min); return (double)sum / (num_elements - 2); } int main() { // 模擬輸入數(shù)據(jù) int data[] = {5, 10, 8, 12, 20, 1, 30, 25, 15, 50, 45, 20, 25, 10, 5}; int n = sizeof(data) / sizeof(data[0]); for (int i = 0; i < n; i++) { update_window(data[i]); if (num_elements > 2) { printf("Filtered output: %.2fn", compute_filtered_output()); } } return 0; }
它還貼心的給了個說明:
真是暖心極了!