简单理解FreeRTOS中事件Event和创建事件类实例任务

1 FreeRTOS中事件的理解

事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能是事件类型的通信,无数据传输。与信号量不同的是,它可以实现一对多,多对多的同步。即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个事件。

2 事件的运作机制

应用一个实例来解释,更加易懂。

任务1对事件3或事件5感兴趣(逻辑或),当发生其中的某一个事件都会被唤醒,并且执行相应操作。而任务2对事件3与事件5感兴趣(逻辑与),当且仅当事件3与事件5都发生的时候,任务2才会被唤醒,如果只有一个其中一个事件发生,那么任务还是会继续等待事件发生。如果接在收事件函数中设置了清除事件位xClearOnExit,那么当任务唤醒后将把事件3和事件5的事件标志清零,否则事件标志将依然存在。

 

3 编写事件主要步骤

3.1 创建事件

FreeRTOS给我们提供了一个创建事件的函数xEventGroupCreate(),当创建一个事件时,系统会首先给我们分配事件控制块的内存空间,然后对该事件控制块进行基本的初始化,创建成功返回事件句柄;创建失败返回NULL。所以,在使用创建函数之前,我们需要先定义有个事件的句柄。

 

3.2 事件组置位

xEventGroupSetBits()用于置位事件组中指定的位,当位被置位之后,阻塞在该位上的任务将会被解锁。使用该函数接口时,通过参数指定的事件标志来设定事件的标志位,然后遍历等待在事件对象上的事件等待列表,判断是否有任务的事件激活要求与当前事件对象标志值匹配,如果有,则唤醒该任务。简单来说,就是设置我们自己定义的事件标志位为1,并且看看有没有任务在等待这个事件,有的话就唤醒它。

EventBits_t xEventGroupSetBits(   EventGroupHandle_t xEventGroup,

                                                              const EventBits_t uxBitsToSet    );

xEventGroup:事件句柄;

uxBitsToSet:指定事件中的事件标志位。如设置uxBitsToSet0x08则只置位位3,如果设置uxBitsToSet0x09则位3和位0                                都需要被置位;

返回值:   返回调用xEventGroupSetBits() 时事件组中的值。

 

3.3 事件等待

FreeRTOS提供了一个等待指定事件的函数——xEventGroupWaitBits(),通过这个函数,任务可以知道事件标志组中的哪些位,有什么事件发生了,然后通过 “逻辑与”、“逻辑或”等操作对感兴趣的事件进行获取,并且这个函数实现了等待超时机制,当且仅当任务等待的事件发生时,任务才能获取到事件信息。在这段时间中,如果事件一直没发生,该任务将保持阻塞状态以等待事件发生。EventGroupWaitBits()用于获取事件组中的一个或多个事件发生标志,当要读取的事件标志位没有被置位时任务将进入阻塞等待状态。

EventBits_t xEventGroupWaitBits(     const EventGroupHandle_t xEventGroup,

                                                                  const EventBits_t uxBitsToWaitFor,

                                                                  const BaseType_t xClearOnExit,

                                                                  const BaseType_t xWaitForAllBits,

                                                                  TickType_t xTicksToWait    );

xEventGroup:事件句柄;

uxBitsToWaitFor:一个按位或的值,指定需要等待事件组中的哪些位置1。如果需要等待bit 0 and/or bit 2那么uxBitsToWaitFor  配置为0x05(0101b)。如果需要等待bits 0 and/or bit 1 and/or bit 2那么uxBitsToWaitFor配置为0x07(0111b);

xClearOnExit:pdTRUE:当xEventGroupWaitBits()等待到满足任务唤醒的事件时,系统将清除由形参uxBitsToWaitFor指定的事件标志位;

pdFALSE:不会清除由形参uxBitsToWaitFor指定的事件标志位;

