FreeRTOS入门教程(事件组概念和函数使用)

文章目录

  • 前言
  • 一、事件组概念
  • 二、事件组和信号量,队列的区别
  • 三、事件组相关函数
  • 三、事件组应用示例
    • 1.等待多个事件
    • 2.任务同步
  • 总结


前言

本篇文章将带大家学习什么是事件组以及如何使用事件组。

一、事件组概念

事件组通常是由一组位(bits)组成的数据结构,其中每一位都对应着某个特定的事件。每个位可以被设置或清除,表示相应的事件发生或未发生。这种位的组合形成了一个类似于二进制数的集合,每个位都代表着某个特定的状态或事件。因此,可以将事件组视为由一系列二进制位构成的数据结构,每个位代表着一个独立的事件状态。

事件组中的每一位可以表示一个特定的事件或状态,任务可以根据这些事件或状态来进行相应的处理。通过设置或清除这些位,可以触发或取消相应的事件处理逻辑。事件组的位通常用于指示某些事件是否发生、是否完成或是否需要进一步处理。这种灵活性使得事件组成为一种强大的工具,用于任务间的同步、通信和协作。

在使用事件组时,可以通过操作单独的位来表示不同的事件或状态,从而实现复杂的任务管理和事件处理。通过适当地设置和清除位,可以实现任务间的协同工作,以满足特定的应用需求。事件组的这种位级别的控制使其成为处理任务间通信和同步的有效工具。

在这里插入图片描述

事件组的位数:

如果 configUSE_16_BIT_TICKS 被设置为 1(启用),则事件组有16位,其中最高的8位(从最高位到第9位)用于内核管理,而剩下的低8位留给用户自定义事件。

如果 configUSE_16_BIT_TICKS 被设置为 0(禁用),则事件组有32位,其中最高的8位(从最高位到第25位)用于内核管理,而剩下的低24位留给用户自定义事件。

二、事件组和信号量,队列的区别

1.事件组(Event Group):

概念:事件组是由多个位组成的数据结构,用于表示多个事件的状态。任务可以等待事件组中的特定位或位组合被设置,从而实现任务同步。

用途:事件组常用于任务间的事件通知和同步。任务可以等待多个事件中的任意一个或多个同时发生,或者等待所有事件都发生后再继续执行。

特点:事件组允许任务等待多个事件,提供了更灵活的同步机制。

2.信号量(Semaphore):

概念:信号量是一个计数器,用于控制多个任务对共享资源的访问。信号量的值表示可用资源的数量,任务可以请求或释放资源,信号量负责追踪可用资源的数量。

用途:信号量常用于控制共享资源的访问,防止多个任务同时访问共享资源,以避免竞争条件(Race Condition)。

特点:信号量是一个计数器,可以用于控制资源的数量和分配。

2.队列(Queue):

概念:队列是一个数据结构,用于在任务间传递数据。任务可以将数据发送到队列,另一个任务则可以从队列中接收这些数据。

用途:队列常用于任务间的数据传递,允许任务异步地发送和接收数据,实现解耦和通信。

特点:队列是一个数据缓冲区,可以用于存储和传递数据,任务间的数据传递是异步的。

区别总结:

事件组用于任务间的事件通知和同步,任务可以等待多个事件的发生。

信号量用于控制对共享资源的访问,防止多个任务同时访问资源。

队列用于任务间的数据传递,任务可以异步地发送和接收数据。

三、事件组相关函数

xEventGroupCreate() - 创建事件组

EventGroupHandle_t xEventGroupCreate(void);

参数:无
返回值:事件组的句柄 (EventGroupHandle_t)
意义:用于创建一个事件组。该函数会返回一个事件组的句柄,以供后续操作。

xEventGroupSetBits() - 设置事件组位

EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet);

参数:
xEventGroup:事件组的句柄
uxBitsToSet:要设置的位,通常使用位掩码来表示要设置的事件位
返回值:设置后的事件组状态,包括所有事件位的当前状态
意义:用于设置事件组的一个或多个位,表示事件发生。可以使用位掩码将要设置的位传递给该函数。

xEventGroupClearBits() - 清除事件组位

EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear);

参数:
xEventGroup:事件组的句柄
uxBitsToClear:要清除的位,通常使用位掩码来表示要清除的事件位
返回值:清除后的事件组状态,包括所有事件位的当前状态
意义:用于清除事件组的一个或多个位,表示事件未发生。可以使用位掩码将要清除的位传递给该函数。

xEventGroupWaitBits() - 等待事件组位的设置

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

