二十六,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

  1. #include "freertos/event_groups.h"
  2. /*定义事件位 */
  3. #define TASK_1_BIT ( 1 << 0 ) //1
  4. #define TASK_2_BIT ( 1 << 1 ) //10
  5. #define TASK_3_BIT ( 1 << 2 ) //100
  6. #define ALL_SYNC_BITS (TASK_1_BIT | TASK_2_BIT | TASK_3_BIT) //111
  7. /* 创建硬件定时器 */
  8. hw_timer_t * timer = NULL;
  9. /* 创建事件组 */
  10. EventGroupHandle_t eg;
  11. int count = 0;
  12. /* timer ISR callback */
  13. void IRAM_ATTR onTimer(){
  14. BaseType_t xHigherPriorityTaskWoken;
  15. count++;
  16. if(count == 2){
  17. /* 如果counter等于2则设置 task1 */
  18. xEventGroupSetBitsFromISR(eg,TASK_1_BIT, &xHigherPriorityTaskWoken);
  19. }else if(count == 3){
  20. /* 如果counter等于3然后设置任务2的事件位和3 * */
  21. xEventGroupSetBitsFromISR(eg,TASK_2_BIT | TASK_3_BIT, &xHigherPriorityTaskWoken);
  22. }else if(count == 4){
  23. /* counter再次启动 */
  24. count = 0;
  25. }
  26. }
  27. void setup() {
  28. Serial.begin(112500);
  29. eg = xEventGroupCreate();
  30. /* 1/(80MHZ/80) = 1us */
  31. timer = timerBegin(0, 80, true);
  32. /* 将onTimer函数附加到我们的计时器 */
  33. timerAttachInterrupt(timer, &onTimer, true);
  34. /* 设置闹钟每秒调用onTimer函数1 tick为1us
  35. => 1秒为1000000us*/
  36. /* 重复闹钟(第三个参数) */
  37. timerAlarmWrite(timer, 1000000, true);
  38. /* 发出警报 */
  39. timerAlarmEnable(timer);
  40. Serial.println("start timer");
  41. xTaskCreate(
  42. task1, /* 任务功能 */
  43. "task1", /* 任务名称. */
  44. 10000, /* 任务的堆栈大小 */
  45. NULL, /* 任务的参数*/
  46. 1, /* 任务的优先级 */
  47. NULL); /* 跟踪创建任务的任务句柄 */
  48. xTaskCreate(
  49. task2,
  50. "task2",
  51. 10000,
  52. NULL,
  53. 1,
  54. NULL);
  55. xTaskCreate(
  56. task3,
  57. "task3",
  58. 10000,
  59. NULL,
  60. 1,
  61. NULL);
  62. }
  63. void loop() {
  64. }
  65. void task1( void * parameter )
  66. {
  67. for(;;){
  68. /* 永远等待,直到任务1的事件位被设置为 */
  69. EventBits_t xbit = xEventGroupWaitBits(eg, TASK_1_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
  70. Serial.print("task1 has even bit: ");
  71. Serial.println(xbit);
  72. }
  73. vTaskDelete( NULL );
  74. }
  75. /* 此任务类似于sendTask1 */
  76. void task2( void * parameter )
  77. {
  78. for(;;){
  79. EventBits_t xbit = xEventGroupWaitBits(eg, TASK_2_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
  80. Serial.print("task2 has even bit: ");
  81. Serial.println(xbit);
  82. }
  83. vTaskDelete( NULL );
  84. }
  85. void task3( void * parameter )
  86. {
  87. for(;;){
  88. EventBits_t xbit = xEventGroupWaitBits(eg, TASK_3_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
  89. Serial.print("task3 has even bit: ");
  90. Serial.println(xbit);
  91. }
  92. vTaskDelete( NULL );
  93. }

测试结果

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

演示2

  1. #include "freertos/event_groups.h"
  2. /* 定义事件位 */
  3. #define TASK_1_BIT ( 1 << 0 ) //1
  4. #define TASK_2_BIT ( 1 << 1 ) //10
  5. #define TASK_3_BIT ( 1 << 2 ) //100
  6. #define ALL_SYNC_BITS (TASK_1_BIT | TASK_2_BIT | TASK_3_BIT) //111
  7. /* 创建事件组 */
  8. EventGroupHandle_t eg;
  9. void setup() {
  10. Serial.begin(112500);
  11. eg = xEventGroupCreate();
  12. xTaskCreate(
  13. task1, /* 任务函数. */
  14. "task1", /* 任务名称 */
  15. 10000, /* 任务的堆栈大小 */
  16. NULL, /* 任务的参数 */
  17. 3, /*任务的优先级 */
  18. NULL); /* 跟踪创建的任务的任务句柄*/
  19. xTaskCreate(
  20. task2,
  21. "task2",
  22. 10000,
  23. NULL,
  24. 1,
  25. NULL);
  26. xTaskCreate(
  27. task3,
  28. "task3",
  29. 10000,
  30. NULL,
  31. 1,
  32. NULL);
  33. }
  34. void loop() {
  35. }
  36. void task1( void * parameter )
  37. {
  38. for(;;){
  39. Serial.println("task1 done");
  40. /* task 2完成打印,因此设置其事件位并等待其他任务完成 */
  41. EventBits_t uxBits = xEventGroupSync(eg, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
  42. /* 如果其他任务完成,则所有事件位将被设置为*/
  43. if( ( uxBits & ALL_SYNC_BITS ) == ALL_SYNC_BITS ){
  44. Serial.println("task 1 - all task done !!!");
  45. }
  46. }
  47. vTaskDelete( NULL );
  48. }
  49. void task2( void * parameter )
  50. {
  51. for(;;){
  52. Serial.println("task2 done");
  53. /* task 2完成打印,因此设置其事件位 */
  54. EventBits_t uxBits = xEventGroupSync( eg, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
  55. }
  56. vTaskDelete( NULL );
  57. }
  58. void task3( void * parameter )
  59. {
  60. for(;;){
  61. Serial.println("task3 done");
  62. /* task 3完成打印,因此设置其事件位* */
  63. EventBits_t uxBits = xEventGroupSync( eg, TASK_3_BIT, ALL_SYNC_BITS, portMAX_DELAY );
  64. }
  65. vTaskDelete( NULL );
  66. }

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

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
ESP-32

二十五,ESP32 使用定时器中断

2025-4-16 15:09:35

ESP-32

二十七,使用首选项备份ESP32主闪存中的数据

2025-4-16 15:14:48

个人中心
购物车
优惠劵
今日签到
私信列表
搜索