新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 經典單片機C51多任務代碼(改進版)

        經典單片機C51多任務代碼(改進版)

        作者: 時間:2016-11-29 來源:網絡 收藏
        以前曾經發布過一篇http://www.51hei.com/mcu/1616.html 這個是改進版,修正了幾個小問題.

        //說明本源碼來自網絡(DIY超輕量級多任務操作系統一文)
        //============================================================================
        //51實用多任務源碼,歡迎引用改進,有新改進功能請回發一份給我謝謝!(請發郵箱)
        //改進為定時中斷內切換任務
        //任務內可以設定時間片長短,通過改定時器0初置的方法實現
        //置定時器0 TL0=0xFF;的方法可以讓出CPU使用權
        //七彩驚云改進,QQ540953860 13880880726 胥先生
        //采用本源碼請保留各改進人的聯系信息,以便共享和完善,請將各改進前版本備注在代碼后面以便了解發展
        //步驟和各種不同檔次單片機下的靈活引用。
        //請對每一句代碼進行備注謝謝!
        //============================================================================
        //============================================================================
        //你的改進說明寫這兒
        //============================================================================
        #include

        本文引用地址:http://www.104case.com/article/201611/323535.htm

        #define MAX_TASKS 2 //任務槽個數.必須和實際任務數一至
        #define MAX_TASK_DEP 12 //最大棧深.最低不得少于2個,保守值為12.
        //根據程序嵌套層數調整該值大小,同時要算一下會不會溢出,這里的設置很重要。
        //還有就是重入問題,局部變量在任務切換時有可能被另外的任務改寫。
        //#define MAX_TASK_DEP 24 //最大棧深.最低不得少于2個,24.
        unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//任務堆棧數組.
        unsigned char task_id; //當前活動任務號
        unsigned char idata task_sp[MAX_TASKS];//棧指標存放數組
        bit RWCH_BZ=0;//任務切換標志變量

        /*
        //任務切換函數(任務調度器)
        void task_switch(){ //本子程序可以用來讓出CPU使用權
        task_sp[task_id] = SP; //存當前任務SP的值

        if(++task_id == MAX_TASKS) //任務號++并比較,到最大置0以便重復切換任務
        task_id = 0;

        SP = task_sp[task_id]; //讀取下一任務SP值,
        } */

        //任務裝入函數.將指定的函數(參數1)裝入指定(參數2)的任務槽中.如果該槽中原來就有任務,則原任務丟失,但系統本身不會發生錯誤.
        void task_load(unsigned int fn, unsigned char tid){
        task_sp[tid] = task_stack[tid] + 1; //裝入任務SP數據
        task_stack[tid][0] = (unsigned int)fn & 0xff; //裝入任務首地址低位
        task_stack[tid][1] = (unsigned int)fn >> 8; //裝入首地址高位
        }

        //從指定的任務開始運行任務調度.調用該宏后,將永不返回.
        #define os_start(tid) {task_id = tid,SP = task_sp[tid];return;}
        //這里其實就是以改寫SP指針的方法,返回時不再返回調用本子程序的地方,而返回被新設定的SP指針指向的任務1首地址處運行。

        /*============================以下為測試代碼============================*/

        void task1(){ //任務1
        static unsigned char i;
        while(1){
        i++;
        }
        }

        void task2(){//任務2
        static unsigned char j;
        while(1){
        j+=2;
        TL0=0xFF;//用置TL0的辦法來進行讓定時中斷動作從而進行任務切換,讓出CPU使用權給下一任務的方法更好

        }
        }

        void main(){
        //這里裝載了兩個任務,因此在定義MAX_TASKS時也必須定義為2

        //=============================================================
        //單片機初始化
        // mov tmod,#20h ;串口通訊設置 串口方式3 波特9600 晶振11.59適用
        //TMOD=0x20;//定時器1方式2
        TMOD=0x22;//定時器0方式2,定時器1方式2
        // mov Tl1,#0fdh ;
        TL1=0xfa;
        // mov th1,#0fdh ; TEL:028-89951522 轉載請勿刪除,謝謝!
        TH1=0xfa;
        // mov pcon,#128d ;QQ:540953860
        //PCON=128;
        PCON=0x80;
        // mov sp,#60h
        //SP=0x60;
        IP=16;//串口中斷設為高優先級
        // mov scon,#0e0h
        SCON=0xf0;//為e0時禁止接收數據
        //setb tr1
        TR1=1;//開啟定時器1
        TR0=1;//開啟定時器0
        ET0=1;//開定時器0中斷
        TL0=0x50;//定時器0初值設定
        TH0=0x50;//在中斷中設置它可實現時間片調整
        // setb ea

        //=============================================================
        task_load(task1, 0);//將task1函數裝入0號槽
        task_load(task2, 1);//將task2函數裝入1號槽
        EA=1;//開中斷
        os_start(0); //進入任務1
        }
        ckzd() interrupt 4 using 1//串行中斷入口
        {

        }

        timer0zd() interrupt 1 using 2//定時器0中斷入口
        {

        //clr tr1;關閉定時器
        TR0=0;
        //clr et1;關閉定時中斷
        ET0=0;
        // task_switch();//切換任務
        //===========================================
        //切換任務
        task_sp[task_id] = SP;

        if(++task_id == MAX_TASKS)
        {
        task_id = 0;
        RWCH_BZ=1;//當task_id==0時說明所有任都切換了一次,置標志不再對棧進行調整。
        }
        SP = task_sp[task_id];


        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 山丹县| 正蓝旗| 乌兰察布市| 道孚县| 襄城县| 康保县| 临沂市| 富民县| 芦溪县| 平邑县| 隆德县| 弋阳县| 中江县| 雅安市| 灵台县| 南和县| 宁蒗| 丰原市| 呈贡县| 东乡县| 乌拉特后旗| 衡东县| 泸溪县| 红原县| 宜丰县| 通化市| 理塘县| 卓资县| 民权县| 拜城县| 鸡东县| 台南县| 池州市| 彝良县| 前郭尔| 邯郸县| 祁门县| 九寨沟县| 玛沁县| 黑山县| 嘉兴市|