前面寫了switch case做任務調(diào)度的應用,這邊寫一下如何實現(xiàn).像一般的RTOS一樣都有一個任務控制塊(TCB)列表來管理所有的任務,所以這里也需要一個結(jié)構(gòu)體來管理動作任務,這里叫做ACB吧.
動作任務管理結(jié)構(gòu)體
這個結(jié)構(gòu)體用來記錄當前動作任務的當前步驟,函數(shù)地址,事件處理函數(shù)的函數(shù)地址,動作名稱,運行時間等.
typedef struct _ACB
{
uint8_t nStep; // 分支動作步驟
uint8_t nChildID; //子動作ID
uint32_t nDelay; // 延時
uint32_t nStartTime;
uint32_t nUsedTime;
uint32_t nStatus; //當前狀態(tài)
ActionEvent EventQueue[4]; //動作事件隊列
uint8_t nEventCnt; //事件數(shù)量和個數(shù)
void (*AppCallBack)(); //業(yè)務動作函數(shù)指針
void (*EventCallback)(); //事件處理函數(shù)指針
void (*ActionCallback)(); //當前運行的函數(shù)指針
char ActionParam[10]; //動作參數(shù)
//17
char* pActionName; //動作名稱
char* pErrorInfo; //錯誤信息
//8
struct _ACB* next; //上一個控制塊 便于刪除添加到就緒隊列
struct _ACB* prev; //下一個控制塊 便于添加刪除到就緒隊列
} ACB;
動作任務創(chuàng)建
//將OpApp業(yè)務函數(shù)指針和ACB結(jié)構(gòu)體綁定
void AddAction(int nID,void (*OpApp)(),const char* pActionName)
{
if(nID<90)
{
mOS.ActionPool[nID].AppCallBack = OpApp;
mOS.ActionPool[nID].EventCallback = EventAction;
mOS.ActionPool[nID].ActionCallback = OpApp;
mOS.ActionPool[nID].nStatus = 0xff;
mOS.ActionPool[nID].nEventCnt = 0;
mOS.ActionPool[nID].nUsedTime = 0;
mOS.ActionPool[nID].nStartTime = 0;
mOS.ActionPool[nID].pActionName = (char*)pActionName;
}
}
動作任務執(zhí)行
1.動作結(jié)構(gòu)體初始化,添加到就緒隊列
//根據(jù)ID啟動動作任務
int8_t StartAction(uint8_t ActionId)
{
if(ActionId>90)
{
return false;
}
ACB* pAction = &mOS.ActionPool[ActionId];
pAction->ActionStartTime = mOS.SystemTime;
pAction->nStep = STEP1;
pAction->nEventCnt = 0;
pAction->nUsedTime = 0;
pAction->nChildID = 0;
pAction->EventCallback = EventAction;
pAction->ActionCallback = pAction->AppCallBack;//先指向業(yè)務函數(shù)指針
AddReadyActionToTail(pAction); //把當前的控制塊添加到就緒隊列
return true;
}
//將要運行的動作添加到就緒運行隊列
void AddReadyActionToTail(ACB * pAction)
{
pAction->nStaus = 0;
pAction->next = NULL;
pAction->prev = mOS.tail; //
if(mOS.head==NULL)
{
mOS.head = pAction;
}
if(mOS.tail!=NULL) //當就緒鏈表沒有動作時 tail為空
{
mOS.tail->next = pAction;
}
mOS.tail = pAction; //移動尾部指針
}
2.就緒隊列遍歷
inline void AppLoop()
{
mOS.current = mOS.head;
while(mOS.current!=NULL)
{
mOS.current->ActionCallback();
DelFinishAction(); //需要把完成的任務從就緒隊列刪除
mOS.current = mOS.current->next;
}
}
//動作完成后,并計算動作使用時間,從鏈表刪除
inline void DelFinishAction()
{
if(mOS.current->nStatus==0) //動作任務正在運行
{
return ;
}
//統(tǒng)計任務耗時
mOS.current->nUsedTime = mOS.SystemTime - mOS.CurrentAction->nStartTime; //當前時間減去開始時間
if(mOS.head==mOS.tail) //只有一個元素
{
mOS.head= NULL;
mOS.tail = NULL;
return ;
}
if(mOS.current==mOS.head) //頭部刪除,需要將頭部指針往后移動
{
mOS.head = mOS.current->next;
return ;
}
if(mOS.current==mOS.tail) //尾部刪除,需要將尾部指針往前移動
{
mOS.tail = mOS.current->prev;
mOS.tail->next = NULL;
return ;
}
//中間刪除
mOS.current->prev->next = mOS.current->next;
mOS.current->next->prev = mOS.current->prev;
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。
舉報投訴
-
Switch
+關(guān)注
關(guān)注
1文章
542瀏覽量
61753 -
RTOS
+關(guān)注
關(guān)注
25文章
866瀏覽量
122982 -
結(jié)構(gòu)體
+關(guān)注
關(guān)注
1文章
131瀏覽量
11372
發(fā)布評論請先 登錄
相關(guān)推薦
熱點推薦
單片機工程師是程序員嗎
程師做的工作就是程序開發(fā),使用C語言來驅(qū)動單片機的硬件資源,以及完成一個邏輯任務,實現(xiàn)一定的功能的過程。但是單片機工程師又不是嚴格意義上的程序員,因為程序員是純粹在電腦上寫代碼的一個職
發(fā)表于 11-09 09:14
51單片機多任務機制的實現(xiàn)策略研究
從操作系統(tǒng)實現(xiàn)多任務機制的原理入手,分析了51單片機實現(xiàn)多任務機制的基本條件,論述了5l單片機
發(fā)表于 09-19 17:26
?159次下載
51單片機多任務操作系統(tǒng)的原理與實現(xiàn)
51單片機多任務操作系統(tǒng)的原理與實現(xiàn),在51單片機上模擬操作系統(tǒng)
發(fā)表于 02-28 15:09
?17次下載
多個任務時,如何保證單片機工作效率及每個任務完成的及時性?資料下載
電子發(fā)燒友網(wǎng)為你提供多個任務時,如何保證單片機工作效率及每個任務完成的及時性?資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設計、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師
發(fā)表于 04-12 08:41
?3次下載
單片機工程師是程序員嗎?真實的月薪到底有多少?
程師做的工作就是程序開發(fā),使用C語言來驅(qū)動單片機的硬件資源,以及完成一個邏輯任務,實現(xiàn)一定的功能的過程。但是單片機工程師又不是嚴格意義上的程序員,因為程序員是純粹在電腦上寫代碼的一個職
發(fā)表于 11-04 17:36
?16次下載
單片機工控事件
單片機工控通常有延時,電機狀態(tài),傳感器狀態(tài)等通用耗時操作,業(yè)務程序查詢這些狀態(tài),就會產(chǎn)生大量的冗余代碼,不簡潔.使用事件則是把這些通用操作丟給系統(tǒng)去處理,系統(tǒng)操作完成后,則運行業(yè)務程序的下一個Step.
單片機工控實現(xiàn)任務執(zhí)行管理
評論