FreeRTOS—事件标志组

一、事件标志组

1.1.简介

事件标志位是用一个位来表示时间是否发生;事件标志组是一组事件标志位的集合,可以看作一个整数。事件标志组的特点:

  • 它的每一位表示一个事件(高 8 位不算,高 8 位用作存储时间标志组的控制信息)
  • 每一位事件的含义,由用户自己决定,如:bit0 表示按键是否按下,bit1 表示是否接收到消息
  • 任意任务或中断都可以读写这些位
  • 可以等待某一位成立,或者等待多位同时成立

EventBits_t实际上是一个 16 位或 32 位无符号的数据类型,一个事件组就包括了一个EventBits_t数据类型的变量,变量类型定义如下:

//下面的宏默认为0,如果为1就进行if操作
#define configUSE_16_BIT_TICKS 0


typedef TickType_t EventBits_t;
#if(configUSE_16_BIT_TICKS == 1)
	typedef uint16_t TickType_t;
#else
	typedef uint32_t TickType_t;
#endif

虽然使用了 32 位无符号的数据类型变量来存储事件标志,但其中的高 8 位用作存储事件标志组的控制信息,低 24 位用作存储事件标志,因此一个事件组最多可以存储 24 个事件标志,如下图:

在这里插入图片描述

1.2.事件组和队列、信号量的区别

功能唤醒对象事件清除
队列、信号量事件发生时,只会唤醒一个任务是消耗型的资源,队列的数据被读走了就没有了;信号量被获取后就减少
事件标志组事件发生时,会唤醒所有符合条件的任务,可以理解为广播的作用被唤醒的任务有两个选择,可以让事件保留不动,也可以清除事件

二、事件标志组的相关API函数

函数描述
xEventGroupCreate( )使用动态方式创建事件标志组
xEventGroupCreateStstic( )使用静态方式创建事件标志组
xEventGroupWaitBits( )等待事件标志位
xEventGroupSetBits( )设置事件标志位
xEventGroupSetBitsFromISR( )在中断中设置事件标志位
xEventGroupClearBits( )清零事件标志位
xEventGroupClearBitsFromISR( )在中断中清零事件标志位
xEventGroupGetBits( )获取事件组中各事件标志位的值
xEventGroupGetBitsFromISR( )在中断中获取事件组中各事件标志位的值
xEventGroupSync( )设置事件标志位,并等待事件标志位

2.1.使用动态方式创建事件标志组

动态方式创建事件标志组 API 函数的函数原型如下所示:

EventGroupHandle_t xEventGroupCreate(void); 

下面表格是它的返回值:

返回值描述
NULL事件标志组创建失败
其他值事件标志组创建成功,返回其句柄

2.2.清零事件标志位

在任务中清零事件标志位 API 函数的函数原型如下所示:

EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup, 
								 const EventBits_t  uxBitsToClear) 

下面表格是它的形参和描述:

形参描述
xEventGroup待操作的事件标志组
uxBitsToSet待清零的事件标志位

下面表格是它的返回值:

返回值描述
整数清零事件标志位之前事件组中事件标志位的值

2.3.设置事件标志位

在任务中设置事件标志位 API 函数的函数原型如下所示:

EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup, 
							   const EventBits_t  uxBitsToSet) 

下面表格是它的形参和描述:

形参描述
xEventGroup待操作的事件标志组
uxBitsToSet待设置的事件标志位

下面表格是它的返回值:

返回值描述
整数函数返回时,事件组中的事件标志位值

2.4.等待事件标志位

等待事件标志位使用的是函数 xEventGroupWaitBits( ),其函数原型如下所示:

EventBits_t xEventGroupWaitBits(EventGroupHandle_t xEventGroup, 
								const EventBits_t  uxBitsToWaitFor, 
								const BaseType_t   xClearOnExit, 
								const BaseType_t   xWaitForAllBits, 
								TickType_t   	   xTicksToWait) 

下面表格是它的形参和描述:

