STM32CubeMx+FreeRTOS+Clion运用事件组开发按键

文章目录

  • 1、事件组
  • 2、范例
    • 2.1 功能
    • 2.2 步骤
      • 生成
      • 代码
        • 配置
        • 编写
      • API 函数介绍
        • 创建
        • 删除
        • 设置事件标志位
        • 等待事件标志位
  • 3、参考文章

1、事件组

一个事件标志组有多个事件位,每个事件位表示了一个事件的标志。 比如我们用事件标志组的bit0表示事件A、bit1表示事件B、bit2表示事件C,那么这个事件标志组至少可以表示3个事件是否发生。 相比于信号量,它用作信号同步时,只能表示一个资源的有无;而事件标志组,它可以同时表示多个资源的有无。

上述的例子,相当于这个事件标志组实现了等效于3个二值信号量的功能,任务可以在一个事件标志组上同时等待A、B、C三个事件。 任务在等待事件标志组的事件时,可以选等待该组中的一个或某几个事件位。比如上述例子中,虽然事件标志组表示了A、B、C三个事件,但是用户可以设置为只等待A和B。
此外,事件标志组与信号量不同的另一点,是它可以选择在等待到某个事件位时是否对该事件位清零。而使用信号量时,获取到一个信号量时,信号量的计数会自动减1。

2、范例

2.1 功能

创建KEYTaskGetEventTask 两个任务。前者负责检测按键,用于设置事件标志位;后者负责等待接收事件。

2.2 步骤

生成

如图,新建两个任务
STM32CubeMx+FreeRTOS+Clion运用事件组开发按键_第1张图片

STM32CubeMx+FreeRTOS+Clion运用事件组开发按键_第2张图片

代码

配置

配置两个按键任务,FreeRTOS v1版本无法自动生成事件组,这里需手动生成。

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
//创建事件标志
#define Event_Key0 (0x01<<0)
#define Event_Key1 (0x01<<1)
#define Event_KeyUp (0x01<<2)
/* USER CODE END PD */
 
//..............
 
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
EventGroupHandle_t Event_Key_Handle = NULL; //事件组句柄
/* USER CODE END Variables */    
 
//..............
 
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
  Event_Key_Handle = xEventGroupCreate();//创建事件组
  /* USER CODE END Init */
  
  //..............
  
}
编写

对两个任务进行编写

void StartKeyTask(void const * argument)
{
  /* USER CODE BEGIN StartKeyTask */
  /* Infinite loop */
  for(;;)
  {
    osDelay(20);
    if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == 0){
        xEventGroupSetBits(Event_Key_Handle, Event_Key0);
    }
    else if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0){
        xEventGroupSetBits(Event_Key_Handle, Event_Key1);
    }
    else if(HAL_GPIO_ReadPin(KEY_UP_GPIO_Port, KEY_UP_Pin) == 1){
        xEventGroupSetBits(Event_Key_Handle, Event_KeyUp);
    }

  }
  /* USER CODE END StartKeyTask */
}

/* 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 myEventBits_1;
  /* Infinite loop */
  for(;;)
  {
      myEventBits_1 = xEventGroupWaitBits(Event_Key_Handle, Event_Key0|Event_Key1|Event_KeyUp, pdTRUE, pdFALSE, portMAX_DELAY);
      if(myEventBits_1 == Event_Key0){
          HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
      }
      else if(myEventBits_1 == Event_Key1){
          HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
      }
      else if(myEventBits_1 == Event_KeyUp){
          HAL_GPIO_WritePin(GPIOD, LED0_Pin|LED1_Pin, GPIO_PIN_SET);
      }
    osDelay(1);
  }
  /* USER CODE END StartGetEventTask */
}

API 函数介绍

创建
EventGroupHandle_t xEventGroupCreate( void );

/*
创建一个事件组,返回它的句柄。
 * 此函数无需动态分配内存,所以需要先有一个StaticEventGroup_t结构体,并传入它的指针
 * 返回值: 返回句柄,非NULL表示成功
*/
删除
/*
 * xEventGroup: 事件组句柄,你要删除哪个事件组
 */
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
设置事件标志位
/* 设置事件组中的位
 * xEventGroup: 哪个事件组
 * uxBitsToSet: 设置哪些位? 
 *              如果uxBitsToSet的bitX, bitY为1, 那么事件组中的bitX, bitY被设置为1
 *               可以用来设置多个位,比如 0x15 就表示设置bit4, bit2, bit0
 * 返回值: 返回原来的事件值(没什么意义, 因为很可能已经被其他任务修改了)
 */
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
                                    const EventBits_t uxBitsToSet );
等待事件标志位

先引入一个概念:unblock condition。一个任务在等待事件发生时,它处于阻塞状态;当期望的时间发生时,这个状态就叫"unblock condition",非阻塞条件,或称为"非阻塞条件成立";当"非阻塞条件成立"后,该任务就可以变为就绪态。

使用xEventGroupWaitBits来等待事件,可以等待某一位、某些位中的任意一个,也可以等待多位;等到期望的事件后,还可以清除某些位。

EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
                                 const EventBits_t uxBitsToWaitFor,
                                 const BaseType_t xClearOnExit,
                                 const BaseType_t xWaitForAllBits,
                                 TickType_t xTicksToWait );

STM32CubeMx+FreeRTOS+Clion运用事件组开发按键_第3张图片

3、参考文章

【FreeRtos学习笔记】STM32 CubeMx——EventGroup(事件组)

韦东山freeRTOS系列教程之【第八章】事件组(event group)

STM32CubeMX之freeRTOS事件组

STM32CubeIDE+FreeRTOS事件实验

你可能感兴趣的:(STM32,stm32,嵌入式硬件,单片机)