xWaitForAllBits:pdTRUE:当形参uxBitsToWaitFor指定的位都置位的时候,xEventGroupWaitBits()才满足任务唤醒的条件,这也是“逻辑与”等待事件,并且在没有超时的情况下返回对应的事件标志位的值;pdFALSE:当形参uxBitsToWaitFor指定的位有其中任意一个置位的时候,这也是常说的“逻辑或”等待事件,在没有超时的情况下函数返回对应的事件标志位的值;

xTicksToWait:最大超时时间,单位为系统节拍周期,常量portTICK_PERIOD_MS用于辅助把时间转换成MS;

返回值:   返回事件中的哪些事件标志位被置位,返回值很可能并不是用户指定的事件位,需要对返回值进行判断再处理。

 

4 实验结果

打印的显示截图如下:

/***
*****************************************************************************************
主程序和各个任务程序,截取程序主要部分,各个文件的句柄放在头文件里面的,需要读者自己加入
就行了,最好再声明一下任务函数,另外我发现程序转过来后注释全成了乱码,但是不影响程序运行
*****************************************************************************************
**
*/

static void KEY_Task(void* parameter)
{
while(1)
    {
			if(Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PIN)==KEY_ON)
			{
			printf("KEY1±»°´ÏÂ\n");
			xEventGroupSetBits( Event_Handle, KEY1_EVENT );
			}
			vTaskDelay(10);
    }
}

static void LED3_Task(void* parameter)
{
   EventBits_t R_event;
	while(1)
	{
		R_event= xEventGroupWaitBits( Event_Handle,
		                                KEY1_EVENT,
		                                 pdTRUE,
	                                    pdTRUE,
		                             portMAX_DELAY);
		printf("½ÓÊܵ½Ê¼þKEY1_EVENT\n");
		if(  R_event==KEY1_EVENT)
		{
		LED3_ON;
		vTaskDelay(500);
		LED3_OFF;
		}
	}
}

static void AppTaskCreate(void)
{
	BaseType_t xReturn=pdPASS;
	
	taskENTER_CRITICAL();  
	 
		Event_Handle=xEventGroupCreate();
		 if(NULL!= Event_Handle)
		 printf("Event_Handleʼþ´´½¨Íê³É\n");

    	xReturn  = xTaskCreate( (TaskFunction_t)KEY_Task,  
					                  (const char*)"KEY_Task",              
					                  (uint32_t)128 ,   
					                  (void *) NULL,                 
                                  (UBaseType_t) 4,           
					          (TaskHandle_t *) &KEY_Task_Handle);   
					                  
    if(pdPASS==xReturn)
	    printf ("KEY_Task founded successfully by bieber\n");
    else 
	    printf("KEY_Task founded failed by biebier\n");

    	/* ½¨Á¢ÈÎÎñLED3_Task  */
    xReturn  = xTaskCreate( (TaskFunction_t)LED3_Task,  
					                  (const char*)"LED3_Task",             
					                  (uint32_t)128 ,  
					                  (void *) NULL,              
                                     (UBaseType_t) 5,             
					             (TaskHandle_t *)&LED3_Task_Handle);    
					                  
    if(pdPASS==xReturn)
	    printf ("LED3_Task founded successfully by bieber\n");
    else 
	    printf("LED3_Task founded failed by biebier\n");		
		
	vTaskDelete(AppTaskCreate_Handle);   
	
		taskEXIT_CRITICAL();        					   
}

int main(void)

{
  BaseType_t xReturn=pdPASS;  
  BSP_Init();   
	printf(" ²âÊÔ³ÌÐò¿ªÊ¼ \n");

 xReturn = xTaskCreate( (TaskFunction_t) AppTaskCreate, 
					                  (const char *)"APPTaskCreate",             
					                  (uint32_t)512 ,  
					                  (void *) NULL,           
                                      (UBaseType_t) 1,            
					                  (TaskHandle_t *)&AppTaskCreate_Handle); 
  if(pdPASS== xReturn)
	  vTaskStartScheduler();     
	else
		return -1;
  while(1);

}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值