STM32---FreeRTOS事件标志组

news2025/3/18 18:34:12

一、简介

事件标志位:用一个位,来表示事件是否发生

事件标志组:一组事件标志位的集合,可以简单的理解时间标志组,就是一个整体。

事件标志租的特点:

        它的每一个位表示一个时间(高8位不算);

        每一个事件的含义,由用户自己决定,如:bit0表示按键是否按下,bit1表示是否接收到消息...(这些位的值为1:表示事件发生了;值为0,表示事件未发生)

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

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

 虽然使用了 32 位无符号的数据类型变量来存储事件标志, 但其中的高8位用作存储事件标志组的控制信息低24位用作存储事件标志 ,所以说一个事件组最多可以存储 24 个事件标志!

事件标志组、队列和信号量的区别? 

二、相关API函数 

三、实验

 代码:

main.c

#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "freertos_demo.h"
#include "Delay.h"
#include "sys.h"
#include "usart.h"
#include "LED.h"
#include "Key.h"

 
 int main(void)
 {	
	 
	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4 
	 uart_init(115200);	 
	 delay_init();
	 Key_Init();
	 LED_Init();
	 
	    // 创建任务
   FrrrRTOS_Demo();
		 	  
}

freertos_demo.c

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"
#include "LED.h"
#include "Key.h"
#include "usart.h"
#include "delay.h"

/******************************************************************任务配置****************************************************/
//任务优先级
#define START_TASK_PRIO					1
//任务堆栈大小	
#define START_TASK_STACK_SIZE 	128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);


//任务优先级
#define TASK1_PRIO							2
//任务堆栈大小	
#define TASK1_STACK_SIZE 				128  
//任务句柄
TaskHandle_t Task1_Handler;
//任务函数
void task1(void *pvParameters);
 
//任务优先级
#define TASK2_PRIO							3
//任务堆栈大小	
#define TASK2_STACK_SIZE 				128  
//任务句柄
TaskHandle_t Task2_Handler;
//任务函数
void task2(void *pvParameters);


 
#define		EVENTBIT0 	(1<<0)
#define		EVENTBIT1 	(1<<1)




/******************************************************************任务函数****************************************************/
EventGroupHandle_t	eventgroud_handle;


void FrrrRTOS_Demo(void)
{
			 //创建开始任务
		xTaskCreate((TaskFunction_t )start_task,            			//任务函数
                ( char*         )"start_task",          			//任务名称
                (uint16_t       )START_TASK_STACK_SIZE, 			//任务堆栈大小
                (void*          )NULL,                  			//传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       			//任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   			//任务句柄 
	  // 启动任务调度
		vTaskStartScheduler();
	 
}


 void start_task(void *pvParameters)
{
	  taskENTER_CRITICAL();           //进入临界区
	
		/*创建事件标志组*/
		eventgroud_handle = xEventGroupCreate();
		if(eventgroud_handle != NULL)
		{
			printf("\r\n事件标志组创建成功\r\n");
		}

    //创建1任务
    xTaskCreate((TaskFunction_t )task1,     	
                (const char*    )"task1",   	
                (uint16_t       )TASK1_STACK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )TASK1_PRIO,	
                (TaskHandle_t*  )&Task1_Handler); 
    //创建2任务
    xTaskCreate((TaskFunction_t )task2,     
                (const char*    )"task2",   
                (uint16_t       )TASK2_STACK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&Task2_Handler);    
								
  
		
    vTaskDelete(NULL); 							//删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}


//1 实现队列写入和信号量释放函数
void task1(void *pvParameters)
{
	uint8_t				key = 0;
//	EventBits_t		eventbit;
	
	while(1)
	{

		key = Key_GetNum();
		if(key == 2)
		{
			xEventGroupSetBits( eventgroud_handle,EVENTBIT0);		//将事件标志组bit0位置1

		}else if(key == 3){
			xEventGroupSetBits( eventgroud_handle,EVENTBIT1);		//将事件标志组bit0位置1
		
		}
		
		vTaskDelay(10);
	}
}


// 任务2 获取队列集消息函数
void task2(void *pvParameters)
{
		EventBits_t	event_bit = 0;
	
    // 任务主循环
    while (1)
    {
			event_bit = xEventGroupWaitBits(eventgroud_handle,				//事件标志组句柄
													EVENTBIT0|EVENTBIT1,									//等待事件标志组的bit0和bit1
													pdTRUE,																//成功等待到事件标志位后,清除事件标志组中的bit位
													pdTRUE,																//等待时间标志组bit0和bit1位都置1,都成立				
													portMAX_DELAY);												//死等		
			printf("等待到的事件标志位值为:%d\r\n",event_bit);
		}
}

key.c

#include "stm32f10x.h"                  // Device header
#include "FreeRTOS.h"
#include "task.h"
#include "usart.h"
#include "Delay.h"
 
/**
  * 函    数:按键初始化
  * 参    数:无
  * 返 回 值:无
	* 按键:PB4/PB12/PB14
  */
void Key_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOB的时钟
 
	/*GPIO初始化*/
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_4 | GPIO_Pin_12 | GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);						
}
 
 
/**
  * 函    数:按键获取键码
  * 参    数:无
  * 返 回 值:按下按键的键码值,范围:0~3,返回0代表没有按键按下
  * 注意事项:此函数是阻塞式操作,当按键按住不放时,函数会卡住,直到按键松手
  */
