事件標志組實驗是在 FreeRTOS 中創建了兩個任務,一個是設置事件任務,一個是等待事件任務,兩個任務獨立運行, 設置事件任務通過檢測按鍵的按下情況設置不同的事件標志位,等待事件任務則獲取這兩個事件標志位,並且判斷兩個事件是否都發生,如果是則輸出相應信息。 等待事件任務的等待時間是 osWaitForeve,一直在 等待事件的發生, 等待到事件之后清除對應的事件標記位 。
創建工程RTOS_EventGroup,
配置HCLK,使用內部晶振,頻率為180MHZ(根據板子設置)

將SYS中時基源(Timebase Source)改為除SysTick之外的任意定時器即可,如:

配置板載的按鍵KEY1和KEY2

配置FreeRTOS,使用CMSIS_V1,

定義兩個任務,KEYTask和GetEventTask

Ctrl + S生成代碼
修改代碼,
1,在main.h中添加
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */
2,在mian.c中添加
/* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define KEY1_EVENT (0x01 << 0)//設置事件掩碼的位 0 #define KEY2_EVENT (0x01 << 1)//設置事件掩碼的位 1 /* USER CODE END PD */ ... ... ... /* USER CODE BEGIN PV */ EventGroupHandle_t Event_Handle = NULL; /* USER CODE END PV */ ... ... ... /* USER CODE BEGIN PFP */ int _write(int file , char *ptr,int len) { int i = 0; for(i = 0;i<len;i++) ITM_SendChar((*ptr++)); return len; } /* USER CODE END PFP */ ... ... ... /* USER CODE BEGIN 2 */ Event_Handle = xEventGroupCreate(); printf("starting...\n"); /* USER CODE END 2 */
3,在main.c中修改2個任務入口函數的內容
/* USER CODE BEGIN Header_StartKEYTask */ /** * @brief Function implementing the KEYTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartKEYTask */ void StartKEYTask(void const * argument) { /* USER CODE BEGIN 5 */ /* Infinite loop */ for(;;) { if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1) { /**/ osDelay(5); if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1) { while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1); printf("KEY1 is pressed.\n"); xEventGroupSetBits(Event_Handle, KEY1_EVENT); } } if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1) { /**/ osDelay(5); if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1) { while(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1); printf("KEY2 is pressed.\n"); xEventGroupSetBits(Event_Handle, KEY2_EVENT); } } osDelay(10); } /* USER CODE END 5 */ }
/* USER CODE BEGIN Header_StartGetEventTask */ /** * @brief Function implementing the GetEventTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartGetEventTask */ void StartGetEventTask(void const * argument) { /* USER CODE BEGIN StartGetEventTask */ EventBits_t r_event; /* Infinite loop */ for(;;) { r_event = xEventGroupWaitBits(Event_Handle,/*事件對象句柄*/ KEY1_EVENT | KEY2_EVENT,/*接收任務感興趣的事件*/ pdTRUE,/* 退出時清除事件位 */ pdTRUE,/* 滿足感興趣的所有事件 */ osWaitForever);/* 指定超時事件,一直等 */ if ((r_event & (KEY1_EVENT|KEY2_EVENT)) == (KEY1_EVENT|KEY2_EVENT)) { /* 如果接收完成並且正確 */ printf ( "Press KEY1 and KEY2\n"); } else printf ( "Event error!\n"); } /* USER CODE END StartGetEventTask */ }
修改完畢后點擊 小錘子 構建工程,然后點擊Debug,按如下步驟配置ITM調試



全速運行之前一定要先點擊SWV ITM data Console 頁面中的紅色圓圈

現象:

分析:
2個任務:KEYTask負責檢測按鍵,當按鍵1按下時,將KEY1_Event位置位,觸發一個事件 1 ,當按鍵2按下時,將KEY2_Event位置位,觸發一個事件 2
GetEventTask負責等待接收事件 ,當所有位都被設置或等待超時時退出,等待時間為一直等待。
可以看到,當只按下一個鍵時,GetEventTask任務不會執行,必須當兩個按鍵都被按下時,才會輸出提示信息。
