91精品国产麻豆国产自产在线_大香蕉琪琪色免费在线视频_性高朝久久久久久久久久_97久久精品亚洲中文字幕无码_精品久久久久久综合日本_精品久久久噜噜噜久久久_欧美国产日韩精品_亚洲欧洲日产国码av系列天堂_樱桃成人免费在线视频高清无码_91中文字幕午夜看片福利

歡迎光臨!1kic網(wǎng)專注于為電子元器件行業(yè)提供免費及更實惠的芯片ic交易網(wǎng)站。
熱門關(guān)鍵詞: LM358 TL431 ULN2003 OP07 STM32F103C8T6
在51上寫的一個簡單的多任務(wù)調(diào)度
來源: | 作者: | 發(fā)表于:2013-05-25
在51上寫的一個簡單的多任務(wù)調(diào)度 ,AT89S52 MCU
在51上寫的一個簡單的多任務(wù)調(diào)度 
  作者:1kic.com  出處:中華IC網(wǎng) 
 
    看大家都在學操作系統(tǒng),我也想學學。所以想用51寫一個來玩玩,發(fā)現(xiàn)比較郁悶。 

    弄了幾下,不想再弄了,51弄這個沒啥意思。我用的89S52,除了速度慢,RAM資源 太少之外,其它都還過得去。弄了一點代碼出來,放在那也沒啥用,不如拿上來 給新手看看,一個任務(wù)調(diào)度的雛形是什么樣子的~~~~~~~~~這些代碼沒有經(jīng)過優(yōu)化, 我只求實現(xiàn)任務(wù)切換的功能。 

    利用定時器2產(chǎn)生10mS的定時中斷作為時鐘節(jié)拍,任務(wù)切換時保存工作寄存器等操作 嵌入了匯編指令,因此Task_Switch.C文件要做相應(yīng)的設(shè)置才能編譯通過。受硬件資源和編譯器的限制,有很多無奈。程序只好這樣寫了,不管怎么說,到底是能調(diào)度起來了。 

注:這里是老版本,后面又改動的新版本1kic.com。 

/******************************************************* 
本程序只供學習使用,未經(jīng)作者允許,不能用于其它任何用途 

AT89S52 MCU 使用24M晶振 時鐘節(jié)拍設(shè)置為10mS 

main.c file 

Created by Computer-lov. 
Date: 2005.10.27 

Copyright(C) Computer-lov 2005-2015 
All rigths reserved 

******************************************************/ 

#include <at89x52.h> 
#include "task_switch.h" 
#include "MAIN.H" 


//燈 
#define LED1 P1_7 
#define LED2 P1_6 
#define LED3 P1_5 
#define LED4 P1_4 
#define LED5 P0_1 
#define LED6 P3_7 

#define ON_LED1()   LED1=0 
#define OFF_LED1()  LED1=1 

#define ON_LED2()   LED2=0 
#define OFF_LED2()  LED2=1 

#define ON_LED3()   LED3=0 
#define OFF_LED3()  LED3=1 

#define ON_LED4()   LED4=0 
#define OFF_LED4()  LED4=1 

#define ON_LED5()   LED5=0 
#define OFF_LED5()  LED5=1 

#define ON_LED6()   LED6=0 
#define OFF_LED6()  LED6=1 

//按鈕 
#define KEY1 P1_0 
#define KEY2 P1_1 
#define KEY3 P1_2 
#define KEY4 P1_3 

//OS運行標志 
unsigned char OS_running; 

//堆棧申請 
unsigned char idata Stack[MAX_TASK][S_DEPTH]; 

//運行時間 
unsigned int Running_Time; 

//程序控制塊 
PCB pcb[MAX_TASK]; 

//當前運行任務(wù)的ID號 
unsigned char Current_ID; 

 

