【FreeRTOS(十二)】事件标志组

事件标志组

事件标志位

事件位用来表明某个事件是否发生,事件位通常用作事件标志,比如下面的几个例子:

  • 当收到一条消息并且把这条消息处理掉以后就可以将某个位(标志)置 1,当队列中没有消息需要处理的时候就可以将这个位(标志)置 0。
  • 当把队列中的消息通过网络发送输出以后就可以将某个位(标志)置 1,当没有数据需要从网络发送出去的话就将这个位(标志)置 0。
  • 现在需要向网络中发送一个心跳信息,将某个位(标志)置 1。现在不需要向网络中发送心跳信息,这个位(标志)置 0。

事件组

一个事件组就是一组的事件位,事件组中的事件位通过位编号来访问,同样,以上面列出的三个例子为例:

  • 事件标志组的 bit0 表示队列中的消息是否处理掉。
  • 事件标志组的 bit1 表示是否有消息需要从网络中发送出去。
  • 事件标志组的 bit2 表示现在是否需要向网络发送心跳信息。

事件标志组的数据类型为 EventGroupHandle_t,当 configUSE_16_BIT_TICKS 为 1 的时候事件标志组可以存储 8 个事件位,当 configUSE_16_BIT_TICKS 为 0 的时候事件标志组存储 24个事件位。
在这里插入图片描述


创建事件标志组 xEventGroupCreate

创建一个事件标志组

EventGroupHandle_t xEventGroupCreate( void )

参数:
	无

返回值:
	NULL: 事件标志组创建失败。
	其他值: 创建成功的事件标志组句柄。

将指定的事件位清零 xEventGroupClearBits

将事件标志组中的指定事件位清零

EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, 
								  const EventBits_t uxBitsToClear );

参数:
	xEventGroup:要操作的事件标志组的句柄。
	uxBitsToClear :要清零的事件位,比如要清除 bit3 的话就设置为 0X08。可以同时清除多个bit,如设置为 0X09 的话就是同时清除 bit3 和 bit0。

返回值:
	任何值:将指定事件位清零之前的事件组值。

将指定的事件位置 1 xEventGroupSetBits

设置指定的事件位为 1

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, 
							    const EventBits_t uxBitsToSet );

参数:
	xEventGroup:要操作的事件标志组的句柄。
	uxBitsToClear:指定要置 1 的事件位,比如要将 bit3 值 1 的话就设置为 0X08。可以同时将多个 bit 置 1,如设置为 0X09 的话就是同时将 bit3 和 bit0 置 1。

返回值:	
	任何值:在将指定事件位置 1 后的事件组值。

获取事件标志组值 xEventGroupGetBits

获取当前事件标志组的值,也就是各个事件位的值。

EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );

参数:
	xEventGroup:要获取的事件标志组的句柄。

返回值:
	任何值:当前事件标志组的值。

等待指定的事件位 xEventGroupWaitBits

调用函数以后如果任务要等待的事件位还没有准备好(置 1 或清零)的话任务就会进入阻塞态,直到阻塞时间到达或者所等待的事件位准备好。

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

参数:
	xEventGroup:指定要等待的事件标志组。
	uxBitsToWaitFord:指定要等待的事件位,比如要等待bit0和()bit2的时候此参数就是0X05,如果要等待 bit0 和()bit1 和()bit2 的时候此参数就是 0X07。
	xClearOnExit:此参数要是为pdTRUE的话,那么在退出此函数之前由参数uxBitsToWaitFor所设置的这些事件位就会清零。如果设置位 pdFALSE 的话这些事件位就不会改变。
	xWaitForAllBits:此参数如果设置为 pdTRUE 的话,当 uxBitsToWaitFor 所设置的这些事件位都置 1,或者指定的阻塞时间到的时候函数 xEventGroupWaitBits()才会返回。当此函数为 pdFALSE 的话,只要 uxBitsToWaitFor 所设置的这些事件 位 其 中 的 任 意 一 个 置 1 , 或 者 指 定 的 阻 塞 时 间 到 的 话 函 数xEventGroupWaitBits()就会返回。
	xTicksToWait:设置阻塞时间,单位为节拍数。

返回值:
	任何值: 返回当所等待的事件位置 1 以后的事件标志组的值,或者阻塞时间到。根据这个值我们就知道哪些事件位置 1 了。如果函数因为阻塞时间到而返回的话那么这个返回值就不代表任何的含义。

同步时间组 xEventGroupSync

使用事件组使得两个或多个任务同步的方法。该函数允许置位一个或多个事件位,然后等待所需事件位置位。当所需事件位置位后该函数返回,并在返回前将相关位复位。

EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
							const EventBits_t uxBitsToSet,
							const EventBits_t uxBitsToWaitFor,
							TickType_t xTicksToWait );
参数:
	xEventGroup:表示事件组名称。
	uxBitsToSet:需要置位的位。
	uxBitsToWaitFor:需要等待的置位后的事件组的值。
	xTicksToWait :阻塞等待的时间。

返回值:
	若所有相关位均已置位,则返回的值为复位前的数据组的值,若超时则返回的值为阻塞等待的时间。

