小容量單片機(jī)系統(tǒng)的C語言程序結(jié)構(gòu)
發(fā)布時(shí)間:2008/5/26 0:00:00 訪問次數(shù):602
2002年初,筆者著手寫一個(gè)ic卡預(yù)付費(fèi)電表的工作程序,該電表使用philips公司的8位51擴(kuò)展型單片機(jī)87lpc764,要求實(shí)現(xiàn)很多功能,包括熄顯示、負(fù)荷計(jì)算與控制、指示閃爍以及電表各種參數(shù)的查詢等,總之,要使用時(shí)間的單元很多。筆者當(dāng)時(shí)使用asm51完成了這個(gè)程序的編寫,完成后的程序量是2kb多一點(diǎn)。后來,由于種種原因,這個(gè)程序并沒有真正使用,只是作了一些改動(dòng)之后用在一個(gè)老化設(shè)備上進(jìn)行計(jì)時(shí)與負(fù)荷計(jì)算。約一年后,筆者又重新改寫了這些代碼。
1 系統(tǒng)的改進(jìn)
可以說,這個(gè)用asm51實(shí)現(xiàn)的代碼是沒有什么組織性可言的,要什么功能就加入什么功能,弄得程序的結(jié)構(gòu)非常松散,其實(shí)這也是導(dǎo)致筆者最終決定重新改寫這些代碼的原因。
大家知道,87lpc764有4kb的flash rom,而筆者的程序量只有2kb多點(diǎn),因而第一個(gè)想法是改用c語言作為主要的開發(fā)語言,應(yīng)該不至于導(dǎo)致代碼空間不夠用。其次,考慮到需要定時(shí)功能的模塊(或稱任務(wù),以下統(tǒng)稱任務(wù))較多,有必要對這些任務(wù)進(jìn)行有序的管理。筆者考慮使用時(shí)間片輪詢方式,即給每個(gè)要求時(shí)間管理的任務(wù)以一個(gè)時(shí)間間隔,時(shí)間間隔一到,即運(yùn)行其代碼,達(dá)到合理使用系統(tǒng)定時(shí)器資源的目的。就51系統(tǒng)而言,一般至少一個(gè)定時(shí)器可用來進(jìn)行時(shí)間片的輪詢;谝陨系南敕ǎ瑯(gòu)造了下述數(shù)據(jù)類型。
typedef unsigned char uint8
typedef struct {
void (*proc)(void); //處理程序
uint8 ms_count; //時(shí)間片大小
} _op_;
數(shù)據(jù)結(jié)構(gòu)定義好之后,接著就是實(shí)現(xiàn)代碼,包括三部分,即初始化數(shù)據(jù)、時(shí)間片的刷新與時(shí)間到執(zhí)行。
初始化數(shù)據(jù)。
#define proc_cnt 0x08 //定義過程或任務(wù)數(shù)量
//任務(wù)棧初始化
code _op_ op[proc_cnt]={{ic_check,10},{disp_loop,100},
{calc_power,150},{set_led,2},…
};
//設(shè)置時(shí)間片初始值
data uint8 time_val[proc_cnt]={10,100,150,2,…};
時(shí)間片刷新。
void time_int1(void) interrupt 3
{ uint8 cnt;
time_counter:=time_unit;
for(cnt=0;cnt { time_val[cnt]--; } } 任務(wù)的執(zhí)行。 void main(void){ uint8 cnt; init(); //程序初始化 interrupt_on(); //打開中斷 do{ for(cnt=0;cnt { if(!time_val[cnt]) { time_val[cnt]=op[cnt].ms_count; op[cnt].proc(); } } }while(1); } 在上面的結(jié)構(gòu)定義中,proc是不能帶參數(shù)的,各任務(wù)之間的通信可以定義一個(gè)參數(shù)內(nèi)存塊,通過一種機(jī)制進(jìn)行數(shù)據(jù)信息交互,如定義一個(gè)全局變量。對于小容量單片機(jī)系統(tǒng)而言,需要這樣做的任務(wù)并不多,總?cè)蝿?wù)量也不會(huì)太多,因而這種協(xié)調(diào)并不太難處理。 也許大家都有這樣的認(rèn)識(shí),即一個(gè)實(shí)時(shí)系統(tǒng)中,差不多所有的具體任務(wù)都是有時(shí)間屬性的,即使是不需要定時(shí)的過程或任務(wù),也不見得要時(shí)時(shí)進(jìn)行查詢與刷新。如ic卡介質(zhì)檢測,保證每秒一次就足夠了。因而,這些任務(wù)也可以列入到這個(gè)結(jié)構(gòu)中來。 在以上的程序代碼中,考慮到單片機(jī)系統(tǒng)的ram限制,不能像一些實(shí)時(shí)os那樣將任務(wù)棧建立在ram中。筆者將任務(wù)棧建立在代碼空間,因而不能在程序運(yùn)行時(shí)動(dòng)態(tài)地加入任務(wù),因此要求在程序編譯時(shí),任務(wù)棧已經(jīng)確定。同時(shí),定義一組計(jì)數(shù)值旗標(biāo)time_val,記錄程序運(yùn)行時(shí)的時(shí)間量,并在一個(gè)定時(shí)器中斷中對其進(jìn)行刷新。改變時(shí)間片刷新中斷過程語句time_counter:=time_unit;中的time_unit,可以改變系統(tǒng)時(shí)間片的刷新粒度,一般這個(gè)值由系統(tǒng)的最小時(shí)間度量值確定。 同時(shí),由任務(wù)的執(zhí)行流程可知,此種系統(tǒng)構(gòu)造并沒有改變其前/后臺(tái)系統(tǒng)的性質(zhì),只是對后臺(tái)邏輯操作序列進(jìn)行了有效管理。同時(shí),如果將任務(wù)執(zhí)行流程進(jìn)行一些更改,并保證時(shí)間片小的任務(wù)前置,如下述程序。 do{ for(cnt=0;cnt if(!time_val[cnt]){ time_val[cnt]=op[cnt].ms_count; op[cnt].proc(); break; //執(zhí)行完成后,重新進(jìn)行優(yōu)先調(diào)度 } } }while(1); 則系統(tǒng)變?yōu)橐粋(gè)以執(zhí)行頻率為優(yōu)先級的任務(wù)調(diào)度系統(tǒng)。當(dāng)然,設(shè)置此種方式得非常小心,并要注意時(shí)間片的分配,如果時(shí)間片過小,則可能導(dǎo)致執(zhí)行頻率較低的任務(wù)難以被執(zhí)行;而如果存在兩個(gè)同樣的時(shí)間片,則更加危險(xiǎn),可能導(dǎo)致第二個(gè)具有相同時(shí)間片的任務(wù)不被執(zhí)行,因而,時(shí)間片的分配要合理,并保證其唯一性。 2 性能分析與任務(wù)拆分 以上兩種任務(wù)管理方式,前一種按任務(wù)棧的順序與時(shí)間片的大小依次進(jìn)行調(diào)度,暫且稱其為流水作業(yè)調(diào)度;而后一種,且稱其為頻率優(yōu)先調(diào)度。兩種方式各有優(yōu)缺點(diǎn)。流水作業(yè)調(diào)度
2002年初,筆者著手寫一個(gè)ic卡預(yù)付費(fèi)電表的工作程序,該電表使用philips公司的8位51擴(kuò)展型單片機(jī)87lpc764,要求實(shí)現(xiàn)很多功能,包括熄顯示、負(fù)荷計(jì)算與控制、指示閃爍以及電表各種參數(shù)的查詢等,總之,要使用時(shí)間的單元很多。筆者當(dāng)時(shí)使用asm51完成了這個(gè)程序的編寫,完成后的程序量是2kb多一點(diǎn)。后來,由于種種原因,這個(gè)程序并沒有真正使用,只是作了一些改動(dòng)之后用在一個(gè)老化設(shè)備上進(jìn)行計(jì)時(shí)與負(fù)荷計(jì)算。約一年后,筆者又重新改寫了這些代碼。
1 系統(tǒng)的改進(jìn)
可以說,這個(gè)用asm51實(shí)現(xiàn)的代碼是沒有什么組織性可言的,要什么功能就加入什么功能,弄得程序的結(jié)構(gòu)非常松散,其實(shí)這也是導(dǎo)致筆者最終決定重新改寫這些代碼的原因。
大家知道,87lpc764有4kb的flash rom,而筆者的程序量只有2kb多點(diǎn),因而第一個(gè)想法是改用c語言作為主要的開發(fā)語言,應(yīng)該不至于導(dǎo)致代碼空間不夠用。其次,考慮到需要定時(shí)功能的模塊(或稱任務(wù),以下統(tǒng)稱任務(wù))較多,有必要對這些任務(wù)進(jìn)行有序的管理。筆者考慮使用時(shí)間片輪詢方式,即給每個(gè)要求時(shí)間管理的任務(wù)以一個(gè)時(shí)間間隔,時(shí)間間隔一到,即運(yùn)行其代碼,達(dá)到合理使用系統(tǒng)定時(shí)器資源的目的。就51系統(tǒng)而言,一般至少一個(gè)定時(shí)器可用來進(jìn)行時(shí)間片的輪詢;谝陨系南敕,構(gòu)造了下述數(shù)據(jù)類型。
typedef unsigned char uint8
typedef struct {
void (*proc)(void); //處理程序
uint8 ms_count; //時(shí)間片大小
} _op_;
數(shù)據(jù)結(jié)構(gòu)定義好之后,接著就是實(shí)現(xiàn)代碼,包括三部分,即初始化數(shù)據(jù)、時(shí)間片的刷新與時(shí)間到執(zhí)行。
初始化數(shù)據(jù)。
#define proc_cnt 0x08 //定義過程或任務(wù)數(shù)量
//任務(wù)棧初始化
code _op_ op[proc_cnt]={{ic_check,10},{disp_loop,100},
{calc_power,150},{set_led,2},…
};
//設(shè)置時(shí)間片初始值
data uint8 time_val[proc_cnt]={10,100,150,2,…};
時(shí)間片刷新。
void time_int1(void) interrupt 3
{ uint8 cnt;
time_counter:=time_unit;
for(cnt=0;cnt { time_val[cnt]--; } } 任務(wù)的執(zhí)行。 void main(void){ uint8 cnt; init(); //程序初始化 interrupt_on(); //打開中斷 do{ for(cnt=0;cnt { if(!time_val[cnt]) { time_val[cnt]=op[cnt].ms_count; op[cnt].proc(); } } }while(1); } 在上面的結(jié)構(gòu)定義中,proc是不能帶參數(shù)的,各任務(wù)之間的通信可以定義一個(gè)參數(shù)內(nèi)存塊,通過一種機(jī)制進(jìn)行數(shù)據(jù)信息交互,如定義一個(gè)全局變量。對于小容量單片機(jī)系統(tǒng)而言,需要這樣做的任務(wù)并不多,總?cè)蝿?wù)量也不會(huì)太多,因而這種協(xié)調(diào)并不太難處理。 也許大家都有這樣的認(rèn)識(shí),即一個(gè)實(shí)時(shí)系統(tǒng)中,差不多所有的具體任務(wù)都是有時(shí)間屬性的,即使是不需要定時(shí)的過程或任務(wù),也不見得要時(shí)時(shí)進(jìn)行查詢與刷新。如ic卡介質(zhì)檢測,保證每秒一次就足夠了。因而,這些任務(wù)也可以列入到這個(gè)結(jié)構(gòu)中來。 在以上的程序代碼中,考慮到單片機(jī)系統(tǒng)的ram限制,不能像一些實(shí)時(shí)os那樣將任務(wù)棧建立在ram中。筆者將任務(wù)棧建立在代碼空間,因而不能在程序運(yùn)行時(shí)動(dòng)態(tài)地加入任務(wù),因此要求在程序編譯時(shí),任務(wù)棧已經(jīng)確定。同時(shí),定義一組計(jì)數(shù)值旗標(biāo)time_val,記錄程序運(yùn)行時(shí)的時(shí)間量,并在一個(gè)定時(shí)器中斷中對其進(jìn)行刷新。改變時(shí)間片刷新中斷過程語句time_counter:=time_unit;中的time_unit,可以改變系統(tǒng)時(shí)間片的刷新粒度,一般這個(gè)值由系統(tǒng)的最小時(shí)間度量值確定。 同時(shí),由任務(wù)的執(zhí)行流程可知,此種系統(tǒng)構(gòu)造并沒有改變其前/后臺(tái)系統(tǒng)的性質(zhì),只是對后臺(tái)邏輯操作序列進(jìn)行了有效管理。同時(shí),如果將任務(wù)執(zhí)行流程進(jìn)行一些更改,并保證時(shí)間片小的任務(wù)前置,如下述程序。 do{ for(cnt=0;cnt if(!time_val[cnt]){ time_val[cnt]=op[cnt].ms_count; op[cnt].proc(); break; //執(zhí)行完成后,重新進(jìn)行優(yōu)先調(diào)度 } } }while(1); 則系統(tǒng)變?yōu)橐粋(gè)以執(zhí)行頻率為優(yōu)先級的任務(wù)調(diào)度系統(tǒng)。當(dāng)然,設(shè)置此種方式得非常小心,并要注意時(shí)間片的分配,如果時(shí)間片過小,則可能導(dǎo)致執(zhí)行頻率較低的任務(wù)難以被執(zhí)行;而如果存在兩個(gè)同樣的時(shí)間片,則更加危險(xiǎn),可能導(dǎo)致第二個(gè)具有相同時(shí)間片的任務(wù)不被執(zhí)行,因而,時(shí)間片的分配要合理,并保證其唯一性。 2 性能分析與任務(wù)拆分 以上兩種任務(wù)管理方式,前一種按任務(wù)棧的順序與時(shí)間片的大小依次進(jìn)行調(diào)度,暫且稱其為流水作業(yè)調(diào)度;而后一種,且稱其為頻率優(yōu)先調(diào)度。兩種方式各有優(yōu)缺點(diǎn)。流水作業(yè)調(diào)度
熱門點(diǎn)擊
- 基于MC9S08GB32的便攜式無水阻槳頻船
- 關(guān)于DS18B20測量溫度的幾個(gè)問題
- 單片機(jī)顯控系統(tǒng)中的漢字輸入
- RFMD®擴(kuò)展了業(yè)界領(lǐng)先的EDGE產(chǎn)
- AD8302在幅相檢測系統(tǒng)中的應(yīng)用
- ATSC制數(shù)字電視機(jī)頂盒研究
- 采用高速高分辨率信號采集卡構(gòu)成超聲探傷系統(tǒng)
- 基于數(shù)字移相的高精度脈寬測量系統(tǒng)
- 理想的非編與非編的理想(上)
- 基礎(chǔ)儀器的示波器:領(lǐng)舞電子測試市場(下)
推薦技術(shù)資料
- CV/CC InnoSwitch3-AQ 開
- URF1DxxM-60WR3系
- 1-6W URA24xxN-x
- 閉環(huán)磁通門信號調(diào)節(jié)芯片NSDRV401
- SK-RiSC-SOM-H27X-V1.1應(yīng)
- RISC技術(shù)8位微控制器參數(shù)設(shè)
- 多媒體協(xié)處理器SM501在嵌入式系統(tǒng)中的應(yīng)用
- 基于IEEE802.11b的EPA溫度變送器
- QUICCEngine新引擎推動(dòng)IP網(wǎng)絡(luò)革新
- SoC面世八年后的產(chǎn)業(yè)機(jī)遇
- MPC8xx系列處理器的嵌入式系統(tǒng)電源設(shè)計(jì)
- dsPIC及其在交流變頻調(diào)速中的應(yīng)用研究