消息队列和事件标志组

UCOSIII提供了消息队列的功能,消息队列可以在任务与任务间、中断和任务间传递信息,实现了任务接收来自其他任务或中断的任意类型不同长度的消息。

消息队列与信号量的逻辑相同,任务能够从队列里面读取消息(信号量),当队列中的(信号量)消息是空时,读取消息(信号量)的任务将被阻塞,用户还可以指定阻塞的任务时间 timeout,在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。

消息队列是一种异步的通信方式。通过消息队列服务,任务或中断服务程序可以将消息放入消息队列中。同样,一个或多个任务可以从消息队列中获得消息。

一、消息队列

在UCOSIII中,常用的消息队列API函数有三个:OSQCreate()、OSQPost()和OSQPend()。

声明消息队列

c 复制代码
OS_Q queue;                             //声明消息队列

创建消息队列函数OSQCreate():

该函数用于创建一个消息队列,并返回一个消息队列的句柄。可以通过该句柄来操作消息队列,例如发送消息和接收消息。

cpp 复制代码
void OSQCreate (OS_Q *p_q,             //指向消息队列的指针
                CPU_CHAR *p_name,      //队列的名字
                OS_MSG_QTY max_qty,    //最多可存放消息的数目
                OS_ERR *p_err)         //返回错误类型

向消息队列发送消息函数OSQPost():

该函数用于向消息队列发送消息。可以将需要传递的数据作为参数传入该函数,函数会将数据放入消息队列中,供其他任务或线程使用。

c 复制代码
void OSQPost (OS_Q *p_q,               //消息变量指针
              void *p_void,            //要发送的数据的指针
              OS_MSG_SIZE msg_size,    //数据字节大小
              OS_OPT opt,              //先进先出和发布给全部任务的形式
              OS_ERR *p_err)           //返回错误类型
c 复制代码
OS_OPT_POST_FIFO	默认采用 FIFO 方式发送
OS_OPT_POST_LIFO	采用 LIFO 方式发送消息
OS_OPT_POST_1	将消息发布到最高优先级的等待任务
OS_OPT_POST_ALL	向所有等待的任务广播消息
OS_OPT_POST_NO_SCHED	发送消息但是不进行任务调度

等待消息队列函数OSQPend():

该函数用于等待消息队列中的消息。当消息队列中有消息时,该函数会将消息取出并返回给调用者。如果消息队列为空,则该函数会一直等待,直到有消息到达。

c 复制代码
    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)                //返回错误类型
OS_OPT_PEND_BLOCKING   没有获取到信号量就等待
OS_OPT_PEND_NON_BLOCKING    没有获取到信号量就也不等待

案例:主任务执行按键扫描,并将扫描结果发送至消息队列。按键处理任务等待按键消息,获取到消息后根据按键扫描结果开启定时器,定时器中断发送字符串到消息队列,显示任务等待获取字符串消息队列,获取后后展示消息队列。

c 复制代码
#define KEYMSG_Q_NUM	1	//按键消息队列的数量
#define DATAMSG_Q_NUM	4	//发送数据的消息队列的数量
OS_Q KEY_Msg;		//定义一个消息队列,用于按键消息传递,模拟消息邮箱
OS_Q DATA_Msg;		//定义一个消息队列,用于发送数据
						
定时器
u8 tmr1sta=0; 	//标记定时器的工作状态
OS_TMR	tmr1;	//定义一个定时器
void tmr1_callback(void *p_tmr,void *p_arg); //定时器1回调函数
void start_task(void *p_arg)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	
	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);  	//统计任务                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间
    CPU_IntDisMeasMaxCurReset();	
#endif
	