/////////////////////////////////////調(diào)用該函數(shù)使任務(wù)延時t個時鐘節(jié)拍//////////////////////// 
///////////////////////////////////// 輸入?yún)?shù):0<t<256       ////////////////////////////// 
/////////////////////////////////////  一個時鐘節(jié)拍為10mS    /////////////////////////////// 
void OS_Delay(unsigned char t) 
{ 
EA=0;                         //關(guān)中 
pcb[Current_ID].Suspend=1;    //任務(wù)掛起 
pcb[Current_ID].Delay=t;      //設(shè)置延遲節(jié)拍數(shù) 
EA=1;                         //開中 
task_switch();                //任務(wù)切換 
} 
//////////////////////////////////////////////////////////////////////////////////////////// 


///////////////////////////////////掛起任務(wù) //////////////////////////////////////////////// 
/*void OS_Suspend(void) 
{ 
EA=0; 
pcb[Current_ID].Suspend=1;    //任務(wù)掛起 
EA=1; 
task_switch();                //任務(wù)切換 
}*/ 
//////////////////////////////////////////////////////////////////////////////////////////// 

/////////////////////////////////////////創(chuàng)建一個任務(wù)//////////////////////////////////////////// 
///////////////////////////////函數(shù)入口:Task_ID 分配給任務(wù)的唯一ID號 ////////////////////////// 
//////////////////////////////           Task_Priority  任務(wù)優(yōu)先級     ///////////////////////// 
///////////////////////////////          Task_p    任務(wù)入口地址 
///////////////////////////////          Stack_p   任務(wù)堆棧棧低地址   /////////////////////////// 
void Task_Create(unsigned char Task_ID,unsigned char Task_Priority,unsigned int Task_p,unsigned char Stack_p) 
{ 
unsigned char i; 

for(i=0;i<S_DEPTH;i++) 
  { 
   ((unsigned char idata *)Stack_p)[i]=0;         //初始化清空堆棧 
  } 

((unsigned char idata *)Stack_p)[0]=Task_p;         //將任務(wù)入口地址保存在堆棧 
((unsigned char idata *)Stack_p)[1]=Task_p>>8; 

pcb[Task_ID].Task_SP=Stack_p+Num_PUSH_bytes+1;   //設(shè)置好堆棧指針 
pcb[Task_ID].Priority=Task_Priority;             //設(shè)置任務(wù)優(yōu)先級 
pcb[Task_ID].Suspend=0;                          //任務(wù)初始不掛起 
pcb[Task_ID].Delay=0;                            //任務(wù)初始不延時 
} 
///////////////////////////////////////////////////////////////////////////////////////////// 

 

 

/////////////////////////////////////空閑任務(wù),優(yōu)先級最低/////////////////////////////////// 
////////////////////////////////////二個LED不停的閃爍 ////////////////////////////////////// 
void task_idle(void) 
{ 
static unsigned long int i;    //使用static申明局部變量,避免臨時變量使用相同地址 
while(1) 
  { 
   ON_LED1();    //LED1亮 
   for(i=0;i<0x2000;i++)        //延遲 
    { 
    } 
   OFF_LED1();   //LED1關(guān) 
   for(i=0;i<0x2000;i++) 
    { 
     ON_LED6();    //LED6閃爍很快,看起來是一直亮的 
     OFF_LED6(); 
    } 
  } 
} 
////////////////////////////////////////////////////////////////////////////////////////////// 

/////////////////////////////////////任務(wù)1  檢測按鈕1 并控制LED2亮滅////////////////////////// 
void task_1(void) 
{ 
// static unsigned int  j; 
while(1) 
  { 
    ON_LED2(); 
    while(KEY1)OS_Delay(6);     //等待KEY1按鍵按下 
    while(!KEY1)OS_Delay(6);    //等待KEY1釋放 
    OFF_LED2(); 
    while(KEY1)OS_Delay(6); 
    while(!KEY1)OS_Delay(6); 
   } 
} 
//////////////////////////////////////////////////////////////////////////////////////////////// 

