STM32FreeRTOS-事件组1(STM32Cube高效开发教程)

news2024/11/18 23:31:07

文章目录

  • 一、事件组的原理和功能
    • 1、事件组与队列信号量特点
    • 2、事件组存储结构
    • 3、事件组运行原理
  • 二、事件组部分函数
    • 1、xEventGroupCreate()创建事件组函数
    • 2、xEventGroupSetBits()事件组置位函数
    • 3、xEventGroupSetBitsFromISR()事件组置位函数ISR版本
    • 4、xEventGroupClearBits()事件位清零函数
    • 5、xEventGroupClearBitsFromISR()事件位清零函数ISR版本
    • 6、xEventGroupGetBits()读取事件组当前的值
    • 7、xEventGroupWaitBits()等待事件组成立

一、事件组的原理和功能

1、事件组与队列信号量特点

事件组是FreeRTOS中的一种对象,且FreeRTOS默认就可以使用事件组,无需设置相关参数,但是使用之前需要使用创建函数创建事件组对象。
在这里插入图片描述
事件标志组与队列信号量的区别:
在这里插入图片描述

2、事件组存储结构

事件组有一个内部变量存储事件标志,当configUSE_16_BIT_TICKS为0时,这个变量是32位的,否则是16位的,在STM32上处理器上是32位的。

使用了32位无符号的数据类型变量来存储事件标志,但其中的高8位用作存储事件标志组的控制信息,低24位用作存储事件标志,所以说一个事件组最多可以存储 24 个事件标志!
在这里插入图片描述

一个事件组中的所有事件位保存在一个EventBits_t类型的变量里,所以一个事件又称为一个“事件位”
在这里插入图片描述

3、事件组运行原理

在这里插入图片描述

(1)设置事件组中的位与某个事件对应,检测到事件发生时将相应的位置1,表示事件发生了。
(2)可以有1个或多个任务等待事件组中的事件发生,可以是各个事件都发生(事件位的与运算),或某个事件发生(事件位的或运算)。
(3)假设图中的Task1和Task2都以阻塞状态等待两个事件都发生,当Bit2和Bit0都被置为1后(不分先后顺序),两个任务都会被解除阻塞状态。所以 事件组具有广播功能。
在这里插入图片描述

二、事件组部分函数

函数所在文件如下图所示:
在这里插入图片描述

1、xEventGroupCreate()创建事件组函数

以动态分配内存方式创建事件组,无参数,返回值是创建的事件组句柄变量(一个指针变量),其他函数在操作事件组时都使用事件组句柄变量作为输入参数。
在这里插入图片描述
返回值类型EventGroupHandle_t的定义如下:
在这里插入图片描述
在这里插入图片描述

2、xEventGroupSetBits()事件组置位函数

在这里插入图片描述

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;

参数1:要操作的事件组句柄
参数2:要置位的事件位掩码
返回值:置位成功后事件组当前的值

类型EventBits_t的定义如下,也就是TickType_t,在STM32处理器上,等同于类型uint32_t

被置位的事件位为1,未被置位的事件位为0,一个事件只对应事件组中的一个事件位,一个事件发生只需要置位一个事件位
在这里插入图片描述

需要置位事件组中的bit7,则位掩码是0x80
需要置位事件组中的bit0,则位掩码是0x01
同时置位事件组中的bit7和bit0,则位掩码是0x81
官方代码段举例:

