程序的多任務和資源復用舉例C51源程序
有一臺機電設備,有兩個按鍵,控制設備的兩個不同部分。
現(xiàn)要求:
每個按鍵按下,相應控制程序運行。但兩個按鍵可以同時按下,就是說兩個控制程序可能
需要同時運行。使用一個89C52,如何編寫程序?
注:此程序不使用RTOS等操作系統(tǒng)。
/*程序說明:
一)產(chǎn)生波形可以使用中斷中計數(shù)來產(chǎn)生精確的波形。
本答案中為更能體現(xiàn)程序的多任務和資源復用問題,采用主程序循環(huán)產(chǎn)生。
二)請?zhí)貏e注意,題意是兩個程序在并發(fā)運行,實際按本答案可以擴展到N個不同任務同時運行,在此就不討論。
(對大程序結(jié)構(gòu)增加了很多其它的概念)
三)因為在論壇上直接貼出,所以程序放在一個文件中。
應該按Timer.c, Key.c, Const.h(存放常量定義),Task1, Task2, Answer.c存放
*/
#include
/*Timer*/
bit fTimer0_2ms; /*T0中斷產(chǎn)生的標志,準備傳遞給主循環(huán)*/
bit fSYS_2ms; /*系統(tǒng)T0中斷產(chǎn)生的標志,12M,主循環(huán)使用*/
bit fSYS_20ms; /*每20MS產(chǎn)生一次的消息*/
#define INT2MSCOUNT 10 /*產(chǎn)生2MS所需要的時間次數(shù)*/
unsigned char da
#define INT20MSCOUNT 10 /*產(chǎn)生20MS所需要的時間次數(shù),在20MS基礎上*/
unsigned char da
/*KEY*/
unsigned char da
unsigned char da
sbit iKey1=P1^0; /*按鍵的輸入口*/
sbit iKey2=P1^1;
bit fKey1; /*為簡單化,沒使用隊列保存鍵值,使用標志*/
bit fKey2; /*為簡單化,沒使用隊列保存鍵值,使用標志*/
/*Task1*/
unsigned char da
unsigned char da
unsigned int da
sbit oTask1=P1^2; /*輸出方波口*/
/*Task2*/
unsigned char da
unsigned char da
sbit oTask2=P1^3; /*輸出方波口*/
/*---------------------------------------------------------------------------*/
/*產(chǎn)生以1MS為基礎的系統(tǒng)定時信號,T0作為基準定時器*/
/*************************************************
定時器T0初始化0.2MS,12M
*************************************************/
void Timer0_Init()
{
TMOD|=0x2; /*8位定時器*/
TL0=TH0=~(200)+1; /*12M*/
TR0=1;
ET0=1;
}
/*************************************************
定時器0的中斷服務,產(chǎn)生fTimer0_2ms
*************************************************/
void timer0(void) interrupt 1 /*T0中斷*/
{
mTimer_2msReg--;
if(mTimer_2msReg==0){
mTimer_2msReg=INT2MSCOUNT; /*產(chǎn)生1MS所需要的寄存器*/
fTimer0_2ms=1;
}
}
/*************************************************
控制消息fSYS_2ms
*************************************************/
void Timer0_MainLoop()
{
fSYS_2ms=0;
fSYS_20ms=0;
if(fTimer0_2ms){
fTimer0_2ms=0; /*接收中斷過來的時間標志,轉(zhuǎn)換為消息*/
fSYS_2ms=1; /*此消息在一周內(nèi)有效,被外部程序復用*/
/*產(chǎn)生20MS的消息*/
mTimer_20msReg--;
if(mTimer_20msReg==0){
mTimer_20msReg=INT20MSCOUNT; /*產(chǎn)生20MS所需要的寄存器,在20MS基礎上*/
fSYS_20ms=1;
}
}
}
/*---------------------------------------------------------------------------*/
/*按鍵掃描,包含兩個掃描任務*/
/**********************************************
每次系統(tǒng)時間進入一次,20ms.這里把20MS判斷放進來,好看點
按鍵掃描循環(huán)
為簡單化,沒使用隊列保存鍵值,使用標志
那些重復發(fā)出N鍵,在這個結(jié)構(gòu)中非常容易加上
**********************************************/
void Key_MainLoop()
{
if(fSYS_20ms==0)return;
switch(mKey1SwapTask){
case 0:/***有按鍵按下嗎?***/
if(iKey1==0){
mKey1SwapTask=1;
}
break;
case 1: /***鍵按下去抖延時***/
mKey1SwapTask=2; /***延時一個系統(tǒng)時間***/
break;
case 2: /***鍵值判斷***/
if(iKey1==0){
fKey1=1; /*按鍵有效*/
mKey1SwapTask=3; /*去按鍵去抖*/
}
else mKey1SwapTask=0; /*抖動*/
break;
case 3: /***有松開嗎?***/
if(iKey1==1){
mKey1SwapTask=4;
}
break;
case 4: /***鍵松開去抖延時***/
mKey1SwapTask=5; /***延時一個系統(tǒng)時間***/
break;
case 5: /***鍵值判斷***/
if(iKey1==1){
mKey1SwapTask=0; /*去按鍵檢測開始*/
}
else mKey1SwapTask=3; /*抖動*/
break;
}
switch(mKey2SwapTask){
case 0:/***有按鍵按下嗎?***/
if(iKey2==0){
mKey2SwapTask=1;
}
break;
case 1: /***鍵按下去抖延時***/
mKey2SwapTask=2; /***延時一個系統(tǒng)時間***/
break;
case 2: /***鍵值判斷***/
if(iKey2==0){
fKey2=1; /*按鍵有效*/
mKey2SwapTask=3; /*去按鍵去抖*/
}
else mKey2SwapTask=0; /*抖動*/
break;
case 3: /***有松開嗎?***/
if(iKey2==1){
mKey2SwapTask=4;
}
break;
case 4: /***鍵松開去抖延時***/
mKey2SwapTask=5; /***延時一個系統(tǒng)時間***/
break;
case 5: /***鍵值判斷***/
if(iKey2==1){
mKey2SwapTask=0; /*去按鍵檢測開始*/
}
else mKey2SwapTask=3; /*抖動*/
break;
}
}
/*---------------------------------------------------------------------------*/
/*任務一*/
/**********************************************
一個部分輸出1HZ的方波,2S后停止。
**********************************************/
void Task1_MainLoop()
{
switch(mTask1Id){
case 0: if(fKey1){
fKey1=0; /*接收該鍵值*/
mTask1_1HzReg=500/2; /*1hz時間寄存器,500ms,以2MS為單位*/
mTask1_2SReg=2000/2; /*2S時間寄存器,500ms,以2MS為單位*/
oTask1=0;
mTask1Id=1;
}
break;
case 1: if(fSYS_2ms){
mTask1_1HzReg--;
if(mTask1_1HzReg==0){
oTask1=~oTask1;
mTask1_1HzReg=500/2; /*1hz時間寄存器,500ms,以2MS為單位*/
}
mTask1_2SReg--;
if(mTask1_2SReg==0){
oTask1=1; /*2S時間到*/
mTask1Id=0;
}
}
break;
}
}
/*---------------------------------------------------------------------------*/
/*任務二*/
/**********************************************
一個一直輸出1.2hz的方波,直到按鍵再次按
**********************************************/
void Task2_MainLoop()
{
switch(mTask2Id){
case 0: if(fKey2){
fKey2=0; /*接收該鍵值*/
mTask2_1p2HzReg=416/2; /*1hz時間寄存器,832/2ms,以2MS為單位*/
oTask2=0;
mTask2Id=1;
}
break;
case 1: if(fKey2){
fKey2=0;
oTask2=1;
mTask2Id=0;
}
else {
if(fSYS_2ms){
mTask2_1p2HzReg--;
if(mTask2_1p2HzReg==0){
oTask2=~oTask1;
mTask2_1p2HzReg=416/2; /*1hz時間寄存器,832/2ms,以2MS為單位*/
}
}
}
break;
}
}
/*---------------------------------------------------------------------------*/
/*主程序*/
void main(){
Timer0_Init();
EA=1;
while(1){
Timer0_MainLoop();
Key_MainLoop();
Task1_MainLoop();
Task2_MainLoop();
}
}
評論