FreeRTOS事件标志组

使用信号量来同步的话,任务只能与单个事务或任务进行同步,有时候某个任务可能会需要与多个事件或任务进行同步,此时信号量就无能为力了,FreeRTOS为此提供了一个可选的解决方法,那就是事件标志组。

0x01 事件标志组

事件标志组的数据类型为EventGroupHandle_t,当configUSE_16_BIT_TICKS为1的时候,事件标志组可以存储8个事件位,当configUSE_16_BIT_TICKS设置为0的时候,可以存储24个事件位。事件0存在在bit0上,EventGroupHandle_t变量的位1就是事件1。

0x02 创建事件标志组

FreeRTOS提供了两个用于创建事件标志组的函数

  • xEventGroupCreate():使用动态方法创建事件标志组
  • xEventGroupCreateStatic():使用静态方法创建事件标志组
EventGroupHandle_t xEventGroupCreate( void );
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer );

pxEventGroupBuffer :保存事件标志组结构体
xEventGroupCreate所需要的内存通过动态内存管理方法分配,当configUSE_16_BIT_TICKS为1的时候,事件标志组可以存储8个事件位(bit0-bit7),当configUSE_16_BIT_TICKS设置为0的时候,可以存储24个事件位(bit0-bit23)。

xEventGroupCreateStatic所需要的内存用户自己分配

0x03 设置事件位

FreeRTOS提供了4个函数用来设置事件标志组中事件位,事件位的设置包括清零和置1两种操作

  • xEventGroupClearBits():将指定的事件位清零,用在任务中

  • xEventGroupClearBitsFromISR():将指定的事件位清零,用在中断服务中

  • xEventGroupSetBits():将指定的事件位置1,用在任务中

  • xEventGroupSetBitsFromISR():将指定的事件位置1,用在中断中

EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
  • EventGroupHandle_t xEventGroup:要操作的时间标志组的句柄
  • EventBits_t uxBitsToClear:要清零的事件位,比如要清除bit3的话就设置0x08,可以同时清除多个位,如设置0x09,就同时清除bit3和bit0
	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
  • EventGroupHandle_t xEventGroup:要操作的时间标志组的句柄
  • EventBits_t uxBitsToClear:要清零的事件位,比如要清除bit3的话就设置0x08,可以同时清除多个位,如设置0x09,就同时清除bit3和bit0
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
  • EventGroupHandle_t xEventGroup:要操作的事件标志组的句柄
  • EventBits_t uxBitsToSet:指定要置1的事件位,比如要置bit3为1的话就设置0x08,可以同时设置多个位,如设置0x09,就同时置bit3和bit0为1
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
  • EventGroupHandle_t xEventGroup:要操作的事件标志组的句柄
  • EventBits_t uxBitsToSet:指定要置1的事件位,比如要置bit3为1的话就设置0x08,可以同时设置多个位,如设置0x09,就同时置bit3和bit0为1
  • BaseType_t *pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换,传入pdTRUE在退出中断函数之前一定进行一次任务切换

0x04 获取事件标志组值

FreeRTOS提供了两个API函数用来查询事件标志组值。

  • xEventGroupGetBits():获取当前事件标志组的值(各个事件位的值),用在任务中
  • xEventGroupGetBitsFromISR():获取当前事件标志组的值,用在中断服务函数中
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
  • EventGroupHandle_t xEventGroup :要获取的事件标志组的句柄
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
  • EventGroupHandle_t xEventGroup :要获取的事件标志组的句柄

0x05 等待指定的事件位

某个任务可能需要与多个事件进行同步,那么这个任务就需要等待并判断多个事件位,FreeRTOS提供xEventGroupWaitBits()完成这个功能。如果任务要等待的事件位还没有准备好,任务就会进入阻塞态。

EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
  • EventGroupHandle_t xEventGroup:指定要等待的时间标志组
  • EventBits_t uxBitsToWaitFor:指定要等待的事件位,比如要等待bit0和bit2的时间此参数就是0x05
  • const BaseType_t xClearOnExit:此参数为pdTRUE的话,那么在退出此函数之前由参数uxBitsToWaitFor指定的这些事件位就会清零,如果设置为pdFALSE的话,这些事件位就不会改变。
  • const BaseType_t xWaitForAllBits:此参数如果设置为pdTRUE的话,当uxBitsToWaitFor所设置的这些事件为都置1,或者指定的阻塞时间到的时候xEventGroupWaitBits函数才会返回,当设置为pdFALSE的话,只要uxBitsToWaitFor所设置的这些事件位其中的任意一个置1,或者指定的阻塞时间到的话,函数xEventGroupWaitBits就会返回
  • TickType_t xTicksToWait :设置阻塞时间,单位为节拍数

返回值:
返回当前所等待事件位置1以后的事件标志组的值,或者阻塞时间到,根据这个值,我们就知道哪些事件位置1了,如果函数因为阻塞时间到返回的话,那么这个返回值就不代表任何的含义。

实验

