FreeRTOS复习笔记(五) —— 事件组

FreeRTOS复习笔记(五) —— 事件组

1.本例程思路:

创建四个任务,一个任务用于设置事件位,另外三个任务获取事件位,
KEY_GPIO(PA0)下降沿,第一次设置事件位1,第二次设置事件位2,第三次清除事件位1;
第一个获取任务(低优先级),获取到事件1后,不清除事件位;
第三个获取任务(高优先级),同时获取到事件1,2后,不清除事件位;
第二个获取任务(中优先级),获取到事件2后,清除事件位;

现象应为,
KEY_GPIO第一个下降沿,第一个任务一直打印输出信息直到KEY_GPIO第三个下降沿;
KEY_GPIO第二个下降沿,第三个任务,第二个任务依次打印一条输出信息;
KEY_GPIO第三个下降沿,第一个任务停止打印输出信息;

创建事件使用 xEventGroupCreate 函数,设置事件位、清除事件位分别使用 xEventGroupSetBits、xEventGroupClearBits函数,等待事件使用 xEventGroupWaitBits 函数

2.代码编写

/**
  ******************************************************************************
  * @文件名: xxx.c
  * @作  者: author
  * @版  本: v1.0.0
  * @日  期: 2021.12.27
  * @简  介: 无
  * @注  意: 无
  ******************************************************************************
  */
#include "stm32f10x.h"

#include "dr_usart.h"
#include "dr_led.h"
#include "dr_key.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"

void AppTaskCreateTask(void *);
void LEDTask(void *);
void LED2Task(void *);
void ___3Task(void *);
void KEYTask(void *);

/* --- 事件 --- */
EventGroupHandle_t TestEventGroup_Handle = NULL;

/**
  * @简  介: 无
  * @参  数: 无
  * @返回值: 无
  */
int main(void)
{
	/* --------- --------- --------- --------- --------- --------- ---------  */
	
	/* 中断分组4 */
	NVIC_Priority_Group_Config();                                        /* * */
	
	/* 串口1配置 */
	USART1_Config();                                                     /* * */
	
	/* LED(PA8, PA6)配置 */
	LED_GPIO_Config();                                                   /* * */
	
	/* KEY(PA0)配置 */
	KEY_GPIO_Config();
	
	/* --------- --------- --------- --------- --------- --------- ---------  */

	/* 创建任务 */
	xTaskCreate(AppTaskCreateTask, "AppTaskCreateTask", 128, NULL, 1, NULL);
	
	/* 开启任务调度 */
	vTaskStartScheduler();
	
	while(1);
}

/**
  * @简  介: 无
  * @参  数: 无
  * @返回值: 无
  */
void AppTaskCreateTask(void *pvParameters)
{
	/* 临界区 */
	taskENTER_CRITICAL();
	
	/* 创建任务 */
	xTaskCreate(LEDTask, "LEDTask", 128, NULL, 2, NULL);

	xTaskCreate(LED2Task, "LED2Task", 128, NULL, 3, NULL);

	xTaskCreate(___3Task, "___3Task", 128, NULL, 4, NULL);

	xTaskCreate(KEYTask, "KEYTask", 128, NULL, 5, NULL);

	/* 创建事件 */
	TestEventGroup_Handle = xEventGroupCreate();

	if (TestEventGroup_Handle != NULL)
		printf("--- TestEventGroup was created ---.\r\n\r\n");

	vTaskDelete(NULL);

	taskEXIT_CRITICAL();
}

EventBits_t _event1 = 0;

/**
  * @简  介: 无
  * @参  数: 无
  * @返回值: 无
  */
void LEDTask(void *pvParameters)
{
	for (;;)
	{
		/*                            事件句柄               指定位           是否清除      是否等待所有位   等待超时*/
		/* 等待指定事件指定位,        EventGroupHandle_t     uxBitsToWaitFor  xClearOnExit  xWaitForAllBits  xTicksToWait */
		_event1 = xEventGroupWaitBits(TestEventGroup_Handle, 0x0001,          pdFALSE,      pdFALSE,         portMAX_DELAY);

		if (_event1 & 0x0001)
			printf("event1 has been obtained.\r\n");

		GPIOA->ODR ^= ((uint16_t)0x0100); /* 翻转LED(PA8) */
		
//		printf("LED %s\r\n", ((GPIOA->IDR & 0x0100) != 0) ? "is running." : "stops running.");

		vTaskDelay(100);
	}
}

EventBits_t _event2 = 0;

