微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > μC/OS-II的任务之间的通讯与同步

μC/OS-II的任务之间的通讯与同步

时间:10-08 来源:互联网 点击:

程序要从消息队列中取消息时, 必须使用OSQAccept()函数, 而不能使用OSQPend()函数。

程序清单L6.25无等待地从消息队列中取一条消息

void*OSQAccept(OS_EVENT*pevent)

{

void*msg;

OS_Q*pq;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_Q){(1)

OS_EXIT_CRITICAL();

return((void*)0);

}

pq=pevent->OSEventPtr;

if(pq->OSQEntries!=0){(2)

msg=*pq->OSQOut++;(3)

pq->OSQEntries--;

if(pq->OSQOut==pq->OSQEnd){

pq->OSQOut=pq->OSQStart;

}

}else{

msg=(void*)0;(4)

}

OS_EXIT_CRITICAL();

return(msg);

}

6.8.6 清空一个消息队列,OSQFlush()

OSQFlush()函数允许用户删除一个消息队列中的所有消息,重新开始使用。程序清单L6.26是该函数的源代码。和前面的其它函数一样,该函数首先检查pevent指针是否是执行一个消息队列[L6.26(1)],然后将队列的插入指针和取出指针复位,使它们都指向队列起始单元,同时,将队列中的消息数设为0[L6.26(2)]。这里,没有检查该消息队列的等待任务列表是否为空,因为只要该等待任务列表不空,.OSQEntries就一定是0。唯一不同的是,指针.OSQIn和.OSQOut此时可以指向消息队列中的任何单元,不一定是起始单元。

程序清单L6.26清空消息队列

INT8UOSQFlush(OS_EVENT*pevent)

{

OS_Q*pq;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_Q){(1)

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

pq=pevent->OSEventPtr;

pq->OSQIn=pq->OSQStart;(2)

pq->OSQOut=pq->OSQStart;

pq->OSQEntries=0;

OS_EXIT_CRITICAL();

return(OS_NO_ERR);

}

6.8.7 查询一个消息队列的状态,OSQQuery()

OSQQuery()函数使用户可以查询一个消息队列的当前状态。 程序清单L6.27是该函数的源代码。OSQQuery()需要两个参数:一个是指向消息队列的指针pevent。它是在建立一个消息队列时,由OSQCreate()函数返回的;另一个是指向OS_Q_DATA(见uCOS_II.H)数据结构的指针pdata。该结构包含了有关消息队列的信息。在调用OSQQuery()函数之前,必须先定义该数据结构变量。OS_Q_DATA结构包含下面的几个域:

.OSMsg 如果消息队列中有消息,它包含指针.OSQOut所指向的队列单元中的内容。如果队列是空的,.OSMsg包含一个NULL指针。

.OSNMsgs是消息队列中的消息数(.OSQEntries的拷贝)。

.OSQSize 是消息队列的总的容量

.OSEventTbl[]和.OSEventGrp是消息队列的等待任务列表。通过它们,OSQQuery()的调用函数可以得到等待该消息队列中的消息的任务总数。

OSQQuery()函数首先检查pevent指针指向的事件控制块是一个消息队列[L6.27(1)],然后复制等待任务列表[L6.27(2)]。如果消息队列中有消息[L6.27(3)],.OSQOut指向的队列单元中的内容被复制到OS_Q_DATA结构中[L6.27(4)], 否则的话, 就复制一个NULL指针[L6.27(5)]。

最后,复制消息队列中的消息数和消息队列的容量大小[L6.27(6)]。

程序清单L6.27程序消息队列的状态

INT8UOSQQuery(OS_EVENT*pevent,OS_Q_DATA*pdata)

{

OS_Q*pq;

INT8Ui;

INT8U*psrc;

INT8U*pdest;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_Q){(1)

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

pdata->OSEventGrp=pevent->OSEventGrp;(2)

psrc=pevent->OSEventTbl[0];

pdest=pdata->OSEventTbl[0];

for(i=0;i

*pdest++=*psrc++;

}

pq=(OS_Q*)pevent->OSEventPtr;

if(pq->OSQEntries>0){(3)

pdata->OSMsg=pq->OSQOut;(4)

}else{

pdata->OSMsg=(void*)0;(5)

}

pdata->OSNMsgs=pq->OSQEntries;(6)

pdata->OSQSize=pq->OSQSize;

OS_EXIT_CRITICAL();

return(OS_NO_ERR);

}

6.8.8 使用消息队列读取模拟量的值

在控制系统中,经常要频繁地读取模拟量的值。这时,可以先建立一个定时任务OSTimeDly()[见5.00节,延时一个任务,OSTimeDly()],并且给出希望的抽样周期。然后,如图F6.11所示,让A/D采样的任务从一个消息队列中等待消息。该程序最长的等待时间就是抽样周期。当没有其它任务向该消息队列中发送消息时,A/D采样任务因为等待超时而退出等待状态并进行执行。这就模仿了OSTimeDly()函数的功能。

也许,读者会提出疑问,既然OSTimeDly()函数能完成这项工作,为什么还要使用消息队列呢?这是因为,借助消息队列,我们可以让其它的任务向消息队列发送消息来终止A/D采样任务等待消息,使其马上执行一次A/D采样。此外,我们还可以通过消息队列来通知A/D采样程序具体对

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top