#if	OS_CFG_SCHED_ROUND_ROBIN_EN     //当使用时间片轮转的时候
	 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif	
		
	OS_CRITICAL_ENTER();	        //进入临界区
	//创建消息队列KEY_Msg
	OSQCreate ((OS_Q*		)&KEY_Msg,	//消息队列
                (CPU_CHAR*	)"KEY Msg",	//消息队列名称
                (OS_MSG_QTY	)KEYMSG_Q_NUM,	//消息队列长度,这里设置为1
                (OS_ERR*	)&err);		//错误码
	//创建消息队列DATA_Msg
	OSQCreate ((OS_Q*		)&DATA_Msg,	
                (CPU_CHAR*	)"DATA Msg",	
                (OS_MSG_QTY	)DATAMSG_Q_NUM,	
                (OS_ERR*	)&err);	
	//创建定时器1
	OSTmrCreate((OS_TMR		*)&tmr1,		//定时器1
                (CPU_CHAR	*)"tmr1",		//定时器名字
                (OS_TICK	 )0,			//0ms
                (OS_TICK	 )50,          //50*10=500ms
                (OS_OPT		 )OS_OPT_TMR_PERIODIC, //周期模式
                (OS_TMR_CALLBACK_PTR)tmr1_callback,//定时器1回调函数
                (void	    *)0,			//参数为0
                (OS_ERR	    *)&err);		//返回的错误码
	//创建主任务
	OSTaskCreate((OS_TCB 	* )&Main_TaskTCB,		
				 (CPU_CHAR	* )"Main task", 		
                 (OS_TASK_PTR )main_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )MAIN_TASK_PRIO,     
                 (CPU_STK   * )&MAIN_TASK_STK[0],	
                 (CPU_STK_SIZE)MAIN_STK_SIZE/10,	
                 (CPU_STK_SIZE)MAIN_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,  					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);			
	//创建按键任务
	OSTaskCreate((OS_TCB 	* )&Keyprocess_TaskTCB,		
				 (CPU_CHAR	* )"Keyprocess task", 		
                 (OS_TASK_PTR )Keyprocess_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )KEYPROCESS_TASK_PRIO,     
                 (CPU_STK   * )&KEYPROCESS_TASK_STK[0],	
                 (CPU_STK_SIZE)KEYPROCESS_STK_SIZE/10,	
                 (CPU_STK_SIZE)KEYPROCESS_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,  					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);			
	//创建MSGDIS任务
	OSTaskCreate((OS_TCB 	* )&Msgdis_TaskTCB,		
				 (CPU_CHAR	* )"Msgdis task", 		
                 (OS_TASK_PTR )msgdis_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )MSGDIS_TASK_PRIO,     
                 (CPU_STK   * )&MSGDIS_TASK_STK[0],	
                 (CPU_STK_SIZE)MSGDIS_STK_SIZE/10,	
                 (CPU_STK_SIZE)MSGDIS_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,  					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);	
	OS_CRITICAL_EXIT();	           //退出临界区
	OSTaskDel((OS_TCB*)0,&err);	   //删除start_task任务自身
}

//定时器1的回调函数
void tmr1_callback(void *p_tmr,void *p_arg)
{
	u8 *pbuf;
	static u8 msg_num;
	OS_ERR err;
	pbuf = mymalloc(10);	//申请10个字节
	if(pbuf)	//申请内存成功
	{
		msg_num++;
		sprintf((char*)pbuf,"ALIENTEK %d",msg_num);
		//发送消息
		OSQPost((OS_Q*		)&DATA_Msg,		
				(void*		)pbuf,
				(OS_MSG_SIZE)10,
				(OS_OPT		)OS_OPT_POST_FIFO,
				(OS_ERR*	)&err);
		if(err != OS_ERR_NONE)
		{
			myfree(pbuf);	//释放内存
			OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1
			tmr1sta = !tmr1sta;
			LCD_ShowString(10,150,100,16,16,"TMR1 STOP! ");
		}
	}	
}

