第06章 中断管理
约 869 字大约 3 分钟
2026-01-19
6.1 核心知识点
相关宏:
configKERNEL_INTERRUPT_PRIORITY 设置PendSV/SVC的中断优先级,通常配置为最低优先级(15)。
configMAX_SYSCALL_INTERRUPT_PRIORITY 调用taskDISABLE_INTERRUPTS()会屏蔽优先级数值>=该值的中断
configMAX_API_CALL_INTERRUPT_PRIORITY 是configMAX_SYSCALL_INTERRUPT_PRIITY 的旧版名称,现在两个名称都支持,但推荐使用 configMAX_SYSCALL_INTERRUPT_PRIORITY相关函数:
taskDISABLE_INTERRUPTS(); 屏蔽优先级数值大于等于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断
taskENABLE_INTERRUPTS(); 取消屏蔽中断
taskENTER_CRITICAL() 进入临界区
taskEXIT_CRITICAL() 退出临界区
taskENTER_CRITICAL_FROM_ISR() 中断服务程序中进入临界区
taskEXIT_CRITICAL_FROM_ISR() 中断服务程序中退出临界区6.4 STM32 中的中断管理
6.4.1 STM32 中断优先级设置

6.4.2 STM32 屏蔽中断

如:BASEPRI设置为0x50(只看bit7-bit4,也就是5),代表中断优先级在 5~15 内的均被屏蔽,0~4 的中断优先级正常执行。
6.3 案例
① 需求
设置 FreeRTOS 能够屏蔽的的中断优先级范围:5~15。
使用两个TIM2、TIM3两个定时器每隔1s产生一个更新中断,TIM2中断优先级为4,TIM3中断优先级为6。
按下按键 SW3 屏蔽中断,按下按键 SW4 取消屏蔽中断② CubeMX 设置



③ 代码
FreeRTOS.h
添加如下配置:
// 设置允许屏蔽优先级数值>=5的中断
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (5 << 4)
// configMAX_API_CALL_INTERRUPT_PRIORITY 是 configMAX_SYSCALL_INTERRUPT_PRIORITY 旧版名称(兼容性写法)
#define configMAX_API_CALL_INTERRUPT_PRIORITY configMAX_SYSCALL_INTERRUPT_PRIORITYApp_Task.c
注意:不能使用阻塞延时,阻塞延时内容会有进入和退出临界区的过程,退出临界区的时候会取消屏蔽中断!
#include "App_Task.h"
// 任务3 ------------------------------------
// 任务3函数的原型
void task3_callback(void *pvParameters);
// 任务3名称
#define TASK3_NAME "task3"
// 任务3堆栈大小
#define TASK3_STACK_SIZE 128
// 任务3的优先级
#define TASK3_PRIORITY 3
// 任务3的句柄
TaskHandle_t task3_handle;
/**
* @brief 启动 FreeRTOS 任务管理
*
*/
void App_Task_Start(void)
{
// 进入临界区
taskENTER_CRITICAL();
// 创建任务3
xTaskCreate(task3_callback, TASK3_NAME, TASK3_STACK_SIZE, NULL, TASK3_PRIORITY, &task3_handle) == pdPASS ? printf("任务3创建成功! \n") : printf("任务3穿件失败! \n");
// 退出临界区
taskEXIT_CRITICAL();
// 启动任务调度器 ( vTaskStartScheduler() 后面的代码不会被执行)
printf("任务调度器启动... \n");
vTaskStartScheduler();
}
// 任务3函数的实现
void task3_callback(void *pvParameters)
{
printf("任务3启动... \n");
while (1)
{
// 检测按键是否按下
switch (Int_Key_IsDetect())
{
case 3:
// 按键SW3被触发,屏蔽中断
printf("SW3被触发, 屏蔽中断 ... \n");
taskDISABLE_INTERRUPTS();
break;
case 4:
// 按键SW4被触发,取消屏蔽中断
printf("SW4被触发, 取消屏蔽中断 ... \n");
taskENABLE_INTERRUPTS();
break;
default:
break;
}
// 不能使用阻塞延时,阻塞延时内容会有进入和退出临界区的过程,退出临界区的时候会取消屏蔽中断
// vTaskDelay(100);
// 延时100ms
HAL_Delay(100);
}
}main.c
int main(void)
{
/* 前面代码省略 ... */
/* USER CODE BEGIN 2 */
// 打印标题
printf("FreeRTOS Exmaple ... \n");
// 启动TIM2的更新中断
HAL_TIM_Base_Start_IT(&htim2);
// 启动TIM3的更新中断
HAL_TIM_Base_Start_IT(&htim3);
// 启动FreeRTOS任务管理, 一旦启动FreeRTOS,后面代码将不会执行
App_Task_Start();
/* USER CODE END 2 */
/* 后面代码省略 ... */
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM6) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
// 如果是TIM2的更新中断
if (htim->Instance == TIM2)
{
printf("TIM2更新中断触发...\n");
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
}
// 如果是TIM3的更新中断
if (htim->Instance == TIM3)
{
printf("TIM3更新中断触发...\n");
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
}
/* USER CODE END Callback 1 */
}