事件组是一个32位的位掩码,用于任务之间的事件通知或同步。

1. xEventGroupCreate

功能:创建一个新的事件组。

参数:无

返回值

  • 成功时返回 EventGroupHandle_t 类型的事件组句柄。
  • 失败时返回 NULL,通常是由于内存分配失败。

示例

EventGroupHandle_t xEventGroup;
xEventGroup = xEventGroupCreate();
if (xEventGroup == NULL) {
    // 处理错误
}

2. xEventGroupSetBits

功能:设置事件组中的一个或多个位。

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );

参数

  • xEventGroup:要操作的事件组句柄。
  • uxBitsToSet:要设置的位的位掩码。

返回值:事件组在调用此函数之前的值。

示例

#define BIT_0 (1 << 0)
xEventGroupSetBits(xEventGroup, BIT_0);

3. xEventGroupClearBits

功能:清除事件组中的一个或多个位。

EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );

参数

  • xEventGroup:要操作的事件组句柄。
  • uxBitsToClear:要清除的位的位掩码。

返回值:事件组在调用此函数之前的值。

示例

#define BIT_0 (1 << 0)
xEventGroupClearBits(xEventGroup, BIT_0);

4. xEventGroupWaitBits

功能:等待指定的位被设置,带有可选的超时参数。

EventBits_t xEventGroupWaitBits(
    EventGroupHandle_t xEventGroup,
    const EventBits_t uxBitsToWaitFor,
    const BaseType_t xClearOnExit,
    const BaseType_t xWaitForAllBits,
    TickType_t xTicksToWait
);

参数

  • xEventGroup:要操作的事件组句柄。
  • uxBitsToWaitFor:等待的位的位掩码。
  • xClearOnExit:是否在退出时清除等待的位。
  • xWaitForAllBits:是否等待所有指定的位被设置。
  • xTicksToWait:等待的最大时间(以系统tick计时)。超时后放回0,再次调用后继续等待。

返回值:满足条件时事件组的值。

示例

#define BIT_0 (1 << 0)
xEventGroupWaitBits(xEventGroup, BIT_0, pdTRUE, pdFALSE, portMAX_DELAY);

5. xEventGroupGetBits

功能:获取当前事件组的值。

参数

  • xEventGroup:要操作的事件组句柄。

返回值:当前事件组的值。

示例

EventBits_t uxBits;
uxBits = xEventGroupGetBits(xEventGroup);

6. xEventGroupDelete

功能:删除一个事件组。

参数

  • xEventGroup:要删除的事件组句柄。

返回值:无

示例

vEventGroupDelete(xEventGroup);

xEventGroupSetBitsFromISR 函数说明

功能: 在中断上下文中设置事件组中的一个或多个位。

BaseType_t xEventGroupSetBitsFromISR(
    EventGroupHandle_t xEventGroup,
    const EventBits_t uxBitsToSet,
    BaseType_t *pxHigherPriorityTaskWoken
);

参数

  • xEventGroup:要操作的事件组句柄。
  • uxBitsToSet:要设置的位的位掩码。
  • pxHigherPriorityTaskWoken:这是一个输出参数,如果调用这个函数后需要切换上下文来唤醒一个更高优先级的任务,它将被设置为 pdTRUE。在中断处理函数结束时应调用 portYIELD_FROM_ISR 以进行实际的上下文切换。

返回值

  • pdPASS:表示位成功设置。
  • pdFAIL:表示位未设置(可能因为中断上下文中事件组管理内存不足等原因)。

使用示例

假设我们有一个中断服务例程(ISR),它需要通知一个任务某个事件发生,可以使用 xEventGroupSetBitsFromISR 进行设置。

#include "FreeRTOS.h"
#include "event_groups.h"
#include "task.h"

// 定义事件位
#define BIT_0 (1 << 0)

// 声明事件组句柄
extern EventGroupHandle_t xEventGroup;

// 中断服务例程
void vISRHandler(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    // 在中断中设置事件位
    xEventGroupSetBitsFromISR(xEventGroup, BIT_0, &xHigherPriorityTaskWoken);

    // 如果需要,执行上下文切换
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

// 任务函数
void vTaskFunction(void *pvParameters) {
    EventBits_t uxBits;

    for (;;) {
        // 等待BIT_0被设置
        uxBits = xEventGroupWaitBits(
            xEventGroup,
            BIT_0,
            pdTRUE,
            pdFALSE,
            portMAX_DELAY
        );

        if ((uxBits & BIT_0) != 0) {
            // 处理事件
            printf("Task received BIT_0\n");
        }
    }
}

int main(void) {
    // 创建事件组
    xEventGroup = xEventGroupCreate();
    if (xEventGroup == NULL) {
        // 处理事件组创建失败的情况
        printf("Event group creation failed!\n");
        return 1;
    }

    // 创建任务
    xTaskCreate(vTaskFunction, "Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 启动调度器
    vTaskStartScheduler();

    // 永远不会运行到这里
    for (;;);
    return 0;
}

下面是一个使用事件组的完整示例:

这个示例展示了如何创建事件组,设置和清除事件位,等待事件位,以及删除事件组:

#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"

// 定义事件位
#define BIT_0 (1 << 0)
#define BIT_1 (1 << 1)

// 定义任务优先级
#define TASK_PRIORITY (tskIDLE_PRIORITY + 1)

// 声明事件组句柄
EventGroupHandle_t xEventGroup;

void vTask1(void *pvParameters) {
    for (;;) {
        // 模拟一些工作
        vTaskDelay(pdMS_TO_TICKS(1000));
        // 设置BIT_0
        xEventGroupSetBits(xEventGroup, BIT_0);
        printf("Task 1 set BIT_0\n");
    }
}

void vTask2(void *pvParameters) {
    for (;;) {
        // 模拟一些工作
        vTaskDelay(pdMS_TO_TICKS(2000));
        // 设置BIT_1
        xEventGroupSetBits(xEventGroup, BIT_1);
        printf("Task 2 set BIT_1\n");
    }
}

void vTask3(void *pvParameters) {
    EventBits_t uxBits;
    for (;;) {
        // 等待BIT_0和BIT_1被设置,并在退出时清除这些位
        uxBits = xEventGroupWaitBits(
            xEventGroup,
            BIT_0 | BIT_1,
            pdTRUE,  // 在退出时清除这些位
            pdTRUE,  // 等待所有指定的位
            portMAX_DELAY  // 永久等待
        );

        if ((uxBits & (BIT_0 | BIT_1)) == (BIT_0 | BIT_1)) {
            // 所有指定的事件位都被设置
            printf("Task 3: All bits are set. Proceeding...\n");
        }
    }
}

int main(void) {
    // 创建事件组
    xEventGroup = xEventGroupCreate();
    if (xEventGroup == NULL) {
        // 处理事件组创建失败的情况
        printf("Event group creation failed!\n");
        return 1;
    }

    // 创建任务
    xTaskCreate(vTask1, "Task 1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, NULL);
    xTaskCreate(vTask2, "Task 2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, NULL);
    xTaskCreate(vTask3, "Task 3", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, NULL);

    // 启动调度器
    vTaskStartScheduler();

    // 永远不会运行到这里
    for (;;);
    return 0;
}

 

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