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.使用串口觀察輸出資訊

經驗證,程式運行結果與預想一致
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/396321.html
標籤:其他