参数:
xEventGroup:事件组的句柄
uxBitsToWaitFor:等待的位,通常使用位掩码来表示要等待的事件位
xClearOnExit:指定是否在退出时清除等待的位(可选参数)
xWaitForAllBits:指定是否等待所有位都被设置(可选参数)
xTicksToWait:等待的最大时间(以时钟节拍为单位),如果设置为 0,则将一直等待
返回值:返回事件组的当前状态,包括所有事件位的当前状态
意义:用于等待事件组中的特定位被设置。根据参数的设置,可以选择等待所有位都被设置或只等待其中之一被设置,还可以选择在等待完成后清除等待的位。

xEventGroupSync() 函数用于同步多个任务的操作,使它们能够在相同的时间点上等待一组特定的事件。它通过等待事件组的特定位或位组合被设置来实现同步。

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

参数:

xEventGroup:要同步的事件组的句柄。
uxBitsToSet:需要设置的位,通常使用位掩码来表示要设置的事件位。
uxBitsToWaitFor:需要等待的位,通常使用位掩码来表示要等待的事件位。
xTicksToWait:等待的最大时间(以时钟节拍为单位),如果设置为 0,则将一直等待。
返回值:

该函数返回事件组的当前状态,包括所有事件位的当前状态。

意义:

xEventGroupSync() 函数的目的是等待指定的位被设置,并在这些位被设置时进行同步。

当调用 xEventGroupSync() 函数时,调用任务将等待事件组中的指定位被设置,同时设置另一组位。一旦事件组中的所有指定位都被设置,调用任务将继续执行。

如果超过指定的等待时间(由 xTicksToWait 参数确定),但事件组中的指定位仍未被设置,调用任务将根据超时行为采取相应措施。

通过 xEventGroupSync() 函数,你可以实现任务间的同步操作,确保多个任务在特定事件发生时同时执行。这对于某些需要多任务协作的场景非常有用,例如在任务需要同时开始执行某个操作时,或者需要等待某些条件满足后再执行后续操作时。

三、事件组应用示例

1.等待多个事件

下面的代码创建了三个任务,分别是洗菜,生火,炒菜三个任务,炒菜任务需要等待洗菜和生火两个任务完成后才能够继续执行,否则就阻塞无法执行。

/* 事件组句柄 */
EventGroupHandle_t xEventGroup;/* bit0: 洗菜* bit1: 生火* bit2: 炒菜*/
#define WASHING  (1<<0)
#define FIRING   (1<<1)
#define COOKING  (1<<2)static void vWashingTask( void *pvParameters )
{int i = 0;/* 无限循环 */for( ;; ){printf("I am washing %d time....\r\n", i++);/* 发出事件: 我洗完菜了 */xEventGroupSetBits(xEventGroup, WASHING);	/* 等待大厨炒完菜, 再继续洗菜 */xEventGroupWaitBits(xEventGroup, COOKING, pdTRUE, pdTRUE, portMAX_DELAY);}
}static void vFiringTask( void *pvParameters )
{int i = 0;/* 无限循环 */for( ;; ){/* 等待洗完菜, 才生火 */xEventGroupWaitBits(xEventGroup, WASHING, pdFALSE, pdTRUE, portMAX_DELAY);printf("I am firing %d time....\r\n", i++);/* 发出事件: 我生好火了 */xEventGroupSetBits(xEventGroup, FIRING);			}
}static void vCookingTask( void *pvParameters )
{int i = 0;/* 无限循环 */for( ;; ){/* 等待2件事: 洗菜, 生火 */xEventGroupWaitBits(xEventGroup, WASHING|FIRING, pdTRUE, pdTRUE, portMAX_DELAY);printf("I am cooking %d time....\r\n", i++);/* 发出事件: 我炒好菜了 */xEventGroupSetBits(xEventGroup, COOKING);			}
}//创建事件组
xEventGroup = xEventGroupCreate( );/* 创建3个任务: 洗菜/生火/炒菜
*/
xTaskCreate( vWashingTask, "Task1", 1000, NULL, 1, NULL );
xTaskCreate( vFiringTask,  "Task2", 1000, NULL, 2, NULL );
xTaskCreate( vCookingTask, "Task3", 1000, NULL, 3, NULL );

2.任务同步

