当前位置: 首页 > news >正文

FreeRTOS-事件组

学习目标

  1. 理解什么是事件组
  2. 理解事件组标志位
  3. 掌握事件组开发流程

学习内容

概念

在FreeRTOS中,事件组(Event Group)是一种用于任务间同步和通信的机制。事件组允许任务等待和检测多个事件的状态,并在事件发生时进行通知。

事件组由一组标志位(或事件位)组成,每个标志位代表一个特定的事件。任务可以等待某些标志位被置位或清除,也可以设置或清除标志位。

以下是事件组的一些关键概念:

  1. 事件组句柄(Event Group Handle):

事件组句柄是用于标识和操作事件组的变量。它可以在创建事件组时由FreeRTOS分配,也可以通过函数返回。

  1. 标志位(Event Bit):

标志位是事件组中的单个位,它表示一个特定的事件。每个标志位可以被置位或清除,以表示事件发生或未发生。

标志位通常用二进制位来表示,如第0位、第1位等。可以使用位操作函数进行置位和清除操作。

  1. 等待事件(Waiting Events):

任务可以通过等待事件组中的一个或多个标志位来暂停执行,直到这些标志位满足特定的条件。

等待事件可以通过函数如xEventGroupWaitBits()、xEventGroupSync()等实现。

  1. 通知事件(Signaling Events):

任务可以通过设置或清除事件组中的标志位来通知其他任务事件的发生。

通知事件可以通过函数如xEventGroupSetBits()、xEventGroupClearBits()等实现。

通过使用事件组,任务可以进行有效的同步和通信,实现复杂的任务调度和协调。任务可以等待多个事件同时发生,也可以通过设置或清除标志位来触发其他任务的执行。

请注意,事件组是FreeRTOS中的一个特性,具体的使用方法和函数可能因不同的FreeRTOS版本而略有差异。建议参考相关的FreeRTOS文档和参考资料以获取更详细和准确的信息。

事件标志位

  1. 事件标志为一个32位的数字。也就是采用uint32_t来记录事件状态。
  2. 32位的状态分为高8位和低24位。
  3. 高8位位系统级事件和状态,由操作系统自行管理,无需开发人员关系。
  4. 低24位表示24种事件,每1个bit位表示一种事件,由开发人员控制这些事件位。
  5. 低24位中,每一位的取值是0或者1,0表示当前位对应的事件没有触发,1表示当前位的事件触发了。

开发流程

  1. 创建事件组
  2. 开启一个任务,用来等待事件触发
  3. 开启一个任务,用来改变事件触发

事件组标志位像一个订阅中心一样,一方可以订阅事件的触发,一方可以改变事件的状态。

功能介绍

功能

描述

xEventGroupCreate

创建事件组

xEventGroupSetBits

将事件状态改为触发

xEventGroupWaitBits

等待事件触发

创建事件组
EventGroupHandle_t xEventGroupCreate();

返回值为事件组的句柄。

触发事件

将事件状态改为触发

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet )

参数说明:

  1. EventGroupHandle_t xEventGroup:事件组的句柄。
  2. const EventBits_t uxBitsToSet:事件标志位。

返回值:

当前触发的事件有哪些。

等待事件触发
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToWaitFor,const BaseType_t xClearOnExit,const BaseType_t xWaitForAllBits,TickType_t xTicksToWait )

参数说明:

1.EventGroupHandle_t xEventGroup:事件组的句柄。

2.const EventBits_t uxBitsToWaitFor:等待事件组的哪个标志位。可以是多个标志位。例如:     一个标志位(索引为1):0x02

   两个标志位(索引为1和3):0x0A(0x08 + 0x02)

3.const BaseType_t xClearOnExit:等待事件触发后,是否清除这个事件,如果清除,其他的订阅者将不会收到,不清除,就会收到。

 pdTRUE表示清除 

   pdFALSE表示不清除。

4.const BaseType_t xWaitForAllBits:指定是否等待所有的标志位都被设置。

   pdTRUE 表示等待所有标志位都被设置。(都为1)

 pdFALSE 表示只要有任何一个标志位被设置就可以继续执行任务。(任意一个为1)

5.TickType_t xTicksToWait:等待标志位被设置的超时时间,以 FreeRTOS 的 Tick 单位表示。        可以使用 pdMS_TO_TICKS 宏将毫秒转换为 Tick 值。

    如果设置为 portMAX_DELAY,则表示无限等待,直到标志位被设置。

返回值表示已设置的标志位。

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

参数说明:

  1. EventGroupHandle_t xEventGroup:事件组句柄
  2. const EventBits_t uxBitsToSet:要设置的标志位
  3. const EventBits_t uxBitsToWaitFor:要等待的事件标志位
  4. TickType_t xTicksToWait:等待的超时时间
清理事件

案例

