第13章 事件标志组
约 1025 字大约 3 分钟
2026-01-19
13.1 核心知识点
事件标志组概述:
事件标志组就像是一个共享的标志牌集合,每个标志位都代表一种特定的状态或事件,任务可以等待或设置这些标志位,从而实现任务之间的协同工作。
可以实现多条件触发,例如,设备启动需同时满足“传感器初始化完成”(位0)和“网络连接就绪”(位1)。相关宏
configUSE_16_BIT_TICKS 决定系统滴答计数器使用16位(=1)还是32位(=0)注意: 事件组的核心是一个位掩码变量(
EventBits_t,实际类型为TickType_t),其位宽由configUSE_16_BIT_TICKS决定
相关类型:
EventGroupHandle_t 事件标志组句柄的类型
EventBits_t 事件标志组值的类型相关函数
xEventGroupCreate() 使用动态方式创建事件标志组
xEventGroupCreateStatic() 使用静态方式创建事件标志组
xEventGroupClearBits() 清零事件标志位
xEventGroupClearBitsFromISR() 在中断中清零事件标志位
xEventGroupSetBits() 设置事件标志位
xEventGroupSetBitsFromISR() 在中断中设置事件标志位
xEventGroupWaitBits() 等待事件标志位
xEventGroupSync() 设置事件标志位,并等待事件标志位13.2 案例
① 需求
task1:读取按键按下键值,根据不同键值将事件标志组相应事件位置 1,模拟事件发生。
按键 SW3 按下,第 0 位置 1
按键 SW4 按下,第 1 位置 1
按键 SW5 按下,第 2 位置 1
task2:等待事件标志组中0、1、2 事件位都置 1,处理相应操作② 代码
App_Task.h
添加头文件包含和宏定义:
#include "event_groups.h"
// 宏定义 事件组掩码 第0位掩码
#define EVENT_BIT_0 (1 << 0)
// 宏定义 事件组掩码 第1位掩码
#define EVENT_BIT_1 (1 << 1)
// 宏定义 事件组掩码 第2位掩码
#define EVENT_BIT_2 (1 << 2)App_Task.c
#include "App_Task.h"
// 任务1 ------------------------------------
// 任务1函数的原型
void task1_callback(void *pvParameters);
// 任务1名称
#define TASK1_NAME "task1"
// 任务1堆栈大小
#define TASK1_STACK_SIZE 128
// 任务1的优先级
#define TASK1_PRIORITY 1
// 任务1的句柄
TaskHandle_t task1_handle;
// 任务2 ------------------------------------
// 任务2函数的原型
void task2_callback(void *pvParameters);
// 任务2名称
#define TASK2_NAME "task2"
// 任务2堆栈大小
#define TASK2_STACK_SIZE 128
// 任务2的优先级
#define TASK2_PRIORITY 2
// 任务2的句柄
TaskHandle_t task2_handle;
// 定义事件组的句柄
EventGroupHandle_t event_group_handle;
/**
* @brief 启动 FreeRTOS 任务管理
*
*/
void App_Task_Start(void)
{
// 进入临界区
taskENTER_CRITICAL();
// 创建任务1
xTaskCreate(task1_callback, TASK1_NAME, TASK1_STACK_SIZE, NULL, TASK1_PRIORITY, &task1_handle) == pdPASS ? printf("任务1创建成功! \n") : printf("任务1穿件失败! \n");
// 创建任务2
xTaskCreate(task2_callback, TASK2_NAME, TASK2_STACK_SIZE, NULL, TASK2_PRIORITY, &task2_handle) == pdPASS ? printf("任务2创建成功! \n") : printf("任务2穿件失败! \n");
// 创建事件组
event_group_handle = xEventGroupCreate();
event_group_handle != NULL ? printf("事件组创建成功! \n") : printf("事件组创建失败! \n");
// 退出临界区
taskEXIT_CRITICAL();
// 启动任务调度器 ( vTaskStartScheduler() 后面的代码不会被执行)
printf("任务调度器启动... \n");
vTaskStartScheduler();
}
// 任务1函数的实现
void task1_callback(void *pvParameters)
{
printf("任务1启动... \n");
while (1)
{
// 检测按键
switch (Int_Key_IsDetect())
{
case 3:
// 按键3被按下,将事件组第0位置1
printf("任务1: 按键3被按下, 将事件组第0位置1 \n");
xEventGroupSetBits(event_group_handle, EVENT_BIT_0);
break;
case 4:
// 按键4被按下,将事件组第1位置1
printf("任务1: 按键4被按下, 将事件组第1位置1 \n");
xEventGroupSetBits(event_group_handle, EVENT_BIT_1);
break;
case 5:
// 按键5被按下,将事件组第2位置1
printf("任务1: 按键5被按下, 将事件组第2位置1 \n");
xEventGroupSetBits(event_group_handle, EVENT_BIT_2);
break;
default:
break;
}
}
}
// 任务2函数的实现
void task2_callback(void *pvParameters)
{
printf("任务2启动... \n");
// 定义变量,保存事件组的值
EventBits_t event_bits;
while (1)
{
// 等待时间组中的第0、1、2位都被置1,否则一直阻塞
printf("任务2: 等待事件组中的第0、1、2位都被置1... \n");
event_bits = xEventGroupWaitBits(event_group_handle, EVENT_BIT_0 | EVENT_BIT_1 | EVENT_BIT_2, pdTRUE, pdTRUE, portMAX_DELAY);
printf("任务2: 事件组中的第0、1、2位都被置1, 事件组的值为 0x%02x \n", event_bits);
}
}