• 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...
    ");
      /* 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.
    ");
                  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.
    ");
                  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
    ");
          } else
              printf ( "Event error!
    ");
      }
      /* USER CODE END StartGetEventTask */
    }

    修改完毕后点击 小锤子 构建工程,然后点击Debug,按如下步骤配置ITM调试

     

     全速运行之前一定要先点击SWV ITM data Console 页面中的红色圆圈

    现象:

     分析:

    2个任务:KEYTask负责检测按键,当按键1按下时,将KEY1_Event位置位,触发一个事件 1 ,当按键2按下时,将KEY2_Event位置位,触发一个事件 2
    GetEventTask负责等待接收事件 ,当所有位都被设置或等待超时时退出,等待时间为一直等待。

    可以看到,当只按下一个键时,GetEventTask任务不会执行,必须当两个按键都被按下时,才会输出提示信息。




  • 相关阅读:
    单链队列
    栈的顺序存储表示
    顺序队列
    串的定长顺序存储表示
    串的堆分配存储
    双向循环链表
    单循环链表的表示和实现
    串的块链存储表示
    线性表的顺序表示和实现
    线性表的单链表表示和实现
  • 原文地址:https://www.cnblogs.com/tianxxl/p/12028217.html
Copyright © 2020-2023  润新知