STM32CubeIDE+FreeRTOS中断管理实验
定义了两个按键 KEY1 与 KEY2 的触发方式为中断触发,在中断触发的时候通过消息队列将消息传递给任务, 任务接收到消息就将信息通过printf打印出来。
创建工程RTOS_Interrupt,
配置HCLK,使用内部晶振,频率为180MHZ(根据板子设置)
将SYS中时基源(Timebase Source)改为除SysTick之外的任意定时器即可,如:
配置板载的按键KEY1和KEY2
配置FreeRTOS,使用CMSIS_V1,
定义一个任务,
Ctrl + S生成代码
修改代码,
1,在main.h中添加
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */
2,在mian.c中添加
/* 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 */ printf("starting...\n"); /* USER CODE END 2 */ ... ... ...
3,在main.c中修改任务入口函数的内容
/* USER CODE BEGIN Header_StartGetQueueTask */ /** * @brief Function implementing the GetQueueTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartGetQueueTask */ void StartGetQueueTask(void const * argument) { /* USER CODE BEGIN 5 */ osEvent theEvent; /* Infinite loop */ for(;;) { theEvent = osMessageGet(myQueue01Handle, osWaitForever); if(theEvent.status == osEventMessage) { printf("What triggers the interrupt is KEY%ld !\n",theEvent.value.v); } osDelay(1); } /* USER CODE END 5 */ }
4,在stm32f4xx_it.c中添加代码
/* USER CODE BEGIN Includes */ #include "cmsis_os.h" /* USER CODE END Includes */ ... ... ... /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ extern osMessageQId myQueue01Handle; extern osSemaphoreId myBinarySem01Handle; static uint32_t send_data1 = 1; static uint32_t send_data2 = 2; /* USER CODE END PV */
5,在stm32f4xx_it.c中修改两个按键的中断函数
/** * @brief This function handles EXTI line0 interrupt. */ void EXTI0_IRQHandler(void) { /* USER CODE BEGIN EXTI0_IRQn 0 *///确保是否产生了 EXTI Line 中断 uint32_t ulReturn; /* 进入临界段,临界段可以嵌套 */ ulReturn = taskENTER_CRITICAL_FROM_ISR(); /* 将数据写入(发送)到队列中,等待时间为 0 */ osMessagePut(myQueue01Handle, send_data1,0); //如果需要的话进行一次任务切换 // portYIELD_FROM_ISR(pxHigherPriorityTaskWoken); // osThreadYield(); /* 退出临界段 */ taskEXIT_CRITICAL_FROM_ISR( ulReturn ); /* USER CODE END EXTI0_IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); /* USER CODE BEGIN EXTI0_IRQn 1 */ /* USER CODE END EXTI0_IRQn 1 */ }
/** * @brief This function handles EXTI line[15:10] interrupts. */ void EXTI15_10_IRQHandler(void) { /* USER CODE BEGIN EXTI15_10_IRQn 0 *///确保是否产生了 EXTI Line 中断 uint32_t ulReturn; /* 进入临界段,临界段可以嵌套 */ ulReturn = taskENTER_CRITICAL_FROM_ISR(); /* 将数据写入(发送)到队列中,等待时间为 0 */ osMessagePut(myQueue01Handle, send_data2,0); //如果需要的话进行一次任务切换 // portYIELD_FROM_ISR(pxHigherPriorityTaskWoken); // osThreadYield(); /* 退出临界段 */ taskEXIT_CRITICAL_FROM_ISR( ulReturn ); /* USER CODE END EXTI15_10_IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); /* USER CODE BEGIN EXTI15_10_IRQn 1 */ /* USER CODE END EXTI15_10_IRQn 1 */ }
修改完毕后点击 小锤子 构建工程,然后点击Debug,按如下步骤配置ITM调试
全速运行之前一定要先点击SWV ITM data Console 页面中的红色圆圈
现象:
按下KEY1或KEY2,输出对应的信息。