Example usage:

	//想要置位哪一个事件位通过宏定义操作即可
   #define BIT_0	( 1 << 0 ) //宏定义:置位bit0对应的事件位
   #define BIT_4	( 1 << 4 ) //宏定义:置位bit4对应的事件位


   void aFunction( EventGroupHandle_t xEventGroup )
   {
  		 EventBits_t uxBits; //存放置位函数返回值

		//使用时间位0和事件位4进行置位操作
		//对两个事件位的宏定义进行或操作,就是同时对两个位进行置位(也就是传递的参数2位掩码)
	
		// Set bit 0 and bit 4 in xEventGroup.
		//位掩码是0x11
		uxBits = xEventGroupSetBits(
							xEventGroup,	// The event group being updated.
							BIT_0 | BIT_4 );// The bits being set.
			

		//函数返回值是置位成功后事件组当前的数值
			
		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )//bit0和bit4同时被置位	
		{
			// Both bit 0 and bit 4 remained set when the function returned.
		}
		
		else if( ( uxBits & BIT_0 ) != 0 )//bit0被置位
		{
			// Bit 0 remained set when the function returned, but bit 4 was
			// cleared.  It might be that bit 4 was cleared automatically as a
			// task that was waiting for bit 4 was removed from the Blocked
			// state.
		}
		else if( ( uxBits & BIT_4 ) != 0 )//bit4被置位
		{
			// Bit 4 remained set when the function returned, but bit 0 was
			// cleared.  It might be that bit 0 was cleared automatically as a
			// task that was waiting for bit 0 was removed from the Blocked
			// state.
		}
		else//bit0和bit4均没有被置位
		{
			// Neither bit 0 nor bit 4 remained set.  It might be that a task
			// was waiting for both of the bits to be set, and the bits were
			// cleared as the task left the Blocked state.
		}
   }

3、xEventGroupSetBitsFromISR()事件组置位函数ISR版本

ISR版本相对于任务版本多了最后一个参数:是否需要进行上下文切换的申请
根据参数configUSE_TRACE_FACILITY数值为1或0分为以下两个版本

#if( configUSE_TRACE_FACILITY == 1 )
	BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#else
	#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
#endif

默认的函数原型:
pxHigherPriorityTaskWoken是指针BaseType_t*,是一个返回值(pdTRUE或pdFALSE),表示在退出ISR函数前是否需要申请进行一次任务调度。

BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
									const EventBits_t uxBitsToSet, 
									BaseType_t *pxHigherPriorityTaskWoken );
/*
参数1:事件组句柄
参数2:置位掩码
参数3:退出ISR时是否需要上下文切换
*/
//示意代码如下:
BaseType_t highTaskWoken =pdFALSE;
xEventGroupSetBitsFromISR(xEventGroup, uxBitsToSet, &highTaskWoken);
portYIELD_FROM_ISR(highTaskWoken); //申请进行一次任务调度

Freeertos不允许中断或临界代码段进行不确定的操作,在ISR中进行事件组置位操作时FreeRTOS实际上向定时器守护任务发送了一个消息,将事件组置位操作延后到定时器守护任务里执行。
如果定时器优先值高于当前执行的任务,返回pdtrue,否则返回pdfalse
根据pdtrue手动的进行一次上下文切换,这个函数返回pdtrue表明延后处理的消息成功的发送给了定时器守护任务,当定时器守护任务的队列消息满时,函数会无法接收到新的消息,返回值为pdfalse

4、xEventGroupClearBits()事件位清零函数

函数xEventGroupClearBits()用于在任务函数中将事件组的某些事件位清零,其函数原型是

EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, 
								const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;


参数1:事件组句柄
参数2:要清零的事件位掩码(掩码意义与事件位置位中一样)
返回值:事件位被清零之前的事件组的值

uxBitsToClear是需要清零的事件位的掩码, 需要清零的位设置为1。
将bit0和bit4清零
在这里插入图片描述

5、xEventGroupClearBitsFromISR()事件位清零函数ISR版本

#if( configUSE_TRACE_FACILITY == 1 )
	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
#else
	#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )
#endif

在ISR函数中的事件位清零操作会被延后到定时器守护任务(timer daemon task) 中去处理,函数的返回值为pdTRUE或pdFALSE,如果返回值为pdTRUE表示延后处理的消息成功发送给了定时器守护任务,否则就是没有成功发送。

6、xEventGroupGetBits()读取事件组当前的值

传入事件组句柄(不清空任何位)
在这里插入图片描述

它实际上就是执行了函数xEventGroupClearBits(),只是传递的事件位掩码是0,也就是不清除任何事件位,而返回事件组当前的值
在这里插入图片描述

7、xEventGroupWaitBits()等待事件组成立

函数xEventGroupWaitBits()使当前任务进入阻塞状态,以等待事件组中多个事件位表示的事件成立时再退出阻塞状态。
事件组成立的条件可以是多个事件位都被置位(逻辑与运算) ,或其中某个事件位被置位(逻辑或运算)

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