开启三个任务,等待事件发生。通过按键触发事件发生。观察效果。

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"#include "event_groups.h"
#include "Usart0.h"#define	EVENT_BIT(N)		(1 << N)
#define EVENT_BIT_0			EVENT_BIT(0)
#define EVENT_BIT_1			EVENT_BIT(1)
#define EVENT_BIT_2			EVENT_BIT(2)
#define EVENT_BIT_3			EVENT_BIT(3)
#define EVENT_BIT_4			EVENT_BIT(4)
#define EVENT_BIT_5			EVENT_BIT(5)
#define EVENT_BIT_6			EVENT_BIT(6)
#define EVENT_BIT_7			EVENT_BIT(7)
#define EVENT_BIT_8			EVENT_BIT(8)
#define EVENT_BIT_9			EVENT_BIT(9)
#define EVENT_BIT_10		EVENT_BIT(10)
#define EVENT_BIT_11		EVENT_BIT(11)
#define EVENT_BIT_12		EVENT_BIT(12)
#define EVENT_BIT_13		EVENT_BIT(13)
#define EVENT_BIT_14		EVENT_BIT(14)
#define EVENT_BIT_15		EVENT_BIT(15)
#define EVENT_BIT_16		EVENT_BIT(16)
#define EVENT_BIT_17		EVENT_BIT(17)
#define EVENT_BIT_18		EVENT_BIT(18)
#define EVENT_BIT_19		EVENT_BIT(19)
#define EVENT_BIT_20		EVENT_BIT(20)
#define EVENT_BIT_21		EVENT_BIT(21)
#define EVENT_BIT_22		EVENT_BIT(22)
#define EVENT_BIT_23		EVENT_BIT(23)TaskHandle_t            task_handler;
TaskHandle_t            task_key_handler;
TaskHandle_t            task1_handler;
TaskHandle_t            task2_handler;
TaskHandle_t            task3_handler;
EventGroupHandle_t			event_group;void task1(void *pvParameters) {EventBits_t bits;while(1) {bits = xEventGroupWaitBits(event_group, EVENT_BIT_0, pdTRUE, pdFALSE, portMAX_DELAY);printf("task1: %d\r\n", bits);vTaskDelay(1000);}vTaskDelete(NULL);
}void task2(void *pvParameters) {EventBits_t bits;while(1) {bits = xEventGroupWaitBits(event_group, EVENT_BIT_0, pdTRUE, pdTRUE, portMAX_DELAY);printf("task2: %d\r\n", bits);vTaskDelay(2000);}vTaskDelete(NULL);
}void task3(void *pvParameters) {EventBits_t bits = 0;while(1) {bits = xEventGroupWaitBits(event_group, EVENT_BIT_0, pdTRUE, pdTRUE, portMAX_DELAY);printf("task3: %d\r\n", bits);vTaskDelay(3000);}vTaskDelete(NULL);
}void task_key(void *pvParameters) {FlagStatus pre_state = RESET;while(1) {FlagStatus state = gpio_input_bit_get(GPIOA, GPIO_PIN_0);if(SET == state && pre_state == RESET) {// 当前高电平, 上一次为低电平,按下pre_state = state;printf("set bit \r\n");xEventGroupSetBits(event_group, EVENT_BIT_0);} else if(RESET == state && pre_state == SET) {// 当前高电平, 上一次为低电平,抬起pre_state = state;}vTaskDelay(20);}
}void start_task(void *pvParameters) {GPIO_config();Usart0_init();event_group = xEventGroupCreate();if(event_group != NULL) {printf("group success\r\n");}taskENTER_CRITICAL();xTaskCreate(task_key, "task_key", 64, NULL, 0, &task_key_handler);xTaskCreate(task1, "task1", 64, NULL, 4, &task1_handler);xTaskCreate(task2, "task2", 64, NULL, 3, &task2_handler);xTaskCreate(task3, "task3", 64, NULL, 2, &task3_handler);vTaskDelete(task_handler);taskEXIT_CRITICAL();
}void Usart0_recv(uint8_t *data, uint32_t len)
{// printf("recv: %s\n", data);xEventGroupSetBitsFromISR(event_group, EVENT_BIT_0, NULL);}static void GPIO_config() {// 时钟初始化rcu_periph_clock_enable(RCU_GPIOA);// 配置GPIO模式gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0);
}int main(void)
{nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);xTaskCreate(start_task, "start_task", 128, NULL, 0, &task_handler);vTaskStartScheduler();while(1) {}
}
http://www.dtcms.com/a/299434.html

相关文章:

  • Cortex-M3内核SysTick定时器介绍
  • `munmap`系统调用及示例
  • 柔性智造:华控智能的垂直整合定制方案
  • 微服务springcloud http客户端feign
  • 伟淼科技李志伟:破解二代接班传承困局,系统性方案破除三代魔咒
  • Redis缓存策略以及bigkey的学习(九)
  • C语言——学习笔记
  • 数据结构(4)单链表算法题(上)
  • Linux DNS 服务器正反向解析
  • 深入分析计算机网络传输层和应用层面试题
  • 从压缩到加水印,如何实现一站式图片处理
  • 编程语言Java——核心技术篇(四)集合类详解
  • 从0开始学linux韦东山教程Linux驱动入门实验班(5)
  • C语言中:形参与实参的那些事
  • 分类预测 | MATLAB实现CPO-SVM冠豪猪算法优化支持向量机分类预测
  • 分类预测 | MATLAB实现DBO-SVM蜣螂算法优化支持向量机分类预测
  • pyskl-Windows系统使用自己的数据集训练(一)
  • 《C++ list 完全指南:从基础到高效使用》
  • 【洛谷】单向链表、队列安排、约瑟夫问题(list相关算法题)
  • 扣子(Coze)宣布开源两大核心项目——Coze Studio(扣子开发平台)和Coze Loop(扣子罗盘),附安装步骤
  • ubuntu下docker安装thingsboard物联网平台详细记录(附每张图)
  • 如何在 Ubuntu 24.04 或 22.04 中创建自定义 Bash 命令
  • 商汤InternLM发布最先进的开源多模态推理模型——Intern-S1
  • 【机器学习深度学习】LLamaFactory微调效果与vllm部署效果不一致如何解决
  • 开源智能体框架(Agent Zero)
  • VLAN的划分(基于华为eNSP)
  • Android 蓝牙学习
  • 使用Netty搭建一个网络聊天室
  • ​P1103 书本整理 - 洛谷​
  • 方正小标宋简3.0,可编辑