设计四个任务:
start_task:用来创建其他三个任务和事件标志组
eventsetbit_task:读取按键值,根据不同的按键值将事件标志组中相应的事件位置1,用来模拟事件的发生
eventgroup_task:同时等待事件标志组中的多个事件位,当这些事件位都置1的话就将其显示到LCD上,并且也通过串口打印出来

start_task代码:

void start_task(void *pvParameter)
{taskENTER_CRITICAL();EventGroup_Handler=xEventGroupCreate();xTaskCreate(eventsetbit_task,"eventsetbit_task",256,NULL,2,&EventSetBit_Handler);xTaskCreate(eventgroup_task,"eventgroup_task",256,NULL,4,&EventGp_Handler);xTaskCreate(eventquery_task,"eventquery_task",256,NULL,3,&EventQuery_Handler);vTaskDelete(StartTask_Handler);taskEXIT_CRITICAL();
}

创建三个任务和一个事件状态标志组

void eventsetbit_task(void *pvParameter)
{u8 key;while(1){if(EventGroup_Handler!=NULL){key = KEY_Scan(0);switch(key){case KEY1_PRES:xEventGroupSetBits(EventGroup_Handler,2);break;case WKUP_PRES:xEventGroupSetBits(EventGroup_Handler,4);break;}}vTaskDelay(10);}
}

eventsetbit_task检查KEY1和KEY_UP有无按下,KEY1按下将bit1设置为1,KEY_UP按下将bit2设置为1

//中断服务函数
void EXTI3_IRQHandler(void)
{BaseType_t Result,xHigherPriorityTaskWoken;delay_xms(50);						//消抖if(KEY0==0){Result=xEventGroupSetBitsFromISR(EventGroup_Handler,EVENTBIT_0,&xHigherPriorityTaskWoken);if(Result!=pdFAIL){portYIELD_FROM_ISR(xHigherPriorityTaskWoken);}}__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_3);	//清除中断标志位
}

kEY0按下将bit0值1

eventgroup_task检查bit0、bit1、bit2是否都置为1了

void eventgroup_task(void *pvParameter)
{u8 num;EventBits_t EventValue;while(1){if(EventGroup_Handler!=NULL){EventValue=xEventGroupWaitBits(EventGroup_Handler,7,pdTRUE,pdTRUE,portMAX_DELAY);printf("事件标志组的值:%d\r\n",EventValue);LCD_ShowxNum(174,110,EventValue,1,16,0);num++;LED1 = !LED1;LCD_Fill(6,131,233,313,lcd_discolor[num%14]);}else{vTaskDelay(10);}}}

查询当前的事件标志组的值,然后显示出来

void eventquery_task(void *pvParameter)
{u8 num=0;EventBits_t NewValue,LastValue;while(1){if(EventGroup_Handler!=NULL){NewValue=xEventGroupGetBits(EventGroup_Handler);if(NewValue!=LastValue){LastValue = NewValue;printf("事件标志组的值: %d\r\n",NewValue);LCD_ShowxNum(174,110,NewValue,1,16,0);}}num++;if(num==0){num=0;LED0 = !LED0;}vTaskDelay(50);}
}

在这里插入图片描述

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

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

相关文章

FusionCharts等产品简介

以前做柱状图、饼形图等图表都是根据数据绘制出来的静态图,偶然看到别人的一套系统,居然可以让柱状图的柱子动画般的逐个出现,效果还是很不错的。不要跟我抬杠说不就是展现数据嘛,静态图表有什么不好,要知道用户一般可…

Eclipse和Tomcat绑定并且将上传资源到Tomcat上

步骤如下: 创建一个Dynamic Web Project(图一) Target runtime 选择Apache Tomcat v7.0版本(图二) 切记要选择 v7.0 和2.5 (若没有图二选项见图三) 然后,点击window --> Prefer…

FreeRTOS任务通知

从v8.2.0版本开始,FreeRTOS新增了任务通知这个功能,可以使用任务通知来代替信号量、消息队列、事件标志组等这些东西,使用任务通知的话效率会更高。 任务通知在FreeRTOS是一个可选的选项,要使用任务通知的话就需要将宏configUSE_T…

kinect在openni下也能玩抠出人物换背景

之前想了个很拉风的名字《用kinect玩穿越》,但是现在功能还不是很完善,细节处理也不是很好,脸皮没有足够的厚,所以呢还是叫换背景吧。 这里面包含两个技术要点: 一、抠出活动人物 在微软的SDK里深度图像的前3位即0-2位…

Emit学习-基础篇-基本概念介绍

之前的Hello World例子应该已经让我们对Emit有了一个模糊的了解,那么Emit到底是什么样一个东西,他又能实现些什么功能呢?昨天查了点资料,大致总结了下,由于才开始学习肯定有不完善的地方,希望大家能够批评指…

The FreeRTOS Distribution(介绍、移植、类型定义)

1 Understand the FreeRTOS Distribution 1.1 Definition :FreeRTOS Port FreeRTOS目前可以在20种不同的编译器构建,并且可以在30多种不同的处理器架构上运行,每个受支持的编译器和处理器组合被认为是一个单独的FreeRTOS Port。 1.2 Build…