uint8_t Key_GetNum(void)
{
	uint8_t KeyNum = 0;																				//定义变量,默认键码值为0
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4) == 0)			  //读PB4输入寄存器的状态,如果为0,则代表按键1按下
	{
		KeyNum= GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4);
		delay_xms(20);																					//延时消抖
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4) == 0);	//等待按键松手
		delay_xms(20);																					//延时消抖
		KeyNum = 1;																							//置键码为1
	}
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0)			
	{
		KeyNum= GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12);
		delay_xms(20);											
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0);	
		delay_xms(20);									
		KeyNum = 2;											
	}
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)			
	{
		KeyNum= GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14);
		delay_xms(20);											
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0);	
		delay_xms(20);									
		KeyNum = 3;											
	}
	
	return KeyNum;																						//返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
}
 
 
 
 
 

四、实验解析

 只有两个按键同时按下时,才会打印;

五、重点

动态方式创建事件标志组API函数:

EventGroupHandle_t    xEventGroupCreate ( void ) ;

清除事件标志位API函数:

EventBits_t   ( EventGroupHandle_t     xEventGroup,                           const EventBits_t     uxBitsToClear );

设置事件标志位API函数:

EventBits_t   xEventGroupSetBits(  EventGroupHandle_t     xEventGroup,                           const EventBits_t         uxBitsToSet    );

 等待事件标志位API函数:

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

同步函数: 

EventBits_t    xEventGroupSync(   EventGroupHandle_t     xEventGroup,                                                                                     const EventBits_t     uxBitsToSet,                       

                                                       const EventBits_t     uxBitsToWaitFor,                                                                               TickType_t         xTicksToWait) ;

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

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

相关文章

Word 小黑第40套

对应大猫43 主题 -浏览主题 -选择W样式标准文件就行 1级段落和2级段落&#xff08;用项目符号不影响原本段落文字符号 颜色修改为自动&#xff09; 整段变红的 不是把光标定位到红色字体那里 要选择几个红色字体 再创建样式 插入的空白页一定要是下一页&#xff0c;不能插空白…

【Linux我做主】浅谈Shell及其原理

浅谈Linux中的Shell及其原理 Linux中Shell的运行原理github地址前言一、Linux内核与Shell的关系1.1 操作系统核心1.2 用户与内核的隔离 二、Shell的演进与核心机制2.1 发展历程2.2 核心功能解析2.3 shell的工作流程1. 用户输入命令2. 解析器拆分指令3. 扩展器处理动态内容变量替…

数据结构篇——二叉树的存储与遍历

一、引入 书接上文&#xff0c;文于此续。上文我们学到了树的存储结构&#xff0c;那么今天&#xff0c;我们来学习下几种特殊的二叉树以及关于它的各种遍历&#xff0c;让我们一起加油吧。 二、特殊的二叉树 二叉树的特殊形式这里介绍3种&#xff0c;其中需要着重记忆的有…

分而治之:用于 RGB-T 显著目标检测的 Confluent Triple-Flow 网络(问题)

摘要 问题一&#xff1a;RGB-thermal显著对象检测这是什么&#xff1f; RGB图像是可见光的三通道图像&#xff0c;而thermal是热红外图像&#xff0c;通常为单通道&#xff0c;记录物体的热辐射信息。结合RGB和thermal两种模态的数据&#xff0c;可以利用两者的互补信息&…

求职招聘网站源码,找工作招工系统,支持H5和各种小程序

招聘找活招工平台系统源码 招聘求职找工作软件 发布信息积分充值招聘系统,里面带纤细教程 功能介绍: 招工小程序主要针对工地招工工人找工作,工地可以发布招工信息,工人可以发布找活信息,招工信息可以置顶,置顶需要积分,积分可以通过签到、分享邀请好友、充值获取,后…

企业微信群聊机器人开发

拿到机器人hook 机器人开发文档 https://developer.work.weixin.qq.com/document/path/91770

基于Python的tkinter开发的一个工具,解析图片文件名并将数据自动化导出为Excel文件

文章目录 一、开发背景与业务价值二、系统架构设计1. 分层架构图解2. 核心类结构3. 文件解析流程 三、关键技术实现详解1. 高性能文件名解析引擎2. 可视化数据展示3. 智能Excel导出模块 四、完整代码五、行业应用展望 一、开发背景与业务价值 在零售行业会员管理场景中&#x…

Flutter_学习记录_状态管理之GetX

1. 状态管理、Flutter Getx介绍 1.1 状态管理 通俗的讲&#xff1a;当我们想在多个页面&#xff08;组件/Widget&#xff09;之间共享状态&#xff08;数据&#xff09;&#xff0c;或者一个页面&#xff08;组件/Widget&#xff09;中的多个子组件之间共享状态&#xff08;数…

