消息队列和事件标志组

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);
	}
}
相关推荐
Java移动技术栈2 小时前
深入理解 Java 队列:实现原理、场景与实战指南
java·消息队列
善 .2 小时前
单片机的内存是指RAM还是ROM
单片机·嵌入式硬件
超级码农ProMax2 小时前
STM32——“SPI Flash”
stm32·单片机·嵌入式硬件
Asa3193 小时前
stm32点灯Hal库
stm32·单片机·嵌入式硬件
end_SJ5 小时前
初学stm32 --- 外部中断
stm32·单片机·嵌入式硬件
gantengsheng5 小时前
基于51单片机和OLED12864的小游戏《贪吃蛇》
单片机·嵌入式硬件·游戏·51单片机
嵌入式小强工作室6 小时前
stm32 查找进硬件错误方法
stm32·单片机·嵌入式硬件
委员7 小时前
基于NodeMCU的物联网窗帘控制系统设计
单片机·mcu·物联网·智能家居·iot
wenchm7 小时前
细说STM32F407单片机DMA方式读写SPI FLASH W25Q16BV
stm32·单片机·嵌入式硬件
南城花随雪。7 小时前
单片机:实现自动关机电路(附带源码)
单片机·嵌入式硬件