Eclipse项目左上角出现大红色感叹号怎么办?

出现大红色感叹号是因为环境不匹配 解决方法: 右击出现大红色感叹号的项目 点击 Libraries,将有叉号的给Remove掉 然后再点击 Add Library —> JRE System Library —> Next 勾选第二个即可 之后,就不会出现大红色感叹号了。

PCB---STM32最小系统制作过程

PCB 制作过程STM32核心模块连接外部电源晶振OSC_IN(8MHz)OSC32_IN(32.768MHz)复位下载口BOOT模式电源模块添加功能UARTWKUPSTM32核心模块 这里我们以STM32F103C8T6为列,先将芯片的原理图放到原理图中 对于STM32,有几个模块是核心&#xff0…

FreeRTOS---堆内存管理(一)

FreeRTOS的堆内存管理简介动态内存分配及其与 FreeRTOS 的相关性动态内存分配选项内存分配方案Heap_1heap_2Heap_3Heap_4设置heap_4的起始地址Heap_5vPortDefineHeapRegions()堆相关的函数xPortGetFreeHeapSizexPortGetMinimumEverFreeHeapSizeMalloc调用失败的Hook函数这篇文章…

FreeRTOS--堆内存管理(二)

堆内存管理代码具体实现heap_1内存申请函数内存释放函数heap_2内存块内存堆初始化函数内存块插入函数内存申请函数判断是不是第一次申请内存开始分配内存内存释放函数heap_3heap_4内存堆初始化函数内存块插入函数heap_5上一篇文章说了FreeRTOS实现堆内存的原理,这一…

css中的node.js_在Node App中使用基本HTML,CSS和JavaScript

css中的node.jsYou may think this is not important, but it is!. As a beginner in node.js, most coding exercises are always server sided. 您可能认为这并不重要,但确实如此! 作为node.js的初学者,大多数编码练习始终都是服务器端的。…

Binary String Matching(C++)

题目描述: Given two strings A and B, whose alphabet consist only ‘0’ and ‘1’. Your task is only to tell how many times does A appear as a substring of B? For example, the text string B is ‘1001110110’ while the pattern string A is ‘11’, you should…

VisualStudio2019配置OpenCV

VisualStudio2019配置OpenCV配置0x01 准备0x02 配置系统环境0x03 复制文件0x04 配置VisualStudio2019测试配置 0x01 准备 下载opencv,官网地址:https://opencv.org/releases/# 下载之后,自行安装 0x02 配置系统环境 找到高级系统设置 …

Visual Studio进行linux远程开发

目录准备工作创建一个项目配置远程项目准备工作 查看linux IP地址 安装了工具 sudo apt-get install openssh-server g gdb make ninja-build rsync zip开启ssh服务: sudo service ssh startVS2019按装了linux功能,如果没有,找到Visual S…

在给定总和K的二叉树中找到级别

Description: 描述: The article describes how to find the level in a binary tree with given sum K? This is an interview coding problem came in Samsung, Microsoft. 本文介绍了如何在给定总和K下在二叉树中找到级别 ? 这是一个面试编码问题&a…

++i与i++的根本性区别(两个代码对比搞定)

首先来看i 代码如下&#xff1a; #include <stdio.h> #include <stdlib.h> int main() {int i0;int ai;printf("%d\n",a);printf("%d\n\n\n",i);return 0; }输出结果如下&#xff1a; 解释&#xff1a;i其实是两行代码的简写形式&#xff0c…

Python | 使用matplotlib.pyplot创建线图

Problem statement: Write a program in python (using matplotlib.pyplot) to create a line plot. 问题陈述&#xff1a;用python编写程序(使用matplotlib.pyplot)以创建线图。 Program: 程序&#xff1a; import matplotlib.pyplot as pltx [1,2,3,4,5,6,7,8,9,10]y [3,…

linux内核设计与实现---从内核出发

获取、编译、安装内核1 获取内核源码安装内核源代码何处安装源码使用补丁2 内核源码树3 编译内核减少编译的垃圾信息衍生多个编译作业安装内核启用指定内核作为引导4 内核开发的特点没有libc库头文件没有内存保护机制容积小而固定的栈1 获取内核源码 在linux内核官方网站http:…

linux内核设计与实现---进程管理

进程管理1 进程描述符及任务结构分配进程描述符进程描述符的存放进程状态设置当前进程状态进程上下文进程家族树2 进程创建写时拷贝fork()vfork()3 线程在Linux中的实现内核线程4 进程终结删除进程描述符孤儿进程造成的进退微谷5 小结进程的另一个名字叫做任务&#xff08;task…

生日蜡烛(蓝桥杯)

某君从某年开始每年都举办一次生日party&#xff0c;并且每次都要吹熄与年龄相同根数的蜡烛。 现在算起来&#xff0c;他一共吹熄了236根蜡烛。 请问&#xff0c;他从多少岁开始过生日party的&#xff1f; 请填写他开始过生日party的年龄数。 注意&#xff1a;你提交的应该是…