www.pudn.com > 51_00_OS.rar > main.c, change:2006-02-24,size:17426b


/******************************************************* 
*************基于51内核的圈圈操作系统***************** 
 
本程序只供学习使用,未经作者许可,不得用于其它任何用途 
 
 
main.c file 
 
Created by Computer-lov 
Date: 2005.10.27 
 
Edit date:2006.2.24 
 
Version V1.2 
Copyright(C) Computer-lov 2005-2015 
All rigths reserved 
 
******************************************************/ 
 
#include "at89x52.h" 
 
#include "OS_core.h" 
#include "task_switch.h" 
#include "MAIN.H" 
 
#include "UART.H" 
 
//#define Debug 
 
 
//灯 
 
#define LED1 P1_4 
#define LED2 P1_5 
#define LED3 P1_6 
#define LED4 P1_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 KEY1 P1_0 
#define KEY2 P1_1 
#define KEY3 P1_2 
#define KEY4 P1_3 
 
 
 
volatile unsigned char second,minute,hour;   //系统时钟 
 
volatile unsigned char Msg_1_Receiver=0;     //初始化无任务接收此消息 
 
/////////////////////////////////////空闲任务,优先级最低/////////////////////////////////// 
///////////////////////////////////// 注意,永远不要挂起空闲任务  ////////////////////////// 
////////////////////////// 并且空闲任务必须第一个被创建,且优先级最低  ///////////////////// 
////////////////在os_core.h中使用#define CPU_STAT后 可以用来统计CPU的使用率 //////////////// 
void task_idle(void) 
{ 
//static unsigned long int i;  //使用static申明局部变量,避免变量被分配到相同的地址 
 
#ifdef CPU_STAT                  //如果需要CPU使用率统计 
 
 static unsigned long int total_count;    //则声明相应变量 
 static unsigned long int current_count; 
 static unsigned char time,j; 
 
 total_count=0; 
 current_count=0; 
 
 
 time=(unsigned char)OS_Run_Time;        //初始化time 
 
 while(time==(unsigned char)OS_Run_Time);  //等待,直到OS_Run_Time的值改变了 
 
 time=(unsigned char)OS_Run_Time;          //保存这时的时间 
 
 while(1) 
  { 
   //此时所有任务都处于挂起状态,由统计这时的CPU资源 
   //使用跟下面一样的结构,使其生成一样的代码,提高准确性 
   if((unsigned char)OS_Run_Time-time>=100)      //共统计1秒钟的时间 
    { 
     //这条语句的作用,是为了保证上下代码结构一样,让编译器生成一样结构的代码 
     j=(total_count-current_count)/(total_count); 
     break; 
    } 
   total_count++;             //累加CPU资源 
  } 
 
 
 for(j=0;j<MAX_TASK;j++)      //将挂起的任务唤醒 
  { 
   OS_pcb[j].Suspend=0; 
  } 
#endif 
  
 while(1)                    //死循环 
  { 
 
#ifdef CPU_STAT              //如果需要统计CPU使用率 
   while(1) 
    { 
     //测量100个时钟节拍的CPU资源,然后跟没有其它任务运行时的CPU资源比较 
     if((unsigned char)OS_Run_Time-time>=100) 
      { 
       //计算比率 
       // CPU使用率越高,则本任务运行的时间就越短,current_count的值就越小 
       //total_count与current_count的差,占total_count的比例,就是CPU使用率 
       //最后结果被放大了100倍,保存在j中。 
       j=(total_count-current_count)/(total_count/100); 
 
 
        //将计算结果通过消息发送给接收消息的任务显示 
       OS_Send_Msg(OS_Current_ID,Msg_1_Receiver,j);  
  
       current_count=0;                        //清0 
       time=(unsigned char)OS_Run_Time; 
       while(time==(unsigned char)OS_Run_Time); 
       time=(unsigned char)OS_Run_Time;         //重新开始统计 
       break; 
      } 
     current_count++;   //累加CPU资源 
    } 
#endif 
 
  } 
} 
////////////////////////////////////////////////////////////////////////////////////////////// 
 
