专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

裸机中的战斗机,一个裸机调度器

作者:huqin   来源:本站原创   点击数:  更新时间:2014年02月01日   【字体:
下面代码是来自51hei的一个代码,其中一个是将任务放在一个队列里面轮转执行,更重要的是一个—LINE—神一般的应用。


#include <stc89c51.h>
 #include <stdio.h>
 
 /*****************小小调度器部分开始********************************************/ 

这里开始是重点 
 #define  _SS   static char lc=0; switch(lc){   case 0: lc=0;
 #define  _EE   }; lc=0; 
 #define  WaitX(a,b)  settimer(&lc,__LINE__,a,b); return ; case __LINE__:
这里是重点的结束

 
 struct TASK {
   char td;
   void (*fp)();
 };
 #define MAXTASKS 5
 struct TASK tasks[MAXTASKS];
 
 //设置定时器
 void settimer(char *lc,char  line,char  tmrid,int d){
   *lc=line;
   tasks[tmrid].td=d;
 }
 //逻辑定时器处理,在定时器中断里调用
 void dectimers() { 
  unsigned char i;   
  for (i=0;i<MAXTASKS;i++){ 
    if (tasks[i].td>0)  tasks[i].td--;  
  }
 }
 //任务调度函数,在main里面运行
 void runtasks() {
    unsigned char i;    
    for(i=0;i<MAXTASKS;i++)
    {   
      if (tasks[i].fp!=0){    
    if (tasks[i].td==0){
      tasks[i].td=-1;  
      tasks[i].fp();
  }  
  }  
  }
 }
 /****************小小调度器部分结束*******************************************************/
 
 
 sbit KEY = P3^2;
 unsigned char code numtab[16]={0x24,0x6F,0xE0,0x62,0x2B,0x32,0x30,0x67,0x20,0x22,0x21,0x38,0xB4,0x68,0xB0,0xB1};
 
 
 sfr IAP_CONTR = 0xC7;
 sfr WDT_CONTR = 0xC1;
 
 //清除看门狗
 void clr_wdt()
 {
   WDT_CONTR =0x3C; 
 }
 
 //初始化定时器
 void InitT0()
 {
  TMOD = 0x21;
  IE |= 0x82;  // 12t
  TL0=0Xff;
  TH0=0Xb7;
  TR0 = 1;
 }
 //定时器中断
 void INTT0(void) interrupt 1 using 1
 {
  TL0=0Xff;    //10ms 重装
  TH0=0Xb7;
  dectimers();
 }
 
 sbit LED1= P2^4;  
 
 //任务一,状态机写法
 void ontimer0(){ 
   LED1=!LED1;  // LED1引脚接在发光管负极,LED1=0 为亮,LED1=1为灭。
 
   //重装定时器
   if (LED1) tasks[0].td=45;  //450mS 灭
   else tasks[0].td=5;  //50ms  亮
 }
 
 //任务二,状态机写法
 char keycount=0;
 void task1(){
  if(KEY==0) {
    keycount++;
    if (keycount>20) IAP_CONTR = 0x60;
  }
  else{
     keycount=0;
  }
  //重装定时器
  tasks[1].td=5;
 }
 
 
 //任务三,伪线程写法
神一样的代码就在这里了。 
 void  task2()
 {
  static char i;
 _SS
 
 while(1){
 
  for(i=0;i<=9;i++){ //从0--9快速显示,间隔200mS
   WaitX(2,20);        这里是一个delay,但是,程序退出了,然后下一次时间到了之后直接就回到这里执行了。太强大了。一直没有想到可以用LINE+switch case这么使用。
   P1=numtab[i];
  }
  for(i=0;i<=9;i++){ //从0--9慢速显示,间隔500mS
   WaitX(2,50);        
   P1=numtab[i];
  }
 }
 
 _EE
 }
 
 
 
 void main()
 {
  unsigned char KeyNum;
  P3M0 = 0x00;
  P3M1 =0x00;
  //WDT_CONTR= 0x00;   //关闭看门狗
  P1 = 0xff;         //关显示
 
    clr_wdt();
 
  InitT0();
 
  KEY =1; //按键IO口
  KeyNum=0; //按下次数
 
     //装载任务:
  tasks[0].fp=ontimer0; 
  tasks[1].fp=task1; 
  tasks[2].fp=task2; 
  
     //循环调度
  while(1){
  runtasks();
  clr_wdt();
  }
 }
关闭窗口

相关文章