【网络】数据流(Data Workflow)Routes(路由)、Controllers(控制器)、Models(模型) 和 Middleware(中间件)

在图片中&#xff0c;数据流&#xff08;Data Workflow&#xff09;描述了应用程序中数据的流动过程&#xff0c;涉及 Routes&#xff08;路由&#xff09;、Controllers&#xff08;控制器&#xff09;、Models&#xff08;模型&#xff09; 和 Middleware&#xff08;中间件&…

Git下载安装(保姆教程)

目录 1、Git下载 2、Git安装&#xff08;windows版&#xff09; &#xff08;1&#xff09;启动安装程序 &#xff08;2&#xff09;阅读许可协议 &#xff08;3&#xff09;选择安装路径 &#xff08;4&#xff09;选择组件 &#xff08;5&#xff09;选择开始菜单文件夹…

Blender-MCP服务源码2-依赖分析

Blender-MCP服务源码2-依赖分析 有个大佬做了一个Blender-MCP源码&#xff0c;第一次提交代码是【2025年3月7号】今天是【2025年月15日】也就是刚过去一周的时间&#xff0c;所以想从0开始学习这个代码&#xff0c;了解一下大佬们的开发思路 1-核心知识点 from mcp.server.fas…

LabVIEW压比调节器动态试验台

本案介绍了一种基于LabVIEW的压比调节器动态试验台的设计&#xff0c;通过实用的LabVIEW图形化编程语言&#xff0c;优化了数据采集与处理的整个流程。案例通过实际应用展示了设计的专业性与高效性&#xff0c;以及如何通过系统化的方法实现精确的动态测试和结果分析。 ​ 项目…

2025-03-17 Unity 网络基础1——网络基本概念

文章目录 1 网络1.1 局域网1.2 以太网1.3 城域网1.4 广域网1.5 互联网&#xff08;因特网&#xff09;1.6 万维网1.7 小结 2 IP 地址2.1 IP 地址2.2 端口号2.3 Mac 地址2.4 小结 3 客户端与服务端3.1 客户端3.2 服务端3.3 网络游戏中的客户端与服务端 1 网络 ​ 在没有网络之前…

springboot441-基于SpringBoot的校园自助交易系统(源码+数据库+纯前后端分离+部署讲解等)

&#x1f495;&#x1f495;作者&#xff1a; 爱笑学姐 &#x1f495;&#x1f495;个人简介&#xff1a;十年Java&#xff0c;Python美女程序员一枚&#xff0c;精通计算机专业前后端各类框架。 &#x1f495;&#x1f495;各类成品Java毕设 。javaweb&#xff0c;ssm&#xf…

浅谈数据分析及数据思维

目录 一、数据分析及数据分析思维&#xff1f;1.1 数据分析的本质1.2 数据分析思维的本质1.2.1 拥有数据思维的具体表现1.2.2 如何培养自己的数据思维1.2.2.1 书籍1.2.2.2 借助工具1.2.2.3 刻意练习 二、数据分析的价值及必备能力&#xff1f;2.1 数据分析的价值2.1.1 现状分析…

自定义uniapp组件,以picker组件为例

编写目的 本文说明基于vue3定义uniapp组件的关键点&#xff1a; 1、一般定义在components文件夹创建组件&#xff0c;组件与页面已经没有明确的语法格式区别&#xff0c;所以可以与页面的语法保持一致 &#xff1b; 2、组件定义后使用该组件的页面不需要引用组件即可使用&am…

【操作系统安全】任务4:Windows 系统网络安全实践里常用 DOS 命令

目录 一、引言 二、网络信息收集类命令 2.1 ipconfig 命令 2.1.1 功能概述 2.1.2 实例与代码 2.2 ping 命令 2.2.1 功能概述 2.2.2 实例与代码 2.3 tracert 命令 2.3.1 功能概述 2.3.2 实例与代码 三、网络连接与端口管理类命令 3.1 netstat 命令 3.1.1 功能概述…

【从零开始学习计算机科学】信息安全(二)物理安全

【从零开始学习计算机科学】信息安全(二)物理安全 物理安全物理安全的涵义物理安全威胁常见物理安全问题物理安全需求规划物理安全需求设备安全防盗和防毁机房门禁系统机房入侵检测和报警系统防电磁泄漏防窃听设备管理设备维护设备的处置和重复利用设备的转移电源安全电源调整…

LeetCode hot 100—验证二叉搜索树

题目 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 示例 1&#…

MongoDB 可观测性最佳实践

MongoDB 介绍 MongoDB 是一个高性能、开源的 NoSQL 数据库&#xff0c;它采用灵活的文档数据模型&#xff0c;非常适合处理大规模的分布式数据。MongoDB 的文档存储方式使得数据结构可以随需求变化而变化&#xff0c;提供了极高的灵活性。它支持丰富的查询语言&#xff0c;允许…