STM32---FreeRTOS事件标志组

一、简介

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

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

事件标志租的特点:

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

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

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

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

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

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

二、相关API函数

三、实验

代码:

main.c

cs 复制代码
#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

cs 复制代码
#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

cs 复制代码
#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) ;

相关推荐
promising-w1 小时前
硬件工程师入门教程(四)
嵌入式硬件
坏柠1 小时前
STM32与HAL库开发实战:深入探索ESP8266的多种工作模式
stm32·单片机·嵌入式硬件
电鱼智能的电小鱼2 小时前
SAIL-RK3576核心板应用方案——无人机视觉定位与地面无人设备通信控制方案
linux·嵌入式硬件·无人机·边缘计算
Amy.com2 小时前
嵌入式2-按键
stm32·单片机·嵌入式硬件
printf_013 小时前
HAL库STM32常用外设—— CAN通信(一)
stm32·单片机·嵌入式硬件
小麦嵌入式3 小时前
Linux驱动开发实战(五):Qt应用程序点RGB灯(保姆级快速入门!)
linux·驱动开发·stm32·嵌入式硬件·mcu·qt·ubuntu
小禾苗_4 小时前
32单片机——BEEP
单片机·嵌入式硬件
听风lighting4 小时前
嵌入式八股ARM篇
c语言·arm开发·单片机·嵌入式硬件
螺丝工人5 小时前
stm32 L432KC(mbed)入门第一课
stm32·单片机·嵌入式硬件