uCOSIII实时操作系统 十 事件标志组

目录

事件标志组:

事件标志组API函数:

创建事件标志组:

等待事件标志组:

向事件标志组发送标志:

事件标志组实验:


事件标志组:

有时候一个任务可能需要和多个事件同步这个时候就需要使用事件标志组。时间标志组与任务之间有两种同步机制:“或”同步和“与”同步,当一个事件发生,任务都被同步的同步机制是“或”同步需要所有的事件都发生任务才会被同步的机制是“与”同步。如下图所示:

下边是正点原子对他的解释:

为什么要使用事件标志组???直接搞个全局变量不就行了吗???真的可以吗

事件标志组是实现多任务同步的有效机制之一。在裸机编程的时候使用全局变量确实方便,但是在加上RTOS后就是另一种情况了。

  1. 使用事件标志组可以让RTOS内核有效的管理任务,而全局变量是无法做到的,任务的超时等机制需要用户自己去实现。(麻烦至极)
  2. 使用全局变量就要防止多任务的访问冲突,而使用事件标志组则处理好了这个问题,用户无需担心。
  3. 使用事件标志组可以有效的解决中断服务程序和任务之间的同步问题。

事件标志组API函数:

创建事件标志组:

在使用事件标志组之前,需要调用OSFlagCreate()创建一个事件标志组,而在创建事件标志组之前需要先定一个事件标志组(eg: OS_FLAG_GRP EventFlag;)。

OSFlagCreate()函数原型:

p_grp:指向事件标志组,

p_name:事件标志组的名字。

flags:定义事件标志组的初始值。

p_err:用来保存调用此函数后返回的错误码

   

等待事件标志组:

等待一个事件标志组需要调用函数OSFlagPend()函数,函数原型如下:

OSFlagPend()函数允许将事件标志组里事件标志的“与或”组合状态设置成任务的等待条件。

任务等待的条件可以使标志组里任意一个标志置位或者清零,也可以是所有事件标志都置位或者清零。如果任务等待的事件标志组不满足设置的条件,那么该任务被置位挂起,直到等待的事件标志组满足条件,指定的超时时间到,事件标志被删除或者被另一个任务终止了该任务的挂起状态。

参数:

p_grp : 指向时间标志组,

flags :   bit序列,任务需要等待事件标志组的哪个位就是把这个序列对应的位置1.根据设置这个序列可以是8bit,16bit,32bit比如任务需要等待事件标志组的bit0或者bit1(无论是等待置位还是清零)flag的值就是0x03。

 timeout:指定等待事件标志组的超时时间(时钟节拍数),如果在指定的超时时间内所等待的一个或多个事件没有发生,那么任务恢复运行。如果此值设置为 0,则任务就将一直等待下去,直到一个或多个事件发生。

 opt:决定任务等待的条件是所有标志置位、所有标志清零、任意一个标志置位还是任 意一个标志清零,具体定义如下:

OS_OPT_PEND_FLAG_CLR_ALL        等待事件标志组所有的位清零

OS_OPT_PEND_FLAG_CLR_ANY        等待事件标志组中任意一个标志清零

OS_OPT_PEND_FLAG_SET_ALL        等待事件标志组中所有的位置位

OS_OPT_PEND_FLAG_SET_ANY        等待事件标志组中任意一个标志置位 

上边调用四个选项的时候还可以搭配下边三个选项。

OS_OPT_PEND_FLAG_CONSUME       用来设置是否保留该事件的标志状态

OS_OPT_PEND_NON_BLOCKING        标志组不满足条件时,不挂起任务

OS_OPT_PEND_BLOCKING                  标志组不满足条件时挂起任务

这里应该注意选项OS_OPT_PEND_FLAG_CONSUME       的使用方法,如果我们希望任务等待事件标志组的任意一个标志置位,并在满  足条件后将对应的标志清零,那么就可以搭配OS_OPT_PEND_FLAG_CONSUME。       