//主任务的任务函数
void main_task(void *p_arg)
{
	u8 key,num;
	OS_ERR err;
	u8 *p;
	while(1)
	{
		key = KEY_Scan(0);  //扫描按键
		if(key)
		{
			//发送消息
			OSQPost((OS_Q*		)&KEY_Msg,		
					(void*		)&key,
					(OS_MSG_SIZE)1,
					(OS_OPT		)OS_OPT_POST_FIFO,
					(OS_ERR*	)&err);
		}
		OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);   //延时10ms
	}
}

//按键处理任务的任务函数
void Keyprocess_task(void *p_arg)
{	
	u8 num;
	u8 *key;
	OS_MSG_SIZE size;
	OS_ERR err;
	while(1)
	{
		//请求消息KEY_Msg
		key=OSQPend((OS_Q*			)&KEY_Msg,   
					(OS_TICK		)0,
                    (OS_OPT			)OS_OPT_PEND_BLOCKING,
                    (OS_MSG_SIZE*	)&size,		
                    (CPU_TS*		)0,
                    (OS_ERR*		)&err);
		switch(*key)
		{
			case WKUP_PRES:		//KEY_UP控制LED1
				LED1 = ~LED1;
				break;
			case KEY1_PRES:		//KEY1控制定时器1
				tmr1sta = !tmr1sta;
				if(tmr1sta) 
				{
					OSTmrStart(&tmr1,&err);
					LCD_ShowString(10,150,100,16,16,"TMR1 START!");
				}
				else
				{
					OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); 
					LCD_ShowString(10,150,100,16,16,"TMR1 STOP! ");
				}
				break;
		}
	}
}

//显示消息队列中的消息
void msgdis_task(void *p_arg)
{
	u8 *p;
	OS_MSG_SIZE size;
	OS_ERR err; 
	while(1)
	{                                            
		p=OSQPend((OS_Q*		)&DATA_Msg,               //请求消息
				  (OS_TICK		)0,
                  (OS_OPT		)OS_OPT_PEND_BLOCKING,
                  (OS_MSG_SIZE*	)&size,	
                  (CPU_TS*		)0,
                  (OS_ERR*		)&err);
		LCD_ShowString(5,270,100,16,16,p);
		myfree(p);	                                      //释放内存
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
	}
}

二、任务内建消息队列

任务创建函数中的消息队列设置参数:OS_MSG_QTY q_size

c 复制代码
void  OSTaskCreate (  OS_TCB          *p_tcb,//指向任务的任务控制块
                    CPU_CHAR      *p_name,//任务名字
                    OS_TASK_PTR    p_task,//任务函数名字
                    void           *p_arg,//传递给任务的参数
                    OS_PRIO        prio,//任务优先级
                    CPU_STK         *p_stk_base,//任务堆栈基地址
                    CPU_STK_SIZE   stk_limit,//任务堆栈深度
                    CPU_STK_SIZE   stk_size,//任务堆栈大小
                    OS_MSG_QTY     q_size,//可选消息队列大小
         OS_TICK   time_quanta,//使能时间片轮转调度,默认时钟节拍除以10
         void              *p_ext,//指向用户补充的存储区
         OS_OPT                opt,//任务的特定选项
         OS_ERR          *p_err)//保存错误码

任务消息等待

c 复制代码
void  *OSTaskQPend (OS_TICK       timeout,     	//超时等待时间
                    OS_OPT        opt,		    //是否使用阻塞
                    OS_MSG_SIZE  *p_msg_size,	//指向存放大小变量
                    CPU_TS       *p_ts,		    //时间戳
                    OS_ERR       *p_err)

任务消息发送

c 复制代码
void  OSTaskQPost (OS_TCB       *p_tcb,		//指向消息要发送的任务块
                   void         *p_void,		//要发送的数据指针
                   OS_MSG_SIZE   msg_size,	//发送数据大小
                   OS_OPT        opt,			//发送操作类型选项
                   OS_ERR       *p_err)
OS_OPT_POST_FIFO    //先进先出
          OS_OPT_POST_LIFO   //先进后出
          OS_OPT_POST_NO_SCHED	//发送后不进行任务调度选项可以作|操作

