打印
[51单片机]

通用小调度器(基于C语言)

[复制链接]
3850|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
smset|  楼主 | 2013-8-8 10:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <stc89c51.h>
/****小小调度器开始**********************************************/
#define MAXTASKS 3
volatile unsigned char timers[MAXTASKS];
#define _SS static unsigned char _lc; switch(_lc){default:
#define _EE ;}; _lc=0; return 255;
#define WaitX(tickets)  do {_lc=__LINE__; return tickets ;} while(0); case __LINE__:

#define RunTask(TaskName,TaskID) do { if (timers[TaskID]==0) timers[TaskID]=TaskName(); }  while(0);
#define RunTaskA(TaskName,TaskID) { if (timers[TaskID]==0) {timers[TaskID]=TaskName(); continue;} }   //前面的任务优先保证执行

#define CallSub(SubTaskName) do {unsigned char currdt; _lc=__LINE__; return 0; case __LINE__:  currdt=SubTaskName(); if(currdt!=255) return currdt;} while(0);
#define UpdateTimers() {unsigned char i; for(i=MAXTASKS;i>0 ;i--){if((timers[i-1]!=0)&&(timers[i-1]!=255)) timers[i-1]--;}}

#define SEM unsigned int
//初始化信号量
#define InitSem(sem) sem=0;
//等待信号量
#define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);
//等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE
#define WaitSemX(sem,tickets)  do { sem=tickets+1; WaitX(0); if(sem>1){ sem--;  return 1;} } while(0);
//发送信号量
#define SendSem(sem)  do {sem=0;} while(0);

/*****小小调度器结束*******************************************************/


sbit LED1 = P2^1;
sbit LED2 = P2^2;

sbit LED0 = P2^5;

unsigned char task0(){
_SS
  while(1){
   WaitX(50);
   LED0=!LED0;   
  }
_EE
}

unsigned char  task1(){
_SS
  while(1){
   WaitX(100);
   LED1=!LED1;   
  }
_EE
}

unsigned char  task2(){
_SS
  while(1){
   WaitX(100);
   LED2=!LED2;   
  }
_EE
}

void InitT0()
{
        TMOD = 0x21;
        IE |= 0x82;  // 12t
        TL0=0Xff;
        TH0=0XDB;
        TR0 = 1;
}

void INTT0(void) interrupt 1 using 1
{
    TL0=0Xff;    //10ms 重装
    TH0=0XDB;//b7;   

    UpdateTimers();

    RunTask(task0,0);//任务0具有精确按时获得执行的权限,建议:task0每次执行消耗时间<0.5个 ticket
}




void main()
{
        InitT0();
        while(1){
           //RunTask(task0,0);
           RunTaskA(task1,1);//任务1具有比任务2高的运行权限                  
           RunTaskA(task2,2);//任务2具有低的运行权限                  
      }
}

这可能是世界上消耗资源最小的调度器代码了:
支持256个顶级任务,每个顶级任务最小消耗1个字节RAM,子任务最小消耗0字节RAM。

相关帖子

沙发
逍遥派掌门| | 2013-10-22 15:17 | 只看该作者

   _EE 的那一行, 在MDK中报警: “unreachable code”

使用特权

评论回复
板凳
wangch_sh| | 2013-10-22 16:00 | 只看该作者
RTX51吧。

使用特权

评论回复
地板
逍遥派掌门| | 2013-10-22 16:35 | 只看该作者
不是RTX51,楼主的仅是调度器而已。

使用特权

评论回复
5
coody| | 2013-10-22 16:54 | 只看该作者
模仿protothread调度器,类似于使用switch case的

使用特权

评论回复
6
不起眼| | 2013-10-22 19:38 | 只看该作者
有点意思,不过任务函数里只能使用静态变量,否则运行会出现问题。
另外当waitX过多时,任务切换效率较低。

使用特权

评论回复
7
JasonWangSE| | 2013-10-23 12:35 | 只看该作者
没理解怎么用,按楼主的代码,_SS定义处switch语句开始,但是在下面的while(1)循环里面调用WaitX,相当于case __LINE__出现在while(1)中,应该编译不过啊。我试着将_SS和_EE挪到while(1)循环里面,但是又会出现default语句每次都会执行的问题,这样每次都将_lc赋值为__LINE__然后返回,是否和代码的初衷不一样啊。楼主要不帮忙说明一下?

使用特权

评论回复
8
coody| | 2013-10-23 13:05 | 只看该作者
我也做过一个改良版本,提升效率,增加等待节拍数

使用特权

评论回复
9
1021352522| | 2015-11-26 19:58 | 只看该作者
这不是smset大神吗

使用特权

评论回复
10
discussant| | 2015-11-26 21:50 | 只看该作者
这个任务调度器要几级堆栈?在PIC的8位单片机可以用吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