/**
  * @简  介: 无
  * @参  数: 无
  * @返回值: 无
  */
void LED2Task(void *pvParameters)
{
	for (;;)
	{
		/*                            事件句柄               指定位           是否清除      是否等待所有位   等待超时*/
		/* 等待指定事件指定位,        EventGroupHandle_t     uxBitsToWaitFor  xClearOnExit  xWaitForAllBits  xTicksToWait */
		_event2 = xEventGroupWaitBits(TestEventGroup_Handle, 0x0002,          pdTRUE,       pdFALSE,         portMAX_DELAY);

		if (_event2 & 0x0002)
			printf("event2 has been obtained.\r\n");

		GPIOA->ODR ^= ((uint16_t)0x0040); /* 翻转LED(PA6) */

		vTaskDelay(100);
	}
}

EventBits_t _event3 = 0;

/**
  * @简  介: 无
  * @参  数: 无
  * @返回值: 无
  */
void ___3Task(void *pvParameters)
{
	for (;;)
	{
		/*                            事件句柄               指定位           是否清除      是否等待所有位   等待超时*/
		/* 等待指定事件指定位,        EventGroupHandle_t     uxBitsToWaitFor  xClearOnExit  xWaitForAllBits  xTicksToWait */
		_event3 = xEventGroupWaitBits(TestEventGroup_Handle, 0x0003,          pdFALSE,      pdTRUE,          portMAX_DELAY);

		if ( (_event3 & 0x0003) == 0x0003 )
			printf("event3 has been obtained.\r\n");

		vTaskDelay(100);
	}
}

EventBits_t _event0 = 0;

/**
  * @简  介: 无
  * @参  数: 无
  * @返回值: 无
  */
void KEYTask(void *pvParameters)
{
	uint8_t level_high = 0;
	uint8_t level_low  = 0;
	uint8_t edge_fall  = 0;
	uint8_t edge_rise  = 0;
	uint8_t _switch    = 0;
	
	for (;;)
	{
		/* 高电平/上升沿检测 */
		if ( (GPIOA->IDR & 0x0001) != 0 )
		{
			if (level_low == 1)   edge_rise = 1;
			
			level_low  = 0;      level_high = 1;
		}
		
		/* 低电平/下降沿检测 */
		if ( (GPIOA->IDR & 0x0001) == 0 )
		{
			if (level_high == 1) edge_fall  = 1;
			
			level_high = 0;      level_low  = 1;
		}

		if (edge_fall) /* 出现下降沿 */
		{
			switch(_switch)
			{
					/*                     事件句柄           指定位*/
			case 0: /* 设置指定事件指定位, EventGroupHandle_t uxBitsToSet */
				_event0 = xEventGroupSetBits(TestEventGroup_Handle, 0x0001);
				_switch++;
				break;

			case 1: /* 设置事件位 */
				_event0 = xEventGroupSetBits(TestEventGroup_Handle, 0x0002);
				_switch++;
				break;
					/*                     事件句柄           指定位*/
			case 2: /* 清除指定事件指定位, EventGroupHandle_t uxBitsToClear */
				_event0 = xEventGroupClearBits(TestEventGroup_Handle, 0x0001);
				_switch = 0;
				break;

			default:
				_switch = 0;
				break;
			}
		}
		
		edge_fall = 0;
		edge_rise = 0;
		(void)edge_rise;
		(void)_event0;
	
		vTaskDelay(20);
	}
}

3.使用串口观察输出信息
SSS005.001
经验证,程序运行结果与预想一致

版权声明:本文为CSDN博主「SSS&10&01」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45691873/article/details/122181588

生成海报
点赞 0

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

FreeRTOS复习笔记(四) —— 信号量

FreeRTOS复习笔记(四) —— 信号量 一、二值信号量与计数信号量 1.本例程思路: 本篇将二值信号量与计数信号量写入同一段代码,使用 _USE_BINARY_SEMAPHORE 与 _USE_COUNT

GD32F205在IAR上移植FreeRTOS

简述: 1、主芯片:GD32F205VET6 2、编译器:IAR V8.40.1 3、系统:FreeRTOS V9.0 第一步:准备最简工程与系统 1、准备一个GD32

freertos与rtthread内核实现的不同处

一直在使用rtos作为主要开发内容,却没有详细了解过rtos的内核实现机制。最近一个月,抽了点时间将freertos和rtthread的内核代码看了下,了解了实时系统的实现机制和设计思想。这里学习fre