案例

主任务检测按键按下后开启定时器,定时器中断服务函数发送消息数组,显示任务等待定时器发送消息数组后接收并展示消息数组。

c 复制代码
//开始任务函数
void start_task(void *p_arg)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	
	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);  	//统计任务                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间
    CPU_IntDisMeasMaxCurReset();	
#endif
	
#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
	 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif	
		
	OS_CRITICAL_ENTER();	//进入临界区
	//创建定时器1
	OSTmrCreate((OS_TMR		*)&tmr1,		//定时器1
                (CPU_CHAR	*)"tmr1",		//定时器名字
                (OS_TICK	 )0,			//0ms
                (OS_TICK	 )50,          //50*10=500ms
                (OS_OPT		 )OS_OPT_TMR_PERIODIC, //周期模式
                (OS_TMR_CALLBACK_PTR)tmr1_callback,//定时器1回调函数
                (void	    *)0,			//参数为0
                (OS_ERR	    *)&err);		//返回的错误码
	//创建主任务
	OSTaskCreate((OS_TCB 	* )&Main_TaskTCB,		
				 (CPU_CHAR	* )"Main task", 		
                 (OS_TASK_PTR )main_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )MAIN_TASK_PRIO,     
                 (CPU_STK   * )&MAIN_TASK_STK[0],	
                 (CPU_STK_SIZE)MAIN_STK_SIZE/10,	
                 (CPU_STK_SIZE)MAIN_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,  					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);	
	//创建MSGDIS任务
	OSTaskCreate((OS_TCB 	* )&Msgdis_TaskTCB,		
				 (CPU_CHAR	* )"Msgdis task", 		
                 (OS_TASK_PTR )msgdis_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )MSGDIS_TASK_PRIO,     
                 (CPU_STK   * )&MSGDIS_TASK_STK[0],	
                 (CPU_STK_SIZE)MSGDIS_STK_SIZE/10,	
                 (CPU_STK_SIZE)MSGDIS_STK_SIZE,		
                 (OS_MSG_QTY  )TASK_Q_NUM,		//任务Msgdis_task需要使用内建消息队列,消息队列长度为4					
                 (OS_TICK	  )0,  					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);	
	OS_CRITICAL_EXIT();	//退出临界区
	OSTaskDel((OS_TCB*)0,&err);	//删除start_task任务自身
}

//定时器1的回调函数
void tmr1_callback(void *p_tmr,void *p_arg)
{
	u8 *pbuf;
	static u8 msg_num;
	OS_ERR err;
	pbuf = mymalloc(10);	//申请10个字节
	if(pbuf)	//申请内存成功
	{
		msg_num++;
		sprintf((char*)pbuf,"ALIENTEK %d",msg_num);
		//发送消息
		OSTaskQPost((OS_TCB*	)&Msgdis_TaskTCB,	//向任务Msgdis发送消息
                    (void*		)pbuf,
                    (OS_MSG_SIZE)10,
                    (OS_OPT		)OS_OPT_POST_FIFO,
					(OS_ERR*	)&err);
		if(err != OS_ERR_NONE)
		{
			myfree(pbuf);	//释放内存
			OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1
			tmr1sta = !tmr1sta;
			LCD_ShowString(40,150,100,16,16,"TMR1 STOP! ");
		}
	}	
}

//主任务的任务函数
void main_task(void *p_arg)
{
	u8 key,num;
	OS_ERR err;
	u8 *p;
	while(1)
	{
		key = KEY_Scan(0);  //扫描按键
		if(key==WKUP_PRES)
		{
			tmr1sta = !tmr1sta;
			if(tmr1sta) 
			{
				OSTmrStart(&tmr1,&err);
				LCD_ShowString(40,150,100,16,16,"TMR1 START!");
			}
			else
			{
				OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1
				LCD_ShowString(40,150,100,16,16,"TMR1 STOP! ");
			}
		}
		OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);   //延时10ms
	}
}

