UCOSIII操作系统——消息队列篇(1)消息队列

UCOSIII其他内容导航不迷路
UCOSIII操作系统-简介
UCOSIII操作系统——任务篇(1)创建任务
UCOSIII操作系统——任务篇(2)相关API函数
UCOSIII操作系统——系统初始化篇(1)系统初始化
UCOSIII操作系统——系统初始化篇(2)CPU,SysTick,内存初始化
UCOSIII操作系统——硬件初始化篇(1)硬件初始化以及开始运行系统
正在更新整理…

说在前面:
这个内容不适合0基础的人,因为这里只讲了应用层面的东西,并没有深入内核讲解,所以要从零开始学UCOSIII的朋友,可以先去学完入门内容,再来观看这个笔记加深印象。
这篇文章是个人学习整理,如有错误请指正

UCOSIII操作系统——消息队列篇(1)消息队列

消息队列常用函数

函数 描述
OSQCreate() 创建消息队列
OSQDel() 消息队列删除
OSQPost() 消息队列发送
OSQPend() 消息队列获取

消息队列概念简介

队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列里面读取消息。

创建消息队列->OSQCreate()

  • 函数原型
void  OSQCreate (OS_Q        *p_q,     //消息队列指针
                 CPU_CHAR    *p_name,  //消息队列名称
                 OS_MSG_QTY   max_qty, //消息队列大小(不能为0)
                 OS_ERR      *p_err)   //返回错误类型
  • 在调用创建消息队列函数之前要定义一个消息队列结构体
OS_Q queue;           //声明消息队列
  • 创建实例
/* 创建消息队列 queue */
OSQCreate ((OS_Q         *)&queue,            //指向消息队列的指针
           (CPU_CHAR     *)"Queue For Test",  //队列的名字
           (OS_MSG_QTY    )20,                //最多可存放消息的数目
           (OS_ERR       *)&err);             //返回错误类型

消息队列删除->OSQDel()

队列删除函数是根据队列结构体(队列句柄)直接删除的,删除之后这个消息队列的所有信息都会被系统清空,而且不能再次使用这个消息队列了,但是需要注意的是,如果某个消息队列没有被定义,那也是无法被删除的。想要使用消息队列删除函数就必须将OS_CFGQ_DEL_EN宏定义配置为1

  • 函数原型
#if OS_CFG_Q_DEL_EN > 0u             //如果使能了 OSQDel() 函数
OS_OBJ_QTY  OSQDel (OS_Q    *p_q,    //消息队列指针
                    OS_OPT   opt,    //选项
                    OS_ERR  *p_err)  //返回错误类型
  • 选项
    OS_OPT_DEL_NO_PEND: //如果只在没有任务等待的情况下删除队列
    OS_OPT_DEL_ALWAYS: //无论如何必须删除消息队列
  • 应用实例
/* 删除消息队列 queue */
OSQDel ((OS_Q *)&queue, //指向消息队列的指针
		OS_OPT_DEL_NO_PEND,
		(OS_ERR *)&err); //返回错误类型

消息队列发送->OSQPost()

  • 函数原型
void  OSQPost (OS_Q         *p_q,      //消息队列指针
               void         *p_void,   //消息指针(看解释)
               OS_MSG_SIZE   msg_size, //消息大小(单位:字节)
               OS_OPT        opt,      //选项 
               OS_ERR       *p_err)    //返回错误类型
  • 消息指针
    要发送的数据的指针,将内存块首地址通过队列“发送出去”,可以是"字符串"也可以是数组,在接受消息队列的时候可以通过指针取出具体消息。
  • 选项
#define OS_OPT_POST_FIFO (OS_OPT)			(0x0000u) /* 默认采用FIFO 方式发送 */
#define OS_OPT_POST_LIFO (OS_OPT)			(0x0010u) /*采用LIFO 方式发送消息*/
#define OS_OPT_POST_1 (OS_OPT)				(0x0000u) /*将消息发布到最高优先级的等待任务*/
#define OS_OPT_POST_ALL (OS_OPT)			(0x0200u) /*向所有等待的任务广播消息*/
#define OS_OPT_POST_NO_SCHED (OS_OPT)		(0x8000u) /*发送消息但是不进行任务调度*/
我们可以使用,上面基本类型来组合出其他几种类型,如下:
OS OPT POST FIFO+ OS OPT POST ALL
OS OPT POST LIFO+ OS OPT POST ALL
OS OPT POST FIFO+ OS OPT POST NO SCHED
OS OPT POST LIFO+ OS OPT POST NO SCHED
OS OPT POST FIFO + OS OPT POST ALL + OS OPT POST NO SCHED
OS OPT POST LIFO + OS OPT POST ALL+ OS OPT POST NO SCHED
  • 应用实例1
