目录
一,介绍
事件组的好处:
– 任务将处于阻塞状态以等待一个或多个事件的组合。它有助于同步多个任务,广播事件(通过设置任务的事件位以通知发生的事件)到多个任务。
– 取消阻止等待相同事件/操作或要发生/完成的事件/操作组合的所有任务。
– 事件标志可以是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 );
}
测试结果
演示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 );
}