5,FreeRTOS中断管理
一、实验目标
创建两个动态任务,栈空间大小均为128字。startTask、Task1。startTask仅运行一次,负责task1任务的创建,startTask任务的删除。Task1负责5S关闭一次中断,5S开启一次中断。
注:本实验基于正点原子FreeRTOS教程的学习总结。
二、实验准备
1.FreeRTOS的Keil动态任务创建与删除程序
2.STM3F407开发板
3.HAL_Init()函数修改
在main()函数中找到HAL_Init()函数,并跳转到函数定义位置,在函数中找到NVIC中断分组函数设置为第四组,即NVIC_PRIORITYGROUP_4。
/* Set Interrupt Group Priority */HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
设置为NVIC_PRIORITYGROUP_4是因为FreeRTOS仅能管理优先级为5-15的中断,而STM32的优先级分组方式4,设置中断优先级为0-15,这样方便FreeRTOS管理中断。
4.基本定时器中断初始化
需要添加基本定时器.c文件,并在mian函数中初始化基本定时器中断。
4.1btim.h头文件修改
首先,在.h文件中添加基本定时的配置信息。这里使用定时器6/7,分别定时为1S输出一次信息。
#define BTIM_TIM6_INT TIM6
#define BTIM_TIM6_INT_IRQn TIM6_DAC_IRQn
#define BTIM_TIM6_INT_IRQHandler TIM6_DAC_IRQHandler
#define BTIM_TIM6_INT_CLK_ENABLE() do{ __HAL_RCC_TIM6_CLK_ENABLE(); }while(0) /* TIM6 时钟使能 */#define BTIM_TIM7_INT TIM7
#define BTIM_TIM7_INT_IRQn TIM7_IRQn
#define BTIM_TIM7_INT_IRQHandler TIM7_IRQHandler
#define BTIM_TIM7_INT_CLK_ENABLE() do{ __HAL_RCC_TIM7_CLK_ENABLE(); }while(0) /* TIM7 时钟使能 */
/******************************************************************************************/void btim_tim6_int_init(uint16_t arr, uint16_t psc); /* 基本定时器 定时中断初始化函数 */
void btim_tim7_int_init(uint16_t arr, uint16_t psc); /* 基本定时器 定时中断初始化函数 */
4.2btim.c源文件修改
定义两个定时器句柄,并进行中断初始化。
TIM_HandleTypeDef g_tim6_handler; /* 定时器参数句柄 */
TIM_HandleTypeDef g_tim7_handler; /* 定时器参数句柄 */
//定时器6中断初始化函数
void btim_tim6_int_init(uint16_t arr, uint16_t psc)
{g_tim6_handler.Instance = BTIM_TIM6_INT; /* 定时器x */g_tim6_handler.Init.Prescaler = psc; /* 分频 */g_tim6_handler.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数模式 */g_tim6_handler.Init.Period = arr; /* 自动装载值 */HAL_TIM_Base_Init(&g_tim6_handler);HAL_TIM_Base_Start_IT(&g_tim6_handler); /* 使能定时器x和定时器更新中断 */
}
//定时器7中断初始化函数
void btim_tim7_int_init(uint16_t arr, uint16_t psc)
{g_tim7_handler.Instance = BTIM_TIM7_INT; /* 定时器x */g_tim7_handler.Init.Prescaler = psc; /* 分频 */g_tim7_handler.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数模式 */g_tim7_handler.Init.Period = arr; /* 自动装载值 */HAL_TIM_Base_Init(&g_tim7_handler);HAL_TIM_Base_Start_IT(&g_tim7_handler); /* 使能定时器x和定时器更新中断 */
}
定义底层驱动。设置定时器6抢占优先级为6,定时器7抢占优先级为4。
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if (htim->Instance == BTIM_TIM6_INT){BTIM_TIM6_INT_CLK_ENABLE(); /* 使能TIMx时钟 */HAL_NVIC_SetPriority(BTIM_TIM6_INT_IRQn, 6, 0); /* 抢占6 */HAL_NVIC_EnableIRQ(BTIM_TIM6_INT_IRQn); /* 开启ITMx中断 */}if (htim->Instance == BTIM_TIM7_INT){BTIM_TIM7_INT_CLK_ENABLE(); /* 使能TIMx时钟 */HAL_NVIC_SetPriority(BTIM_TIM7_INT_IRQn, 4, 0); /* 抢占4 */HAL_NVIC_EnableIRQ(BTIM_TIM7_INT_IRQn); /* 开启ITMx中断 */}
}
添加中断服务函数与中断回调函数。
//中断服务函数
void BTIM_TIM6_INT_IRQHandler(void)
{HAL_TIM_IRQHandler(&g_tim6_handler); /* 定时器回调函数 */
}
void BTIM_TIM7_INT_IRQHandler(void)
{HAL_TIM_IRQHandler(&g_tim7_handler); /* 定时器回调函数 */
}
//回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if (htim->Instance == BTIM_TIM6_INT){printf("TIME6正在运行,优先级为6!!\r\n");}else if (htim->Instance == BTIM_TIM7_INT){printf("TIME7正在运行,优先级为4!!!!\r\n");}
}
5.mian函数初始化
6.所需API函数介绍
portDISABLE_INTERRUPTS函数用来关闭FreeRTOS所管理的中断。
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
portENABLE_INTERRUPTS函数用来开启FreeRTOS所管理的中断。
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
三、代码编写
3.1修改Task1的任务函数内容
Task1实现5S关中断,5S开中断。
//任务1,实现5S关中断,5S开中断
void task1(void *pvParameters)
{uint8_t task1_num = 0;while(1){if(++task1_num == 5){task1_num = 0;portDISABLE_INTERRUPTS();printf("关中断\r\n");delay_ms(5000);portENABLE_INTERRUPTS();printf("开中断\r\n");delay_ms(5000);}vTaskDelay(100);}
}
四、实验现象
系统复位后,实现5S关中断,5S开中断。关闭中断时,被FreeRTOS管理的优先级为6的定时器6停止工作,而优先级为4的定时器7不受影响。