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…

租用服务器后需要注意什么呢

租用服务器后需要注意什么呢 1、从IDC服务商中接收到服务器时,需要对服务器的各项性能进行测试确认,并做好记录以便对服务器的性能做到心中有数。 2、在服务器租用交接时,要了解服务器的安全设置情况,对服务器安全技术方面不了解…

深度学习硬件配置推荐(kaggle学习)

目录 1. 基础推荐2. GPU显存与内存是一个1:4的配比?3. deep learning 入门和kaggle比赛4. 有些 Kaggle 比赛数据集很大,可能需要更多的 GPU 显存,请推荐显存4. GDDR6和HBM25. HDD 或 SATA SSD 1. 基础推荐 假设您作为一个深度学习入门学者的…

【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]查看更多(文末阅读原文) 比赛主办方 吉利汽车集团、阿…

智能指针

unique_ptr 为什么引入智能指针unique_ptr 普通指针的不足 内存泄漏:最常见的00问题是忘记释放分配给指针的内存,导致内存泄漏。这通常发生在异常情况或程序员忘记在不再需要内存时释放它。悬空指针:当对象被删除,但指针未被重…

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

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

怎么让英文大语言模型支持中文?--构建中文tokenization--继续预训练--指令微调

1 构建中文tokenization 参考链接:https://zhuanlan.zhihu.com/p/639144223 1.1 为什么需要 构建中文tokenization? 原始的llama模型对中文的支持不太友好,接下来本文将讲解如何去扩充vocab里面的词以对中文进行token化。 1.2 如何对 原始数…

单独使用logback作为日志

文章目录 引入logback的依赖logback.xml测试 具体配置,可参看:LogBack日志学习(全面) logback使用实战 log4j使用实战 log4j2使用实战 Java日志系统之Logback Java日志系统之Slf4j Java日志系统之Log4j 引入logback的依赖 …

JAVA观察者模式-案例

Java观察者模式 import java.util.ArrayList; import java.util.List; // 主题接口,定义了添加、删除观察者等方法 interface Subject { void register(Observer observer); void unregister(Observer observer); void notifyObservers(String message); …

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

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

探索数据结构世界之排序篇章(超级详细,你想看的都有)

-文章开头必看 1.!!!本文排序默认都是排升序 2.排序是否稳定值指指排完序之后相同数的相对位置是否改变 3.代码相关解释我都写在注释中了,方便对照着看 1.插入排序1.1直接插入排序1.2希尔排序1.2.1单趟1.2.2多趟基础版——排完一…