形参描述
xEvenrGroup等待的事件标志组
uxBitsToWaitFor等待的事件标志位,可以用逻辑或等待多个事件标志位
xClearOnExit成功等待到事件标志位后,清除事件组中对应的事件标志位,pdTRUE:清除 uxBitsToWaitFor 指定位;pdFALSE:不清除
xWaitForAllBits等待 uxBitsToWaitFor 中的所有事件标志位(逻辑与),pdTRUE:等待的位,全都为 1;pdFALSE:等待的位,某个为 1
xTicksToWait获取等待的阻塞时间

下面表格是它的返回值:

返回值描述
等待的事件标志位值等待事件标志位成功,返回等待到的事件标志位
其他值等待事件标志位失败,返回事件组中的事件标志位

2.5.同步函数

此函数一般用于多任务同步,其中每个任务都必须等待其他任务达到同步点,然后才能继续执行。函数xEventGroupSync( )的函数原型如下所示:

EventBits_t xEventGroupSync(EventGroupHandle_t xEventGroup, 
							const EventBits_t  uxBitsToSet, 
							const EventBits_t  uxBitsToWaitFor, 
							TickType_t  	   xTicksToWait) 

下面表格是它的形参和描述:

形参描述
xEventGroup等待事件标志所在事件组
uxBitsToSet达到同步点后,要设置的事件标志
uxBitsToWaitFor等待的事件标志
xTicksToWait等待的阻塞时间

下面表格是它的返回值:

返回值描述
等待的事件标志位值等待事件标志位成功,返回等待到的事件标志位
其他值等待事件标志位失败,返回事件组中的事件标志位

三、实验

3.1.实验设计

本实验将设计三个任务:

  • start_task:创建 task1 和 task2,并创建事件标志组
  • task1:读取按键按下键值,根据不同键值将事件标志组相应事件位置 1,模拟事件发生
  • task2:同时等待事件标志组中的多个事件位,当这些事件位都置 1 就执行相应的处理

3.2.软件设计

在 start_task 创建事件标志组:

//全局变量和宏定义
EventGroupHandle_t eventGroup_handle;
#define   Bit0    1 << 0
#define   Bit1    1 << 1

void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();   
	
	eventGroup_handle = xEventGroupCreate();
	if(eventGroup_handle != NULL)
	{
		printf("事件标志组创建成功\r\n");
	}

	xTaskCreate((TaskFunction_t)    task1,	
                (char*)             "task1",
                (uint16_t)          TASK1_STACK_SIZE,
                (void*)             NULL,
                (UBaseType_t)       TASK1_PRIO,
                (TaskHandle_t*)     &task1_handler);

	xTaskCreate((TaskFunction_t)    task2,	
                (char*)             "task2",
                (uint16_t)          TASK2_STACK_SIZE,
                (void*)             NULL,
                (UBaseType_t)       TASK2_PRIO,
                (TaskHandle_t*)     &task2_handler);
				
	vTaskDelete(NULL);	
    taskEXIT_CRITICAL();            
}

下面是实现设置事件标志位和等待标志位,task2 的等待事件标志位需要 Bit0 和 Bit1 都置 1 才能打印下面句子:

void task1(void *pvParameters)
{
	uint8_t key = 0;
	while(1)
	{
		key = key_scan(0);
		if(key == KEY0_PRES)
		{
			xEventGroupSetBits(eventGroup_handle, Bit0);
		}else if(key == KEY1_PRES)
		{
			xEventGroupSetBits(eventGroup_handle, Bit1);	
		}
	}
}

void task2(void *pvParameters)
{
	EventBits_t event_bits = 0;
	while(1)
	{
		event_bits = xEventGroupWaitBits(eventGroup_handle, Bit0 | Bit1, pdTRUE, pdTRUE, portMAX_DELAY);
		printf("等待到的事件标志位值为:%#x\r\n",event_bits);
	}
}

下图是程序运行的结果图,0x3 = 0x1 + 0x2。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值