ucos信号量消息队列

消息队列

测试代码

全局变量

static int msg_int;
OS_Q DATA_Msg;//消息队列

主任务

void start_task(void *p_arg){
    ....
 OSQCreate ((OS_Q*       )&DATA_Msg, 
                (CPU_CHAR*  )"DATA Msg",    
                (OS_MSG_QTY )1, 
                (OS_ERR*    )&err); 
    ...
}                

led任务0

void led0_task(void *p_arg)
{
	
	CPU_INT08U *msg;//指向信息的指针
	OS_ERR err;
	p_arg = p_arg;
	
	
	while(1)
	{
		msg = malloc(10); //开辟10个字节内存
		if(msg!=NULL){
		sprintf((char *)msg,"%d",msg_int++);//内存空间赋值,msg_int作为变量
		OSQPost((OS_Q*      )&DATA_Msg,     
                (void*      )msg,
                (OS_MSG_SIZE)10,
                (OS_OPT     )OS_OPT_POST_FIFO,
                (OS_ERR*    )&err);
							}
		if(err!=OS_ERR_NONE){
			break;
		}
		OSTimeDlyHMSM(0,0,3,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时2s
	}
}

led任务1

void led1_task(void *p_arg){
  CPU_TS  ts;
	OS_ERR err;
	OS_MSG_SIZE size;
	CPU_INT08U *msg;//指向信息的指针
	p_arg = p_arg;
	while(1)
	{
			msg=OSQPend((OS_Q*        )&DATA_Msg,   
                  (OS_TICK      )0,
                  (OS_OPT       )OS_OPT_PEND_BLOCKING,
                  (OS_MSG_SIZE* )&size, 
                  (CPU_TS*      )0,
                  (OS_ERR*      )&err);
		if(msg!=NULL){//接收到一次邮箱就闪烁一次
		LED0=0;
		OSTimeDlyHMSM(0,0,0,50,OS_OPT_TIME_HMSM_STRICT,&err); //延时200ms
		LED0=1;
		OSTimeDlyHMSM(0,0,0,50,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
		free(msg);//释放接受的数据内存
		}
	}
}

和信号量类似,消息队列可用于传递信息,不同的是消息队列的数据结构可以携带具体的数据参数,并以指针的方式传递,同时还有LIFO(后进先出)和FIFO(先进先出)两种模式,用于配合紧急状态下的消息输出,个人认为消息队列的最大用处是对于连续信号在不同任务之间的传递,需要注意的是,当一个任务从消息队列中取出一个消息后,消息队列会剔除该信息,也就是同一个信息不会被收到两次,保证信息的连续和实时性。
OSQPend()函数中包含的OS_MsgQGet()函数中包含以下代码即实现了该功能

...

    p_void          = p_msg->MsgPtr;//获取消息指针
   *p_msg_size      = p_msg->MsgSize;
    if (p_ts != (CPU_TS *)0) {
       *p_ts  = p_msg->MsgTS;
    }
    p_msg_q->OutPtr = p_msg->NextPtr;//消息指向下一个消息对象,相当于剔除已经接受的邮箱(邮箱队列是一个闭环的结构,使其能够不断循环下去)
    if (p_msg_q->OutPtr == (OS_MSG *)0) {//当下一个消息对象没有实体数据时,将默认配置为空邮箱
        p_msg_q->InPtr      = (OS_MSG   *)0;
        p_msg_q->NbrEntries = (OS_MSG_QTY)0;
    } else {
        p_msg_q->NbrEntries--;
    }
    p_msg->NextPtr    = OSMsgPool.NextPtr;                  /* Return message control block to free list              */
    OSMsgPool.NextPtr = p_msg;
    OSMsgPool.NbrFree++;//增加空闲邮箱数量
    OSMsgPool.NbrUsed--;
   *p_err             = OS_ERR_NONE;
    return (p_void);

在上面的代码中可以看到,信息是通过指针msg作为OSQPost()的参数进行传输的,其指向内存中声明的一块区域,如果在目标任务收到该指针后,不会再使用该内存的情况下,建议直接free释放该区域内存,避免数据过多导致内存碎片化。

参考
UCOS学习笔记——消息队列
UCOSIII消息队列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值