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

释放双眼,带上耳机,听听看~!
00:00
00:00

一,介绍

事件组的好处:

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

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

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

测试结果

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

演示2

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

测试结果

二十六,ESP32 使用事件组同步多个任务-广播事件
图2 :任务1等待任务2和任务3的完成

予人玫瑰,手有余香

给TA打赏
共0人
还没有人赞赏,快来当第一个赞赏的人吧!
    ESP32ESP32-基础

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

    2018-10-21 8:17:33

    ESP32ESP32-基础

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

    2018-10-23 12:05:04

    0 条回复 A文章作者 M管理员
    向来缘浅,奈何情深
    欢迎您,新朋友,感谢参与互动!
      暂无讨论,说说你的看法吧
    个人中心
    购物车
    优惠劵
    今日签到
    私信列表
    搜索
    '); })();