2002年初,筆者著手寫一個IC卡預付費電錶的工作程序,該電錶使用Philips公司的8位51擴展型單片機87LPC764,要求實現很多功能,包括熄顯示、負荷計算與控制、指示閃爍以及電錶各種參數的查詢等,總之,要使用時間的單元很多。筆者當時使用ASM51完成了這個程序的編寫,完成後的程序量是2KB多一點。後來,由於種種原因,這個程序並沒有真正使用,只是作了一些改動之後用在一個老化設備上進行計時與負荷計算。約一年後,筆者又重新改寫了這些代碼。
typedef unsigned char uInt8
typedef struct {
void (*proc)( void ); /* 處理程序 */
uInt8 ms_count; /* 時間片大小 */
} _op_;
數據結構定義好之後,接著就是實現代碼,包括三部分,即初始化數據、時間片的刷新與時間到執行。
code _op_ Op[proc_cnt] = { { ic_check 10 } { disp_loop 100 }
{ calc_power 150 } { set_led 2 } … };
void time_int1( void ) interrupt 3
{
uInt8 cnt;
Time_Counter: = Time_Unit;
for ( cnt = 0; cnt < proc_cnt; cnt++ )
time_val[cnt]--;
}
任務的執行。
void main( void )
init(); /*程序初始化 */
interrupt_on(); /* 打開中斷 */
do
if ( !time_val[cnt] )
time_val[cnt] = Op[cnt].ms_count;
Op[cnt].proc();
while ( 1 );
也許大家都有這樣的認識,即一個實時系統中,差不多所有的具體任務都是有時間屬性的,即使是不需要定時的過程或任務,也不見得要時時進行查詢與刷新。如IC卡介質檢測,保證每秒一次就足夠了。因而,這些任務也可以列入到這個結構中來。
break; /* 執行完成後,重新進行優先調度 */
以上兩種任務管理方式,前一種按任務棧的順序與時間片的大小依次進行調度,暫且稱其為流水作業調度;而後一種,且稱其為頻率優先調度。兩種方式各有優缺點。流水作業調度的各任務具有等同優先順序,時間片一到即會被按序調用,時間片大小的次序與唯一性不作要求;缺點是可能導致時間片小的,即要求執行得較快的任務等待過長的時間。頻率優先調度的各任務按其時間片的大小,即執行頻率劃分優先順序,時間片小的任務,其執行頻率高,總是具有較高的優先權,但時間片的分配得協調,否則可能會導致執行頻率低的任務長時間等待。
/* 定義兩個任務,並將其加入到任務棧中。 */
code _op_ Op[proc_cnt] = { …{ proc1 100 } { proc2 200 } };
data int time1_Seg; /* 定義一個全局旗標 */
/* 任務實現 */
void proc1( void )
if ( time1_Seg )
exit;
else
time1_Seg = const_Time1; /* 如果時間到了,則恢復初值並 */
/* 接著執行下列代碼。 */
… /* 任務實際執行代碼 */
void proc2( void )
time1_Seg--;