在STM32微控制器中,中断优先级设置是一个关键的概念,它决定了在发生多个中断时,哪些中断能够优先被处理。STM32的中断优先级系统包括抢占优先级(Preemption Priority)和子优先级(Subpriority),这两个优先级共同决定了中断的响应顺序。在本文中,我们将详细探讨这两个优先级如何影响中断响应,并提供相应的代码示例。
抢占优先级与子优先级的基本概念
抢占优先级决定了中断之间的嵌套关系。当一个高抢占优先级的中断发生时,如果当前正在处理一个低抢占优先级的中断,那么高优先级的中断会抢占低优先级中断的执行,直到高优先级中断处理完成。这种机制确保了关键任务能够及时得到处理。
子优先级则在具有相同抢占优先级的中断中起作用。如果两个中断具有相同的抢占优先级,那么子优先级高的中断会先被处理。子优先级的存在使得系统能够在多个同等重要的中断中做出选择,优先处理某些中断。
如何设置抢占优先级和子优先级
在STM32微控制器中,可以通过NVIC(Nested Vectored Interrupt Controller)来设置抢占优先级和子优先级。以下是设置这两个优先级的步骤:
-
选择优先级分组:STM32提供了几种不同的优先级分组模式,通过
NVIC_PriorityGroupConfig()
函数来设置。这个函数决定了抢占优先级和子优先级的位数分配。 -
初始化中断:使用
NVIC_InitTypeDef
结构体来配置特定中断的优先级。通过HAL_NVIC_Init()
函数来应用这些配置。
代码示例
以下是一个代码示例,展示了如何为两个不同的中断设置不同的抢占优先级和子优先级。
#include "stm32f1xx_hal.h"
// 定义中断优先级
#define PREEMPTION_PRIORITY_HIGH (0x0F << NVIC_PRIORITYGROUP_0_PREEMPTION_PRIORITY_POS)
#define SUB_PRIORITY_HIGH (0x0F << NVIC_PRIORITYGROUP_0_SUB_PRIORITY_POS)
#define PREEMPTION_PRIORITY_MEDIUM (0x07 << NVIC_PRIORITYGROUP_0_PREEMPTION_PRIORITY_POS)
#define SUB_PRIORITY_MEDIUM (0x07 << NVIC_PRIORITYGROUP_0_SUB_PRIORITY_POS)
#define PREEMPTION_PRIORITY_LOW (0x00 << NVIC_PRIORITYGROUP_0_PREEMPTION_PRIORITY_POS)
#define SUB_PRIORITY_LOW (0x00 << NVIC_PRIORITYGROUP_0_SUB_PRIORITY_POS)
// 初始化NVIC
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStruct = {0};
// 设置优先级分组为0,4位抢占优先级,0位子优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置高优先级中断
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; // 假设TIM2为高优先级中断
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = PREEMPTION_PRIORITY_HIGH;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = SUB_PRIORITY_HIGH;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
HAL_NVIC_Init(&NVIC_InitStruct);
// 设置中等优先级中断
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; // 假设USART1为中等优先级中断
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = PREEMPTION_PRIORITY_MEDIUM;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = SUB_PRIORITY_MEDIUM;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
HAL_NVIC_Init(&NVIC_InitStruct);
// 设置低优先级中断
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; // 假设EXTI0为低优先级中断
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = PREEMPTION_PRIORITY_LOW;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = SUB_PRIORITY_LOW;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
HAL_NVIC_Init(&NVIC_InitStruct);
}
// 定时器中断处理函数
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim2);
}
// USART中断处理函数
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
// 外部中断处理函数
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI0_IRQHandler();
}
int main(void)
{
HAL_Init();
SystemClock_Config();
NVIC_Configuration();
// 其他初始化代码...
while (1)
{
// 主循环代码...
}
}
void SystemClock_Config(void)
{
// 系统时钟配置代码...
}
在这个示例中,我们首先定义了不同的优先级宏,然后在NVIC_Configuration()
函数中设置了三个不同优先级的中断。TIM2被设置为最高优先级,USART1为中等优先级,EXTI0为最低优先级。这样,当这些中断同时发生时,TIM2的中断将首先被处理,然后是USART1,最后是EXTI0。
结语
STM32微控制器的中断优先级设置是确保系统响应性和实时性的关键。通过合理配置抢占优先级和子优先级,开发者可以确保关键任务得到及时处理,同时避免低优先级任务长时间阻塞高优先级任务的执行。在设计STM32应用程序时,了解和正确使用中断优先级是非常重要的。通过本文的介绍和代码示例,希望能够帮助读者更好地理解和应用STM32的中断优先级设置。
✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进
❤欢迎关注我的知乎:对error视而不见
代码获取、问题探讨及文章转载可私信。
☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。
🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇
点击领取更多详细资料