p_ts:指向一个时间戳,记录了发送、终止和删除事件标志组的时刻,如果为这个指针赋值 NULL,则函数的调用者将不会收到时间戳。

p_err:用来保存调用此函数后返回的错误码。

向事件标志组发送标志:

调用函数OSFlagPost()可以对事件标志组经行置位或者清零,函数原型如下:

一般情况下,需要经行置位或者清零的标志由一个掩码确定(参数:flag)。OSFlagPost()修改完事件标志以后,将检查并使那些等待条件已经满足的任务进入就绪状态,该函数可以对已经置位或者清零的标志进行重复置位和清零操作。

参数:

p_grp:指向事件标志组。

flags:决定对哪些位清零和置位,当 opt 参数为 OS_OPT_POST_FLAG_SET 的时,参flags 中置位的位就会在事件标志组中对应的位也将被置位。当 opt OS_OPT_POST_FLAG_CLR 的时候参数 flags 中置位的位在事件标志组中对应的位将被清零。

 opt:决定对标志位的操作,有两种选项。

OS_OPT_POST_FLAG_SET对标志位进行置位操作
OS_OPT_POST_FLAG_CLR对标志位进行清零操作

p_err: 保存调用此函数后返回的错误码。

事件标志组实验:

设计一个程序,只有按下KEY0和KEY1(不需要同时按下)时任务任务C才可以执行。

实验源码:

 #include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "includes.h"