//显示消息队列中的消息
void msgdis_task(void *p_arg)
{
	u8 *p;
	OS_MSG_SIZE size;
	OS_ERR err; 
	while(1)
	{
		//请求消息
		p=OSTaskQPend((OS_TICK		)0,
                      (OS_OPT		)OS_OPT_PEND_BLOCKING,
                      (OS_MSG_SIZE*	)&size,
                      (CPU_TS*		)0,
                      (OS_ERR*      )&err );
		LCD_ShowString(40,270,100,16,16,p);
		myfree(p);	//释放内存
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
	}
}

三、事件标志组

当任务需要与多个事件的发生同步时,可以使用事件标志组。等待多个事件时,任何一个事件发生,任务才被同步,这种同步机制称为"或"同步,当所有的事件都发生时,任务才能被同步,这种同步机制被称为"与"同步。

创建一个事件标志组

调用函数OSFlagCreate()创建一个事件标志组

c 复制代码
void  OSFlagCreate (OS_FLAG_GRP  *p_grp,             //指向事件标志组
                 CPU_CHAR     *p_name,           //事件标志组的名字
                    OS_FLAGS      flags,           //定义事件标志组的初始值
                    OS_ERR       *p_err)

/请求等待一个事件标志组

等待一个事件标志组需要调用函数OSFlagPend()

c 复制代码
OS_FLAGS  OSFlagPend (OS_FLAG_GRP  *p_grp,     //指向事件标志组
                      OS_FLAGS      flags,     //bit序列
                      OS_TICK       timeout,  //等待事件标志组的超时时间(节拍数)
                      OS_OPT        opt,     //决定任务等待的条件
                      CPU_TS       *p_ts,       //指向一个时间戳
                      OS_ERR       *p_err)

向事件标志组发送事件标志

c 复制代码
OS_FLAGS  OSFlagPost (OS_FLAG_GRP  *p_grp,   //指向事件标志组
                      OS_FLAGS      flags,   //决定对哪些位清零和置位
                      OS_OPT        opt,    //决定对标志位的操作
                      OS_ERR       *p_err)

案例:

时间标志组处理任务等待按键1和按键2标志位都置位后才会就绪执行,主任务中按键1和按键2按下分别向事件标志组发送按键1和按键2事件标志。

c 复制代码
事件标志组//
#define KEY0_FLAG		0x01
#define KEY1_FLAG		0x02
#define KEYFLAGS_VALUE	0X00						
OS_FLAG_GRP	EventFlags;		//定义一个事件标志组
//开始任务函数
void start_task(void *p_arg)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	
	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);  	//统计任务                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间
    CPU_IntDisMeasMaxCurReset();	
#endif
	
#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
	 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif	
		
	OS_CRITICAL_ENTER();	//进入临界区
	//创建一个事件标志组
	OSFlagCreate((OS_FLAG_GRP*)&EventFlags,		//指向事件标志组
                 (CPU_CHAR*	  )"Event Flags",	//名字
                 (OS_FLAGS	  )KEYFLAGS_VALUE,	//事件标志组初始值
                 (OS_ERR*  	  )&err);			//错误码
	//创建主任务
	OSTaskCreate((OS_TCB*     )&Main_TaskTCB,		
				 (CPU_CHAR*   )"Main task", 		
                 (OS_TASK_PTR )main_task, 			
                 (void*       )0,					
                 (OS_PRIO	  )MAIN_TASK_PRIO,     
                 (CPU_STK*    )&MAIN_TASK_STK[0],	
                 (CPU_STK_SIZE)MAIN_STK_SIZE/10,	
                 (CPU_STK_SIZE)MAIN_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,  					
                 (void*       )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR*     )&err);						
	//创建MSGDIS任务
	OSTaskCreate((OS_TCB*     )&Flagsprocess_TaskTCB,		
				 (CPU_CHAR*   )"Flagsprocess task", 		
                 (OS_TASK_PTR )flagsprocess_task, 			
                 (void* 	  )0,					
                 (OS_PRIO	  )FLAGSPROCESS_TASK_PRIO,     
                 (CPU_STK* 	  )&FLAGSPROCESS_TASK_STK[0],	
                 (CPU_STK_SIZE)FLAGSPROCESS_STK_SIZE/10,	
                 (CPU_STK_SIZE)FLAGSPROCESS_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,  					
                 (void* 	  )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR* 	  )&err);	
	OS_CRITICAL_EXIT();	//退出临界区
	OSTaskDel((OS_TCB*)0,&err);	//删除start_task任务自身
}