/*
参数1:事件组句柄
参数2:所等待事件位的掩码(如果需要等待某个事件位置1,掩码中相应的位就设置为1)
参数3:设定值为pdTRUE或pdFALSE,退出时是否清除掩码位(清零)
	pdTRUE则表明在事件组条件成立退出阻塞状态时,会将参数2掩码中指定的所有位全部清零
	如果函数因为超时退出阻塞状态,即使设置为pdTRUE也不会将掩码事件位清零
参数4:设定值为pdTRUE或pdFALSE,是否等待所有位置位(所有同时成立还是某一个成立即可)
	pdTRUE表示事件位全部置1条件成立(逻辑与运算),否则任意一个置1条件成立(逻辑或运算)
	当事件条件成立时,函数就会退出,任务退出阻塞态
参数5:超时阻塞时间

返回值:
*/

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PCM会重塑汽车OTA格局吗(2)

目录 1.概述 2. PCM技术视角下的OTA 3.小结 1.概述 上一篇文章&#xff0c;我们着重讲解了OTA的概述内容&#xff0c;和意法半导体推出的跨域融合MCU的四大特征&#xff0c;其中就包含了OTA技术。 他们针对OTA做了比较创新的设计&#xff0c;在总的可用memory容量不变情况…

【go语言开发】yaml文件配置和解析

本文主要介绍使用第三方库来对yaml文件配置和解析。首先安装yaml依赖库&#xff1b;然后yaml文件中配置各项值&#xff0c;并给出demo参考&#xff1b;最后解析yaml文件&#xff0c;由于yaml文件的配置在全局中可能需要&#xff0c;可定义全局变量Config&#xff0c;便于调用 文…

【基于HTML5的网页设计及应用】——float实现页面布局

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

Nodejs 第五十章(lua的基本使用)

lua基本使用 全局变量局部变量 全局变量是在全局作用域中定义的变量&#xff0c;可以在脚本的任何地方访问。全局变量在定义时不需要使用关键字&#xff0c;直接赋值即可。 xiaoman xmzsprint(xiaoman)局部变量是在特定作用域内定义的变量&#xff0c;只能在其所属的作用域…

MySQL从入门到实战

MySQL从入门到实战 1.连接数据库 在操作数据库之前&#xff0c;需要连接它&#xff0c;输入命令&#xff1a;mysql -u用户名 -p密码。 2.创建数据库 创建完数据库之后我们可以通过show databases;命令查看MySQL中已存在的数据库。[请注意&#xff1a;数据库名区分大小写。] 3…

什么是聚簇索引与非聚集索引和区别?

什么是聚簇索引与非聚集索引和区别? 按物理存储分类:InnoDB的存储方式是聚集索引&#xff0c;MVISAM的存储方式是非聚集索引 test innodb.frm 测试 innodb.ibd Frame表结构 数据表索引数据 test myisam.frm ---->Frame表结构test myisam.MYD_---数据表数据test_myisam.MYl-…

vue-路由跳转和路由传参!!!

需求&#xff1a;在修改商品时&#xff0c;会进行页面跳转&#xff0c;通过点击修改按钮进行页面跳转。这时我们需要将商品的id携带过去 一、首先我们在查询页面实现路由跳转并携带参数。 1.1、修改按钮 <el-button type"primary" size"small" click&qu…

【排序】详解归并排序

一、思想 归并排序的核心思想是分治法&#xff0c;即将大问题分解成小问题来解决&#xff0c;然后再将解决后的小问题的结果合并以解决原来的大问题。具体包括以下几个步骤&#xff1a; 分解&#xff08;Divide&#xff09;&#xff1a;将原始数组不断地二分成更小的子数组&a…

黑马点评-优惠券秒杀业务

全局唯一ID 每个店铺都可以发布同类优惠券&#xff0c;当用户抢购时&#xff0c;就会生成订单并保存到tb_voucher_order这张表中&#xff0c;而订单表如果使用数据库自增ID就存在一些问题&#xff1a; 如果我们的id具有太明显的规则&#xff0c;用户或者说商业对手很容易猜测…

