嵌入式應用程式碼框架(C 語言訊號量 或狀態機)ZosPost
應用場景:
在嵌入式工作中 ,大的專案通常是多人配合完成。每個人程式碼風格,命名習慣,工作思路 都可能不一樣。那程式碼在整個合過程中或後期維護都 是一件很頭痛的事情為此我整理了這個開源庫,希望能對有這方面困擾的朋友有一定幫助。
在專案開發過程中,經常遇到以下情況:
1、某個方法在操作某個硬體時,需要等待一段時間硬體才響應。
2、某個方法在操作某個硬體時,不知道硬體什麼時候才響應。
3、在專案整合過程中,發現同事某些無用功能功,因為不瞭解同事程式碼邏輯和風格無法去除。
4、得到同事一大堆結口函式,使用時無從下手。
為解決這些問題下面就來看一下我認為可行的辦法:
先來看一段程式碼:
ButtonClass_t *ButtonThis=NULL;
ButtonThis=CreateButtonClassMallocNew(); ButtonThis->ButtonDownEvent=ButtonDownEvent;//按下事件回撥 ButtonThis->ButtonUpEvent=ButtonUpEvent; //擡起事件回撥 ButtonThis->ButtonGet=ButtonGet; //輸入模擬讀取 ButtonThis->ButtonSetMode(ButtonThis,TriggerChickOne_e);//按下一次觸發一次
用高階語言的人一個 這個是不是很面熟。沒錯 這特別像C++中的類,但是這個並不是類,而是C的結構體封裝。很多人會覺得奇怪,為什麼用C這樣子來寫程式碼,你不如直接用C++好了,C和C++這個問題我這裡不作討論。
這樣子使用有什麼好處能解決什麼問題:
這樣子書寫,可以很好的解決程式碼整合過程中新功能的增加和刪除。
為什麼這麼說呢:1、刪除無用功能(假如整合過程中ButtonThis 這個按鈕沒有作用,只需要將ButtonThis出現過的地方刪除 即可,無需關心其它程式碼邏輯)
2、增加功能(如果專案中要用到按鈕這個功能 ,只需要建立一個按鈕指標並給他對應的回撥即可)
3、這樣子書寫 留給使用者的所有介面全在這一個ButtonThis結構體指標裡,不用整個工程尋找各個介面。
至此3和4 問題基本得到解決。
接下來我們解決1和2這就要用到我標題提到的ZosPost了 :
同樣先來看一段程式碼
void *ZosThis=NULL;
ButtonClass_t *ButtonThis=NULL;
//按鍵掃描模擬 int ButtonActionTask(int arg,char *argv[]) { ButtonClass_t *Button=( ButtonClass_t *)GetUserThis(argv); TaskStart(GetSystem(argv)); while(1) { Button->Loop(Button); ZosPostDelayedAction(GetThis(argv),10,ButtonActionTask,GetUserThis(argv)); TaskSleep(GetSystem(argv)); } TaskStop(System);
}
//延時模擬 unsigned int i=1; int ActionTask(int arg,char *argv[]) {
void *Argc=(ZosPostClass_t*)argv[0]; ZosPostDelayedAction_t *System=(ZosPostDelayedAction_t*)argv[1];
TaskStart(System);
while(1) { if(i==0)i=1; i=i*2; ZosPostSetInterruptSignalAction(Argc,TASK_DEMO_E,GetSystem(argv)->Action,GetUserThis(argv));//放下一個斷訊號 ZosPostDelayedAction(Argc,i,GetSystem(argv)->Action,GetUserThis(argv)); //啟動一個延時訊號 TaskSleep(System); //放下一個斷點暫時退出本函式 printf("1hello:%d\r\n",i);
i=i*2; ZosPostSetInterruptSignalAction(Argc,TASK_DEMO_E,GetSystem(argv)->Action,GetUserThis(argv)); ZosPostDelayedAction(Argc,i,GetSystem(argv)->Action,GetUserThis(argv)); TaskSleep(System); printf("2hello:%d\r\n",i);
i=i*2; ZosPostSetInterruptSignalAction(Argc,TASK_DEMO_E,GetSystem(argv)->Action,GetUserThis(argv)); ZosPostDelayedAction(Argc,i,GetSystem(argv)->Action,GetUserThis(argv)); TaskSleep(System);
//i=i*2; //ZosPostDelayedAction(Argc,i,Action,NULL); //讓系統鎖定在這裡執行 //TaskEnd(); } TaskStop(System);
}
int main() { printf(" 純C演示 模擬執行緒 \r\n"); ButtonThis=CreateButtonClassMallocNew(); ButtonThis->ButtonDownEvent=ButtonDownEvent;//按下事件回撥 ButtonThis->ButtonUpEvent=ButtonUpEvent; //擡起事件回撥 ButtonThis->ButtonGet=ButtonGet; //輸入模擬讀取 ButtonThis->ButtonSetMode(ButtonThis,TriggerChickOne_e); ZosThis=CreateZosPostDelayedActionClassMalloc(200); // 可能 以使用動態記憶體分配 // ZosThis=CreateZosPostDelayedActionClassUser(ZosThis,uZosBuff,10); //可以手動指定最大協同數量 ZosPostDelayedAction(ZosThis,1,ActionTask,NULL); ZosPostDelayedAction(ZosThis,10,ButtonActionTask,ButtonThis);//模擬檢測按鍵
// ZosPostSetPriorityEvel(ZosThis,ActionTask,66536);//放慢執行ActtionTask們(可以理解為優先順序) while(1) { ZosPostDelayedActionLoop(ZosThis); ZosPostDelayedActionClock(ZosThis); }
}
看到這麼多程式碼 是否有點蒙了 ,但仔細看 你會發現這玩意是否特別像作業系統中的執行緒?
比如: ButtonActionTask這個函式還特別奇怪裡面居然有一個while(1) 這不是死迴圈了麼??呵呵 這個問題以後解釋
先說上面這段程式碼是怎麼解決 前面提到的1 和2 的問題的。
前面說到這玩意像一個執行緒,沒錯 甚至可以理解為它就是一個執行緒(其實不是執行緒只是寫法不一樣而已)上面這段程式碼實現了 在檢測按鍵(ButtonActionTask)的同時也執行了ActionTask中的邏輯處理,在ActionTask 中我們用到了 延時等待 和訊號等待完美解決了
1、某個方法在操作某個硬體時,需要等待一段時間硬體才響應。
2、某個方法在操作某個硬體時,不知道硬體什麼時候才響應。
這2個問題。驗證程式碼稍後我會放入我的GITBUB 希望能對相關人員有所幫助