FreeRTOS入门(05):事件组

2023-10-28

目的

事件组是RTOS中相对常用的用于任务间交互的功能,这篇文章将对相关内容做个介绍。

本文代码测试环境见前面的文章:《FreeRTOS入门(01):基础说明与使用演示》

基础说明

事件组(EventGroup)和单片机硬件的事件或者中断有点像,每个事件组对象就是一个变量(寄存器)。如果 configUSE_16_BIT_TICKS 值为 0 这就是一个32位的变量,为 1 就是一个16位的变量。

事件组对象的高8位供FreeRTOS内部使用,剩余位供用户使用。每一个位(bit)表示一个事件发送,通常该位值为 0 ,表示未发生事件;值为 1 表示发生了事件。

事件组事件在设置的时候可以设置某一位,也可以同时设置某些位。等待事件的任务可以等待某一位有效,也可以等到某些位同时有效。事件被设置后会唤醒所有符合条件的任务(可以用作广播功能)。被唤醒的事件可以选择是否清除事件标志位。

相关函数

// 创建并返回事件组句柄
EventGroupHandle_t xEventGroupCreate( void )

// 删除事件组
// 在被删除的事件组上阻塞的任务将被取消阻塞,并且报告事件组值为0
void vEventGroupDelete( EventGroupHandle_t xEventGroup )

// 获取事件组中某个或某些位,如果不可用则阻塞
// uxBitsToWaitFor表示要等待的标志位(可以设置多个位)
// xClearOnExit为pdTRUE时会在事件发生后清除所等待的标志位,为pdFALSE则不清除
// xWaitForAllBits为pdTRUE时需要等所有等待的标志位都设置后才会返回,为pdFALSE时任意一位设置均会返回
EventBits_t xEventGroupWaitBits( const EventGroupHandle_t xEventGroup,
                                 const EventBits_t uxBitsToWaitFor,
                                 const BaseType_t xClearOnExit,
                                 const BaseType_t xWaitForAllBits,
                                 TickType_t xTicksToWait )

// 设置标志位
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
// 清除标志位
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )

// 事件组的设置与清除在中断中使用的版本,在中断中设置与清除事件组不会立即进行,而是会延时到后面的FreeRTOS守护进程中执行,所以可能需要设置下面才可使用
// INCLUDE_xEventGroupSetBitFromISR, configUSE_TIMERS, INCLUDE_xTimerPendFunctionCall, configUSE_TRACE_FACILITY
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )

// 获取当前事件组状态
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup )
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )

// 同步设置(写和等待合并的功能)
// uxBitsToSet为要写的位,uxBitsToWaitFor为要等待的位
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
                             const EventBits_t uxBitsToSet,
                             const EventBits_t uxBitsToWaitFor,
                             TickType_t xTicksToWait );

使用演示

下面是个基础使用的演示:

#include "debug.h"
#include "FreeRTOS.h"     // 引入头文件
#include "task.h"         // 引入头文件
#include "event_groups.h" // 引入头文件

EventGroupHandle_t xEventGroup; // 事件组句柄

void task1(void *pvParameters) {
    while(1) {
        xEventGroupSetBits(xEventGroup, 0b0011); // bit1 bit0 写1
        vTaskDelete(NULL);
    }
}

void task2(void *pvParameters) {
    while(1) {
        vTaskDelay(500);
        xEventGroupSetBits(xEventGroup, 0b0100); // bit2 写1
        vTaskDelete(NULL);
    }
}

void task3(void *pvParameters) {
    while(1) {
        // 当 bit0 为1时触发,响应后不清除标志位
        EventBits_t uxBits = xEventGroupWaitBits(xEventGroup, 0b0001, pdFALSE, pdFALSE, portMAX_DELAY);
        printf("t3-%d\r\n", uxBits); // 打印事件触发时的标志位
        vTaskDelay(300);
    }
}

void task4(void *pvParameters) {
    while(1) {
        // 当 bit3 bit2 均为0时触发,响应后清除标志位
        EventBits_t uxBits = xEventGroupWaitBits(xEventGroup, 0b0110, pdTRUE, pdTRUE, portMAX_DELAY);
        printf("t4-%d\r\n", uxBits); // 打印事件触发时的标志位
        printf("t4-%d\r\n", xEventGroupGetBits(xEventGroup)); // 打印当前标志位
        xEventGroupClearBits(xEventGroup, 0x0001); // 清除标志位
        printf("t4-%d\r\n", xEventGroupGetBits(xEventGroup)); // 打印当前标志位
    }
}

int main(void) {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);

    xEventGroup = xEventGroupCreate(); //

    xTaskCreate(task1, "task1", 256, NULL, 5, NULL);
    xTaskCreate(task2, "task2", 256, NULL, 5, NULL);
    xTaskCreate(task3, "task3", 256, NULL, 5, NULL);
    xTaskCreate(task4, "task4", 256, NULL, 5, NULL);

    vTaskStartScheduler(); // 任务调度,任务将在这里根据情况开始运行,程序将在这里无序循环

    while(1) {} // 程序不会运行到这里
}