#include "os_app_hooks.h"
#include "key.h"
//UCOSIII中以下优先级用户程序不能使用,ALIENTEK
//将这些优先级分配给了UCOSIII的5个系统内部任务
//优先级0:中断服务服务管理任务 OS_IntQTask()
//优先级1:时钟节拍任务 OS_TickTask()
//优先级2:定时任务 OS_TmrTask()
//优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()
//优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()//创建任务A
//定义任务优先级
#define TASK_A_PRIO 3
//定义任务控制块
OS_TCB TASK_A_TCB;
//定义任务堆栈大小
#define TASK_A_STK_SIZE 128
//定义任务堆栈
CPU_STK TASK_A_STK[TASK_A_STK_SIZE];
//定义任务函数
void TASK_A(void *arg);//创建任务B
//定义任务优先级
#define TASK_B_PRIO 4
//定义任务控制块
OS_TCB TASK_B_TCB;
//定义任务堆栈大小
#define TASK_B_STK_SIZE 128
//定义任务堆栈
CPU_STK TASK_B_STK[TASK_B_STK_SIZE];
//定义任务函数
void TASK_B(void *arg);//创建任务C
//定义任务优先级
#define TASK_C_PRIO 5
//定义任务控制块
OS_TCB TASK_C_TCB;
//定义任务堆栈大小
#define TASK_C_STK_SIZE 128
//定义任务堆栈
CPU_STK TASK_C_STK[TASK_C_STK_SIZE];
//定义任务函数
void TASK_C(void *arg);//共享资源
u8 share_res[256];//定义事件标志
#define KEY0_FLAG 0x01//0000 0001
#define KEY1_FLAG 0x02//0000 0010//定义事件标志组
OS_FLAG_GRP EventFlag;int main(void)
{OS_ERR err1;//错误码变量CPU_SR_ALLOC();//定义临界区需要的变量//硬件初始化delay_init();       //延时初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置uart_init(115200);    //串口波特率设置LED_Init();KEY_Init();OSInit(&err1);//初始化UCOSIIIOS_CRITICAL_ENTER();//进入临界区代码//创建开始任务AOSTaskCreate((OS_TCB 	* )&TASK_A_TCB,		//任务控制块(CPU_CHAR	* )"main TASKA", 		//任务名字(OS_TASK_PTR )TASK_A, 			//任务函数(void		* )0,					//传递给任务函数的参数(OS_PRIO	  )TASK_A_PRIO,     //任务优先级(CPU_STK   * )&TASK_A_STK[0],	//任务堆栈基地址(CPU_STK_SIZE)TASK_A_STK_SIZE/10,	//任务堆栈深度限位(CPU_STK_SIZE)TASK_A_STK_SIZE,		//任务堆栈大小(OS_MSG_QTY  )0,					//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息(OS_TICK	  )0,					//当使能时间片轮转时的时间片长度,为0时为默认长度,(void   	* )0,					//用户补充的存储区(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项(OS_ERR 	* )&err1);				//存放该函数错误时的返回值OS_CRITICAL_EXIT();//退出临界区代码OSStart(&err1);//开启UCOSIIIwhile(1);
}//开始任务函数
void TASK_A(void *arg)
{OS_ERR err2_3;//错误码变量CPU_SR_ALLOC();//定义临界区需要的变量arg = arg;CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err2_3);  	//统计任务                
#endif#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间CPU_IntDisMeasMaxCurReset();	
#endif#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5msOSSchedRoundRobinCfg(DEF_ENABLED,1,&err2_3);  
#endif	//#if OS_CFG_APP_HOOKS_EN				//使用钩子函数
//	App_OS_SetAllHooks();			
//#endif#if OS_CFG_SCHED_ROUND_ROBIN_EN//使用时间片轮转调度功能,时间片长度为一个时钟节拍即1*5=5msOSSchedRoundRobinCfg(DEF_ENABLED,1,&err2_3);
#endifOS_CRITICAL_ENTER();//进入临界区代码//创建事件标志组OSFlagCreate((OS_FLAG_GRP *)&EventFlag,(CPU_CHAR *)"EventFlag",(OS_FLAGS )0,(OS_ERR *)&err2_3);//创建开始任务BOSTaskCreate((OS_TCB 	* )&TASK_B_TCB,		//任务控制块(CPU_CHAR	* )"main TASKB", 		//任务名字(OS_TASK_PTR )TASK_B, 			//任务函数(void		* )0,					//传递给任务函数的参数(OS_PRIO	  )TASK_B_PRIO,     //任务优先级(CPU_STK   * )&TASK_B_STK[0],	//任务堆栈基地址(CPU_STK_SIZE)TASK_B_STK_SIZE/10,	//任务堆栈深度限位(CPU_STK_SIZE)TASK_B_STK_SIZE,		//任务堆栈大小(OS_MSG_QTY  )0,					//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息(OS_TICK	  )0,					//当使能时间片轮转时的时间片长度,为0时为默认长度,(void   	* )0,					//用户补充的存储区(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项(OS_ERR 	* )&err2_3);				//存放该函数错误时的返回值//创建开始任务COSTaskCreate((OS_TCB 	* )&TASK_C_TCB,		//任务控制块(CPU_CHAR	* )"main TASKC", 		//任务名字(OS_TASK_PTR )TASK_C, 			//任务函数(void		* )0,					//传递给任务函数的参数(OS_PRIO	  )TASK_C_PRIO,     //任务优先级(CPU_STK   * )&TASK_C_STK[0],	//任务堆栈基地址(CPU_STK_SIZE)TASK_C_STK_SIZE/10,	//任务堆栈深度限位(CPU_STK_SIZE)TASK_C_STK_SIZE,		//任务堆栈大小(OS_MSG_QTY  )0,					//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息(OS_TICK	  )0,					//当使能时间片轮转时的时间片长度,为0时为默认长度,(void   	* )0,					//用户补充的存储区(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项(OS_ERR 	* )&err2_3);				//存放该函数错误时的返回值OS_CRITICAL_EXIT();//退出临界区代码//任务一执行完函数之后删掉自身OSTaskDel((OS_TCB *)0,&err2_3);			 
}//任务B任务函数  高优先级
void TASK_B(void *arg)
{
//	u8 key;OS_ERR err_B;u8 key;OS_FLAGS num_flag;while(1){key = KEY_Scan(0); //扫描按键if(key==KEY0_PRES){printf("KEY0:向事件标志组发送标志!\r\n");num_flag=OSFlagPost(&EventFlag,KEY0_FLAG,OS_OPT_POST_FLAG_SET,&err_B);//向事件标志组发送标志printf("事件标记组的值为%d\r\n",num_flag);LED0 = ~LED0;}else if(key==KEY1_PRES){printf("KEY1:向事件标志组发送标志!\r\n");num_flag=OSFlagPost(&EventFlag,KEY1_FLAG,OS_OPT_POST_FLAG_SET,&err_B);//向事件标志组发送标志printf("任务B:事件标记组的值为%d\r\n",num_flag);LED1 = ~LED1;}OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err_B); //延时10ms}}//任务C任务函数  中优先级
void TASK_C(void *arg)
{OS_ERR err_C;while(1){//等待事件标志组OSFlagPend (&EventFlag,KEY0_FLAG+KEY1_FLAG,0,OS_OPT_PEND_FLAG_SET_ALL,0,&err_C);printf("任务C等到事件\r\n");printf("任务C:事件标记组的值为%d\r\n",EventFlag.Flags);OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err_C); //延时1s}}

实验现象:

文章参考:正点原子《STM32F1 UCOS开发手册_V2.0》

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

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

相关文章

39.克鲁斯卡尔(Kruskal)算法

一言 已知n个顶点,选n-1条最短的边,不可成环。 概述 克鲁斯卡尔(Kruskal)算法是用来求加权连通图的最小生成树的算法。其基本思想是按照权值从小到大的顺序选择n-1条边,保证这n-1条边不构成回路。 这就要求要首先构…

一百九十一、Flume——Flume配置文件各参数含义(持续完善中)

一、目的 在实际项目的开发过程中,不同Kafka主题的数据规模、数据频率,需要配置不同的Flume参数,而这一切的调试、配置工作,都要建立在对Flume配置文件各参数含义的基础上 二、Flume各参数及其含义 (一)…

集成学习方法(随机森林和AdaBoost)

释义 集成学习很好的避免了单一学习模型带来的过拟合问题 根据个体学习器的生成方式,目前的集成学习方法大致可分为两大类: Bagging(个体学习器间不存在强依赖关系、可同时生成的并行化方法) 流行版本:随机森林(random forest)Boosting(个体…

springboot缓存篇之mybatis一级缓存和二级缓存

前言 相信很多人都用过mybatis,这篇文章主要是介绍mybatis的缓存,了解一下mybatis缓存是如何实现,以及它在实际中的应用 一级缓存 什么是mybatis一级缓存?我们先看一个例子: GetMapping("/list") public…

【Mysql】B+树索引的使用(七)

前言 每个索引都对应一棵 B 树, B 树分为多层,最下边一层是叶子节点,其余的是内节点(非叶子节点)。所有用户记录都存储在 B 树的叶子节点,所有目录项记录都存储在内节点。 InnoDB 存储引擎会自动为主键&am…

Node学习笔记之包管理工具

一、概念介绍 1.1 包是什么 『包』英文单词是package ,代表了一组特定功能的源码集合 1.2 包管理工具 管理『包』的应用软件,可以对「包」进行 下载安装 , 更新 , 删除 , 上传 等操作 借助包管理工具,可…

推理引擎之模型压缩浅析

目录 前言1. 模型压缩架构和流程介绍2. 低比特量化原理2.1 量化基础介绍2.2 量化方法2.3 量化算法原理2.4 讨论 3. 感知量化训练QAT原理3.1 QAT原理3.2 量化算子插入3.3 QAT训练流程3.4 QAT衍生研究3.5 讨论 4. 训练后量化PTQ4.1 动态PTQ4.2 静态PTQ4.3 KL散度实现静态PTQ4.4 量…

最详细STM32,cubeMX 定时器

这篇文章将详细介绍 STM32,cubeMX 定时器的配置和使用。 文章目录 前言一、定时器基础知识二、cubeMX 配置三、定时时长四、自动生成代码讲解五、实验程序总结 前言 实验开发板:STM32F103C8T6。所需软件:keil5 , cubeMX 。实验目的&#xff…

无人机UAV目标检测与跟踪(代码+数据)

前言 近年来,随着无人机的自主性、灵活性和广泛的应用领域,它们在广泛的消费通讯和网络领域迅速发展。无人机应用提供了可能的民用和公共领域应用,其中可以使用单个或多个无人机。与此同时,我们也需要意识到无人机侵入对空域安全…

牛客:NC59 矩阵的最小路径和

牛客:NC59 矩阵的最小路径和 文章目录 牛客:NC59 矩阵的最小路径和题目描述题解思路题解代码 题目描述 题解思路 动态规划,递推公式:matrix[i][j] min(matrix[i-1][j], matrix[i][j-1]) 题解代码 func minPathSum( matrix [][…

【数据科学赛】2023全球智能汽车AI挑战赛 #¥95000 #LLM文档问答 #视频理解

CompHub[1] 最新的比赛会第一时间在群里通知,欢迎加群交流比赛经验!(公众号回复“加群”即可) 以下内容由AI辅助生成,可能存在错误,可进入比赛主页[2]查看更多(文末阅读原文) 比赛主办方 吉利汽车集团、阿…

【C++】:类和对象(中)之拷贝构造函数+赋值运算符重载

拷贝构造函数 概念 在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎 那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢? 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用…

FPGA的斐波那契数列Fibonacci设计verilog,代码和视频

名称:斐波那契数列Fibonacci设计verilog 软件:Quartus 语言:Verilog 代码功能: 设计一个产生斐波那契数列(也叫黄金分割数列)的硬件电路: 斐波那契数列中每个数为其相邻前两个数的和:即FNFN1FN2,(数列…

Python:函数篇(每周练习)

编程题: Python第四章作业(初级) (educoder.net) 题一:无参无返回值函数 def print_hi_human(): # 函数名用小写字母print("人类,你好!")if __name__ __main__:print_hi_human() 题二&#…

设计模式篇---组合模式

文章目录 概念结构实例总结 概念 组合模式:组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。 当我们开发中遇到树形结构的业务时,可以考虑使用组合模式。(我也没有想明白为啥…

Mysql数据库 2.SQL语言 数据类型与字段约束

Mysql数据类型 数据类型:指的是数据表中的列文件支持存放的数据类型 1.数值类型 Mysql当中有多种数据类型可以存放数值,不同的类型存放的数值的范围或者形式是不同的 注:前三种数字类型我们在实际研发中用的很少,一般整数类型…

空中计算(Over-the-Air Computation)学习笔记

文章目录 写在前面 写在前面 本文是论文A Survey on Over-the-Air Computation的阅读笔记: 通信和计算通常被视为独立的任务。 从工程的角度来看,这种方法是非常有效的,因为可以执行孤立的优化。 然而,对于许多面向计算的应用程序…

游戏反虚拟框架检测方案

游戏风险环境,是指独立于原有设备或破坏设备原有系统的环境。常见的游戏风险环境有:iOS越狱、安卓设备root、虚拟机、虚拟框架、云手机等。 因为这类风险环境可以为游戏外挂、破解提供所需的高级别设备权限,所以当游戏处于这些设备环境下&am…

ARM可用的可信固件项目简介

安全之安全(security)博客目录导读 目录 一、TrustedFirmware-A (TF-A) 二、MCUboot 三、TrustedFirmware-M (TF-M) 四、TF-RMM 五、OP-TEE 六、Mbed TLS 七、Hafnium 八、Trusted Services 九、Open CI 可信固件为Armv8-A、Armv9-A和Armv8-M提供了安全软件的参考实现…

【UE5】 ListView使用DataTable数据的蓝图方法

【UE5】 ListView使用DataTable数据的蓝图方法 ListView 是虚幻引擎中的一种用户界面控件,用于显示可滚动的列表。它可以用于显示大量的数据,并提供了各种功能和自定义选项来满足不同的需求。 DataTable是虚幻引擎中的一种数据表格结构,用于存…