事件组
事件位:用于指示事件是否发生,事件位通常称为事件标志;
事件组:就是一组事件位。事件组中的事件位通过位编号来引用;
![[Pasted image 20250518153023.png]]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
EventGroupHandle_t xEventGroupCreate(void);
EventBits_t xEventGroupWaitBits( const EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait );
EventBits xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
EventBits xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
|
实例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" #include "freertos/task.h" #include "esp_log.h"
#define NUM0_BIT BIT0 #define NUM1_BIT BIT1
static EventGroupHandle_t test_event;
void taskA(void *param) { while (1) { xEventGroupSetBits(test_event, NUM0_BIT); vTaskDelay(pdMS_TO_TICKS(1000));
xEventGroupSetBits(test_event, NUM1_BIT); vTaskDelay(pdMS_TO_TICKS(1000)); } }
void taskB(void *param) { EventBits_t ev; while (1) { ev = xEventGroupWaitBits(test_event, NUM0_BIT | NUM1_BIT, pdTRUE, pdFALSE, pdMS_TO_TICKS(5000));
if (ev & NUM0_BIT) { ESP_LOGI("ev", "get BIT0 event"); } if (ev & NUM1_BIT) { ESP_LOGI("ev", "get BIT1 event"); } } }
void app_main(void) { test_event = xEventGroupCreate();
xTaskCreatePinnedToCore(taskA, "taskA", 2048, NULL, 3, NULL, 1);
xTaskCreatePinnedToCore(taskB, "taskB", 2048, NULL, 3, NULL, 1); }
|
内容 |
解释 |
EventGroupHandle_t |
事件组类型,用于管理多个事件位 |
xEventGroupSetBits() |
设置一个或多个事件位 |
xEventGroupWaitBits() |
等待某些事件位被置位 |
pdTRUE (清除标志) |
指定等待完成后是否自动清除这些事件位 |
pdFALSE (等待所有位) |
指定是否等待“所有位”置位(pdTRUE)或“任意一位”置位(pdFALSE) |
![[Pasted image 20250518155912.png]] |
|
直达任务通知
每个RTOS任务都有一个任务通知组。每条任务通知 都有“挂起”或“非挂起”的通知状态,以及一个32位通知值。
直达任务通知是直接发送至任务的事件,而不是通过中间对象(如队列、事件组或信号量)间接发送至任务的事件。
向任务发送“直达任务通知”会将目标任务通知设为“挂起”状态(此挂起不是挂起任务)。
用直达任务通知的时候,无需再初始化或新建其他对象句柄,直接使用任务句柄来操作通知的发送。
说白了就是两个任务间可以直接通信,而不是像队列一样通过变量间接完成。
![[Pasted image 20250518154256.png]]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, );
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t * pulNotificationValue, TickType_t xTicksToWait );
|
实例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" #include "freertos/task.h" #include "esp_log.h"
static TaskHandle_t taskA_handle; static TaskHandle_t taskB_handle;
void taskA(void *param) { uint32_t value = 0; vTaskDelay(pdMS_TO_TICKS(200));
while (1) { xTaskNotify(taskB_handle, value, eSetValueWithoutOverwrite);
vTaskDelay(pdMS_TO_TICKS(1000)); value++; } }
void taskB(void *param) { uint32_t value;
while (1) { xTaskNotifyWait(0x00, ULONG_MAX, &value, portMAX_DELAY);
ESP_LOGI("ev", "notify wait value:%lu", value); } }
void app_main(void) { xTaskCreatePinnedToCore(taskA, "taskA", 2048, NULL, 3, &taskA_handle, 1);
xTaskCreatePinnedToCore(taskB, "taskB", 2048, NULL, 3, &taskB_handle, 1); }
|
![[Pasted image 20250518163208.png]]