久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

經(jīng)典單片機(jī)C51多任務(wù)代碼(改進(jìn)版)

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2012年11月22日   【字體:

以前曾經(jīng)發(fā)布過一篇http://www.zg4o1577.cn/mcu/1616.html  這個(gè)是改進(jìn)版,修正了幾個(gè)小問題.
//說明本源碼來自網(wǎng)絡(luò)(DIY超輕量級多任務(wù)操作系統(tǒng)一文)
//============================================================================
//51實(shí)用多任務(wù)源碼,歡迎引用改進(jìn),有新改進(jìn)功能請回發(fā)一份給我謝謝!(請發(fā)郵箱)
//改進(jìn)為定時(shí)中斷內(nèi)切換任務(wù)
//任務(wù)內(nèi)可以設(shè)定時(shí)間片長短,通過改定時(shí)器0初置的方法實(shí)現(xiàn)
//置定時(shí)器0 TL0=0xFF;的方法可以讓出CPU使用權(quán)
//七彩驚云改進(jìn),QQ540953860 13880880726  胥先生
//采用本源碼請保留各改進(jìn)人的聯(lián)系信息,以便共享和完善,請將各改進(jìn)前版本備注在代碼后面以便了解發(fā)展
//步驟和各種不同檔次單片機(jī)下的靈活引用。
//請對每一句代碼進(jìn)行備注謝謝!
//============================================================================
//============================================================================
//你的改進(jìn)說明寫這兒
//============================================================================
#include <reg51.h>

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

/*
//任務(wù)切換函數(shù)(任務(wù)調(diào)度器)
void task_switch(){ //本子程序可以用來讓出CPU使用權(quán)
        task_sp[task_id] = SP; //存當(dāng)前任務(wù)SP的值

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

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

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

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

 

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

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

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

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

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

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

}

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

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

        if(++task_id == MAX_TASKS)
          {
                task_id = 0;
                RWCH_BZ=1;//當(dāng)task_id==0時(shí)說明所有任都切換了一次,置標(biāo)志不再對棧進(jìn)行調(diào)整。
    }
        SP = task_sp[task_id];
  
if(RWCH_BZ==0)
  {//棧調(diào)整代碼
  SP+=2;//第一次切換程序時(shí)原棧沒有(POP PSW 和POP ACC 數(shù)據(jù)調(diào)整一下,為什么請查匯編代碼)
//為什么要加上面代碼的分析
 //中斷中其實(shí)隱含了以下代碼
//PUSH ACC
//PUSH PSW
//----------------

//中斷內(nèi)的實(shí)際代碼

//----------------
//下面兩句的數(shù)據(jù)在每個(gè)任務(wù)第一次切換時(shí)任務(wù)棧內(nèi)其實(shí)并沒有它的數(shù)據(jù),如果不調(diào)整,這兩句將會(huì)把返回地址數(shù)據(jù)給POP掉
//所以進(jìn)行SP+2處理才會(huì)正常返回切換后的任務(wù),從而騙過CPU
//POP PSW
//POP ACC
//RET
  }
//============================================
// setb et1
  ET0=1;//開中斷
// setb tr1
  TR0=1;//開定時(shí)器

 }
 //===================================

//=======================================================================
/*
//網(wǎng)絡(luò)原碼
#include <reg51.h>

#define MAX_TASKS 2       //任務(wù)槽個(gè)數(shù).必須和實(shí)際任務(wù)數(shù)一至
#define MAX_TASK_DEP 12   //最大棧深.最低不得少于2個(gè),保守值為12.
unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//任務(wù)堆棧.
unsigned char task_id;    //當(dāng)前活動(dòng)任務(wù)號
unsigned char idata task_sp[MAX_TASKS];


//任務(wù)切換函數(shù)(任務(wù)調(diào)度器)
void task_switch(){
        task_sp[task_id] = SP;

        if(++task_id == MAX_TASKS)
                task_id = 0;

        SP = task_sp[task_id];
}

//任務(wù)裝入函數(shù).將指定的函數(shù)(參數(shù)1)裝入指定(參數(shù)2)的任務(wù)槽中.如果該槽中原來就有任務(wù),則原任務(wù)丟失,但系統(tǒng)本身不會(huì)發(fā)生錯(cuò)誤.
void task_load(unsigned int fn, unsigned char tid){
        task_sp[tid] = task_stack[tid] + 1;
        task_stack[tid][0] = (unsigned int)fn & 0xff;
        task_stack[tid][1] = (unsigned int)fn >> 8;
}

//從指定的任務(wù)開始運(yùn)行任務(wù)調(diào)度.調(diào)用該宏后,將永不返回.
#define os_start(tid) {task_id = tid,SP = task_sp[tid];return;}

void task1(){
        static unsigned char i;
        while(1){
                i++;
                task_switch();//編譯后在這里打上斷點(diǎn)
        }
}

void task2(){
        static unsigned char j;
        while(1){
                j+=2;
                task_switch();//編譯后在這里打上斷點(diǎn)
        }
}

void main(){
        //這里裝載了兩個(gè)任務(wù),因此在定義MAX_TASKS時(shí)也必須定義為2
        task_load(task1, 0);//將task1函數(shù)裝入0號槽
        task_load(task2, 1);//將task2函數(shù)裝入1號槽
        os_start(0);
}
*/
//=======================================================================
 

關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 伊人欧美视频 | 国产高清在线精品 | 动漫www.被爆羞羞av44 | 黄色视频a级毛片 | 九一国产精品 | 日韩在线视频免费观看 | 国产一区二区麻豆 | 亚洲女人天堂网 | 国产精品揄拍一区二区 | 成年人网站免费视频 | 国产精品国产成人国产三级 | 天堂一区 | 中文字幕一区二区三区四区五区 | 欧美一区二区在线视频 | 色播视频在线观看 | 中文字幕日韩一区 | 二区三区视频 | 夜夜爽夜夜操 | 欧美日韩视频 | 午夜伦4480yy私人影院 | 爱草在线 | 久久视频免费观看 | 一区二区免费高清视频 | 欧美一级免费 | 网站黄色av| 美女一区 | 久久久久久久久精 | 国产性网 | 国产做a爱片久久毛片 | 国产乱码精品一区二区三区中文 | 韩国av网站在线观看 | 国产欧美一区二区三区在线看 | 国产99久久精品一区二区永久免费 | 久久久精品影院 | 久久av资源网| 一区二区久久电影 | 国产成人a亚洲精品 | 91九色在线观看 | 亚洲成人中文字幕 | 国产一区二区三区久久久久久久久 | 日日噜噜噜夜夜爽爽狠狠视频, |