事件标志组实验是在 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任务不会执行,必须当两个按键都被按下时,才会输出提示信息。
来源:https://www.cnblogs.com/tianxxl/p/12028217.html