在單片機編程中,最主要的是掌握單片機工作的時間節拍,最大限度地利用CPU資源,下面提供一種基於基準定時器進行軟體定時、任務執行採用分時複用的方法,規定每個任務執行的時間,執行時間到後切換下一任務。
u16 Timer_Count = 0,Timer_Count_OverFlow = 0;u16 this_time = 0,last_time = 0,time_overflow = 0;#define Timer_Period 60000#define OutofRunningTime(time) (Timer_Period*Timer_Count_OverFlow+this_time-last_time >= time)#define TIME_MS(x) (1*x)#define TIME_S(x) (1000*x)#define TOTAL_TASK 3 //定義任務總數enum {TASK1,TASK2,TASK3};void 26 interrupt PIT0(void) //中斷定時器,1ms進入一次{Timer_Count ++;if(Timer_Count >= Timer_Period){Timer_Count = 0;Timer_Count_OverFlow ++;}}static u8 task1(void){last_time = Timer_Count;Timer_Count_OverFlow = 0;for(;;){this_time = Timer_Count;do_some_thing();if(OutofRunningTime(TIME_S(2)))return TASK2;}}static u8 task2(void){last_time = Timer_Count;Timer_Count_OverFlow = 0;for(;;){this_time = Timer_Count;do_some_thing();if(OutofRunningTime(TIME_S(2)))return TASK3;}}static u8 task3(void){last_time = Timer_Count;Timer_Count_OverFlow = 0;for(;;){this_time = Timer_Count;do_some_thing();if(OutofRunningTime(TIME_S(2)))return TASK1;}}u8 task_process(u8 task){u8 next_task;switch(task){case TASK1:next_task = task1();break;case TASK2:next_task = task2();break;case TASK3:next_task = task3();break;default:break;}return next_task;}u8 Current_Task = TASK1;void main(void){Current_Task = system_init();for(;;){Current_Task = task_process(Current_Task);}}
代碼中定義了一個時基為1ms的中斷定時器,用Timer_Count作為自由計數值,計數上限為Timer_Period,到達上限後將Timer_Count清零,同時統計一次溢出次數Timer_Count_OverFlow,溢出次數自由計數,直到溢出後清零,進入下一輪迴。 main函數執行的時候進入task_process函數,同時傳遞進入當前需要執行的任務號,首次執行的時候傳遞進去的任務號是TASK1,從task1()開始執行,下面對task1()進行分析。
執行任務函數的時候先記錄當前Timer_Count的值,將溢出次數Timer_Count_OverFlow清零,然後一直執行for迴圈中的do_some_thing(),同時記錄和檢測當前Timer_Count的值,根據當前Timer_Count值和進入任務時的Timer_Count比較,如果時間到達我們需要任務執行的時間,則跳出for迴圈,同時返回下次要執行的任務號,在main函數中根據返回的任務號進入下一任務的執行。
代碼中實現的是基本的軟體架構,並沒有具體程式執行的功能代碼,移植的時候只要使用單片機中的一個定時器,不斷產生1ms的定時中斷即可。