// 时间                   任务         xEventGroup
// tick 0000         0b0000
// tick 0000  task1  0b0011
// tick 0001  task3  0b0011 // 打印输出
// tick 0301  task3  0b0011 // 打印输出
// tick 0500  task2  0b0111
// tick 0501  task4  0b0111 // 打印输出
// tick 0501  task4  0b0001 // 打印输出
// tick 0501  task4  0b0000 // 打印输出

在这里插入图片描述

下面是个同步方式演示:

#include "debug.h"
#include "FreeRTOS.h"     // 引入头文件
#include "task.h"         // 引入头文件
#include "event_groups.h" // 引入头文件

EventGroupHandle_t xEventGroup; // 事件组句柄

void task1(void *pvParameters) {
    while(1) {
        printf("t1s1-%d\r\n", xEventGroupGetBits(xEventGroup)); // 打印事件触发时的标志位
        EventBits_t uxBits = xEventGroupSync(xEventGroup, 0b0001, 0b0011, portMAX_DELAY); // 设置0b0001,等待0b0011
        printf("t1s2-%d\r\n", uxBits); // 打印事件触发时的标志位
        vTaskDelete(NULL);
    }
}

void task2(void *pvParameters) {
    while(1) {
        vTaskDelay(500);
        printf("t2s1-%d\r\n", xEventGroupGetBits(xEventGroup)); // 打印事件触发时的标志位
        EventBits_t uxBits = xEventGroupSync(xEventGroup, 0b0010, 0b0011, portMAX_DELAY); // 设置0b0010,等待0b0011
        printf("t2s2-%d\r\n", uxBits); // 打印事件触发时的标志位
        vTaskDelete(NULL);
    }
}

int main(void) {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);

    xEventGroup = xEventGroupCreate(); //

    xTaskCreate(task1, "task1", 256, NULL, 5, NULL);
    xTaskCreate(task2, "task2", 256, NULL, 5, NULL);

    vTaskStartScheduler(); // 任务调度,任务将在这里根据情况开始运行,程序将在这里无序循环

    while(1) {} // 程序不会运行到这里
}

在这里插入图片描述

总结

就像本文基础说明中介绍的那样,事件组和单片机硬件的事件或者中断有点像,理解了这点的话事件组使用上其实并不复杂的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS入门(05):事件组 的相关文章

  • 【TCP/IP】第五章 IP协议相关技术

    IP Internet Protocol 旨在让最终目标主机收到数据包 但是在这一过程中仅仅有IP时无法实现通信的 必须还有能够解析主机名称和MAC地址的功能 以及数据包在发送过程中异常情况处理的功能 此外 还会涉及IP必不可少的其他功能
  • DSP28335的AD采样读数一直是4095

    这几天做的一个DSP28335控制板测试时发现PWM没问题 但是测AD读数时A0和B0的读数都是4095 简单分析一下 对于DSP的供电 分为3 3V A 1 9V A 3 3V D 1 9V D 其中3 3V是给芯片外围供电 1 91V是
  • 远程java Robot的坑!!!

    1 发现一旦切换程序后 robot无法执行了 请用管理员身份运行 2 远程登陆最小化或关闭 模拟键盘操作失效 因为通过mstsc启动远程桌面连接时 被连接的Windows会启动一个会话 Session 此时你对远程桌面窗口里面的所有操作 鼠

