一 消息队列的相关函数
创建一个消息队列 | OSQCreate() | OS_CFG_Q_EN | OS_Q CommQ; OS_ERR err; OSQCreate(&CommQ,“Comm Queue”,10,&err); |
删除一个消息队列 | OSQDel() | OS_CFG_Q_EN OS_CFG_Q_DEL_EN | OS_Q DispQ; OS_ERR err; OSQDel(&DispQ,OS_OPT_DEL_ALWAYS,&err); |
清空一个消息队列 | OSQFlush() | OS_CFG_Q_EN OS_CFG_Q_FLUSH_EN | OS_Q CommQ; OS_MSG_QTY entries; entries = OSQFlush(&CommQ,&err); |
等待消息队列 | OSQPend() | OS_CFG_Q_EN | OS_Q CommQ; OS_ERR err; OSQPend(&CommQ,100,OS_OPT_PEND_BLOCKING, |
取消等待消息队列 | OSQPendAbort() | OS_CFG_Q_EN OS_CFG_Q_PEND_ABORT_EN | OS_Q CommQ; OS_ERR err; nbr_tasks = OSQPendAbort(&CommQ, |
向消息队列发送一条消息 | OSQPost() | OS_CFG_Q_EN | OS_Q CommQ; OS_ERR err; |
二 使用消息队列
消息队列是uCOS 中任务与任务间、中断与任务间主要的通讯方式,要使用消息队列需要满足下面条件
- 将宏OS_CFG_Q_EN设置为1
- 在创建任务时,OS_MSG_QTY参数不能设置为0.
下面是一则使用消息队列的代码示例,一个任务发送消息,一个任务接受消息并进行打印(代码省略了初始化等其他代码)
#include "main.h"
OS_Q msg_q; //声明消息队列
void RR1_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
/* 发布消息到消息队列 queue */
OSQPost ((OS_Q *)&msg_q, //消息变量指针
(void *)"msg_q test", //要发送的数据的指针,将内存块首地址通过队列“发送出去”
(OS_MSG_SIZE )sizeof ("msg_q test"),//数据字节大小
(OS_OPT )OS_OPT_POST_FIFO | OS_OPT_POST_ALL, //先进先出和发布给全部任务的形式
(OS_ERR *)&err); //返回错误类型
OSTimeDly (1000, OS_OPT_TIME_DLY, &err ); //相对性延时1000个时钟节拍(1s)
}
}
void RR2_task(void *p_arg)
{
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
OS_MSG_SIZE msg_size;
//定义一个局部变量,用于保存关中断前的 CPU 状态寄存器
char * pMsg;
while(1)
{
/* 请求消息队列 queue 的消息 */
pMsg = OSQPend ((OS_Q *)&msg_q, //消息变量指针
(OS_TICK )100, //等待时长
(OS_OPT )OS_OPT_PEND_NON_BLOCKING,//如果没有获取到信号量就等待
(OS_MSG_SIZE *)&msg_size, //获取消息的字节大小
(CPU_TS *)0, //获取任务发送时的时间戳
(OS_ERR *)&err); //返回错误
if ( err == OS_ERR_NONE ) //如果接收成功
{
OS_CRITICAL_ENTER(); //进入临界段
printf ( "\r\n 接收消息的长度:%d 字节,内容:%s\r\n", msg_size, pMsg );
OS_CRITICAL_EXIT();
}
OSTimeDly (1, OS_OPT_TIME_DLY, &err );
}
}
三 任务内置消息队列
向任务发送一条消息 | OSTaskQPost() | OS_CFG_TASK_Q_EN | OS_TCB CommRxTaskTCB; OS_ERR err; OSTaskQPost(&CommRxTaskTCB,&CommRxBuf[0], |
等待消息 | OSTaskQPend() | OS_CFG_TASK_Q_EN | OS_ERR err; OS_MSG_SIZE msg_size; CPU_TS ts; OSTaskQPend(100,OS_OPT_PEND_BLOCKING, &msg_size,&ts,&err); |
取消等待消息 | OSTaskQPendAbort() | OS_CFG_TASK_Q_EN
OS_CFG_TASK_Q_PEND _ABORT_EN | OS_TCB CommRxTaskTCB; OS_ERR err; OSTaskQPendAbort(&CommRxTaskTCB, |
清空任务的消息队列 | OSTaskQFlush() | OS_CFG_TASK_Q_EN | OSTaskQFlush((OS_TCB *)0,&err); |
四 使用任务内置消息队列
led0_task任务中发送消息,led1_task接受消息并将消息通过串口打印
void led0_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(DEF_TRUE){
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
// 发送消息到任务内置队列
OSTaskQPost((OS_TCB* )&DS1TaskTCB, // 向任务 DS1TaskTCB 发送消息
(void* )"task msg",
(OS_MSG_SIZE )sizeof("task msg"),
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
OSTimeDly (1000, OS_OPT_TIME_DLY, &err ); //相对性延时1000个时钟节拍(1s)
}
}
void led1_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
OS_MSG_SIZE size;
void *p_msg;
while(1){
// 请求消息
p_msg = OSTaskQPend((OS_TICK )10, //等待消息的超时时间
(OS_OPT )OS_OPT_PEND_NON_BLOCKING,//是否使用阻塞模式
(OS_MSG_SIZE* )&size, //指向存放消息大小的变量
(CPU_TS* )0, //指向一个时间戳,表明什么时候接收到消息。
(OS_ERR* )&err );
if(err == OS_ERR_NONE){
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
printf ("led1_task:%d 字节,内容:%s\r\n", size, (char *)p_msg );
}
OSTimeDly (1, OS_OPT_TIME_DLY, &err ); //相对性延时1000个时钟节拍(1s)
}
}