/* 发布消息到消息队列 queue */
OSQPost ((OS_Q        *)&queue,                             //消息变量指针
         (void        *)"Fire uC/OS-III",                //要发送的数据的指针,将内存块首地址通过队列“发送出去”
         (OS_MSG_SIZE  )sizeof ( "Fire uC/OS-III" ),     //数据字节大小
         (OS_OPT       )OS_OPT_POST_FIFO | OS_OPT_POST_ALL, //先进先出和发布给全部任务的形式
         (OS_ERR      *)&err);	                            //返回错误类型
  • 应用实例2
u8 buffer[3];
OSQPost ((OS_Q        *)&queue,                             //消息变量指针
		 (void        *)&buffer,                //要发送的数据的指针,将内存块首地址通过队列“发送出去”
		 (OS_MSG_SIZE  )3,     //数据字节大小
		 (OS_OPT       )OS_OPT_POST_FIFO | OS_OPT_POST_ALL, //先进先出和发布给全部任务的形式
		 (OS_ERR      *)&err);	                            //返回错误类型

消息队列获取->OSQPend()

  • 函数原型
void  *OSQPend (OS_Q         *p_q,       //消息队列指针
                OS_TICK       timeout,   //等待期限(单位:时钟节拍)
                OS_OPT        opt,       //选项
                OS_MSG_SIZE  *p_msg_size,//返回消息大小(单位:字节)
                CPU_TS       *p_ts,      //获取等到消息时的时间戳
                OS_ERR       *p_err)     //返回错误类型
  • 等待期限timeout
    等待消息的超时时间,如果在指定的时间没有接收到消息的话,任务就会被唤醒,
    接着运行。这个参数也可以设置为0,表示任务将一直等待下去,直到接收到消息。
  • 选项opt
    用来选择是否使用阻塞模式,有两个选项可以选择。
oS_ OPT_ PEND_ BLOCKING如果没有任何消息存在的话就阻塞任务,一直等待,直到接收到消息。
oS_ OPT_ PEND_ NON_ BLOCKING如果消息队列没有任何消息的话任务就直接返回。
  • 时间戳
    指向一个时间戳,表明什么时候接收到消息。如果这个指针被赋值为NULL的话,说明用户没有要求时间戳。
  • 应用实例1
/*
*********************************************************************************************************
*                                          PEND TASK
*********************************************************************************************************
*/
static  void  AppTaskPend ( void * p_arg )
{
	OS_ERR      err;
	OS_MSG_SIZE msg_size;
	CPU_SR_ALLOC(); //使用到临界段(在关/开中断时)时必需该宏,该宏声明和
									//定义一个局部变量,用于保存关中断前的 CPU 状态寄存器
									// SR(临界段关中断只需保存SR),开中断时将该值还原。
	char * pMsg;
	
	
	(void)p_arg;

					 
	while (DEF_TRUE) {                                       //任务体
		/* 请求消息队列 queue 的消息 */
    pMsg = OSQPend ((OS_Q         *)&queue,                //消息变量指针
                    (OS_TICK       )0,                     //等待时长为无限
                    (OS_OPT        )OS_OPT_PEND_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();
			
		}
	}
}
  • 应用实例2
static  void  AppTaskStart2 (void *p_arg)
{
    OS_ERR      err;
	OS_MSG_SIZE msg_size;
	CPU_SR_ALLOC(); //使用到临界段(在关/开中断时)时必需该宏,该宏声明和
									//定义一个局部变量,用于保存关中断前的 CPU 状态寄存器
									// SR(临界段关中断只需保存SR),开中断时将该值还原。
	u8 a,b,c;
	char * pMsg;

   (void)p_arg;
   
    /* 死循环 */
    while (DEF_TRUE){          
			GPIO_WriteBit(LEDPORT, LED2, (BitAction)(1-GPIO_ReadOutputDataBit(LEDPORT, LED2)));			
			/* 请求消息队列 queue 的消息 */
			pMsg = OSQPend ((OS_Q         *)&queue,                //消息变量指针
											(OS_TICK       )0,                     //等待时长为无限
											(OS_OPT        )OS_OPT_PEND_BLOCKING,  //如果没有获取到信号量就等待
											(OS_MSG_SIZE  *)&msg_size,             //获取消息的字节大小
											(CPU_TS       *)0,                     //获取任务发送时的时间戳
											(OS_ERR       *)&err);                 //返回错误
			
			if ( err == OS_ERR_NONE )                              //如果接收成功
			{
				a=*pMsg;
				pMsg++;
				b=*pMsg;
				pMsg++;
				c=*pMsg;
				
//				a=*pMsg;
//				b=*(pMsg+1);
//				c=*(pMsg+2);
				printf ( "\r\n接收消息:%d,%d,%d°C \r\n", a,b,c);

				OS_CRITICAL_EXIT();
				
			}
    }	
}

指针的用法很重要,在获取具体的消息的时候需要用到

发布了10 篇原创文章 · 获赞 1 · 访问量 121

猜你喜欢

转载自blog.csdn.net/iiinoname/article/details/105192982