FreeRTOS-事件标志组

FreeRTOS-事件标志组

  • 在前面我们已经学习了信号量,我们知道信号量可以用来做任务同步,但是这种任务同步有一个缺点,就是只能在两个任务之间进行同步,所以为了解决这个问题,FreeRTOS提供了事件标志组,使得多任务之间进行同步。

事件标志组表示方法

  • 事件标志组由若干个事件标志位组成,每个事件标志位表示某个事件是否发生。事件标志组的数据类型为EventBits_t,具体定义如下
typedef TickType_t EventBits_t;
#if( configUSE_16_BIT_TICKS == 1 )
	typedef uint16_t TickType_t;
	#define portMAX_DELAY ( TickType_t ) 0xffff
#else
	typedef uint32_t TickType_t;
	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
	#define portTICK_TYPE_IS_ATOMIC 1
#endif
  • 从上面可以看出,当configUSE_16_BIT_TICKS =0时,EventBits_t为32位,否则EventBits_t为16位。但是,EventBits_t中的高8位有其他作用,不能用来表示事件,所以当EventBits_t为32位时,最多能用来表示24个事件。

事件标志组相关API

  • 本章不会深入分析这些API的源码,只是在使用上做一个介绍

xEventGroupCreate()

  • 函数作用:创建时间标志组
  • 函数声明:EventGroupHandle_t xEventGroupCreate( void )
  • 输入参数:无
  • 返回参数:事件标志组句柄

xEventGroupSetBits()

  • 函数作用:设置事件标志位
  • 函数声明:EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
  • 输入参数 xEventGroup:事件标志组句柄
  • 输入参数 uxBitsToSet :事件标志组所要置1的位,比如要使bit2置1,那么uxBitsToSet=0x04=0000 0100
  • 返回参数:事件标志组句柄

xEventGroupClearBits()

  • 函数作用:清除事件标志位
  • 函数声明:EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
  • 输入参数 xEventGroup:事件标志组句柄
  • 输入参数 uxBitsToClear :事件标志组所要清零的位,比如要使bit2置0,那么uxBitsToClear=0x04=0000 0100
  • 返回参数:事件标志组句柄

xEventGroupWaitBits()

  • 函数作用:等待事件标志位
  • 函数声明:EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
  • 输入参数 xEventGroup:事件标志组句柄
  • 输入参数 uxBitsToWaitFor:所要等待的事件标志位,比如要等待bit2,则uxBitsToWaitFor = 0x04,如果既要等待bit2也要等待bit4,则uxBitsToWaitFor = 0x04|0x10
  • 输入参数 xClearOnExit:事件等待完毕后是否清除标志位,如果输入参数为pdTRUE是表示清除,否则不清除。
  • xWaitForAllBits:是否要等待所有标志位,设置为pdTRUE时,需要等待所设置的所有标志位此时相当于与运算,否则只需要等待一个,此时相当于或运算
  • xTicksToWait:设置阻塞时间
  • 返回参数:事件标志组的值

用法示例

实验目的:创建3个事件,分别等待bit0置位,等待bit1置位,等待bit0和bit1均置位,通过按键将bit0和bit1置位
  • 按键处理函数
u8 keyFlag=0;
void key_task(void* pvParameters)
{
	EventBits_t Ebit;
	while(1)
	{
		
		if (Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON)
		{
			if ( (keyFlag&0x01) == 0x01)
				keyFlag &= ~(0x01<<0);
			else
			  keyFlag |= (0x01<<0);
			
			if ( (keyFlag&0x01) == 0x01)
			{
				Ebit = xEventGroupSetBits(Event_Handler,(0x01<<0));
				
				printf("current Ebit = %#x\r\n",Ebit);
			}
			else
			{
				Ebit = xEventGroupClearBits(Event_Handler,(0x01<<0));
				printf("current Ebit = %#x\r\n",Ebit);
			}
		
		}
		
		if (Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON)
		{
			if ( (keyFlag&0x02) == 0x02)
				keyFlag &= ~(0x01<<1);
			else
				keyFlag |= (0x01<<1);
			
			if ( (keyFlag&0x02) == 0x02)
			{
				Ebit = xEventGroupSetBits(Event_Handler,(0x01<<1));
				printf("current Ebit = %#x\r\n",Ebit);
			}
			else
			{
				Ebit = xEventGroupClearBits(Event_Handler,(0x01<<1));
				printf("current Ebit = %#x\r\n",Ebit);
			}
			
		}
		vTaskDelay(10);
	}
}
  • 等待事件任务

void event1_task(void* pvParameters)
{
	while(1)
	{
		if ( (keyFlag&0x01) == 0x01)
			LED0 = 0;
		else
			LED0 = 1;
		xEventGroupWaitBits(Event_Handler,(0x01<<0),pdFALSE,pdTRUE,portMAX_DELAY);
		printf("event1 task running!!\r\n");
		vTaskDelay(1000);
	}
}


void event2_task(void* pvParameters)
{
	while(1)
	{
		if ( (keyFlag&0x02) == 0x02)
			LED1 = 0;
		else
			LED1 = 1;
		xEventGroupWaitBits(Event_Handler,(0x01<<1),pdFALSE,pdTRUE,portMAX_DELAY);
		printf("event2 task running!!\r\n");
		vTaskDelay(1000);
	}
}


void event3_task(void* pvParameters)
{
	while(1)
	{
		if ( (keyFlag&0x03) == 0x03)
			LED2 = 0;
		else
			LED2 = 1;
		xEventGroupWaitBits(Event_Handler,(0x01<<1)|(0x01<<0),pdFALSE,pdTRUE,portMAX_DELAY);
		printf("event3 task running!!\r\n");
		vTaskDelay(1000);
	}
}
  • 创建事件标志组和任务

void start_task(void *pvParameters)
{				
	 Event_Handler = xEventGroupCreate();
	
		xTaskCreate((TaskFunction_t )key_task,            //任务函数
                (const char*    )"key_task",          //任务名称
                (uint16_t       )KEY_STACK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )KEY_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&KeyTask_Handler);   //任务句柄  	
								
	 xTaskCreate((TaskFunction_t )event1_task,            //任务函数
                (const char*    )"event1_task",          //任务名称
                (uint16_t       )EVENT1_STACK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )EVENT1_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&Event1Task_Handler);   //任务句柄  
								
	 xTaskCreate((TaskFunction_t )event2_task,            //任务函数
                (const char*    )"event2_task",          //任务名称
                (uint16_t       )EVENT2_STACK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )EVENT2_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&Event2Task_Handler);   //任务句柄 

		 xTaskCreate((TaskFunction_t )event3_task,            //任务函数
                (const char*    )"event3_task",          //任务名称
                (uint16_t       )EVENT3_STACK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )EVENT3_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&Event3Task_Handler);   //任务句柄 
								
	 vTaskDelete(StartTask_Handler);
}
上一篇:[ 记录 ]


下一篇:测绘的真正出路在于什么?