51/AVR单片机技术驿站!  <在线翻译>     便利工具    特色网址   无弹窗、无插件的绿色站点...  英才招聘   学历查询  喜欢>>收藏我站 

当前位置:首页 > 取经杂谈 > 详细内容
俺在51上写的一个简单的多任务调度
作者:佚名  发布时间:2009/6/16  阅读次数:1364  字体大小: 【】 【】【
     看大家都在学操作系统,我也想学学。所以想用51写一个来玩玩,发现比较郁闷。

       弄了几下,不想再弄了,51弄这个没啥意思。我用的89S52,除了速度慢,RAM资源 太少之外,其它都还过得去。弄了一点代码出来,放在那也没啥用,不如拿上来 给新手看看,一个任务调度的雏形是什么样子的~~~~~~~~~这些代码没有经过优化, 我只求实现任务切换的功能。

       利用定时器2产生10mS的定时中断作为时钟节拍,任务切换时保存工作寄存器等操作 嵌入了汇编指令,因此Task_Switch.C文件要做相应的设置才能编译通过。受硬件资源和编译器的限制,有很多无奈。程序只好这样写了,不管怎么说,到底是能调度起来了。

注:这里是老版本,后面又改动的新版本。

/*******************************************************
本程序只供学习使用,未经作者允许,不能用于其它任何用途

AT89S52 MCU 使用24M晶振 时钟节拍设置为10mS

main.c file

Created by Computer-lov.
Date: 2005.10.27

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

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

#include
#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];

//当前运行任务的ID号
unsigned char Current_ID;



/////////////////////////////////////调用该函数使任务延时t个时钟节拍////////////////////////
///////////////////////////////////// 输入参数:0/////////////////////////////////////   一个时钟节拍为10mS       ///////////////////////////////
void OS_Delay(unsigned char t)
{
EA=0;                                                 //关中
pcb[Current_ID].Suspend=1;       //任务挂起
pcb[Current_ID].Delay=t;           //设置延迟节拍数
EA=1;                                                 //开中
task_switch();                               //任务切换
}
////////////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////挂起任务 ////////////////////////////////////////////////
/*void OS_Suspend(void)
{
EA=0;
pcb[Current_ID].Suspend=1;       //任务挂起
EA=1;
task_switch();                               //任务切换
}*/
////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////创建一个任务////////////////////////////////////////////
///////////////////////////////函数入口:Task_ID 分配给任务的唯一ID号 //////////////////////////
//////////////////////////////                     Task_Priority   任务优先级         /////////////////////////
///////////////////////////////                   Task_p       任务入口地址
///////////////////////////////                   Stack_p     任务堆栈栈低地址     ///////////////////////////
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   {
     ((unsigned char idata *)Stack_p)[i]=0;                 //初始化清空堆栈
   }

((unsigned char idata *)Stack_p)[0]=Task_p;                 //将任务入口地址保存在堆栈
((unsigned char idata *)Stack_p)[1]=Task_p>>8;

pcb[Task_ID].Task_SP=Stack_p+Num_PUSH_bytes+1;     //设置好堆栈指针
pcb[Task_ID].Priority=Task_Priority;                         //设置任务优先级
pcb[Task_ID].Suspend=0;                                                   //任务初始不挂起
pcb[Task_ID].Delay=0;                                                       //任务初始不延时
}
/////////////////////////////////////////////////////////////////////////////////////////////





/////////////////////////////////////空闲任务,优先级最低///////////////////////////////////
////////////////////////////////////二个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关
     for(i=0;i<0x2000;i++)
       {
         ON_LED6();       //LED6闪烁很快,看起来是一直亮的
         OFF_LED6();
       }
   }
}
//////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////任务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);
     }
}
////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////任务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);
     }
}
////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////任务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);
     }
}
////////////////////////////////////////////////////////////////////////////////////////////////

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


///////////////////////////////////主函数//////////////////////////////////////////////////////
void main(void)
{
EA=0;                                       //关中
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]);     //任务0初始化
Task_Create(1,4,(unsigned int)(void *)(&task_1),(unsigned char)Stack[1]);           //任务1初始化
Task_Create(2,3,(unsigned int)(void *)(&task_2),(unsigned char)Stack[2]);           //任务2初始化
Task_Create(3,2,(unsigned int)(void *)(&task_3),(unsigned char)Stack[3]);           //任务3初始化
Task_Create(4,1,(unsigned int)(void *)(&task_4),(unsigned char)Stack[4]);           //任务4初始化

OS_running=0;                                                   //任务未开始运行

Current_ID=MAX_TASK-1;                                 //当前任务为最后一个任务

pcb[Current_ID].Task_SP-=Num_PUSH_bytes;       //调整任务堆栈指针,因为这时任务还未开始调度
                                                                                         //第一次进入中断时,会压栈。所以先将堆栈指针
                                                                                         //往下调Num_PUSH_bytes个字节,避免堆栈溢出
                                                                                         //调整后的SP紧接着的两个字节就是最后一个任务的入口地址
                                                                                         //在第一次中断发生时,返回地址被压入SP后面的两个地址
                                                                                         //在第一次进入中断后,将SP往前调整两字节,这样程序返回时,
                                                                                         //将返回到最后一个任务,而不再返回主函数

SP=pcb[Current_ID].Task_SP;                                     //修改堆栈指针。使其指向任务当前任务的堆栈段

TR2=1;                         //启动定时器2
EA=1;                           //开中断

while(1);                   //死循环。定时器中断发生后,任务开始调度

来源:www.21icbbs.com
我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

网站导航 管理登陆 ┊ 免责声明 问题反馈  友链说明
本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正!
不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作!

    我要报警 Alexa
 mcusy_cn#126.com (请把#改成@) 交流:522422171
本站学习交流群:138..158(高级群1-)、77930286(高级群2)、61804809(群3)
Copyright© MCUSY All Rights Reserved
本站网警备案号: WZ36040002485
  ICP备案证书号:粤ICP备09034963号