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