STM32 FreeRTOS 事件标志组

事件标志组

一、概念

1、事件标志

​ 事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能是事件类型的通信,无数据传输。与信号量不同的是,它可以实现一对多,多对多的同步。即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个事件。

​ 事件标志可以简化成一个个flag标志,在学习阶段,我们常在全局定义一个flag变量来控制某个事件或功能。

例如:led点灯

c 复制代码
uint8_t led_flag;

if (led_flag == 1)
{
    led_open(); 	// 灯打开
}
else if (led_flag != 1)
{
    led_close(); 	// 灯关闭
}

有个疑问?我都能直接通过flag控制,为什么我还需要用事件标志组?

答:全局变量固然是最快最直接的,但是考虑到安全问题,变量放在全局谁都可以访问,谁都可以修改,这就非常不安全,所以用事件标志组就可以避免这样的事情。事件标志组相比于全局变量有更加便利的功能,设定置位标准,更强的逻辑判断等功能。

2、事件标志组

​ 事件标志组是由多个事件组成,保存事件组的状态。事件组存储在一个EventBits_t类型的变量中,该变量在事件组结构体中定义。

宏定义configUSE_16_BIT_TICKS:定义事件存储组大小的

  • configUSE_16_BIT_TICKS为1时,变量uxEventBits就是16位的,其中有8个位用来存储事件组
  • configUSE_16_BIT_TICKS 定义为0,那么变量uxEventBits就是32位的, 其中有24个位用来存储事件组

​ 在STM32中,我们一般将configUSE_16_BIT_TICKS定义为0,那么uxEventBits是32位的,有24个位用来实现事件标志组。每一位代表一个事件,任务通过"逻辑与"或"逻辑或"与一个或多个事件建立关联,形成一个事件组。

​ 例如,如果一个事件组的值是0x92(二进制1001 0010),那么只有事件位1、4和7被设置,因此只有由1、4和7表示的事件发生。下图显示了EventBits_t类型的变量,它设置了事件位1、4和7,并清除了所有其他事件位,使事件组的值为0x92。

任务可以通过设置事件位来实现事件的触发和等待操作。FreeRTOS 的事件仅用于同步,不提供数据传输功能。

二、函数接口

1、头文件

c 复制代码
#include "event_groups.h"

2、事件标志组创建

c 复制代码
EventGroupHandle_t xEventGroupCreate(void)
  • 函数说明:事件标志组创建,并用返回值的句柄对事件标志组操作。
  • 参数:无
  • 返回值:
    • 成功:返回 事件标志组的句柄。
    • 失败:返回 NULL。

3、事件标志组删除

c 复制代码
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
  • 函数说明:用事件标志组句柄删除事件标志组。
  • 参数:
    • xEventGroup :事件标志组的句柄
  • 返回值:无

4、事件标志组指定事件置位

c 复制代码
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, 
                            const EventBits_t uxBitsToSet )
  • 函数说明:用句柄指定某事件在某事件标志组的某个位置(记住宏定义configUSE_16_BIT_TICKS的配置)。
  • 参数:
    • xEventGroup :事件标志组的句柄
    • uxBitsToSet:指定事件的标志位
  • 返回值:
    • 成功:返回调用xEventGroupSetBits()时事件组中的值(uxBitsToSet的值)。
    • 失败:没有失败返回值。注意:返回0(pdPASS),会误以为是失败,其实是第0位被置位了,是正常现象,并没有失败。
  • 例子:

为LED 设置事件标志组并将其设置在第0位

c 复制代码
xEventGroupSetBits( xEventGroup_led,  (1 << 0) ); //  (1 << 0)可以通过这样快速选位置,不需要直接进行计算

5、事件标志组指定事件置位(中断)

c 复制代码
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, 
                                      const EventBits_t uxBitsToSet, 
                                      BaseType_t *pxHigherPriorityTaskWoken )
  • 函数说明:用句柄指定某事件在某事件标志组的某个位置,该函数用在中断中。
  • 参数:
    • xEventGroup :事件标志组的句柄
    • uxBitsToSet:指定事件的标志位
    • pxHigherPriorityTaskWoken:在使用之前必须初始化成 pdFALSE。如果API函数(即xEventGroupSetBitsFromISR)导致一个任务解锁,并且解锁的任务优先级高于当前运行的任务,则API函数(即xEventGroupSetBitsFromISR)将pxHigherPriorityTaskWoken设置成pdTRUE。在中断退出前,触发一次任务切换。pxHigherPriorityTaskWoken 作为一个可选参数,可以设置为NULL。
  • 返回值:
    • 成功:返回 pdPASS
    • 失败:返回 pdFAIL

