FreeRTOS从入门到精通 第十五章(事件标志组)

参考教程:【正点原子】手把手教你学FreeRTOS实时系统_哔哩哔哩_bilibili

一、事件标志组简介

1、概述

(1)事件标志位是一个“位”,用来表示事件是否发生。

(2)事件标志组是一组事件标志位的集合,可以简单的理解事件标志组,是一个整数。

(3)事件标志组的特点:

①每一个位与一个事件相关联,高8位除外,高8位用作存储事件标志组的控制信息。(下图所示的是32 位长度的事件标志组)

②每一位事件的含义,以及高电平和低电平分别代表什么,由用户自己决定。

③任意任务或中断都可以读写这些位。

④可以等待某一位成立,或者等待多位同时成立。

(4)一个事件组就包含了一个EventBits_t数据类型的变量,变量类型EventBits_t的定义如下所示,它实际上是一个16位或32位无符号的数据类型。

typedef TickType_t EventBits_t;
#if ( configUSE_16_BIT_TICKS == 1 )typedef  uint16_t  TickType_t;
#elsetypedef  uint32_t  TickType_t;
#endif
#define  configUSE_16_BIT_TICKS    0 

(5)事件标志组与队列、信号量的区别:

功能

唤醒对象

事件清除

队列、信号量

事件发生时,只会唤醒一个任务

是消耗型的资源,队列的数据被读走就没了;信号量被获取后就减少了

事件标志组

事件发生时,会唤醒所有符合条件的任务,可以理解为“广播”的作用

被唤醒的任务有两个选择,可以让事件保留不动,也可以清除事件

2、事件标志组相关API函数介绍

(1)事件标志组相关API函数概览:

函数

描述

xEventGroupCreate()

使用动态方式创建事件标志组

xEventGroupCreateStatic()

使用静态方式创建事件标志组

xEventGroupClearBits()

清零事件标志位

xEventGroupClearBitsFromISR()

在中断中清零事件标志位

xEventGroupSetBits()

设置事件标志位

xEventGroupSetBitsFromISR()

在中断中设置事件标志位

xEventGroupWaitBits()

等待事件标志位

xEventGroupSync()

设置事件标志位,并等待另一个事件标志位【A事件完成,同时还要等待B事件发生】

(2)xEventGroupCreate函数:

①函数定义:

EventGroupHandle_t xEventGroupCreate
(void
)

②返回值:

返回值

描述

NULL 

事件标志组创建失败

其它值 

事件标志组创建成功,返回其句柄

(3)xEventGroupClearBits函数:

①函数定义:

EventBits_t  xEventGroupClearBits
(EventGroupHandle_t 	xEventGroup,const EventBits_t 		uxBitsToClear
) 

②函数参数:

形参

描述

xEventGroup 

待操作的事件标志组句柄

uxBitsToSet 

待清零的事件标志位

③返回值:

返回值

描述

整数 

清零事件标志位之前事件组中事件标志位的值

(4)xEventGroupSetBits函数:

①函数定义:

EventBits_t  xEventGroupSetBits
(EventGroupHandle_t 	xEventGroup,const EventBits_t 		uxBitsToClear
) 

②函数参数:

形参

描述

xEventGroup 

待操作的事件标志组句柄

uxBitsToSet 

待设置的事件标志位

③返回值:

返回值

描述

整数 

函数返回时,事件组中的事件标志位值

(5)xEventGroupWaitBits函数:

①函数定义:

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

②函数参数:

形参

描述

xEvenrGroup

等待的事件标志组句柄

uxBitsToWaitFor

等待的事件标志位,可以用逻辑或等待多个事件标志位

xClearOnExit

成功等待到事件标志位后,清除事件组中对应的事件标志位,

pdTRUE  :清除uxBitsToWaitFor指定位;

pdFALSE:不清除

xWaitForAllBits

等待 uxBitsToWaitFor 中的所有事件标志位(逻辑与)

pdTRUE:等待的位,全部为1

pdFALSE:等待的位,某个为1

xTicksToWait

等待的阻塞时间

③返回值:

返回值

描述

等待的事件标志位值 

等待事件标志位成功,返回等待到的事件标志位

其它值 

等待事件标志位失败,返回事件组中的事件标志位

(6)xEventGroupSync函数:

