
(这个程序要仔细点看,注释写得最详细,这个看懂了,后面的就应该也能看懂了,这三个程序大部分代码都是差不多的,蓝色粗体字的部分是一些关键语句或可能随着题目要求变化的语句)
#include "includes.h"
#define TASK_STK_SIZE 512 //任务堆栈长度
OS_STK MyTaskStk[TASK_STK_SIZE]; //定义MyTask任务堆栈区
OS_STK YouTaskStk[TASK_STK_SIZE]; //定义YouTask任务堆栈区
INT8U x=0,y=0;//这两个变量分别用来指定要显示字符的横纵坐标,即列和行,标准的DOS窗口是80x25,也就是可以显示80行、25列字符, //有了这两个变量就可以将字符精确的显示在DOS窗口的某个地方。
INT8U times=0;//这个变量用了记录MyTask任务的运行次数
void MyTask(void* pdata);
void YouTask(void* pdata);
void main (void)
{
char* s_M="M";
OSInit(); //初始化uCOS_II
PC_DOSSaveReturn(); //保存Dos环境
PC_VectSet(uCOS, OSCtxSw); //安装uCOS_II中断
OSTaskCreate(MyTask, s_M, &MyTaskStk[TASK_STK_SIZE - 1], 0);// 创建起始任务(此题中要求将MyTask作为起始任务), 将s_M
//作为参数传递给MyTask函数,并将该任务的优先级设置为0(优先级按照题目的规定去设置,一般起始任务要设置为最高[数值越小,优先级越高])。
OSStart(); //启动系统
}
void MyTask (void *pdata)
{
char* s_Y="Y";
char* s="MyTask: I asking YouTask to delete his own!";
#if OS_CRITICAL_METHOD == 3 //如果使用的是第3种方法来开关中断,则需要用到cpu_sr这个变量来保存程序状态字
OS_CPU_SR cpu_sr; //定义cpu_sr这个变量
#endif
pdata = pdata; // 这句可以不写,仅仅只是为了防止编译器报错
OS_ENTER_CRITICAL(); //进入临界段(关中断)
PC_VectSet(0x08, OSTickISR); // 安装uCOS_II时钟中断向量
PC_SetTickRate(OS_TICKS_PER_SEC); // 设置uCOS_II时钟频率
OS_EXIT_CRITICAL(); //退出临界段(开中断)
OSStatInit(); // 创建和初始化uCOS_II的统计任务(这条语句一定不能掉,不然会扣很多分的)
OSTaskCreate(YouTask, s_Y, &YouTaskStk[TASK_STK_SIZE - 1], 2); //在MyTask任务中创建YouTask任务,优先级为2
for (;;)
{
if(times>85) //如果MyTask任务的运行次数大于了85次,就要求YouTask任务删除它自己(这个数值也是由题目规定的,题目要求
{ // MyTask运行多少次后删除YouTask就将此处改成多少
while( OSTaskDelReq(2) != OS_TASK_NOT_EXIST)// 要注意OSTaskDelReq后括号中的2,这个数值是所要删除的任务的
{ //优先级,要删除哪个任务就在此处填入该任务的优先级,该程序中,优先级2对应的任务为YouTask
PC_DispStr(10, 8, s, DISP_FGND_YELLOW+DISP_BGND_BLUE); //在屏幕上的第10列、第8行显示s所代表的字符// 串,s在上面已经定义了。(这些DOS窗口的打印函数在书本附录A[page263]都有介绍)
OSTimeDly(1);
}
}
if(x>50) //当一行打印的字符数大于了50个后,换行,换到该行下面的第二行(因为y=y+2),然后从行首开始打印(因为x=0)
{
x=0;
y+=2;
}
times+=1; //每运行一次times加1,以记录下MyTask任务的运行次数
if(times==10) OSSchedLock(); //当MyTask运行10次后,给调度器加锁,这个数值由题目的要求给定
if(times==80) OSSchedUnlock(); //当MyTask运行80次后,给调度器解锁,这个数值也由题目的要求给定
PC_DispChar(x, y, *(char*)pdata, DISP_BGND_BLACK+DISP_FGND_WHITE); //在x、y指定的位置打印字符”M”
x += 1; // 将列加1,为打印下一字符准备好位置
OSTimeDlyHMSM(0, 0, 3, 0); //等待3秒钟,此处的时间也由题目给定,若要求是延时多少ms或tick,就应该使用函数OSTimeDly()
}
}
void YouTask(void* pdata)
{
char* s1="YouTask: I must delete myself!";
char* s2="YouTask: I have deleted my own!";
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata=pdata;
for(;;)
{
if(OSTaskDelReq(OS_PRIO_SELF)==OS_TASK_DEL_REQ) //YouTask利用函数OSTaskDelReq()来查看自己是否被别人要求删除,
{ //如果是,
PC_DispStr(10, 10, s1, DISP_FGND_WHITE+DISP_BGND_BLACK);//则在指定位置打印字符串s1
OSTimeDlyHMSM(0, 0, 15, 0); //等待15s(此处看题目有没有这个要求,若没有,则可不写
PC_DispStr(10, 12, s2, DISP_FGND_WHITE+DISP_BGND_BLACK); //在指定位置打印字符串s2
OSTaskDel(OS_PRIO_SELF); //自己将自己删除
}
if(x>50)
{
x=0;
y+=2;
}
PC_DispChar(x, y, *(char*)pdata, DISP_BGND_BLACK+DISP_FGND_WHITE ); //在没有被删除时,仍然打印字符”Y”
x += 1;
OSTimeDlyHMSM(0, 0, 1, 0);
}
}
二、编写一个uC/OS-II应用程序,要求:(1) 包含3个用户任务(MyTask、YouTask和InterTask),优先级分别为0、1、2,并把MyTask作为起始任务;(2) 任务InterTask由时钟节拍中断服务程序中的钩子函数在被调用10000次时使用一个信号变量InterKey激活,其他时候不活动; (3) 当程序打印完第一行字符后,取消YouTask任务的延时。
#include "includes.h"
#define TASK_STK_SIZE 512 //任务堆栈长度
OS_STK MyTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
OS_STK YouTaskStk[TASK_STK_SIZE];
OS_STK InterTaskStk[TASK_STK_SIZE];
INT8U x=0, y=0;
BOOLEAN InterKey=FALSE; //这个标志变量用来激活InterTask任务
char* s="The InterTask is running!";
void MyTask(void* pdata);
void YouTask(void* pdata);
void InterTask(void* pdata);
void main (void)
{
char* s_M="M";
OSInit(); //初始化uCOS_II
PC_DOSSaveReturn(); //保存Dos环境
PC_VectSet(uCOS, OSCtxSw); //安装uCOS_II中断
OSTaskCreate(MyTask, s_M, &MyTaskStk[TASK_STK_SIZE - 1],0); //注意优先级要设置为题目的要求
OSStart(); //启动uCOS_II
}
void MyTask (void *pdata)
{
char* s_Y="Y";
char* s_H="H";
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
OS_ENTER_CRITICAL();
PC_VectSet(0x08, OSTickISR); //安装uCOS_II时钟中断向量
PC_SetTickRate(OS_TICKS_PER_SEC); //设置uCOS_II时钟频率
OS_EXIT_CRITICAL();
OSStatInit(); //初始化uCOS_II的统计任务
OSTaskCreate(YouTask, s_Y, &YouTaskStk[TASK_STK_SIZE - 1], 1); //注意优先级要设置为题目的要求
OSTaskCreate(InterTask, s_H, &InterTaskStk[TASK_STK_SIZE - 1], 2); //注意优先级要设置为题目的要求
for (;;)
{
if(x>50)
{
x=0;
y+=2;
}
if(y>1) OSTimeDlyResume(1);//打印完第1行字符后,取消YouTask任务的延时,注意括号中的数值,一定要是被取消延时的任务的
//优先级,此处的1是YouTask任务的优先级。这条语句一定不能掉
PC_DispChar(x, y, *(char*)pdata, DISP_BGND_BLACK+DISP_FGND_WHITE); //打印字符”M”
x += 1;
OSTimeDly(100); //延时100ms或100个tick,此处的值根据题目要求更改,没有要求的话可以就使用这个
}
}
void YouTask(void* pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata=pdata;
for(;;)
{
if(x>50)
{
x=0;
y+=2;
}
PC_DispChar(x, y, *(char*)pdata, DISP_BGND_BLACK+DISP_FGND_WHITE ); //打印字符”Y”
x += 1;
OSTimeDly(500); //此处的值根据题目要求更改,没有要求的话可以就使用这个
}
}
void InterTask(void* pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
for(;;)
{
if(InterKey) //如果InterKey标志的值为真,则:
{
if(x>50)
{
x=0;
y+=2;
}
PC_DispChar(x, y, *(char*)pdata, DISP_BGND_BLACK+DISP_FGND_WHITE );//打印字符”H”
PC_DispStr(5, 6, s, DISP_BGND_BLACK+DISP_FGND_WHITE );//并打印字符串s(已在程序开头定义)
x+=1;
}
InterKey=FALSE; //重新将InterKey标志的值置为假
OSTimeDlyHMSM(0,0,1,0); // 此处的值根据题目要求更改,没有要求的话可以就使用这个
}
}
//--下面的内容和上面的不在同一个文件中,钩子函数几乎都是在OS_CPU_C.c文件中定义的---------------------------------
extern BOOLEAN InterKey; //声明InterKey这个变量是在该文件外部定义的
INT16U InterCtr = 0; //用了记录时钟节拍数,即该钩子函数被调用的次数
void OSTimeTickHook (void)
{
if(InterCtr == 10000) //当时钟tick总数等于10000(这个值按题目中的要求进行设置)时
InterKey = TRUE; //将InterKey标志的值置为真
InterCtr++;
}
三、设计一个应用程序,该程序有MyTask何YouTask两个任务,在任务MyTask中用一个变量记录MyTask的运行次数,并将其作为消息用邮箱Str_Box发给任务YouTask并有任务YouTask显示出来。
(这个题是书上的原题[page156,例5-8],考试估计也是原题,我只是将一些没有用的代码删掉了)
#include "includes.h"
#define TASK_STK_SIZE 512 //任务堆栈长度
OS_STK StartTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
OS_STK MyTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
OS_STK YouTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
char*s;
char*ss;
INT8U err; //用来存放错误代号
INT8U y=0; //字符显示位置
INT32U Times=0; //用来记录MyTask任务的运行次数
OS_EVENT *Str_Box; //定义消息邮箱的指针
void StartTask(void *data); //声明起始任务
void MyTask(void *data); //声明任务
void YouTask(void *data); //声明任务
void main (void)
{
OSInit( ); //初始化uCOS_II
PC_DOSSaveReturn( ); //保存Dos环境
PC_VectSet(uCOS, OSCtxSw); //安装uCOS_II中断
Str_Box = OSMboxCreate ((void*)0); //创建互斥型信号量
OSTaskCreate(StartTask, (void*)0, &StartTaskStk[TASK_STK_SIZE - 1], 0); //注意优先级,要符合题目要求
OSStart( ); //启动多任务管理
}
void StartTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
OS_ENTER_CRITICAL( );
PC_VectSet(0x08, OSTickISR); //安装时钟中断向量
PC_SetTickRate(OS_TICKS_PER_SEC); //设置uCOS_II时钟频率
OS_EXIT_CRITICAL( );
OSStatInit( ); //初始化统计任务
OSTaskCreate(MyTask, (void*)0, &MyTaskStk[TASK_STK_SIZE - 1], 3); //注意优先级,要符合题目要求
OSTaskCreate(YouTask, (void*)0, &YouTaskStk[TASK_STK_SIZE - 1], 4); //注意优先级,要符合题目要求
// 这两个任务创建函数的第2个参数都是”(void*)0”,是因为在这个程序中并没有用到这个参数去给对应的函数传递参数
for (;;)
{
OSTimeDlyHMSM(0, 0, 3, 0); //等待3秒,按照题目的要求进行更改,没有要求的话可以就使用这个
}
}
void MyTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
for (;;)
{
sprintf(s,"%d" ,Times); //将MyTask的运行次数Times以十进制的格式转换成字符串,并存放到s所指向的位置
OSMboxPost(Str_Box,s); //发送消息
Times++;
OSTimeDlyHMSM(0, 0, 1, 0); //等待1秒,按照题目的要求进行更改,没有要求的话可以就使用这个
}
}
void YouTask (void *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
for (;;)
{
ss=OSMboxPend(Str_Box,10,&err); //读取消息邮箱中数据缓冲区的首地址并赋给ss指针
PC_DispStr(10, ++y, ss, DISP_BGND_BLACK+DISP_FGND_WHITE); //打印出所收到的消息的内容
OSTimeDlyHMSM(0, 0, 1, 0); //等待1秒,按照题目的要求进行更改,没有要求的话可以就使用这个
}
}