/////////////////////////////////////  任务1    ////////////////////////// 
void task_1(void) 
{ 
 static unsigned int j;  //使用static申明局部变量,避免变量被分配到相同的地址 
 static unsigned int temp; 
 j=0; 
 
 while(1) 
  { 
   OS_Delay(10);      //延迟10个时钟节拍 
   OS_Enter_Critical();  //进入临界段 
   temp=OS_Run_Time;    //获取当前系统运行的时间值 
   OS_Exit_Critical();  //退出临界段 
   temp-=j;             //j用来保存上一次的时间总数 
                        //用新的时间总数,减掉上一次的时间总数 
                       //就可以得到运行的时间之差 
   if(temp>=100)   //当运行时间之差大于等于100时,表示至少1S过去了,因为1个时钟节拍为10毫秒 
    { 
     temp/=100;    //时钟之差除以100,表示时钟之差为多少秒 
     j+=temp*100;   //j保存当前的时间总数 
     second+=temp;  //调整秒的值 
     if(second>=60)  //如果秒的值大于60 
      { 
       second-=60; 
       minute++; 
       if(minute>=60) 
        { 
         minute-=60; 
         hour++; 
         if(hour>=24) 
          hour-=24; 
        } 
      } 
     get_printer();   //申请打印机资源,显示系统时钟 
     prints("                       System Time:",0); 
     send_a_byte('0'+hour/10);  //显示小时 
     send_a_byte('0'+hour%10); 
     send_a_byte(':'); 
     send_a_byte('0'+minute/10);  //显示分 
     send_a_byte('0'+minute%10); 
     send_a_byte(':'); 
     send_a_byte('0'+second/10);  //显示秒 
     send_a_byte('0'+second%10); 
     prints("",1);                //换行 
     give_up_printer();   //让出打印机使用权 
    } 
  } 
} 
//////////////////////////////////////////////////////////////////////////////////////////////// 
 
unsigned char refresh_time=20;    //用来调整LED1的闪烁快慢及杠的转动速度 
/////////////////////////////////////   任务2    //////////////////////////////////// 
void task_2(void) 
{ 
 
 refresh_time=20;   //初始化为20 
 
 while(1) 
  { 
   get_printer(); 
   send_a_byte(0x08);    //退一格 
   prints("/",0);        //显示一个 (/) 
   give_up_printer(); 
   OS_Delay(refresh_time);   //延迟refresh_time个时钟周期 
 
   get_printer(); 
   send_a_byte(0x08); 
   prints("-",0);       //显示一个  (-) 
   give_up_printer(); 
   OS_Delay(refresh_time); 
  
   ON_LED1();         //开LED1 
 
   get_printer(); 
   send_a_byte(0x08); 
   prints("\\",0);     //显示一个  (\) 
   give_up_printer(); 
   OS_Delay(refresh_time); 
 
   get_printer(); 
   send_a_byte(0x08); 
   prints("|",0);      //显示一个 (|)  这几个轮流显示,有转动的效果 
   give_up_printer(); 
   OS_Delay(refresh_time); 
 
   OFF_LED1(); 
  } 
} 
//////////////////////////////////////////////////////////////////////////////////////////////// 
 
