STM32CubeIDE+FreeRTOS事件實驗


  事件標志組實驗是在 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任務不會執行,必須當兩個按鍵都被按下時,才會輸出提示信息。

 

 





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM