其实,关于中断的概念和定义在之前已经反复学习和实践了,这节主要讲和FreeRTOS相关的中断知识。
中断优先级
任何中断的优先级都大于任务!
在我们的操作系统,中断同样是具有优先级的,并且我们也可以设置它的优先级,但是他的优先 级并不是从 0~15 ,默认情况下它是从 5~15 ,0~4 这 5 个中断优先级不是 FreeRTOS 控制的(5是取决于 configMAX_SYSCALL_INTERRUPT_PRIORITY)。
相关注意!!!
- 在中断中必需使用中断相关的函数
- 中断服务函数运行时间越短越好
实操演示
需求:创建一个队列及一个任务,按下按键 KEY1 触发中断,在中断服务函数里向队列里发送数据,任务则阻塞接收队列数据。
在 C:\mjm_CubeMX_proj 路径下,复制一份Cube的母版并重命名为 :mjm_freeRTOS_inter:
打开相应的Cube文件:
1. 将按钮配置为中断:
1.1 在左侧的NVIC中 打开并设置中断优先级:
2. 找到左侧的Middleware --> FREERTOS,然后在下方找到"Task and Queues",创建一个队列:
3. 生成代码打开Keil:
在stm32f1xx_it.c -> EXTI0_IRQHandler -> HAL_GPIO_EXTI_IRQHandler() -> HAL_GPIO_EXTI_Callback
HAL_GPIO_EXTI_Callback就是可以覆写的中断回调函数:
3.1 在stm32f1xx_it.c中对Callback函数进行重写:
由于使用了其他freertos.c文件的句柄变量,且涉及到了freeRTOS的函数,所以要申明extern变量并添加"cmsis_os.h"库
#include "cmsis_os.h"
extern osMessageQId myQueueHandle;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
uint32_t snd = 1; //要向队列中发送的信息
xQueueSendFromISR(myQueueHandle, &snd, NULL); //注意要用中断相关的队列发送函数
//第一个参数是句柄;第二个参数是要传输的值;第三个变量一般设置为NULL
}
3.2 在freertos.c中写任务的内容:
#include "stdio.h"
void StartDefaultTask(void const * argument)
{
uint32_t rev = 0;
for(;;)
{
if (xQueueReceive(myQueueHandle, &rev, portMAX_DELAY) == pdTRUE){ //队列的接收不再中断中,不需要使用中断相关的函数
printf("rev = %d\r\n", rev);
}
osDelay(1);
}
}
实现效果
打开串口助手并按下KEY1:
可见,成功触发了中断,并在回调函数中向队列成功发送了信息并被任务成功接收!