新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > ucos-ii学习笔记——消息队列的原理及使用

ucos-ii学习笔记——消息队列的原理及使用

作者:时间:2016-11-28来源:网络收藏
Createdon:2012-10-7

Author:zhangbin

本文引用地址:http://www.eepw.com.cn/article/201611/322851.htm

学习笔记

forucos-iiPC

redesignedbyzhangbin

2012-10-7

versions:V-0.1

AllRightsReserved

#include"includes.h"

#defineTASK_STK_SIZE512

#defineN_MESSAGES128

OS_STKStartTaskStk[TASK_STK_SIZE];

OS_STKMyTaskStk[TASK_STK_SIZE];

OS_STKYouTaskStk[TASK_STK_SIZE];

char*s_flag;//该字符串指示哪个任务在运行

//char*s_1;

char*ss;//存放接收到的消息指针

char*s100;//存放发送消息的指针

char*s;

char*s500;

void*MsgGrp[N_MESSAGES];//定义消息指针数组

//创建消息队列,首先需要定义一个指针数组(用于存放消息邮箱),然后把各个消息数据缓冲区的首地址存入这个数组中

//最后再调用函数OSQCreate()来创建消息队列

INT8Uerr;

INT8Uy=0;

OS_EVENT*Str_Q;//定义事件控制块指针队列的事件控制块指针用于存放创建的消息队列的指针

voidMyTask(void*data);

voidStartTask(void*data);

voidYouTask(void*data);

voidmain(void)

{

OSInit();

PC_DOSSaveReturn();

PC_VectSet(uCOS,OSCtxSw);

Str_Q=OSQCreate(&MsgGrp[0],N_MESSAGES);//创建消息队列

//函数的第一个参数&MsgGrp[0]是void**start,是存放消息缓冲区指针数组的地址,它是指向指针数组的指针

//可以用指针数组的首个元素的地址表示

//N_MESSAGES是该数组的大小

//返回值是消息队列的指针Str_Q是OS_EVENT型的指针,是事件控制块型的指针

OSTaskCreate(StartTask,(void*)0,&StartTaskStk[TASK_STK_SIZE-1],0);

OSStart();

}

voidStartTask(void*pdata)

{

#ifOS_CRITICAL_METHOD==3

OS_CPU_SRcpu_sr;

#endif

INT16Skey;

pdata=pdata;

OS_ENTER_CRITICAL();

PC_VectSet(0x08,OSTickISR);

PC_SetTickRate(OS_TICKS_PER_SEC);

OS_EXIT_CRITICAL();

OSStatInit();

OSTaskCreate(MyTask,(void*)0,&MyTaskStk[TASK_STK_SIZE-1],3);

OSTaskCreate(YouTask,(void*)0,&YouTaskStk[TASK_STK_SIZE-1],4);

//s="Howmanystringscouldbegeted?";

//OSQPostFront(Str_Q,s);//发送消息以LIFO后进先出的方式发送

//第一个参数Str_Q是消息队列的指针,是OSQCreate的返回值,第二个参数s是消息指针

for(;;)

{

s_flag="TheStartTaskisrunning!";

PC_DispStr(50,++y,s_flag,DISP_FGND_RED+DISP_BGND_LIGHT_GRAY);//提示哪个任务在运行

if(OSTimeGet()>100&&OSTimeGet()<500)

{

s100="ThevalueofOSTIMEisfrom100to500NOW!!";

OSQPostFront(Str_Q,s100);//发送消息以LIFO后进先出的方式发送

//发送消息以LIFO后进先出的方式发送

//第一个参数Str_Q是消息队列的指针,是OSQCreate的返回值,第二个参数s是消息指针

s="Thestringbelongstowhichtask.";

OSQPostFront(Str_Q,s);//发送消息以LIFO方式发送所以如果要申请消息时,会先得到s,然后才是s100

}

if(OSTimeGet()>1000&&OSTimeGet()<1500)

{

s500="ThevalueofOSTIMEisfrom1000to1500NOW!!";

OSQPostFront(Str_Q,s500);//发送消息

}

if(PC_GetKey(&key)==TRUE)

{

if(key==0x1B)

{

PC_DOSReturn();

}

}

OSTimeDlyHMSM(0,0,1,0);

}

}

voidMyTask(void*pdata)

{

#ifOS_CRITICAL_METHOD==3

OS_CPU_SRcpu_sr;

#endif

pdata=pdata;

for(;;)

{

s_flag="TheMyTaskisrunning!";

PC_DispStr(50,++y,s_flag,DISP_FGND_RED+DISP_BGND_LIGHT_GRAY);//提示哪个任务在运行

ss=OSQPend(Str_Q,0,&err);//请求消息队列,参数分别是:Str_Q为所请求消息队列的指针第二个参数为等待时间

//0表示无限等待,&err为错误信息,返回值为队列控制块OS_Q成员OSQOut指向的消息(如果队列中有消息可用的话),如果

//没有消息可用,在使调用OSQPend的任务挂起,使之处于等待状态,并引发一次任务调度

//因为前面发送消息时使用的是LIFO的方式,所以此处第一次得到的消息是上面最后发送的消息

PC_DispStr(3,y,ss,DISP_FGND_BLACK+DISP_BGND_LIGHT_GRAY);//显示得到的消息

//s_1="M";

PC_DispStr(0,y,"My",DISP_FGND_RED+DISP_BGND_LIGHT_GRAY);//显示是哪一个任务显示的

OSTimeDlyHMSM(0,0,1,0);

}

}

voidYouTask(void*pdata)

{

#ifOS_CRITICAL_METHOD==3

OS_CPU_SRcpu_sr;

#endif

pdata=pdata;

for(;;)

{

s_flag="TheYouTaskisrunning!";

PC_DispStr(50,++y,s_flag,DISP_FGND_RED+DISP_BGND_LIGHT_GRAY);//提示哪个任务在运行

ss=OSQPend(Str_Q,0,&err);//请求消息队列

PC_DispStr(3,y,ss,DISP_FGND_BLACK+DISP_BGND_LIGHT_GRAY);//显示得到的消息

//s_1="Y";

PC_DispStr(0,y,"You",DISP_FGND_RED+DISP_BGND_LIGHT_GRAY);//显示是哪一个任务显示的

OSTimeDlyHMSM(0,0,1,0);

}

}

//运行的现象说明上面分析是正确的,因为当时钟节拍数大于100,小于500时,会发送第一个if语句中的两个字符串s100和s

//下面运行的任务接收到并且显示。当时钟节拍数大于1000小于1500时,发送第二个if语句中的字符串,下面运行的任务

//接收并显示。当时钟节拍数大于1500时,就不再发送消息了,下面的任务得不到消息就无限等待下去,所以就不再显示了

//从运行的现象不难可以看出,有时MyTask或YouTask运行了,但是没有得到消息而处于等待状态

//使用上面的方法可以很清楚地看出任务调度和运行的关系了MyTask和YouTask是交替运行的,因为延迟时间相等



评论


相关推荐

技术专区

关闭