
从上面可以看出,EventBits_t 实际上是一个 16 位或 32 位无符号的数据类型。当 configUSE_16_BIT_TICKS 配置为 0 时,EventBits_t 是一个 32 位无符号的数据类型;当 configUSE_16_BIT_TICKS 配置为 1 时,EventBits_t 是一个 16 为无符号的数据类型。在本套教 程的所有配套例程中,都将配置项 configUSE_16_BIT_TICKS 配置为 0,因此本文就以 EventBits_t 为 32 位无符号数据类型为例进行讲解,对于另外一种情况,也是大同小异的。
虽然说使用了 32 位无符号的数据类型变量来存储事件标志,但这并不意味着,一个 EventBits_t 数据类型的变量能够存储 32 个事件标志,FreeRTOS 将这个 EventBits_t 数据类型的 变量拆分成两部分,其中低 24 位[23:0](configUSE_16_BIT_TICKS 配置位 1 时,是低 8 位[7:0]) 用于存储事件标志,而高 8 位[31:24](configUSE_16_BIT_TICKS 配置位 1 时,依然是高 8 位 [15:8])用作存储事件标志组的一些控制信息,也就是说一个事件组最多可以存储 24 个事件标 志。EventBits_t 数据类型变量的位使用情况如下图所示:
从上图中可以看到,变量中低 24 位中的每一位都是一个事件标志,当某一位被置一时,就 表示这一位对应的事件发生了。
FreeRTOS 事件标志组相关 API 函数
FreeRTOS 提供了事件标志组的一些相关操作函数,如下表所示:















#define EVENTBIT_0 (1<<0)
#define EVENTBIT_1 (1<<1)
#define EVENTBIT_2 (1<<2)
#define EVENTBIT_ALL (EVENTBIT_0|EVENTBIT_1|EVENTBIT_2)
然后在start任务中进行事件标志组的创建:
EventGroupHandle_t EventGroupHandler;
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
EventGroupHandler = xEventGroupCreate();
xTaskCreate((TaskFunction_t )counter_task,
(const char* )"counter_task",
(uint16_t )COUNTER_STK_SIZE,
(void* )NULL,
(UBaseType_t )COUNTER_TASK_PRIO,
(TaskHandle_t* )&CounterTask_Handler);
xTaskCreate((TaskFunction_t )api_task,
(const char* )"api_task",
(uint16_t )API_STK_SIZE,
(void* )NULL,
(UBaseType_t )API_TASK_PRIO,
(TaskHandle_t* )&ApiTask_Handler);
xTaskCreate((TaskFunction_t )led_green_task,
(const char* )"led_green_task",
(uint16_t )LED_GREEN_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED_GREEN_TASK_PRIO,
(TaskHandle_t* )&LedGreenTask_Handler);
xTaskCreate((TaskFunction_t )led_red_task,
(const char* )"led_red_task",
(uint16_t )LED_RED_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED_RED_TASK_PRIO,
(TaskHandle_t* )&LedRedTask_Handler);
xTaskCreate((TaskFunction_t )ws2812b_task,
(const char* )"ws2812b_task",
(uint16_t )WS2812B_STK_SIZE,
(void* )NULL,
(UBaseType_t )WS2812B_TASK_PRIO,
(TaskHandle_t* )&Ws2812bTask_Handler);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
然后在led闪烁以及在ws2812b任务中进行事件标志组的中事件置位:
void led_green_task(void *pvParameters)
{
unsigned char led_green_on_flag = 0;
while(1)
{
if(led_green_on_flag)
{
LED_GREEN_ON;
xEventGroupSetBits( (EventGroupHandle_t )EventGroupHandler, (EventBits_t )EVENTBIT_0);
}else
{
LED_GREEN_OFF;
}
led_green_on_flag = ~led_green_on_flag;
vTaskDelay(500);
}
}
void led_red_task(void *pvParameters)
{
unsigned char led_red_on_flag = 0;
while(1)
{
if(led_red_on_flag)
{
LED_RED_ON;
}else
{
xEventGroupSetBits( (EventGroupHandle_t )EventGroupHandler, (EventBits_t )EVENTBIT_1);
LED_RED_OFF;
}
led_red_on_flag = ~led_red_on_flag;
vTaskDelay(2000);
}
}
void ws2812b_task(void *pvParameters)
{
unsigned char ws2812b_change_flag = 0;
while(1)
{
if(ws2812b_change_flag)
{
ws2812b_write_rgb(0, 20, 0);
xEventGroupSetBits( (EventGroupHandle_t )EventGroupHandler, (EventBits_t )EVENTBIT_2);
}else
{
ws2812b_write_rgb(0, 0, 0);
}
ws2812b_change_flag = ~ws2812b_change_flag;
vTaskDelay(3000);
}
}
最后在api任务以及counter任务中分别进行事件标志组的触发实验以及获取事件标志位实验:
void api_task(void *pvParameters)
{
while(1)
{
xEventGroupWaitBits( (EventGroupHandle_t )EventGroupHandler,
(EventBits_t )EVENTBIT_ALL,
(BaseType_t )pdTRUE,
(BaseType_t )pdTRUE,
(TickType_t )portMAX_DELAY);
taskENTER_CRITICAL();
printf("\r\n三个事件全部触发!\r\n");
taskEXIT_CRITICAL();
vTaskDelay(20);
}
}
EventBits_t event_val_current = 0;
EventBits_t event_val_last = 0;
void counter_task(void *pvParameters)
{
while(1)
{
event_val_current = xEventGroupGetBits((EventGroupHandle_t)EventGroupHandler);
if(event_val_current != event_val_last)
{
event_val_last = event_val_current;
taskENTER_CRITICAL();
printf("\r\n当前的事件标志数量为:º%d.\r\n", (unsigned char)event_val_current);
taskEXIT_CRITICAL();
}
vTaskDelay(10);
}
}
下载验证:
补充:注释掉事件标志组触发逻辑:
NOTE:可以看到当前的事件标志都处于置位状态,0B 0000 0111 = 7