代码示例:事件组等待

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "freertos/event_groups.h"

#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )

/* Declare a variable to hold the created event group. */
EventGroupHandle_t xCreatedEventGroup;

void Task1(void *pvParam)
{
    while(1)
    {
        printf("----------------!\n");
        printf("task1 begin to wait!\n");

        /* Wait a maximum of 100ms for either bit 0 or bit 4 to be set within the event group. Clear the bits before exiting. */
        xEventGroupWaitBits(xCreatedEventGroup,         /* The event group being tested. */
                                    BIT_0 | BIT_4,      /* The bits within the event group to wait for. */
                                    pdTRUE,             /* BIT_0 and BIT_4 should be cleared before returning. */
                                    pdFALSE,            /* Don't wait for both bits, either bit will do. */
                                    portMAX_DELAY );    /* Wait a maximum of 100ms for either bit to be set. */

        printf("----------------!\n");
        printf("in task1, BIT_0 or BIT_4 is set!\n");

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void Task2(void *pvParam)
{
    vTaskDelay(pdMS_TO_TICKS(1000));

    while(1)
    {
        printf("----------------!\n");
        printf("task2 begin to set bit0!\n");

        xEventGroupSetBits(xCreatedEventGroup, BIT_0);

        vTaskDelay(pdMS_TO_TICKS(5000));

        printf("----------------!\n");
        printf("task2 begin to set bit4!\n");

        xEventGroupSetBits(xCreatedEventGroup, BIT_4);

        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}

void app_main(void)
{

    /* Attempt to create the event group. */
    xCreatedEventGroup = xEventGroupCreate();
    /* Was the event group created successfully? */
    if (xCreatedEventGroup == NULL)
    {
        /* The event group was not created because there was insufficient FreeRTOS heap available. */
        printf("Event group create fail!\n");
    }
    else
    {
        /* The event group was created. */
        vTaskSuspendAll();

        xTaskCreate(Task1, "Task1", 1024 * 5, NULL, 1, NULL);
        xTaskCreate(Task2, "Task2", 1024 * 5, NULL, 1, NULL);

        xTaskResumeAll();
    }
}

代码示例:事件组同步

在这里插入图片描述

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "freertos/event_groups.h"

/* Bits used by the three tasks. */
#define TASK_0_BIT (1 << 0)
#define TASK_1_BIT (1 << 1)
#define TASK_2_BIT (1 << 2)
#define ALL_SYNC_BITS (TASK_0_BIT | TASK_1_BIT | TASK_2_BIT)

/* Use an event group to synchronize three tasks. It is assumed this event group has already been created elsewhere. */
EventGroupHandle_t xEventBits;

void Task0(void *pvParam)
{
    while (1)
    {
        printf("----------------!\n");
        printf("task0 begin!\n");

        vTaskDelay(pdMS_TO_TICKS(1000));

        printf("----------------!\n");
        printf("task0 set bit0!\n");

        xEventGroupSync(xEventBits,
                        TASK_0_BIT,     /* The bit to set. */
                        ALL_SYNC_BITS,  /* The bits to wait for. */
                        portMAX_DELAY); /* Timeout value. */

        printf("task0 sync!\n");

        vTaskDelay(pdMS_TO_TICKS(1000));
        
    }
}

void Task1(void *pvParam)
{
    while (1)
    {
        printf("----------------!\n");
        printf("task1 begin!\n");

        vTaskDelay(pdMS_TO_TICKS(3000));

        printf("----------------!\n");
        printf("task1 set bit1!\n");

        xEventGroupSync(xEventBits,
                        TASK_1_BIT,     /* The bit to set. */
                        ALL_SYNC_BITS,  /* The bits to wait for. */
                        portMAX_DELAY); /* Timeout value. */

        printf("task1 sync!\n");

        vTaskDelay(pdMS_TO_TICKS(1000));
        
    }
}

void Task2(void *pvParam)
{
    while (1)
    {
        printf("----------------!\n");
        printf("task2 begin!\n");

        vTaskDelay(pdMS_TO_TICKS(5000));

        printf("----------------!\n");
        printf("task2 set bit2!\n");

        xEventGroupSync(xEventBits,
                        TASK_2_BIT,     /* The bit to set. */
                        ALL_SYNC_BITS,  /* The bits to wait for. */
                        portMAX_DELAY); /* Timeout value. */

        printf("task2 sync!\n");

        vTaskDelay(pdMS_TO_TICKS(1000));
        
    }
}

void app_main(void)
{
    xEventBits = xEventGroupCreate();

    if (xEventBits == NULL)
    {
        printf("Event group create fail!\n");
    }
    else
    {
        vTaskSuspendAll();

        xTaskCreate(Task0, "Task1", 1024 * 5, NULL, 1, NULL);
        xTaskCreate(Task1, "Task1", 1024 * 5, NULL, 1, NULL);
        xTaskCreate(Task2, "Task2", 1024 * 5, NULL, 1, NULL);

        xTaskResumeAll();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eiker_3169

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值