【教3妹学编程-算法题】超过阈值的最少操作数 II

2哥 : 叮铃铃&#xff0c;3妹&#xff0c;准备复工了啊&#xff0c;过年干嘛呢&#xff0c;是不是逛吃逛吃&#xff0c;有没有长胖呢。 3妹&#xff1a;切&#xff0c;不想上班&#xff0c;假期能不能重来一遍啊&#xff0c;虽然在家我妈张罗着要给我相亲呢。可是在家还是很好的…

基于springboot+vue的精简博客系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

数据结构中红黑树的概念以及代码

红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉搜索树&#xff0c;它在插入和删除节点时通过一系列的旋转和重新着色操作来保持平衡。红黑树的平衡性质使得它的查找、插入和删除操作的时间复杂度都能保持在 O(log n) 红黑树的定义如下&#xff1a; 每个节点要…

帝国CMS仿某猫办公PPT模板商城整站素材资源下载网站源码带手机端优化版

适合做创意设计模板下载的网站&#xff0c;涵盖行业优质精品PPT模板、视频素材、Word模板、Excel模板、音效及配乐素材等&#xff0c;集办公设计模板于一体&#xff0c;下载办公创意设计模板就选择这块源码&#xff01; 源码下载地址&#xff1a;帝国CMS仿某猫办公PPT模板商城…

基于laspy的点云数据存取及基于Open3D的点云数据可视化

一、基于laspy的点云数据存取 &#xff08;一&#xff09;激光雷达点云数据的LAS存储格式[1] LAS&#xff08;LASer&#xff09;格式是一种为激光雷达点云数据的交换和存档而设计的文件格式&#xff0c;是一种被American Society for Photogrammetry and Remote Sensing&#…

Claude 3正式发布,超越GPT-4,一口气读15万单词,OpenAI最强的大对手!

目录 多模态AI大模型Claude 3&#xff08;https://www.anthropic.com/news/claude-3-family&#xff09;Claude 3 的三个版本新增功能&#xff0c;chatgpt没有的使用成本总结 多模态AI大模型Claude 3&#xff08;https://www.anthropic.com/news/claude-3-family&#xff09; …

C# 中 TryParse 将字符串转换为特定类型的方法

在 C# 中&#xff0c;TryParse 是一个用于将字符串转换为特定类型的方法。它用于尝试解析字符串并将其转换为指定类型的值&#xff0c;而不会引发异常。如果解析成功&#xff0c;它将返回 true 并将解析结果存储在输出参数中&#xff1b;如果解析失败&#xff0c;它将返回 fals…

分析开源机器学习框架TensorFlow

TensorFlow是一个开源的机器学习框架&#xff0c;由Google开发和维护。它提供了一个灵活的编程环境&#xff0c;可用于构建和训练各种机器学习模型。TensorFlow的基本概念和使用场景如下&#xff1a; 张量&#xff08;Tensor&#xff09;&#xff1a;在TensorFlow中&#xff0c…

FairTune:优化参数高效微调以实现医学图像分析的公平性

paper&#xff1a;https://arxiv.org/abs/2310.05055 code&#xff1a; https://github.com/Raman1121/FairTune 摘要和介绍 人工智能在医疗健康应用中的应用正在迅速增长。然而&#xff0c;人工智能模型一再被证明对不同的人口统计学亚群体表现出不必要的偏见——AI模型在由…

《 前端挑战与未来:如何看待“前端已死”》

在技术领域,时常会有一些激进的言论引发热议,比如近年来不少人声称“前端已死”。这样的言论引发了广泛的讨论和反思。本文将从几个方向探讨这个话题:为什么会出现“前端已死”的言论、如何看待这种说法、前端技术的未来发展趋势以及前端人如何应对这场职位突围战。 为什么会…

超级副业SOP,各行各业,太全了!

最近收集到一份资料&#xff0c;包含了几乎各行各业的SOP&#xff0c;实在是太全了&#xff0c;这里准备分享给大家 这里可能有一些朋友还不知道&#xff0c;SOP是个什么东西呢 百度说法&#xff1a;所谓SOP&#xff0c;是 Standard Operating Procedure三个单词中首字母的大写…