[经验分享] 【家中宝】 esp32s2 freertos任务之间的通信 Event Groups

damiaa   2022-9-14 10:52 楼主

                                【家中宝】 esp32s2 freertos任务之间的通信 Event Groups

用操作系统,就会发现,任务与任务之间,线程与线程之间,中断和任务之间都不能直接的用全局变量来整。那样会出问题的。

那怎么办?freertos就给了写方法。这里就esp32s2来简单的聊一下这个问题。虽然我也不是那么的懂

本章中只讨论一下事件组 Event Groups的使用。因为wifi的例子里面就用到了这个。其实每个程序中可以用很多个事件组的。这里就用两个。

   事件组的用途很广可以从中断中设置,从任务中判断接收。从任务中设置,从任务中判断接收只是函数不一样每个事件组有8位或24位事件位(可以设置)。

这个很适合于为信号传递,比如按键的按下就是一个很好的例子:按键任务中有24个按键,每个按键按下对于一个事件标记发送,其他任务中就可以监测使用它。

还有可以使用这个进行任务的同步

更多资料可以参考:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/system/freertos.html?highlight=event%20groups#_CPPv418xEventGroupSetBits18EventGroupHandle_tK11EventBits_t

具体使用如下代码

#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"//这个头文件是一定要的
#include "esp_system.h"
#include "esp_spi_flash.h"
EventGroupHandle_t xEventGroup1;//定义事件组句柄
EventGroupHandle_t xEventGroup2;
#define BIT_0 ( 1 << 0 )
#define BIT_4 ( 1 << 4 )
//下面函数判断时间是否发生和处理
void aFunction( EventGroupHandle_t xEventGroup )
{
     EventBits_t uxBits;
     const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
     uxBits = xEventGroupWaitBits(
                 xEventGroup,    // 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.
                 xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.

     if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
     {
         printf("xEventGroup xEventGroupWaitBits() returned because both bits were set.\n"); 
     }
     else if( ( uxBits & BIT_0 ) != 0 )
     {
         printf("xEventGroup xEventGroupWaitBits() returned because just BIT_0 was set.\n");
     }
     else if( ( uxBits & BIT_4 ) != 0 )
     {
         printf("xEventGroup xEventGroupWaitBits() returned because just BIT_4 was set.\n");
     }
     else
     {
         
     }
     uxBits = xEventGroupWaitBits(
                 xEventGroup2,    // 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.
                 xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.

     if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
     {
         printf("xEventGroup2 xEventGroupWaitBits() returned because both bits were set.\n"); 
     }
     else if( ( uxBits & BIT_0 ) != 0 )
     {
         printf("xEventGroup2 xEventGroupWaitBits() returned because just BIT_0 was set.\n");
     }
     else if( ( uxBits & BIT_4 ) != 0 )
     {
         printf("xEventGroup2 xEventGroupWaitBits() returned because just BIT_4 was set.\n");
     }
     else   {   }
}

// Task to create a queue and post a value.
void vATask( void *pvParameters )
{
    
    while(1)
    {   //这里定期的设置和清除事件标志位 以便任务vADifferentTask能收到事件标记
        xEventGroupSetBits(
                         xEventGroup1,    // The event group being updated.
                         BIT_0 | BIT_4 );// The bits being set.
        printf("xEventGroupSetBits xEventGroup1 BIT_0 | BIT_4\n");                 
        vTaskDelay(1000 / portTICK_PERIOD_MS); 
        xEventGroupClearBits(
                             xEventGroup1,    // The event group being updated.
                             BIT_0 | BIT_4 );// The bits being cleared.
        printf("xEventGroupClearBits xEventGroup1 BIT_0 | BIT_4\n");                 
        vTaskDelay(1000 / portTICK_PERIOD_MS); 
        xEventGroupSetBits(
                         xEventGroup2,    // The event group being updated.
                         BIT_0 | BIT_4 );// The bits being set.
        printf("xEventGroupSetBits xEventGroup2 BIT_0 | BIT_4\n");                 
        vTaskDelay(1000 / portTICK_PERIOD_MS); 
        xEventGroupClearBits(
                             xEventGroup2,    // The event group being updated.
                             BIT_0 | BIT_4 );// The bits being cleared.
        printf("xEventGroupClearBits xEventGroup2 BIT_0 | BIT_4\n");                 
        vTaskDelay(1000 / portTICK_PERIOD_MS); 
    }
}

// Task to receive from the queue.
void vADifferentTask( void *pvParameters )
{
    while(1)
    {
        printf("xEventGroup1 。。。。。。。。。。。。。。。。。\n");
        aFunction( xEventGroup1 );//定期调用aFunction( xEventGroup1 )判断是否有事件产生
        printf("xEventGroup2 。。。。。。。。。。。。。。。。。\n");
        aFunction( xEventGroup2 );//定期调用aFunction( xEventGroup2 )判断是否有事件产生
        vTaskDelay(100 / portTICK_PERIOD_MS); 
    }
}
void app_main(void)
{
    printf("Hello world!\n");

    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    //这里创建两个任务,创建两个事件组, 之所以创建两个事件组是为了说明程序中能创建多个事件组。
    xTaskCreate(vATask, "vATask", 1024*2, NULL, configMAX_PRIORITIES-3, NULL);
    xTaskCreate(vADifferentTask, "vADifferentTask", 1024*2, NULL, configMAX_PRIORITIES-4, NULL);
    xEventGroup1 =xEventGroupCreate();
    xEventGroup2 =xEventGroupCreate();
    
    while(1){
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
 
}

 

本帖最后由 damiaa 于 2022-9-14 11:12 编辑

回复评论 (1)

FreeRTOS的事件组就和RTThread的事件集一样。这个功能用途确实多。

点赞  2022-9-14 13:43
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复