ucosiii之消息列队

ucosiii消息队列的数据信息覆盖:
在里面不断存入消息就可以了。然而在实测时发现每当连续存入两条消息时,后面的会覆盖掉前面的内容,有点十分不理解,DEBUG发现,这个队列中两条消息的指针都指向同一个内存了,所以会出现这个问题。其实,在创建消息队列的时候并没有为所存储的消息分配内存空间,这个需要用户自己去手动分配,也是因为每个消息占用的内存空间并不固定,无法事先分配好。

任务间的通信:
一个任务或者中断服务程序有时候需要和另一个任务交流信息,这个就是消息传递的过程就叫做任务间通信。
任务间的消息传递可以通过2种途径:一z是通过全局变量,二是通过发布消息。
使用全局变量的时候每个任务或者中断服务程序都必须保证其对全局变量的独占访问。消息也可以通过消息队列作为中介发布给任务。

消息构成
1、指向数据的指针
2、数据长度
3、记录消息发布时刻的时间戳。

消息队列的使用
1、指针指向的可以是一块数据区域或者甚至是一个函数。
2、消息的内容必须一直保持可见性,可见性是指代表消息的变量必须在接收消息的任务代码范围内有效。这是因为发布的数据采用的是指针传递,也就是引用传递,并不是值传递。也就是说,发布的消息本身并不产生内存拷贝,可以使用动态内存分配的方式来给消息分配一个内存块,或者,也可以传递一个指向全局变量、全局数据结构、全局数组或者函数的指针。
3、消息队列的相关操作,ISR只能发布消息,不能等待。
4、消息发布方发布消息时可以指定是先入先出模式(FIFO)还是设置为后入先出模式(LIFO),例如ISR发布的消息可以使用LIFO这样可以绕开其他消息最先传递到任务。

消息队列相关函数
ucosiii之消息列队_第1张图片
ucosiii之消息列队_第2张图片
ucosiii之消息列队_第3张图片
ucosiii之消息列队_第4张图片

ucosiii之消息列队_第5张图片
在这里插入图片描述

消息列队例子

OS_Q DATA_Msg;				//定义一个消息队列,用于发送数据
u8 data[10] = {0};			//用于发送数据

//创建消息队列DATA_Msg
OSQCreate ((OS_Q*		)&DATA_Msg,	
                (CPU_CHAR*	)"DATA Msg",	
                (OS_MSG_QTY	)4,	//消息队列长度,这里设置为4,可以存放4组消息,但是消息队列的数据都是指向同一地址,也就是数据都是一样的
                (OS_ERR*	)&err);	
                
//查询DATA_Msg消息队列中的总队列数量和剩余队列数量
u8 check_msg_queue(OS_Q *Msg)
{
	u8 msgq_remain_size;	//消息队列剩余大小
	
	msgq_remain_size = Msg->MsgQ.NbrEntriesSize-Msg->MsgQ.NbrEntries;
	
	return msgq_remain_size;
}


//在任务执行时,发送消息
//发送信息给等待任务内建的消息队列
void Msg_SendData(void *p_arg)
{
	static u8 num = 0;
	OS_ERR err;
	if( check_msg_queue(&DATA_Msg) )//查询DATA_Msg消息队列中的总队列数量和剩余队列数量
	{
		sprintf((char*)data,"data:%d",num++);
		OSQPost((OS_Q*		)&DATA_Msg,		
				(void*		)(void *)data,				//不能是局部变量,
				(OS_MSG_SIZE)10,						//发送10个字节
				(OS_OPT		)OS_OPT_POST_FIFO,
				(OS_ERR*	)&err);
				
		if(err != OS_ERR_NONE)
		{	
			printf("TaskQ_DataTMR:%d\r\n", err);			
			OSTmrStop(&msgQctmr,OS_OPT_TMR_NONE,0,&err); //停止定时器
		}
	}
}

//任务接收消息队列的数据
void Msg_ReceiveData(void *p_arg)
{
	u8 *p;
	OS_MSG_SIZE size;
	OS_ERR err; 
	CPU_SR_ALLOC();
	
	while(1)
	{

		p=(u8 *)OSQPend((OS_Q*		)&DATA_Msg,   		//请求消息
				  (OS_TICK		)0,
                  (OS_OPT		)OS_OPT_PEND_BLOCKING,
                  (OS_MSG_SIZE*	)&size,	
                  (CPU_TS*		)0,
                  (OS_ERR*		)&err);
		printf("%s\r\n", p);
		OSTimeDlyHMSM(0,0,5,0,OS_OPT_TIME_PERIODIC,&err);	
	}
}

任务内建消息队列
任务内建消息队列不想消息队列那样需要用OSQCreate ()创建一个消息队列,任务内建消息队列直接在创建任务的时候在参数OS_MSG_QTY 设置消息队列长度就可以像消息队列那样使用了,但是和消息队列用的函数不一样,任务内建消息队列函数如下:
ucosiii之消息列队_第6张图片
ucosiii之消息列队_第7张图片
在这里插入图片描述
ucosiii之消息列队_第8张图片

//查询OS_TCB 对应的任务内建消息队列中的总队列数量和剩余队列数量
u8 Check_TaskMsgQueue(OS_TCB *TCB)
{
	u8 p[20] = {0};
	CPU_SR_ALLOC();
	u8 msgq_remain_size;	//消息队列剩余大小

	msgq_remain_size =Msgdis_TaskTCB.MsgQ.NbrEntriesSize-Msgdis_TaskTCB.MsgQ.NbrEntries;	
	
	return msgq_remain_size;
}

你可能感兴趣的:(ucosiii)