/////////////////////////////////////    任务3     ////////////////////////// 
void task_3(void) 
{ 
 static unsigned char buf;   //使用static申明局部变量,避免变量被分配到相同的地址 
 static unsigned int temp; 
 while(1) 
  { 
   buf=get_a_byte();       //从串口接收一个数据 
   LED2=~LED2; 
 
   get_printer();          //申请打印机使用 
   prints("                                          You pressed \"",0); 
   send_a_byte(buf);       //回显 
   prints("\" key!",1); 
   give_up_printer(); 
 
   switch(buf) 
    { 
     case 's':                 //收到小写的s,秒值减小1 
               get_printer(); 
               prints("Second:",0); 
               second--; 
               if(second>60)second=59; 
               send_a_byte('0'+second/10); 
               send_a_byte('0'+second%10); 
               prints("",1); 
               give_up_printer(); 
               break; 
                
     case 'm':                 //收到小写的m,分值减小1 
               get_printer(); 
               prints("Minute:",0); 
               minute--; 
               if(minute>60)minute=59; 
               send_a_byte('0'+minute/10); 
               send_a_byte('0'+minute%10); 
               prints("",1); 
               give_up_printer(); 
               break; 
 
     case 'h':                 //收到小写的h,小时值减小1 
               get_printer(); 
               prints("Hour:",0); 
               hour--; 
               if(hour>24)hour=23; 
               send_a_byte('0'+hour/10); 
               send_a_byte('0'+hour%10); 
               prints("",1); 
               give_up_printer(); 
               break; 
 
     case 'S':                 //收到大写的S,秒值增加1 
               get_printer(); 
               prints("Second:",0); 
               second++; 
               if(second>=60)second-=60; 
               send_a_byte('0'+second/10); 
               send_a_byte('0'+second%10); 
               prints("",1); 
               give_up_printer(); 
               break; 
 
     case 'M':                 //收到大写的M,分值增加1 
               get_printer(); 
               prints("Minute:",0); 
               minute++; 
               if(minute>=60)minute-=60; 
               send_a_byte('0'+minute/10); 
               send_a_byte('0'+minute%10); 
               prints("",1); 
               give_up_printer(); 
               break; 
     case 'H':                 //收到大写的H,小时值增加1 
               get_printer(); 
               prints("Hour:",0); 
               hour++; 
               if(hour>=24)hour-=24; 
               send_a_byte('0'+hour/10); 
               send_a_byte('0'+hour%10); 
               prints("",1); 
               give_up_printer(); 
               break; 
 
     case '+':                //收到"+",加快转动速度 
     case '=':                //因为主键盘上"="跟"+"在同一个键 
               if(refresh_time>1)refresh_time/=2;   //缩短刷新时间 
               get_printer(); 
               prints("refresh_time=",0); 
               send_a_byte('0'+refresh_time/10); 
               send_a_byte('0'+refresh_time%10); 
               prints("",1); 
               give_up_printer(); 
               break; 
 
     case '-':                //收到"-",减慢转动速度 
               if(refresh_time<30)refresh_time*=2;   //增加刷新时间 
               get_printer(); 
               prints("",1); 
               prints("refresh_time=",0); 
               send_a_byte('0'+refresh_time/10); 
               send_a_byte('0'+refresh_time%10); 
               prints("",1); 
               give_up_printer(); 
               break; 
 
     case 'k': 
     case 'K':                //要删除一个任务时,先按下K键。然后再输入要删除的任务号 
                              //注意:这个任务号是在创建任务时由OS自动分配的,请在创建任务时记下 
               prints("",1);  //换行 
               prints("",1); 
               prints("Ready for kill.....",1); 
               prints("Please input number of task:",1);  //显示一些提示信息 
               prints("",1); 
               buf=get_a_byte();    //从串口接收一字节数据 
               if((buf>='0')&&(buf<'9'))   //如果在数字范围内 
                { 
                 temp=OS_Task_Kill(buf-'0');  //根据接收到数据删除一个任务 
                 if((temp&0xff00)==OS_Successful)  //如果成功删除 
                  { 
                   get_printer();          //则显示信息 
                   prints("",1); 
                   prints("",1); 
                   prints("Task ",0); 
                   send_a_byte((temp&0xff)+'0');   //显示被删除的任务ID 
                   prints(" has been killed!",1);                  
                   prints("Task kill successful!",1); 
                   prints("",1); 
                   give_up_printer(); 
                  } 
                 else        //如果删除不成功 
                  { 
                   get_printer(); 
                   prints("",1); 
                   prints("",1); 
                   if((temp&0xff00)==OS_Task_Not_Exist)   //如果是因为任务不存在 
                    { 
                     prints("Task not exist!",1);  //返回信息 
                    } 
                   if((temp&0xff00)==OS_Task_Cannot_Be_Killed)  //如果是因为任务不允许删除 
                    { 
                     prints("Task cannot be killed!",1);  //返回信息 
                    } 
                   prints("Task kill failed!",1);  //返回删除失败的信息 
                   prints("",1); 
                   give_up_printer(); 
                  } 
                } 
               else    //如果没有输入合适的数字 
                { 
                 get_printer(); 
                 prints("",1); 
                 prints("",1); 
                 prints("Input error!",1);  //返回错误信息 
                 prints("",1); 
                 give_up_printer(); 
                } 
               break; 
 
     case 'c':  
     case 'C': 
                              //创建任务时,先按下C键 
                              //输入要创建的任务号。注意:这个号相当于函数名 
                              //任务创建时,其分配到的ID,跟这个号并不一定一致, 
                              //而是由OS自动分配的一个ID号 
               prints("",1); 
               prints("",1); 
               prints("Ready for create.....",1); 
               prints("Please input number of task:",1); 
               prints("",1); 
               buf=get_a_byte(); 
               if((buf>='1')&&(buf<='4'))   //本演示程序只能创建1-4号任务 
                { 
                 if(buf=='1') 
                  { 
                   temp=OS_Task_Create(3,(unsigned int)(&task_1),0); 
                                   //优先级为3,任务为task_1,无消息 
                  } 
 
                 if(buf=='2') 
                  { 
                   temp=OS_Task_Create(2,(unsigned int)(&task_2),0); 
                                   //优先级为2,任务为task_2,无消息 
                  } 
 
                 if(buf=='3') 
                  { 
                   temp=OS_Task_Create(1,(unsigned int)(&task_3),0); 
                                   //优先级为1,任务为task_3,无消息 
                  } 
 
                 if(buf=='4') 
                  { 
                   temp=OS_Task_Create(0,(unsigned int)(&task_4),(unsigned char)&msg); 
                                   //优先级为0(即最高),任务为task_4,消息指针指向msg 
                  } 
 
                 if((temp&0xFF00)==OS_Successful)   //如果创建成功 
                  { 
                   get_printer(); 
                   prints("",1); 
                   prints("",1); 
                   prints("Task ",0); 
                   send_a_byte((temp&0xff)+'0'); 
                   prints(" has been created!",1); 
                   prints("Task create successful!",1);  //显示信息 
                   prints("",1); 
                   give_up_printer(); 
                  } 
                 else         //如果创建失败 
                  { 
                   get_printer(); 
                   prints("",1); 
                   prints("",1); 
                   if((temp&0xff00)==OS_Resource_Lack)  //资源不足,无法创建 
                    { 
                     prints("Resource lack!",1);   //返回错误信息 
                    } 
                   prints("Task create failed!",1); 
                   prints("",1); 
                   give_up_printer(); 
                  } 
                } 
               else              //如果输入数据不合适 
                { 
                 get_printer(); 
                 prints("",1); 
                 prints("",1); 
                 prints("Input error!",1); 
                 prints("",1); 
                 give_up_printer(); 
                } 
               break; 
                
     default:  break; 
    }    
  } 
} 
//////////////////////////////////////////////////////////////////////////////////////////////// 
 
