二十六,ESP32 使用事件组同步多个任务-广播事件

一,介绍

事件组的好处:

– 任务将处于阻塞状态以等待一个或多个事件的组合。它有助于同步多个任务,广播事件(通过设置任务的事件位以通知发生的事件)到多个任务。

– 取消阻止等待相同事件/操作或要发生/完成的事件/操作组合的所有任务。

– 事件标志可以是0或1.它用于指示事件是否发生。并且由EventBits_t数据类型中的一个位表示。

– 事件组是一组事件标志。

– EventBits_t的值为0x92(1001 0010)。这意味着设置了事件位1,4和7。

– 您必须定义每个事件位的含义。例如:位0表示发送消息事件已完成。

– 让我们进行2次演示:

 +演示1(“任务将处于阻塞状态以等待一个或多个事件的组合”):计时器正在运行,计时器超时时计数器将增加3个任务正在等待反击事件。如果counter等于2,则任务1将离开Blocked状态。如果计数器等于3,则任务2和任务3都将离开阻塞状态,计数器将重置为0. 

+演示2(“同步多个任务”):创建3个任务,其中任务1(最高优先级)将打印“任务1完成“然后等到任务2完成打印”任务2完成“并且任务3完成打印”。

演示1

#include "freertos/event_groups.h"

/*定义事件位 */
#define TASK_1_BIT        ( 1 << 0 ) //1
#define TASK_2_BIT        ( 1 << 1 ) //10
#define TASK_3_BIT        ( 1 << 2 ) //100
#define ALL_SYNC_BITS (TASK_1_BIT | TASK_2_BIT | TASK_3_BIT) //111


/* 创建硬件定时器 */
hw_timer_t * timer = NULL;
/* 创建事件组 */
EventGroupHandle_t eg;
int count = 0;

/* timer ISR callback */
void IRAM_ATTR onTimer(){
  BaseType_t xHigherPriorityTaskWoken;
  count++;
  if(count == 2){
    /* 如果counter等于2则设置 task1 */
    xEventGroupSetBitsFromISR(eg,TASK_1_BIT, &xHigherPriorityTaskWoken);
  }else if(count == 3){
    /* 如果counter等于3然后设置任务2的事件位和3 * */
    xEventGroupSetBitsFromISR(eg,TASK_2_BIT | TASK_3_BIT, &xHigherPriorityTaskWoken);
  }else if(count == 4){
    /*  counter再次启动 */
    count = 0;
  }
}

void setup() {

  Serial.begin(112500);
  eg = xEventGroupCreate();

 
  /* 1/(80MHZ/80) = 1us  */
  timer = timerBegin(0, 80, true);

  /* 将onTimer函数附加到我们的计时器 */
  timerAttachInterrupt(timer, &onTimer, true);

  /* 设置闹钟每秒调用onTimer函数1 tick为1us 
  => 1秒为1000000us*/
  /* 重复闹钟(第三个参数) */
  timerAlarmWrite(timer, 1000000, true);

  /* 发出警报 */
  timerAlarmEnable(timer);
  Serial.println("start timer");
  
  xTaskCreate(
      task1,           /* 任务功能 */
      "task1",        /* 任务名称. */
      10000,                    /* 任务的堆栈大小 */
      NULL,                     /* 任务的参数*/
      1,                        /* 任务的优先级 */
      NULL);                    /* 跟踪创建任务的任务句柄 */
  xTaskCreate(
      task2,           
      "task2",        
      10000,                    
      NULL,                   
      1,                       
      NULL);                    
  xTaskCreate(
      task3,          
      "task3",        
      10000,                   
      NULL,                     
      1,                        
      NULL);                    
}

void loop() {

}

void task1( void * parameter )
{
  for(;;){
    /* 永远等待,直到任务1的事件位被设置为 */
    EventBits_t xbit = xEventGroupWaitBits(eg, TASK_1_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
    Serial.print("task1 has even bit: ");
    Serial.println(xbit);
  }
  vTaskDelete( NULL );
}
/* 此任务类似于sendTask1 */
void task2( void * parameter )
{

  for(;;){
    
    EventBits_t xbit = xEventGroupWaitBits(eg, TASK_2_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
    Serial.print("task2 has even bit: ");
    Serial.println(xbit);
  }
  vTaskDelete( NULL );
}
void task3( void * parameter )
{
  for(;;){
   
    EventBits_t xbit = xEventGroupWaitBits(eg, TASK_3_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
    Serial.print("task3 has even bit: ");
    Serial.println(xbit);
  }
  vTaskDelete( NULL );
}

测试结果

二十六,ESP32 使用事件组同步多个任务-广播事件
图1:任务正在等待设置事件位

演示2

#include "freertos/event_groups.h"

/* 定义事件位 */
#define TASK_1_BIT        ( 1 << 0 ) //1
#define TASK_2_BIT        ( 1 << 1 ) //10
#define TASK_3_BIT        ( 1 << 2 ) //100
#define ALL_SYNC_BITS     (TASK_1_BIT | TASK_2_BIT | TASK_3_BIT) //111

/* 创建事件组 */
EventGroupHandle_t eg;

void setup() {

  Serial.begin(112500);
  eg = xEventGroupCreate();
  
  xTaskCreate(
      task1,           /* 任务函数. */
      "task1",        /* 任务名称 */
      10000,                    /* 任务的堆栈大小 */
      NULL,                     /* 任务的参数 */
      3,                        /*任务的优先级 */
      NULL);                    /* 跟踪创建的任务的任务句柄*/
  xTaskCreate(
      task2,           
      "task2",        
      10000,                   
      NULL,                     
      1,                        
      NULL);                    
  xTaskCreate(
      task3,          
      "task3",      
      10000,                    
      NULL,                    
      1,                       
      NULL);                    
}

void loop() {

}

void task1( void * parameter )
{
  for(;;){
    Serial.println("task1 done");
    /* task 2完成打印,因此设置其事件位并等待其他任务完成 */
    EventBits_t uxBits = xEventGroupSync(eg, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
    /* 如果其他任务完成,则所有事件位将被设置为*/
    if( ( uxBits & ALL_SYNC_BITS ) == ALL_SYNC_BITS ){
        Serial.println("task 1 - all task done !!!");
    }
  }
  vTaskDelete( NULL );
}

void task2( void * parameter )
{

  for(;;){
    Serial.println("task2 done");
    /* task 2完成打印,因此设置其事件位 */
    EventBits_t uxBits = xEventGroupSync( eg, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
  }
  vTaskDelete( NULL );
}
void task3( void * parameter )
{
  for(;;){
    Serial.println("task3 done");
    /*  task 3完成打印,因此设置其事件位* */
    EventBits_t uxBits = xEventGroupSync( eg, TASK_3_BIT, ALL_SYNC_BITS, portMAX_DELAY );
  }
  vTaskDelete( NULL );
}

测试结果

二十六,ESP32 使用事件组同步多个任务-广播事件
图2 :任务1等待任务2和任务3的完成
「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论