tags: [source-summary] type: source source: "尚硅谷嵌入式技术之FreeRTOS实时操作系统 V1.0.3 — 第13章 事件标志组" author: "尚硅谷研究院" date: 2026-07-17
用生活理解:事件标志组就像任务清单上的多个"待办事项"打勾。你可以等"所有事项都完成"(AND逻辑)才行动,也可以等"任意一个完成"(OR逻辑)就行动。打勾后还可以选择"自动擦掉"(自动清除)或"留着标记"(手动清除)。
事件标志组(Event Group)是 FreeRTOS 中用于任务间事件通知和同步的轻量级机制。每个标志位代表一个特定的状态或事件。
xEventGroupClearBits()事件标志组中的所有事件位存储在 EventBits_t 类型的单个无符号整数变量中。位 0 存储事件 0,位 1 存储事件 1,以此类推。
事件标志组 vs 信号量:
| 事件标志组 | 信号量 |
|---|---|
| 事件通知和同步 | 资源控制和同步 |
| 每个位代表不同事件 | 计数器表示可用资源数量 |
| 任务可等待多个位同时/任一个发生 | 任务等待计数值 > 0 |
| Function | Params | Description |
|---|---|---|
xEventGroupCreate() |
无 | 动态创建事件标志组 |
xEventGroupSetBits() |
xEventGroup, uxBitsToSet |
设置事件标志位 |
xEventGroupClearBits() |
xEventGroup, uxBitsToClear |
清零事件标志位 |
xEventGroupWaitBits() |
xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait |
等待事件标志位 |
xEventGroupSync() |
xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait |
设置并等待(原子操作) |
xEventGroupGetBits() |
xEventGroup |
获取当前事件标志位值 |
学习使用 FreeRTOS 事件标志组:
File: P15/15_事件标志组/Core/Src/freertos_demo.c
#include "event_groups.h" /* 事件标志组头文件 */
/* 任务配置 */
#define START_TASK_PRIORITY 1
#define START_TASK_STACK_DEPTH 128
TaskHandle_t start_task_handler;
void Start_Task(void *pvParameters);
#define TASK1_PRIORITY 2
#define TASK1_STACK_DEPTH 128
TaskHandle_t task1_handler;
void Task1(void *pvParameters);
#define TASK2_PRIORITY 3
#define TASK2_STACK_DEPTH 128
TaskHandle_t task2_handler;
void Task2(void *pvParameters);
EventGroupHandle_t eventgroup_handle; /* 事件标志组句柄 */
#define EVENTBIT_0 (1 << 0) /* 定义事件位0 */
#define EVENTBIT_1 (1 << 1) /* 定义事件位1 */
void FreeRTOS_Start(void)
{
xTaskCreate((TaskFunction_t)Start_Task,
(char *)"Start_Task",
(configSTACK_DEPTH_TYPE)START_TASK_STACK_DEPTH,
(void *)NULL,
(UBaseType_t)START_TASK_PRIORITY,
(TaskHandle_t *)&start_task_handler);
vTaskStartScheduler();
}
/* 启动任务:创建事件标志组和工作任务 */
void Start_Task(void *pvParameters)
{
taskENTER_CRITICAL();
/* 创建事件标志组 */
eventgroup_handle = xEventGroupCreate();
if (eventgroup_handle != NULL) {
printf("事件标志组创建成功\r\n");
}
xTaskCreate((TaskFunction_t)Task1,
(char *)"Task1",
(configSTACK_DEPTH_TYPE)TASK1_STACK_DEPTH,
(void *)NULL,
(UBaseType_t)TASK1_PRIORITY,
(TaskHandle_t *)&task1_handler);
xTaskCreate((TaskFunction_t)Task2,
(char *)"Task2",
(configSTACK_DEPTH_TYPE)TASK2_STACK_DEPTH,
(void *)NULL,
(UBaseType_t)TASK2_PRIORITY,
(TaskHandle_t *)&task2_handler);
vTaskDelete(NULL);
taskEXIT_CRITICAL();
}
/* task1:KEY1 -> EVENTBIT_0,KEY2 -> EVENTBIT_1 */
void Task1(void *pvParameters)
{
uint8_t key = 0;
while (1) {
key = Key_Detect();
if (key == KEY1_PRESS) {
/* 将事件标志组的bit0位置1 */
xEventGroupSetBits(eventgroup_handle, EVENTBIT_0);
} else if (key == KEY2_PRESS) {
/* 将事件标志组的bit1位置1 */
xEventGroupSetBits(eventgroup_handle, EVENTBIT_1);
}
vTaskDelay(10);
}
}
/* task2:等待bit0和bit1都置位 */
void Task2(void *pvParameters)
{
EventBits_t event_bit = 0;
while (1) {
/* 等待事件标志组的bit0和bit1位都置1,成功后自动清除,永久等待 */
event_bit = xEventGroupWaitBits(
eventgroup_handle, /* 事件标志组句柄 */
EVENTBIT_0 | EVENTBIT_1, /* 等待bit0和bit1 */
pdTRUE, /* 成功等待后自动清除标志位 */
pdTRUE, /* 等待所有位都置1(AND) */
portMAX_DELAY); /* 永久等待 */
printf("等待到的事件标志位值=%#x\r\n", event_bit);
}
}
/* FreeRTOSConfig.h — 无额外配置,事件标志组默认使能 */
| Function | Parameters | Return | Description |
|---|---|---|---|
EventGroupHandle_t xEventGroupCreate() |
无 | NULL=失败 | 动态创建事件标志组 |
EventBits_t xEventGroupSetBits(xEventGroup, uxBitsToSet) |
句柄, 待置位掩码 | 设置后的值 | 设置事件位 |
EventBits_t xEventGroupClearBits(xEventGroup, uxBitsToClear) |
句柄, 待清除掩码 | 清除后的值 | 清除事件位 |
EventBits_t xEventGroupWaitBits(xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait) |
句柄, 等待掩码, 退出时清除?, 等待所有?, 超时 | 等待结果 | 阻塞等待事件位 |
EventBits_t xEventGroupSync(xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait) |
句柄, 设置位, 等待位, 超时 | 同步结果 | 设置并等待(原子) |
EventBits_t xEventGroupGetBits(xEventGroup) |
句柄 | 当前值 | 获取当前所有位值 |
BaseType_t xEventGroupSetBitsFromISR(xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken) |
句柄, 置位掩码, 唤醒标记 | pdPASS/pdFAIL | ISR中设置位 |
EVENTBIT_23 是最大可用位。xWaitForAllBits = pdTRUE 是 AND(等待所有),pdFALSE 是 OR(等待任一)。初学时容易混淆。xClearOnExit = pdTRUE 表示等待成功后自动清除已匹配的位。如果多个任务等待同一位,建议手动清除以免误清。xEventGroupSetBitsFromISR() → 不要直接在 ISR 中调用 xEventGroupSetBits()。