①函数定义:

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

②函数参数:

形参

描述

xEventGroup 

等待事件标志所在事件组

uxBitsToSet 

达到同步点后,要设置的事件标志

uxBitsToWaitFor 

等待的事件标志

xTicksToWait 

等待的阻塞时间

③返回值:

返回值

描述

等待的事件标志位值 

等待事件标志位成功,返回等待到的事件标志位

其它值 

等待事件标志位失败,返回事件组中的事件标志位

二、事件标志组实验

1、原理图与实验目标

(1)原理图(串口外设的接法与列表项的插入和删除实验相同,下图未示出):

(2)实验目标:

①设计3个任务——start_task、task1、task2:

[1]start_task:用于创建其它三个任务,并创建事件标志组。

[2]task1:读取按键按下键值,根据不同键值将事件标志组相应事件位置1,模拟事件发生(按下某个按键,对应的标志位置1)。

[3]task2:同时等待事件标志组中的多个事件位,当这些事件位都置1的话就执行相应的处理(串口打印信息),同时清除标志位。

②预期实验现象:

[1]程序下载到板子上后,暂时没有任何现象。

[2]按下相关按键,串口会输出相应的信息。

2、实验步骤

(1)将“队列集操作实验”的工程文件夹复制一份,在拷贝版中进行实验。

(2)更改FreeRTOS_experiment.c文件的内容,如下所示。

