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开始调度 }