随机推荐

  • springboot项目配置定时任务及注解时间配置

    SpringApplication引入注解 EnableScheduling 开启定时任务 在自定义类上加入注解 Component 可以不使用 在 Configuration 中存在 Configuration 在具体的方法上加入注解 S
  • React 生命周期&&diff算法

    目录 事件处理 收集表单数据 高阶函数 函数科里化 生命周期 认识生命周期 生命周期流程图 旧 生命周期流程图 新 getSnapshotBeforeUpdate应用场景 生命周期总结 DOM的diff算法 概念 key的值的作用 案例 事
  • 2019大厂Android高级面试题汇总

    前言 金三银四 很多同学心里大概都准备着年后找工作或者跳槽 最近有很多同学都在交流群里求大厂面试题 正好我电脑里面有这方面的整理 于是就发上来分享给大家 这些题目是网友去百度 小米 乐视 美团 58 猎豹 360 新浪 搜狐等一线互联网公司
  • 第一章

    1 写出Java领域的相关技术 答 Java主要有三类 Javase javame javaee JavaSE是Java技术的核心 提供基础的Java开发工具 Javaee主要用于网络程序和企业级应用的开发 2 简述Java程序中的注释的作
  • 软考高项之进度管理——攻坚记忆

    软考高项之进度管理 攻坚记忆 一 进度管理过程 二 规划进度管理和制定进度计划区别 三 重要的工具与技术 四 相关重要概念 一 进度管理过程 1 规划进度管理 需要写一个文档 进度管理计划 里面规定了如何做好进度管理 2 定义活动 识别和记
  • 接口请求之加密参数(用户名和密码),使用md5方法加密

    一 接口请求涉及到一些类似用户名和密码等敏感信息的东西 请求肯定要进行加密 当然首先你得问开发 他们对参数是否加密 用了什么方式进行加密 我这里就用md5加密方式对请求的密码进行加密 二 前端对字符串类型的密码进行加密 输出秘钥 传递时候是
  • MySQL必知必会 学习笔记 第二十六章 管理事务处理

    并非所有引擎都支持事务处理 MyISAM不支持 InnoDB支持 事务处理可用来维护数据库的完整性 它保证成批的MySQL操作要么完全执行 要么完全不执行 如果没有错误发生 整组语句写到数据库表 如果发生错误 将已经执行的部分语句进行回退
  • Linux下快速比较两个目录的不同

    每次更新版本就想要在Linux下比较目录a和目录b中文件列表的差别 然后对目录a比目录b中多出的文件 少掉的文件分别做处理 但是 在网上搜索了多次也都没找到能直接处理好的工具 所以想了很多不少方法 自我感觉都不错 而且网上似乎没有这方面的文
  • IFNULL、ISNULL、NULLIF(SYBASE)

    IFNULL expr1 expr2 如果expr1为NULL 返回值为expr2 假如expr1不为NULL 则IFNULL 的返回值为expr1 ISNULL expr1 expr2 如果expr1值为NULL 则返回值为expr2 如
  • ubuntu不能输入美元符号_听说 90% 的人都在 win10 下使用 ubuntu 子系统了!

    win10下安装 配置与使用ubuntu子系统完全指南 最近 遇到很多Python第三方库不支持Windows系统或则安装很繁琐要不就是要安装vc 环境 都比较麻烦 对于开发者而言 Mac真的是个不错的选择 Linux就更不用说了 一直听过
  • java爬取当当网所有分类的图书信息(ISBN,作者,出版社,价格,所属分类等)

    java爬取当当网所有分类的图书信息 ISBN 作者 出版社 价格 所属分类等 顺手写的 没有建立新项目 放我自己的项目的一个文件夹里了 有兴趣的朋友可以拉下来试试 https gitee com panlufei demo blob ma
  • RN获取屏幕高宽、自适应(rem)设置

    RN获取屏幕高宽 自适应 rem 设置 1 引入Dimensions 2 通过Dimensions get window width height 获取屏幕高宽 pxToDp自适应js文件 import Dimensions from re
  • AD17无法导出外形层gerber文件

    近日在工作的时候发现Keep OUT层导出的gerber文件 后缀为 GKO 中无内容 导致板厂加工时发现无外形层 发现原因 板子外框线我是在Keep OUT层画的 双击线条发现Keepout选项被勾选 当我把其中一条线条的Keepout选
  • Jquery JqGrid常用方法

    记录平时开发中所用到的JqGrid方法 先附上一个jqgrid 详细介绍的链接 http blog mn886 net jqGrid 1 删除多行数据 var selectedId one grid jqGrid getGridParam
  • 怎么检测硬盘是否有坏道

    硬盘是电脑上非常重要的一个部分 硬盘的好坏也决定了电脑运行的稳定 硬盘最常见的就是出现坏道 一旦有了坏道 将会表现出一些异常的状况 如发出怪音 无法完成分区和格式化的操作 读取文件或运行程序时出错 磁盘占用100 甚至蓝屏等 那怎么检测硬盘
  • Windows下快速启动Kafka以及三种发送消息的方式

    目录 一 下载Kafka 二 启动kafka 2 1 启动kafka前得先启动zk 2 2 启动kafka 三 操作Kafka 3 1 创建 Kafka 主题 Topic 3 2 将信息写入主题 Topic 3 3 读取信息 四 Java实
  • linux下 在终端查看并设置串口

    1 查看串口设备 一般为ttyUSB0 ls dev 2 查看串口的波特率等信息 stty F dev ttyUSB0 a 3 设置串口波特率 数据模式 该命令将串口1 dev ttyUSB0 设置成115200波特率 8位数据模式 stt
  • linux设备驱动的实现与理解

    linux设备驱动的实现与理解 在linux中对字符设备的驱动编写 驱动插入以及使用驱动文件进行逻辑控制 其中这份代码写在嵌入式板中 通过控制io来实现灯的亮灭 但是设备驱动的实现流程与灯无关 大致的流程都体现在代码中 我感觉这份博客我自己
  • 重新出发,找回那个丢失的自己

    时隔一年多了 当初不顾一切的过来 就不要再因为眼前的困难而选择逃避 正视自己的不足 解决它 不忘初心 坚定 believe yourself
  • FreeRTOS入门(05):事件组

    文章目录 目的 基础说明 相关函数 使用演示 总结 目的 事件组是RTOS中相对常用的用于任务间交互的功能 这篇文章将对相关内容做个介绍 本文代码测试环境见前面的文章 FreeRTOS入门 01 基础说明与使用演示 基础说明 事件组 Eve