//主任务的任务函数
void main_task(void *p_arg)
{
	u8 key,num;
	OS_FLAGS flags_num;
	OS_ERR err;
	while(1)
	{
		key = KEY_Scan(0);  //扫描按键
		if(key == KEY0_PRES)
		{
			//向事件标志组EventFlags发送标志
			flags_num=OSFlagPost((OS_FLAG_GRP*)&EventFlags,
								 (OS_FLAGS	  )KEY0_FLAG,
								 (OS_OPT	  )OS_OPT_POST_FLAG_SET,
					             (OS_ERR*	  )&err);
			printf("事件标志组EventFlags的值:%d\r\n",flags_num);
		}
		else if(key == KEY1_PRES)
		{
			//向事件标志组EventFlags发送标志
			flags_num=OSFlagPost((OS_FLAG_GRP*)&EventFlags,
								 (OS_FLAGS	  )KEY1_FLAG,
								 (OS_OPT	  )OS_OPT_POST_FLAG_SET,
								 (OS_ERR*     )&err);
			printf("事件标志组EventFlags的值:%d\r\n",flags_num);
		}
		OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);   //延时10ms
	}
}

//事件标志组处理任务
void flagsprocess_task(void *p_arg)
{
	u8 num;
	OS_ERR err; 
	while(1)
	{
		//等待事件标志组
		OSFlagPend((OS_FLAG_GRP*)&EventFlags,
				   (OS_FLAGS	)KEY0_FLAG+KEY1_FLAG,
		     	   (OS_TICK     )0,
				(OS_OPT	 )OS_OPT_PEND_FLAG_SET_ALL+OS_OPT_PEND_FLAG_CONSUME,
				   (CPU_TS*     )0,
				   (OS_ERR*	    )&err);
		num++;
		LED1 = ~LED1;
		LCD_Fill(6,131,233,313,lcd_discolor[num%14]);
		printf("事件标志组EventFlags的值:%d\r\n",EventFlags.Flags);
	}
}
相关推荐
茶杯梦轩3 天前
从零起步学习RabbitMQ || 第二章:RabbitMQ 深入理解概念 Producer、Consumer、Exchange、Queue 与企业实战案例
服务器·后端·消息队列
初次攀爬者4 天前
Kafka 基础介绍
spring boot·kafka·消息队列
初次攀爬者5 天前
RocketMQ 消息可靠性保障与堆积处理
后端·消息队列·rocketmq
初次攀爬者5 天前
RocketMQ 集群介绍
后端·消息队列·rocketmq
初次攀爬者5 天前
RocketMQ 基础学习
后端·消息队列·rocketmq
初次攀爬者6 天前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
DemonAvenger8 天前
Kafka性能调优:从参数配置到硬件选择的全方位指南
性能优化·kafka·消息队列
悠哉悠哉愿意9 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
Lester_11019 天前
STM32霍尔传感器输入口设置为复用功能输入口时,还能用GPIO函数直接读取IO的状态吗
stm32·单片机·嵌入式硬件·电机控制
LCG元9 天前
低功耗显示方案:STM32L0驱动OLED,动态波形绘制与优化
stm32·嵌入式硬件·信息可视化