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;
#else
	typedef  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位置为1

EventGroupHandle_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_task
	xTaskCreate((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位置1
            xEventGroupSetBits(eventgroup_handle, EVENTBIT_0);
        }
		else if(key == 2)
        {
            //将事件标志组的bit1位置1
            xEventGroupSetBits(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位均置1
                pdTRUE,      //等待到事件标志位后,清除事件标志组的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)多任务调度执行阶段较为简单,这里不再赘述。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习数据结构(5)单向链表的实现

&#xff08;1&#xff09;头部插入 &#xff08;2&#xff09;尾部删除 &#xff08;3&#xff09;头部删除 &#xff08;4&#xff09;查找 &#xff08;5&#xff09;在指定位置之前插入节点 &#xff08;6&#xff09;在指定位置之后插入节点 &#xff08;7&#xff09;删除…

Golang :用Redis构建高效灵活的应用程序

在当前的应用程序开发中&#xff0c;高效的数据存储和检索的必要性已经变得至关重要。Redis是一个快速的、开源的、内存中的数据结构存储&#xff0c;为各种应用场景提供了可靠的解决方案。在这个完整的指南中&#xff0c;我们将学习什么是Redis&#xff0c;通过Docker Compose…

18 大量数据的异步查询方案

在分布式的应用中分库分表大家都已经熟知了。如果我们的程序中需要做一个模糊查询&#xff0c;那就涉及到跨库搜索的情况&#xff0c;这个时候需要看中间件能不能支持跨库求交集的功能。比如mycat就不支持跨库查询&#xff0c;当然现在mycat也渐渐被摒弃了(没有处理笛卡尔交集的…

Redis代金卷(优惠卷)秒杀案例-单应用版

优惠卷表:优惠卷基本信息,优惠金额,使用规则 包含普通优惠卷和特价优惠卷(秒杀卷) 优惠卷的库存表:优惠卷的库存,开始抢购时间,结束抢购时间.只有特价优惠卷(秒杀卷)才需要填写这些信息 优惠卷订单表 卷的表里已经有一条普通优惠卷记录 下面首先新增一条秒杀优惠卷记录 { &quo…

编程题-三数之和(中等)

题目&#xff1a; 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。注意&#xff1a;答案中不可以包含重复的三…

过年回家的意义,

年前&#xff0c;我特想让家里人到深圳过年&#xff0c;想让他们看看深圳&#xff0c;看看外面好玩的样子&#xff0c;跟我妈提了两次&#xff0c;她两次的借口都是家里养着的那几头猪&#xff0c;还有好多鸡鸭要喂&#xff0c;说家里一定得要有人守&#xff0c;人走远是不行的…

一文读懂 Faiss:开启高维向量高效检索的大门

一、引言 在大数据与人工智能蓬勃发展的当下&#xff0c;高维向量数据如潮水般涌现。无论是图像、音频、文本&#xff0c;还是生物信息领域&#xff0c;都离不开高维向量来精准刻画数据特征。然而&#xff0c;在海量的高维向量数据中进行快速、准确的相似性搜索&#xff0c;却…

扩展无限可能:Obsidian Web Viewer插件解析

随着 Obsidian 1.8.3 正式版的发布&#xff0c;备受期待的官方核心插件——Web Viewer 也终于上线。本文将从插件启用、设置以及应用场景三个方面详细介绍如何使用这一新功能&#xff0c;和大家一起更好地利用 Obsidian 进行内容管理和知识整理。 插件启用 Web Viewer作为官方…

22.Word:小张-经费联审核结算单❗【16】

目录 NO1.2 NO3.4​ NO5.6.7 NO8邮件合并 MS搜狗输入法 NO1.2 用ms打开文件&#xff0c;而不是wps❗不然后面都没分布局→页面设置→页面大小→页面方向→上下左右&#xff1a;页边距→页码范围&#xff1a;多页&#xff1a;拼页光标处于→布局→分隔符&#xff1a;分节符…

仿真设计|基于51单片机的贪吃蛇游戏

目录 具体实现功能 设计介绍 51单片机简介 资料内容 仿真实现&#xff08;protues8.7&#xff09; 程序&#xff08;Keil5&#xff09; 全部内容 资料获取 具体实现功能 利用单片机8*8点阵实现贪吃蛇游戏的控制。 仿真演示视频&#xff1a; 51-基于51单片机的贪吃蛇游…

【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(二)

目录 1 -> HML语法 1.1 -> 页面结构 1.2 -> 数据绑定 1.3 -> 普通事件绑定 1.4 -> 冒泡事件绑定5 1.5 -> 捕获事件绑定5 1.6 -> 列表渲染 1.7 -> 条件渲染 1.8 -> 逻辑控制块 1.9 -> 模板引用 2 -> CSS语法 2.1 -> 尺寸单位 …

CPU、GPU、NPU

文章目录 内存、带宽、时延&#xff1a;尽可能提高算力的利用率&#xff01;AI 芯片基础 内存、带宽、时延&#xff1a;尽可能提高算力的利用率&#xff01; CPU计算本质&#xff1a;数据如何传输【AI芯片】芯片基础03 横坐标&#xff1a;算力敏感度&#xff0c;每次操作能执…

11.QT控件:输入类控件

1. Line Edit(单行输入框) QLineEdit表示单行输入框&#xff0c;用来输入一段文本&#xff0c;但是不能换行。 核心属性&#xff1a; 核心信号&#xff1a; 2. Text Edit(多行输入框) QTextEdit表示多行输入框&#xff0c;也是一个富文本 & markdown编辑器。并且能在内容超…

蓝桥杯刷题DAY1:前缀和

所谓刷题&#xff0c;讲究的就是细心 帕鲁服务器崩坏【算法赛】 “那个帕鲁我已经观察你很久了&#xff0c;我对你是有些失望的&#xff0c;进了这个营地&#xff0c;不是把事情做好就可以的&#xff0c;你需要有体系化思考的能力。” 《幻兽帕鲁》火遍全网&#xff0c;成为…

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

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

Office / WPS 公式、Mathtype 公式输入花体字、空心字

注&#xff1a;引文主要看注意事项。 1、Office / WPS 公式中字体转换 花体字 字体选择 “Eulid Math One” 空心字 字体选择 “Eulid Math Two” 使用空心字时&#xff0c;一般不用斜体&#xff0c;取消勾选 “斜体”。 2、Mathtype 公式输入花体字、空心字 2.1 直接输…

Baklib对比其他知识管理工具的优势及应用效果全面分析

内容概要 Baklib知识中台作为一种集成化的数字化平台&#xff0c;其核心功能围绕知识的高效管理、共享以及运用展开。这一平台不仅为企业提供了统一的知识管理架构&#xff0c;还依托智能化技术&#xff0c;使得组织内外的知识资源能够实现流畅的交互与利用。通过Baklib&#…

python:洛伦兹变换

洛伦兹变换&#xff08;Lorentz transformations&#xff09;是相对论中的一个重要概念&#xff0c;特别是在讨论时空的变换时非常重要。在四维时空的背景下&#xff0c;洛伦兹变换描述了在不同惯性参考系之间如何变换时间和空间坐标。在狭义相对论中&#xff0c;洛伦兹变换通常…

Janus-Pro 论文解读:DeepSeek 如何重塑多模态技术格局

Janus-Pro&#xff1a;多模态领域的璀璨新星——技术解读与深度剖析 一、引言 在人工智能的浩瀚星空中&#xff0c;多模态理解与生成模型犹如耀眼的星座&#xff0c;不断推动着技术边界的拓展。Janus-Pro作为这一领域的新兴力量&#xff0c;以其卓越的性能和创新的架构&#x…

稀疏混合专家架构语言模型(MoE)

注&#xff1a;本文为 “稀疏混合专家架构语言模型&#xff08;MoE&#xff09;” 相关文章合辑。 手把手教你&#xff0c;从零开始实现一个稀疏混合专家架构语言模型&#xff08;MoE&#xff09; 机器之心 2024年02月11日 12:21 河南 选自huggingface 机器之心编译 机器之心…