新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 程序的多任務和資源復用舉例C51源程序

        程序的多任務和資源復用舉例C51源程序

        作者: 時間:2016-11-18 來源:網絡 收藏
        程序的多任務資源復用舉例

        有一臺機電設備,有兩個按鍵,控制設備的兩個不同部分。
        現要求:
        每個按鍵按下,相應控制程序運行。但兩個按鍵可以同時按下,就是說兩個控制程序可能
        需要同時運行。使用一個89C52,如何編寫程序?

        注:此程序不使用RTOS等操作系統。


        /*程序說明:
        一)產生波形可以使用中斷中計數來產生精確的波形。
        本答案中為更能體現程序的多任務和資源復用問題,采用主程序循環產生。
        二)請特別注意,題意是兩個程序在并發運行,實際按本答案可以擴展到N個不同任務同時運行,在此就不討論。
        (對大程序結構增加了很多其它的概念)
        三)因為在論壇上直接貼出,所以程序放在一個文件中。
        應該按Timer.c, Key.c, Const.h(存放常量定義),Task1, Task2, Answer.c存放
        */
        #include

        /*Timer*/
        bit fTimer0_2ms; /*T0中斷產生的標志,準備傳遞給主循環*/
        bit fSYS_2ms; /*系統T0中斷產生的標志,12M,主循環使用*/
        bit fSYS_20ms; /*每20MS產生一次的消息*/

        #define INT2MSCOUNT 10 /*產生2MS所需要的時間次數*/
        unsigned char data mTimer_2msReg=INT2MSCOUNT; /*產生2MS所需要的寄存器*/
        #define INT20MSCOUNT 10 /*產生20MS所需要的時間次數,在20MS基礎上*/
        unsigned char data mTimer_20msReg=INT20MSCOUNT; /*產生20MS所需要的寄存器,在20MS基礎上*/

        /*KEY*/
        unsigned char data mKey1SwapTask; /***按鍵任務寄存器***/
        unsigned char data mKey2SwapTask; /***按鍵任務寄存器***/
        sbit iKey1=P1^0; /*按鍵的輸入口*/
        sbit iKey2=P1^1;

        bit fKey1; /*為簡單化,沒使用隊列保存鍵值,使用標志*/
        bit fKey2; /*為簡單化,沒使用隊列保存鍵值,使用標志*/


        /*Task1*/
        unsigned char data mTask1Id; /*任務一的任務號*/
        unsigned char data mTask1_1HzReg; /*1hz時間寄存器*/
        unsigned int data mTask1_2SReg; /*2S時間寄存器*/
        sbit oTask1=P1^2; /*輸出方波口*/

        /*Task2*/
        unsigned char data mTask2Id; /*任務二的任務號*/
        unsigned char data mTask2_1p2HzReg; /*1.2hz時間寄存器*/
        sbit oTask2=P1^3; /*輸出方波口*/

        /*---------------------------------------------------------------------------*/
        /*產生以1MS為基礎的系統定時信號,T0作為基準定時器*/

        /*************************************************
        定時器T0初始化0.2MS,12M
        *************************************************/
        void Timer0_Init()
        {
        TMOD|=0x2; /*8位定時器*/

        TL0=TH0=~(200)+1; /*12M*/

        TR0=1;
        ET0=1;
        }

        /*************************************************
        定時器0的中斷服務,產生fTimer0_2ms
        *************************************************/
        void timer0(void) interrupt 1 /*T0中斷*/
        {
        mTimer_2msReg--;
        if(mTimer_2msReg==0){
        mTimer_2msReg=INT2MSCOUNT; /*產生1MS所需要的寄存器*/
        fTimer0_2ms=1;
        }
        }

        /*************************************************
        控制消息fSYS_2ms
        *************************************************/
        void Timer0_MainLoop()
        {
        fSYS_2ms=0;
        fSYS_20ms=0;

        if(fTimer0_2ms){
        fTimer0_2ms=0; /*接收中斷過來的時間標志,轉換為消息*/
        fSYS_2ms=1; /*此消息在一周內有效,被外部程序復用*/
        /*產生20MS的消息*/
        mTimer_20msReg--;
        if(mTimer_20msReg==0){
        mTimer_20msReg=INT20MSCOUNT; /*產生20MS所需要的寄存器,在20MS基礎上*/
        fSYS_20ms=1;
        }
        }
        }

        /*---------------------------------------------------------------------------*/
        /*按鍵掃描,包含兩個掃描任務*/
        /**********************************************
        每次系統時間進入一次,20ms.這里把20MS判斷放進來,好看點
        按鍵掃描循環
        為簡單化,沒使用隊列保存鍵值,使用標志
        那些重復發出N鍵,在這個結構中非常容易加上
        **********************************************/
        void Key_MainLoop()
        {
        if(fSYS_20ms==0)return;

        switch(mKey1SwapTask){
        case 0:/***有按鍵按下嗎?***/
        if(iKey1==0){
        mKey1SwapTask=1;
        }
        break;
        case 1: /***鍵按下去抖延時***/
        mKey1SwapTask=2; /***延時一個系統時間***/
        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; /***延時一個系統時間***/
        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; /***延時一個系統時間***/
        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; /***延時一個系統時間***/
        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();
        }
        }


        評論


        技術專區

        關閉
        主站蜘蛛池模板: 阿巴嘎旗| 泸水县| 大荔县| 育儿| 建德市| 册亨县| 建宁县| 东乡| 布尔津县| 石嘴山市| 池州市| 美姑县| 柯坪县| 屏东县| 刚察县| 澄城县| 凭祥市| 页游| 常熟市| 嵊泗县| 溧水县| 金昌市| 文昌市| 宁海县| 普兰县| 城口县| 法库县| 闻喜县| 汉阴县| 泰宁县| 和田县| 梅河口市| 永胜县| 土默特右旗| 壶关县| 兴国县| 黑水县| 麻江县| 昌都县| 玉溪市| 福海县|