目录
一、事件组介绍
事件组和队列、信号量等不太一样,主要集中在2个地方:
- 唤醒谁?
- 队列、信号量:事件发生时,只会唤醒一个任务
- 事件组:事件发生时,会唤醒所有符号条件的任务,简单地说它有"广播"的作用
- 是否清除事件?
- 队列、信号量:是消耗型的资源,队列的数据被读走就没了;信号量被获取后就减少了
- 事件组:被唤醒的任务有两个选择,可以让事件保留不动,也可以清除事件
以上图为列,事件组的常规操作如下:
- 先创建事件组
- 任务C、D等待事件:
- 等待什么事件?可以等待某一位、某些位中的任意一个,也可以等待多位。简单地说就是"或"、"与"的关系。
- 得到事件时,要不要清除?可选择清除、不清除。
- 任务A、B产生事件:设置事件组里的某一位、某些位
二、事件组函数
1、创建
/* 创建一个事件组,返回它的句柄。
* 此函数内部会分配事件组结构体
* 返回值: 返回句柄,非NULL表示成功
*/
EventGroupHandle_t xEventGroupCreate( void );
2、删除
/*
* xEventGroup: 事件组句柄,你要删除哪个事件组
*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
3、设置事件
/* 设置事件组中的位
* xEventGroup: 哪个事件组
* uxBitsToSet: 设置哪些位?
* 如果uxBitsToSet的bitX, bitY为1, 那么事件组中的bitX, bitY被设置为1
* 可以用来设置多个位,比如 0x15 就表示设置bit4, bit2, bit0
* 返回值: 返回原来的事件值(没什么意义, 因为很可能已经被其他任务修改了)
*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet );
四、等待事件函数案例
1、任务目的
任务一与任务二同时计数,一个计数到30,一个计数到10;两个任务都执行完,任务三开始执行
2、代码实现
1、创建句柄、事件组与任务
EventGroupHandle_t eventgroupwaithandle;
//event group dengdai
eventgroupwaithandle = xEventGroupCreate();
xTaskCreate(task_eventgroupwait1,"task_eventgroupwait1",128,NULL,osPriorityNormal,NULL);
xTaskCreate(task_eventgroupwait2,"task_eventgroupwait2",128,NULL,osPriorityNormal,NULL);
xTaskCreate(task_eventgroupwait3,"task_eventgroupwait3",128,NULL,osPriorityNormal,NULL);
2、函数代码实现
void task_eventgroupwait1(void *param)
{
int num = 20;
for( ;; )
{
while(num <= 30)
{
num++;
OLED_ShowNum(0,0,num,3,16);
vTaskDelay(500);
}
//设置事件0
xEventGroupSetBits(eventgroupwaithandle,(1<<0));
}
}
void task_eventgroupwait2(void *param)
{
int rec = 0;
for( ;; )
{
while(rec <= 30)
{
rec++;
OLED_ShowNum(0,3,rec,3,16);
vTaskDelay(500);
}
//设置事件1
xEventGroupSetBits(eventgroupwaithandle,(1<<1));
}
}
void task_eventgroupwait3(void *param)
{
for( ;; )
{
//等待事件0与1都完成
xEventGroupWaitBits(eventgroupwaithandle,(1<<0)|(1<<1),pdTRUE,pdTRUE,portMAX_DELAY);
led_on(green);
}
}
3、等待事件函数
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait );
xEventGroup | 等待哪个事件组? |
uxBitsToWaitFor | 等待哪些位?哪些位要被测试? |
xWaitForAllBits | 怎么测试?是"AND"还是"OR"? pdTRUE: 等待的位,全部为1; pdFALSE: 等待的位,某一个为1即可 |
xClearOnExit | 函数提出前是否要清除事件? pdTRUE: 清除uxBitsToWaitFor指定的位 pdFALSE: 不清除 |
xTicksToWait | 如果期待的事件未发生,阻塞多久。 可以设置为0:判断后即刻返回; 可设置为portMAX_DELAY:一定等到成功才返回; 可以设置为期望的Tick Count,一般用*pdMS_TO_TICKS()*把ms转换为Tick Count |
返回值 | 返回的是事件值, 如果期待的事件发生了,返回的是"非阻塞条件成立"时的事件值; 如果是超时退出,返回的是超时时刻的事件值。 |
五、同步点
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait );
xEventGroup | 哪个事件组? |
uxBitsToSet | 要设置哪些事件?我完成了哪些事件? 比如0x05(二进制为0101)会导致事件组的bit0,bit2被设置为1 |
uxBitsToWaitFor | 等待那个位、哪些位? 比如0x15(二级制10101),表示要等待bit0,bit2,bit4都为1 |
xTicksToWait | 如果期待的事件未发生,阻塞多久。 可以设置为0:判断后即刻返回; 可设置为portMAX_DELAY:一定等到成功才返回; 可以设置为期望的Tick Count,一般用*pdMS_TO_TICKS()*把ms转换为Tick Count |
返回值 | 返回的是事件值, 如果期待的事件发生了,返回的是"非阻塞条件成立"时的事件值; 如果是超时退出,返回的是超时时刻的事件值。 |