/////////////////////////////////////任務(wù)2  檢測按鈕2 并控制LED3亮滅////////////////////////// 
void task_2(void) 
{ 
// static unsigned int  j; 
while(1) 
  { 
    ON_LED3(); 
    while(KEY2)OS_Delay(5); 
    while(!KEY2)OS_Delay(5); 
    OFF_LED3(); 
    while(KEY2)OS_Delay(5); 
    while(!KEY2)OS_Delay(5); 
   } 
} 
//////////////////////////////////////////////////////////////////////////////////////////////// 

/////////////////////////////////////任務(wù)3  檢測按鈕3 并控制LED4亮滅////////////////////////// 
void task_3(void) 
{ 
// static unsigned int  j; 
while(1) 
  { 
    ON_LED4(); 
    while(KEY3)OS_Delay(5); 
    while(!KEY3)OS_Delay(5); 
    OFF_LED4(); 
    while(KEY3)OS_Delay(5); 
    while(!KEY3)OS_Delay(5); 
   } 
} 
//////////////////////////////////////////////////////////////////////////////////////////////// 

/////////////////////////////////////任務(wù)4  控制LED5每秒閃一次////////////////////////// 
void task_4(void) 
{ 
// static unsigned int  j; 
while(1) 
  { 
    ON_LED5(); 
    OS_Delay(100);   //LED5每隔1S閃一次 
    OFF_LED5(); 
    OS_Delay(100); 
   } 
} 
//////////////////////////////////////////////////////////////////////////////////////////////// 


///////////////////////////////////主函數(shù)////////////////////////////////////////////////////// 
void main(void) 
{ 
EA=0;                    //關(guān)中 
ET2=1;                   //定時器2開中斷 

T2CON=0x00;              //定時器自動重裝模式 
T2MOD=0x00;              //如果提示這里編譯通不過,可將本行刪除;或自己將定義添上 
                          //因為keil自帶的at89x52.h中沒有T2MOD的定義 
RCAP2H=0xB1; 
RCAP2L=0xE0;             //定時時間為10ms 

Task_Create(0,5,(unsigned int)(void *)(&task_idle),(unsigned char)Stack[0]);   //任務(wù)0初始化 
Task_Create(1,4,(unsigned int)(void *)(&task_1),(unsigned char)Stack[1]);      //任務(wù)1初始化 
Task_Create(2,3,(unsigned int)(void *)(&task_2),(unsigned char)Stack[2]);      //任務(wù)2初始化 
Task_Create(3,2,(unsigned int)(void *)(&task_3),(unsigned char)Stack[3]);      //任務(wù)3初始化 
Task_Create(4,1,(unsigned int)(void *)(&task_4),(unsigned char)Stack[4]);      //任務(wù)4初始化 

OS_running=0;                          //任務(wù)未開始運行 

Current_ID=MAX_TASK-1;                 //當前任務(wù)為最后一個任務(wù) 

pcb[Current_ID].Task_SP-=Num_PUSH_bytes;    //調(diào)整任務(wù)堆棧指針,因為這時任務(wù)還未開始調(diào)度 
                                             //第一次進入中斷時,會壓棧。所以先將堆棧指針 
                                             //往下調(diào)Num_PUSH_bytes個字節(jié),避免堆棧溢出 
                                             //調(diào)整后的SP緊接著的兩個字節(jié)就是最后一個任務(wù)的入口地址 
                                             //在第一次中斷發(fā)生時,返回地址被壓入SP后面的兩個地址 
                                             //在第一次進入中斷后,將SP往前調(diào)整兩字節(jié),這樣程序返回時, 
                                             //將返回到最后一個任務(wù),而不再返回主函數(shù) 

SP=pcb[Current_ID].Task_SP;                   //修改堆棧指針。使其指向任務(wù)當前任務(wù)的堆棧段 

TR2=1;             //啟動定時器2 
EA=1;              //開中斷 

while(1);          //死循環(huán)。定時器中斷發(fā)生后,任務(wù)開始調(diào)度 

 
分享到:
展會信息
市場分析
政策法規(guī)

1kic網(wǎng)-首個免費IC網(wǎng)-電子元器件ic交易網(wǎng)-芯片集成電路代理商供應(yīng)商查詢