文章目录[隐藏]
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.使用串口观察输出信息
经验证,程序运行结果与预想一致
版权声明:本文为CSDN博主「SSS&10&01」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45691873/article/details/122181588
暂无评论