uCOS II 消息队列的使用方法
时间:10-02
整理:3721RD
点击:
1、 需在以下文件中配置如下内容
OS_CFG.H
OS_MAX_QS N //你需要的值
// 根据需要自己配置
2、 建立一个指向消息数组的指针和数组的大小,该指针数组必须申明为void类型,如下:
3、 声明一个OS_EVENT类型的指针指向生成的队列,如下:
4、 调用OSQcreate()函数创建消息队列,如下:
5、 等待消息队列中的消息,
必须保证消息队列已经被建立。
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();
}
}
}
补充:消息队列用于缓冲事件。事件不知道什么时候会到来,也不能保证来了就能迅速得到处理。 使用消息队列,可以保证每个事件都被处理到,以及处理顺序。
还有两种情况下会用到消息队列:
存储外部事件:外部事件由中断收集,然后存储到队列。
串口接收程序中的接收循环缓冲区,可理解为消息队列。
IRQ英文全称Interrupt Request,中文翻译为中断请求线。计算机中有许多设备(例如声卡、硬盘等)他们都能在没有CPU介入的情况下完成一定的工作。但是这些设备还是需要定期中断CPU,让CPU为其做一些特定的工作。如果这些设备要中断CPU的运行,就必需在中断请求线上把CPU中断的信号发给CPU。所以每个设备只能使用自己独立的中断请求线。一般来说在80286以上计算机中,共有16个中断请求线与各种需要用中断的不同外设相连接,(每个中断线有一个标号也就是中断号)。
中断号的分配情况如下:
IRQ 说明
0 定时器
1 键盘
2 串行设备控制器
3 COM2
4 COM1
5 LPT2
6 软盘控制器
7 LPT1
8 实时时钟
9 PC网络
10 可用(Available)
11 可用(Available)
12 PS/2 鼠标
13 数学协处理器
14 硬盘控制器
15 可用(Available)
NM1 奇偶校验
大家现在就可以清楚的看到,IRQ3、4、5、10、11、12、15可供用使用。
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();
}
}
}
补充:消息队列用于缓冲事件。事件不知道什么时候会到来,也不能保证来了就能迅速得到处理。 使用消息队列,可以保证每个事件都被处理到,以及处理顺序。
还有两种情况下会用到消息队列:
存储外部事件:外部事件由中断收集,然后存储到队列。
串口接收程序中的接收循环缓冲区,可理解为消息队列。
IRQ英文全称Interrupt Request,中文翻译为中断请求线。计算机中有许多设备(例如声卡、硬盘等)他们都能在没有CPU介入的情况下完成一定的工作。但是这些设备还是需要定期中断CPU,让CPU为其做一些特定的工作。如果这些设备要中断CPU的运行,就必需在中断请求线上把CPU中断的信号发给CPU。所以每个设备只能使用自己独立的中断请求线。一般来说在80286以上计算机中,共有16个中断请求线与各种需要用中断的不同外设相连接,(每个中断线有一个标号也就是中断号)。
中断号的分配情况如下:
IRQ 说明
0 定时器
1 键盘
2 串行设备控制器
3 COM2
4 COM1
5 LPT2
6 软盘控制器
7 LPT1
8 实时时钟
9 PC网络
10 可用(Available)
11 可用(Available)
12 PS/2 鼠标
13 数学协处理器
14 硬盘控制器
15 可用(Available)
NM1 奇偶校验
大家现在就可以清楚的看到,IRQ3、4、5、10、11、12、15可供用使用。
看看,,,,,,,,,,,,
多谢,我终于搞定了