学号:
嵌入式系统及应用 实验报告
消息队列
学班成
生姓名 级 绩
简介
消息队列就象一个类似于缓冲区的对象,通过消息队列任务和
ISR发送和接收消息,实现数据的通信和同步。消息队列具有一定的容量,可以容纳多条消息,因此可以看成是多个邮箱的组合。
1、实验目的
a)理解消息队列的基本原理,了解任务的各个消息队列基本状态及其变迁过程;
b) 掌握μC/OS-II中消息队列管理的基本方法(创建、启动、挂起、解挂任务);
c)熟练使用μC/OS-II消息队列管理的基本系统调用。
2、实验原理及程序结构 2.1 实验设计
为了说明如何使用消息队列来实现多任务接收数据,我们设计一个系统,按键一按下,LED按照指定节奏闪耀,蜂鸣器按照指定节奏鸣响。假设TaskLED为高优先级的任务,三个任务的处理流程如下。
TaskKEY任务主要代码如下。
LED任务的代码如下。
Beep任务主要代码如下。
源程序说明
1、需在以下文件中配置如下内容 OS_CFG.H
OS_MAX_QS N 你需要的值 根据需要自己配置
#define OS_Q_EN 1 /* Enable (1) or Disable (0) code generation for QUEUES */ #define OS_Q_ACCEPT_EN 1 /* Include code for OSQAccept() */ #define OS_Q_DEL_EN 1 /* Include code for OSQDel() */ #define OS_Q_FLUSH_EN 1 /* Include code for OSQFlush() */ #define OS_Q_POST_EN 1 /* Include code for OSQPost() */ #define OS_Q_POST_FRONT_EN 1 /* Include code for OSQPostFront() */ #define OS_Q_POST_OPT_EN 1 /* Include code for OSQPostOpt() */ #define OS_Q_QUERY_EN 1 /* Include code for OSQQuery() */ 2、建立一个指向消息数组的指针和数组的大小,该指针数组必须申明为void类型,如下: void *MyArrayOfMsg[SIZE];
3、声明一个OS_EVENT类型的指针指向生成的队列,如下: OS_EVENT *QSem;
4、调用OSQcreate()函数创建消息队列,如下: QSem = OSQcreate(&MyArrayOfMsg[0],SIZE);
5、等待消息队列中的消息,OSQPend()。void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err): 必须保证消息队列已经被建立。
timeout定义的是等待超时时间,如果为0则表示无期限的等待 err表示的是在等待消息队列出错时的返回类型,有以下几种: OS_ERR_PEVENT_NULL //消息队列不存在 OS_ERR_EVENT_TYPE
OS_TIMEOUT //消息队列等待超时
OS_NO_ERR //消息队列接收到消息 获得消息队列示例 type *GETQ; INT8U err;
GETQ = (type *)OSQPend(QSem, time, &err); if(err == OS_NO_ERR){ 无错处理 } else{ 出错处理 }
6.1 向消息队列发送一则消息(FIFO),OSQPost(); INT8U OSQPost (OS_EVENT *pevent, void *msg): 函数返回值有:
OS_ERR_PEVENT_NULL OS_ERR_POST_NULL_PTR OS_ERR_EVENT_TYPE OS_Q_FULL OS_NO_ERR 参数:pevent,*msg
6.2 向消息队列发送一则消息(LIFO) INT8U OSQPostFront (OS_EVENT *pevent, void *msg)
6.3 向消息队列发送一则消息(LIFO或者FIFO) INT8U OSQPostOpt (OS_EVENT *pevent, void *msg, INT8U opt) 参数: opt
如果经opt参数中的OS_POST_OPT_BROADCAST位置为1,则所有正在等待消息的任务都能接收到这则消息,并且被OS_EventTaskRdy()从等待列表中删除
如果不是广播方式,则只有等待消息的任务中优先级最高的任务能够进入就绪态。然后,OS_EventTaskRdy()从等待列表中把等待消息的任务中优先级最高的任务删除。
注: 如果此函数由ISR调用,则不会发生任务切换,直到中断嵌套的最外层中断服务子程序调用OSIntExit()函数时,才能进行任务切换
7、无等待的从消息队列中获得消息,OSQAccept(); void *OSQAccept (OS_EVENT *pevent, INT8U *err) err可能的返回值: OS_ERR_PEVENT_NULL OS_Q_EMPTY OS_NO_ERR 函数的返回值:消息,0
8、清空消息队列 INT8U OSQFlush (OS_EVENT *pevent) 函数返回值:
OS_ERR_PEVENT_NULL OS_ERR_EVENT_TYPE OS_NO_ERR
9、获取消息队列的状态,OSQQuery(); INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *p_q_data) 函数返回值:
OS_ERR_PEVENT_NULL OS_ERR_EVENT_TYPE OS_NO_ERR
OS_Q_DATA数据结构在ucos_ii.h中
// 采用消息队列的ADC采样任务原型代码,建议与uC/OS-II作者的ADC通用例程一起使用 // 说明这里消息队列msg_q不用于储存ADC结果。 void ADCTask(void * pParam) {
char *cmd; pParam=pParam; while(1) {
cmd=OSQPend(msg_q,100,&err); // waiting for command if(err==OS_NO_ERR) {
switch (*cmd) {
case '1': printf(\"Command 1\\n\"); break; case '2': printf(\"Command 2\\n\"); break; default : printf(\"Error command.\\n\"); break; } }
else
{// no command , then sampling...
if(err==OS_TIMEOUT) // sampling while timeout. printf(\"ADC sampling ...\"); StoreADResult(); } } }
因篇幅问题不能全部显示,请点此查看更多更全内容