6、等待事件标志组

c 复制代码
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, 
								 const EventBits_t uxBitsToWaitFor, 
								 const BaseType_t xClearOnExit, 
							 	 const BaseType_t xWaitForAllBits, 
							 	 TickType_t xTicksToWait )
  • 函数说明:用句柄指定等待某事件标志组中某位或某几位置位。
  • 参数:
    • xEventGroup :事件标志组的句柄
    • uxBitsToWaitFor:指定等待的位置(事件),如果是多个位置 可以采取 与(|) 的方式。
    • xClearOnExit
      • pdTRUE:在运行xEventGroupWaitBits函数之后,自动将uxBitsToWaitFor指定置位过的位置(事件)清除(复原)。举个例子:某个位置(事件)置位(flag 由0变为1),xEventGroupWaitBits函数触发之后,这个位置(事件)自动清除(flag由1变为0)
      • pdFALSE:不会自动清除。
    • xWaitForAllBits
      • pdTRUE:触发逻辑是 逻辑与,即uxBitsToWaitFor中某个位置(事件)置位后,就会触发这个函数。
      • pdFALSE:触发逻辑是 逻辑或,即uxBitsToWaitFor中全部位置(事件)置位后,就会触发这个函数。
    • xTicksToWait:-最大超时时间,单位为系统节拍周期,常量 portTICK_PERIOD_MS 用于辅助把时间转换成 MS。当超过时间后,函数会往下执行,而不是阻塞。
  • 返回值:函数在阻塞过程中,触发了的位置(事件)的数值。
  • 例子:

等待LED 设置事件标志组,LED位置(位0)被触发。

c 复制代码
#define BIT_0 (1 << 0)

EventBits_t bits;
bits = xEventGroupWaitBits(
        eventGroup_led,	// 事件标志组句柄
        BIT_0,			// LED事件在0位置
        pdTRUE,			// 自动清除
        pdFALSE,		// 逻辑与,有置位就触发
        portMAX_DELAY);	// 一直阻塞

if (bits & BIT_0) // 手动判断 是否是LED位置触发
{
    // ... LED 触发后相关逻辑(如:灯亮)
}

7、事件标志组指定位置清零

c 复制代码
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, 
                                  const EventBits_t uxBitsToClear )
  • 函数说明:用句柄指定某事件标志清除。
  • 参数:
    • xEventGroup :事件标志组的句柄
    • uxBitsToClear:指定事件的标志位
  • 返回值:事件组未清除之前的值(状态)。

8、事件标志组指定位置清零(中断)

c 复制代码
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, 
										const EventBits_t uxBitsToClear )
  • 函数说明:用句柄指定某事件标志清除,该函数用在中断。
  • 参数:
    • xEventGroup :事件标志组的句柄
    • uxBitsToClear:指定事件的标志位
  • 返回值:
    • 成功:返回 pdPASS
    • 失败:返回 pdFAIL

注意事项:

​ 若使用xEventGroupSetBitsFromISRxEventGroupClearBitsFromISR等函数,官方要求3个宏定义生效,详细代码如下:

c 复制代码
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )

BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, 
                                     const EventBits_t uxBitsToSet, 
                                     BaseType_t *pxHigherPriorityTaskWoken )
 {
       ........................                                        
                                                                              
}
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
{
       ........................      
}    

需要将上面3个宏定义置位1。


注:以上均为学习笔记!

相关推荐
Porco.w2 小时前
STM32之ESP8266
stm32·单片机·嵌入式硬件
梁洪飞3 小时前
noc 片上网络
linux·arm开发·嵌入式硬件·arm
日更嵌入式的打工仔4 小时前
RS-485通讯协议
笔记·嵌入式硬件
蓝桥_吹雪4 小时前
HAL库深入了解--STM32与GPIO
单片机·嵌入式硬件
嗯嗯=4 小时前
STM32单片机学习篇5
stm32·单片机·学习
不能跑的代码不是好代码4 小时前
STM32:LED共阴/共阳连接与GPIO控制逻辑的关系,如何实现电平转换
stm32·单片机·嵌入式硬件
Jason_zhao_MR5 小时前
YOLO5目标检测方案-基于米尔RK3576开发板
linux·人工智能·嵌入式硬件·目标检测·计算机视觉·目标跟踪·嵌入式
qq_25814297-npl6 小时前
HEX数据00,显示为ASC码,怎么是是\0
单片机
不做无法实现的梦~6 小时前
使用ros2跑mid360的fastlio2建图
git·单片机·嵌入式硬件·gitcode
Joshua-a6 小时前
正点原子DS100示波器测DC电源纹波方法
单片机·嵌入式硬件