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任务不会执行,必须当两个按键都被按下时,才会输出提示信息。

 

 




posted @ 2019-12-12 11:35  飞起的小田  阅读(5573)  评论(0编辑  收藏  举报