#include <FreeRTOS.h>
#include <task.h>
#include <event_groups.h>// 定义事件组句柄
EventGroupHandle_t xEventGroup;// 生产者任务
void vProducerTask(void *pvParameters) {// 生产数据过程for (int i = 1; i <= 5; i++) {// 生产数据,假设为整数 iprintf("Producing data: %d\n", i);xEventGroupSetBits(xEventGroup, 0x01); // 设置位0(表示数据可用)vTaskDelay(1000 / portTICK_PERIOD_MS); // 模拟生产数据需要时间}
}// 消费者任务
void vConsumerTask(void *pvParameters) {// 等待数据可用xEventGroupSync(xEventGroup,0x01,     // 设置位0,表示数据可用0x01,     // 等待位0被设置portMAX_DELAY  // 无限等待);// 开始处理数据printf("Consumer task started!\n");while (1) {// 处理数据printf("Consuming data\n");vTaskDelay(1000 / portTICK_PERIOD_MS); // 模拟处理数据需要时间}
}int main(void) {// 创建事件组xEventGroup = xEventGroupCreate();// 创建生产者任务xTaskCreate(vProducerTask, "Producer", configMINIMAL_STACK_SIZE, NULL, 1, NULL);// 创建消费者任务xTaskCreate(vConsumerTask, "Consumer", configMINIMAL_STACK_SIZE, NULL, 2, NULL);// 启动调度器vTaskStartScheduler();// 这里不会执行,因为任务是永远不会返回的return 0;
}

总结

本篇文章主要给大家讲解了事件组的概念和具体的函数和使用方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/165206.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux下的命令行参数和环境变量

命令行参数 什么是命令行参数 命令行参数是指在执行命令行程序时&#xff0c;给程序传递的额外参数。在Linux终端中&#xff0c;命令行参数通常通过在命令后面添加空格分隔的参数来传递。 Linux下以main函数举例说明 #include<stdio.h>int main(int argc char* argv[])…

Java:ApacheHttpClient连接寿命(timeToLive)未配置问题分析

一、问题描述 若 Apache HttpClient 未设置 timeToLive&#xff0c;通过服务域名访问服务的实例并且服务域名解析出的 IP 发生变化时&#xff0c;在短时间内会有部分请求出现连接异常错误。 二、问题分析 Apache HttpClient 通过服务域名从连接池获取连接&#xff0c;当连接…

[C语言]排序的大乱炖——喵喵的成长记

宝子&#xff0c;你不点个赞吗&#xff1f;不评个论吗&#xff1f;不收个藏吗&#xff1f; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的很重要…

睿趣科技:抖音小店新手运营攻略

随着短视频平台的兴起&#xff0c;抖音已经成为了一个炙手可热的营销工具。越来越多的商家选择在抖音上开设小店&#xff0c;以此来拓展自己的业务。那么&#xff0c;作为新手&#xff0c;如何运营好自己的抖音小店呢?本文将为您提供一些实用的建议。 首先&#xff0c;要明确自…

如何创建高效的 Python Docker 镜像详解

Docker是打包和部署容器中应用程序的行业标准软件。Docker镜像是构建和运行应用程序的基础&#xff0c;为了充分发挥Docker的潜力&#xff0c;您需要优化镜像以提高资源效率、安全性和性能。这将确保您的应用程序在Docker生态系统内无缝运行。 通过一个实际示例来学习如何实现…

Oracle监听服务启动后停止

问题 解决办法 找到listener.ora文件,箭头指的地方&#xff0c;host改为localhost 如何找到listener.ora 其中1522端口&#xff0c;是我新增的监听服务。之前这个host是一个固定的ip地址&#xff0c;我更换网络环境后&#xff0c;ip地址变了&#xff0c;所以导致监听启动失败。…

ChatGPT(1):ChatGPT初识

1 ChatGPT原理 ChatGPT 是基于 GPT-3.5 架构的一个大型语言模型&#xff0c;它的工作原理涵盖了深度学习和自然语言处理技术。以下是 ChatGPT 的工作原理的一些关键要点&#xff1a; 神经网络架构&#xff1a;ChatGPT 的核心是一个深度神经网络&#xff0c;采用了变种的 Tran…

vue-pdf多页预览异常,Rendering cancelled, page 1 Error at BaseExceptionClosure xxx

项目开发使用vue-pdf,单页情况预览正常&#xff0c;多页vue-pdf预览异常&#xff0c;第一次预览时&#xff0c;会先弹出异常模态窗口&#xff0c;关闭模态窗口&#xff0c;pdf又是正常显示&#xff0c;报错信息及异常截图如下&#xff1a; 报错信息 Rendering cancelled, page…

Nginx集群负载均衡配置完整流程

今天&#xff0c;良哥带你来做一个nginx集群的负载均衡配置的完整流程。 一、准备工作 本次搭建的操作系统环境是win11&#xff0c;linux可配置类同。 1&#xff09;首先&#xff0c;下载nginx。 下载地址为&#xff1a;http://nginx.org/en/download.html 良哥下载的是&am…

vulkan SDK安装

文章目录 一. vulcan官网二.安装流程 一. vulcan官网 https://vulkan.lunarg.com/sdk/home#windows 二.安装流程 点击下载 双击下载的*.exe进行安装 点击下一步 点击下一步 选择安装位置&#xff0c;点击下一步 点击全选&#xff0c;选择下一步 勾选同意&#xf…

2023年中国多功能折叠刀产量、销量及市场规模分析[图]

多功能折叠刀是一种集多种功能于一身的刀具&#xff0c;通常包括切割、开瓶、剥皮、锯木等功能&#xff0c;可以通过折叠和展开的方式来实现不同的功能&#xff0c;具有便携、多用途、安全等特点&#xff0c;广泛应用于户外探险、露营、自驾旅行等场景。 多功能折叠刀行业分类…

grafana v10.1版本设置告警

1. 相关概念概述 如图所示&#xff0c;点击切换菜单标志&#xff0c;可以看到警报相关子选项。 警报规则&#xff1a;通过PromQL语句定义告警规则&#xff0c;即达到怎样的状态触发告警。 联络点&#xff1a; 设置当警报规则实例触发时&#xff0c;如何通知联系人&#xff0c;…

使用Perl和WWW::Mechanize库编写

以下是一个使用Perl和WWW::Mechanize库编写的网络爬虫程序的内容。代码必须使用以下代码&#xff1a;jshk.com.cn/get_proxy 首先&#xff0c;确保已经安装了Perl和WWW::Mechanize库。如果没有&#xff0c;请使用以下命令安装&#xff1a; cpan WWW::Mechanize创建一个新的Pe…

代码随想录二刷 Day 44

01背包问题二维做法先遍历背包或者物品都可以&#xff0c;然后是前序遍历&#xff1b; 一维做法一定先遍历物品然后遍历背包&#xff0c;遍历背包的时候是后序遍历&#xff1b;一维做法还是有点难理解&#xff0c;其实就是后面的数字还是要从前面的推导出来&#xff0c;但是如…

安装Apache2.4

二、安装配置Apache&#xff1a; 中文官网&#xff1a;Apache 中文网 官网 (p2hp.com) 我下的是图中那个版本&#xff0c;最新的64位 下载下后解压缩。如解压到D:\tool\Apache24 PS&#xff1a;特别要注意使用的场景和64位还是32位版本 2、修改Apcahe配置文件 2.1配置Apache…

【音视频流媒体】 3、ffmpeg、ffplay、ffprobe 超详细介绍

文章目录 一、ffmpeg1.1 安装1.2 基本参数 二、ffprobe2.1 查编码格式2.2 查视频时长 五、视频转流5.1 MP4转H2645.2 H264转MP45.3 AVI转MP45.4 MP4转H265 六、视频文件6.1 播放6.2 filter 过滤器6.2.1 crop 6.3 视频截取6.4 视频拼接6.5 获取分辨率 七、视频和图7.1 视频抽帧7…

传输层协议(TCP/UDP协议)

全文目录 端口号端口号范围划分 传输层UDP协议特点基于UDP的应用层协议 TCP协议确认应答机制&#xff08;可靠性&#xff09;延迟应答机制超时重传机制流量控制连接管理机制TIME_WAIT 状态CLOSE_WAIT 状态拥塞控制滑动窗口 TCP、UDP对比TCP的listen第二个参数 端口号 在套接字…

jmeter接口测试避坑指南

接口测试看着很简单&#xff0c;但是操作过程中还是出现很多问题&#xff0c;现总结如下&#xff1a; 一、jmeter中乱码问题 可在jmeter.properties 这个文件里面找到sampleresult.default.encodingxx&#xff0c;后面xx改成utf-8&#xff0c;然后取消注释。 解决jmeter的bod…

【RocketMQ系列五】消息示例-顺序消息延迟消息广播消息的实现

1. 前言 上一篇文章我们介绍了简单消息的实现&#xff0c;本文将主要来介绍顺序消息的实现&#xff0c;顺序消息分为局部顺序消息和全局顺序消息。 顺序消息指的是消费者在消费消息时&#xff0c;按照生产者发送消息的顺序进行消费。即先发送的先消费【FIFO】。 顺序消息分为…