#include "FreeRTOS.h"
#include "task.h"
#include "LED.h"
#include "Key.h"
#include "Serial.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"//宏定义
#define START_TASK_STACK_SIZE 128   //start_task任务的堆栈大小
#define START_TASK_PRIO       1     //start_task任务的优先级
#define TASK1_STACK_SIZE      128   //task1任务的堆栈大小
#define TASK1_PRIO            2     //task1任务的优先级
#define TASK2_STACK_SIZE      128   //task2任务的堆栈大小
#define TASK2_PRIO            3     //task2任务的优先级#define EVENTBIT_0  (1 << 0)  //用该宏时表示希望事件标志组的bit0位置为1
#define EVENTBIT_1  (1 << 1)  //用该宏时表示希望事件标志组的bit1位置为1EventGroupHandle_t  eventgroup_handle;   //定义事件标志组句柄//任务函数声明
void start_task(void);
void task1(void);
void task2(void);//任务句柄
TaskHandle_t start_task_handler;    //start_task任务的句柄
TaskHandle_t task1_handler;         //task1任务的句柄
TaskHandle_t task2_handler;         //task2任务的句柄QueueSetHandle_t queueset_handle;void FreeRTOS_Test(void)
{//创建任务start_taskxTaskCreate((TaskFunction_t)start_task,            //指向任务函数的指针"start_task",                       //任务名字START_TASK_STACK_SIZE,       //任务堆栈大小,单位为字NULL,                          //传递给任务函数的参数START_TASK_PRIO,              //任务优先级(TaskHandle_t *) &start_task_handler  //任务句柄,就是任务的任务控制块);//开启任务调度器vTaskStartScheduler();
}void start_task(void)
{taskENTER_CRITICAL();eventgroup_handle = xEventGroupCreate();         //创建事件标志组if(eventgroup_handle != NULL){Serial_Printf("事件标志组创建成功!!\r\n");}xTaskCreate((TaskFunction_t)                  task1,(char *)                        "task1",(configSTACK_DEPTH_TYPE)    TASK1_STACK_SIZE,(void *)                        NULL,(UBaseType_t)                  TASK1_PRIO,(TaskHandle_t *)                &task1_handler );xTaskCreate((TaskFunction_t)                  task2,(char *)                        "task2",(configSTACK_DEPTH_TYPE)    TASK2_STACK_SIZE,(void *)                        NULL,(UBaseType_t)                  TASK2_PRIO,(TaskHandle_t *)                &task2_handler );vTaskDelete(NULL);taskEXIT_CRITICAL();
}void task1(void)
{uint8_t key = 0;while(1) {key = Key_GetNum();if(key == 1){//将事件标志组的bit0位置1xEventGroupSetBits(eventgroup_handle, EVENTBIT_0);}else if(key == 2){//将事件标志组的bit1位置1xEventGroupSetBits(eventgroup_handle, EVENTBIT_1);}vTaskDelay(10);}
}void task2(void)
{EventBits_t event_bit = 0;while(1){event_bit = xEventGroupWaitBits(eventgroup_handle,         //事件标志组句柄EVENTBIT_0 | EVENTBIT_1,  //等待事件标志组的bit0和bit1位均置1pdTRUE,      //等待到事件标志位后,清除事件标志组的bit0和bit1位pdTRUE,      //等待事件标志组的bit0和bit1位都置1,就成立portMAX_DELAY );           //死等Serial_Printf("等待到的事件标志位值为:%#x\r\n",event_bit);}
}

(3)程序完善好后点击“编译”,然后将程序下载到开发板上,打开串口助手分析信息。

3、程序执行流程

(1)main函数全流程:

①初始化串口模块。

②调用FreeRTOS_Test函数。

(2)测试函数全流程:

①创建任务start_task。

②开启任务调度器。

(3)多任务调度执行阶段较为简单,这里不再赘述。

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

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

相关文章

Leetcode:541

1&#xff0c;题目 2&#xff0c;思路 用List集合来装字符串其中每k个为一个元素单位我们根据题目意思就可以明白list中偶数位需要反转reverse&#xff0c;奇数保持原样再全部拼接一块最后return tostring 3&#xff0c;代码 import java.util.ArrayList; import java.util.…

C语言指针专题四 -- 多级指针

目录 1. 多级指针的核心原理 1. 多级指针的定义 2. 内存结构示意图 3. 多级指针的用途 2. 编程实例 实例1&#xff1a;二级指针操作&#xff08;修改一级指针的值&#xff09; 实例2&#xff1a;动态二维数组&#xff08;二级指针&#xff09; 实例3&#xff1a;三级指…

Linux运维之Linux的安装和配置

目录 Linux的基本概念&#xff1a; 1.为什么要使用Linux&#xff1f; 2.什么是Linux&#xff1f; Linux的安装和配置&#xff1a; 1.下载Linux的虚拟机和镜像文件&#xff1a; 1.1下载虚拟机 1.2下载镜像文件 2.在虚拟机或者物理机中安装Linux操作系统 3.配置虚拟机的…

第一个3D程序!

运行效果 CPP #include <iostream> #include <fstream> #include <string> #include <cmath>#include <GL/glew.h> #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/type_ptr.hpp> #include <glm/gtc/…

deepseek+vscode自动化测试脚本生成

近几日Deepseek大火,我这里也尝试了一下,确实很强。而目前vscode的AI toolkit插件也已经集成了deepseek R1,这里就介绍下在vscode中利用deepseek帮助我们完成自动化测试脚本的实践分享 安装AI ToolKit并启用Deepseek 微软官方提供了一个针对AI辅助的插件,也就是 AI Toolk…

简要介绍C++中的 max 和 min 函数以及返回值

简要介绍C中的 max 和 min 函数 在C中&#xff0c;std::max 和 std::min 是标准库 <algorithm> 中提供的函数&#xff0c;用于比较两个或多个值并返回最大值或最小值。这些函数非常强大且灵活&#xff0c;支持多种数据类型&#xff08;如整数、浮点数、字符串等&#xff…

【MyDB】4-VersionManager 之 3-死锁及超时检测

【MyDB】4-VersionManager 之 3-死锁及超时检测 死锁及超时检测案例背景LockTable锁请求与等待管理 addvm调用addputIntoList&#xff0c;isInList&#xff0c;removeFromList 死锁检测 hasDeadLock方法资源释放与重分配 参考资料 死锁及超时检测 本章涉及代码&#xff1a;top/…

Elasticsearch:如何搜索含有复合词的语言

作者&#xff1a;来自 Elastic Peter Straer 复合词在文本分析和标记过程中给搜索引擎带来挑战&#xff0c;因为它们会掩盖词语成分之间的有意义的联系。连字分解器标记过滤器等工具可以通过解构复合词来帮助解决这些问题。 德语以其长复合词而闻名&#xff1a;Rindfleischetik…

服务器虚拟化实战:架构、技术与最佳实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 服务器虚拟化是现代 IT 基础设施的重要组成部分&#xff0c;通过虚拟化技术可以提高服务器资源利用率、降低硬件成本&am…

【LLM】Ollama框架入门指北

note Ollama是一个开源框架&#xff0c;专门设计用于在本地运行大型语言模型。它的主要特点是将模型权重、配置和数据捆绑到一个包中&#xff0c;从而优化了设置和配置细节&#xff0c;包括GPU使用情况&#xff0c;简化了在本地运行大型模型的过程。Ollama提供了对模型量化的支…

Linux系统:Ubuntu替换镜像源具体方法;

在Linux系统更新下载软件时&#xff0c;如遇因镜像源问题下载失败时&#xff0c;我们就需要替换系统原有镜像源&#xff0c;那么&#xff0c;此时&#xff0c;你是否还在百度四处搜索可以用的镜像源地址&#xff0c;然后反复去测试源地址的正确性呢&#xff0c;下面介绍一个亲测…

使用vhd虚拟磁盘安装两个win10系统

使用vhd虚拟磁盘安装两个win10系统 前言vhd虚拟磁盘技术简介准备工具开始动手实践1.winX选择磁盘管理2.选择“操作”--“创建VHD”3.自定义一个位置&#xff0c;输入虚拟磁盘大小4.右键初始化磁盘5.选择GPT分区表格式6.右键新建简单卷7.给卷起个名字&#xff0c;用于区分8.打开…

HTML(快速入门)

欢迎大家来到我的博客~欢迎大家对我的博客提出指导&#xff0c;有错误的地方会改进的哦~点击这里了解更多内容 目录 一、前言二、HTML基础2.1 什么是HTML?2.2 认识HTML标签2.2.1 HTML标签当中的基本结构2.2.2 标签层次结构 2.3 HTML常见标签2.3.1 标题标签2.3.2 段落标签2.3.3…

d3.js: Relation Graph

d3.js Tags d3/d3 GitHub D3 by Observable | The JavaScript library for bespoke data visualization 下载或 <!-- 引入 D3.js 库 --> <script src"https://d3js.org/d3.v7.min.js"></script> <!-- 引入 D3.js 库 --> <…

Oracle Primavera P6自动进行进度计算

前言 在P6 Professional 有一个自动计划计算的选项&#xff0c;很多人不了解该设置如何使用&#xff0c;以及什么时候该启动这项配置。 详情 P6 Professional 默认为非自动进度计算。启用自动选项后&#xff0c;可以快速查看调度更改的效果。 ​ ​ 如图所示&#xff0c;当你…

反射、枚举以及lambda表达式

一.反射 1.概念&#xff1a;Java的反射&#xff08;reflection&#xff09;机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff0c;既然能拿到那么&am…

【Proteus仿真】【51单片机】简易计算器系统设计

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 联系作者 一、主要功能 1、LCD1602液晶显示 2、矩阵按键​ 3、可以进行简单的加减乘除运算 4、最大 9999*9999 二、使用步骤 系统运行后&#xff0c;LCD1602显示数据&#xff0c;通过矩阵按键…

HarmonyOS简介:HarmonyOS核心技术理念

核心理念 一次开发、多端部署可分可合、自由流转统一生态、原生智能 一次开发、多端部署 可分可合 自由流转 自由流转可分为跨端迁移和多端协同两种情况 统一生态 支持业界主流跨平台开发框架&#xff0c;通过多层次的开放能力提供统一接入标准&#xff0c;实现三方框架快速…

(即插即用模块-特征处理部分) 十九、(NeurIPS 2023) Prompt Block 提示生成 / 交互模块

文章目录 1、Prompt Block2、代码实现 paper&#xff1a;PromptIR: Prompting for All-in-One Blind Image Restoration Code&#xff1a;https://github.com/va1shn9v/PromptIR 1、Prompt Block 在解决现有图像恢复模型时&#xff0c;现有研究存在一些局限性&#xff1a; 现有…

Day24-【13003】短文,数据结构与算法开篇,什么是数据元素?数据结构有哪些类型?什么是抽象类型?

文章目录 13003数据结构与算法全书框架考试题型的分值分布如何&#xff1f; 本次内容概述绪论第一节概览什么是数据、数据元素&#xff0c;数据项&#xff0c;数据项的值&#xff1f;什么是数据结构&#xff1f;分哪两种集合形式&#xff08;逻辑和存储&#xff09;&#xff1f…