unsigned char msg;   //保存消息用的一个变量,也可以使用一个结构体来处理更多的信息 
 
/////////////////////////////////////    任务4 ////////////////////////////////////////////////// 
void task_4(void) 
{ 
 static unsigned char temp;   //使用static申明局部变量,避免变量被分配到相同的地址 
  
 OS_Enter_Critical(); 
 Msg_1_Receiver=OS_Current_ID;   //表示本任务需要接收消息1 
 OS_Exit_Critical(); 
 
 get_printer(); 
 prints("CPU used ratio: 99%",1);   //显示信息 
 give_up_printer(); 
 while(1) 
  { 
   LED3=~LED3;              //LED3闪烁 
   if(OS_Wait_Msg(120))    //等待消息,超时时间设置为1.2秒 
    { 
     temp=*(unsigned char idata*)(OS_pcb[OS_Current_ID].MSG);   //将消息取出 
     if(temp>=100)temp=99;          //为了简化程序,限定最大显示99 
    } 
   else     //如果任务等待超时,即等了1.2秒还没收到统计任务发回的CPU使用率 
    { 
     temp=99;  //则CPU太繁忙,使用率强制设置为99% 
    } 
   get_printer(); 
   prints("CPU used ratio: ",0); 
   send_a_byte('0'+temp/10);      //显示高位 
   send_a_byte('0'+temp%10);      //显示低位 
   send_a_byte('%');              //显示% 
   prints("",1); 
   give_up_printer(); 
  } 
} 
//////////////////////////////////////////////////////////////////////////////////////////////// 
 
 
///////////////////////////////////主函数////////////////////////////////////////////////////// 
void main(void) 
{ 
 EA=0;                    //关中 
 ET2=1;                   //定时器2开中断 
 
 T2CON=0x00;              //定时器自动重装模式 
 T2MOD=0x00;              //如果提示这里编译通不过,可将本行删除;或自己将定义添上 
                          //因为keil自带的at89x52.h中没有T2MOD的定义 
 RCAP2H=0xB1; 
 RCAP2L=0xE0;             //定时时间为10ms 
 
 
 UART_init();           //初始化串口为9600波特率 
 send_a_byte(0x0c); 
 send_a_byte(0x0c);     //如果使用wiindows的超级终端,发这两个可以可靠清屏 
 
 
  
 OS_Init();           //OS初始化 
 
 
//参数意义    优先级      任务入口地址     消息指针 
 OS_Task_Create(255,(unsigned int)(&task_idle),0);   //任务0初始化 
 OS_Task_Create(3,(unsigned int)(&task_1),0);      //任务1初始化 
 OS_Task_Create(2,(unsigned int)(&task_2),0);      //任务2初始化 
 OS_Task_Create(1,(unsigned int)(&task_3),0);      //任务3初始化 
 OS_Task_Create(0,(unsigned int)(&task_4),(unsigned char)&msg); //任务4初始化 
 
 OS_Start();      //OS开始调度 
 
}