欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

stm32学习(3)——NVIC中断优先级分组

程序员文章站 2024-02-25 14:51:57
...

相信大多数铁汁在学习stm32的时候都了解过51单片机的基本内容,对于51单片机来说,中断就那么几个:

  1. 外部中断0
  2. 定时器/计数器0中断
  3. 外部中断1
  4. 定时器/计数器1中断
  5. 串口中断

它们在51单片机中的优先级也是按自上而下的顺序,中断少且优先级明确,这就是大家了解的51单片机中断系统,又顺便复习了一波老知识。

而在stm32f103系列芯片中有60个可屏蔽中断(可屏蔽中断简单来说就是可以由寄存器控制是否产生中断的中断,skr~),从《stm32中文参考手册》中可以看到有这么0-59号一共60个可屏蔽中断。
stm32学习(3)——NVIC中断优先级分组
stm32学习(3)——NVIC中断优先级分组
stm32学习(3)——NVIC中断优先级分组

NVIC中断优先级分组

对于数量如此之多的中断源怎么来进行中断管理也是一个问题,但是stm32给出了很好地解决办法,NVIC中断优先级分组(NVIC不懂没关系,我也不懂,懂分组就行了)
stm32学习(3)——NVIC中断优先级分组
从图中可以看到(application interrupt and reset control register应用中断和复位控制寄存器AIRCR[10:8]这三位,也就是下图中绿色的三位,由这三位共同决定分组配置。
stm32学习(3)——NVIC中断优先级分组
还要了解抢占优先级与响应优先级的基本概念:

  1. 高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的
  2. 抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断
  3. 抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行
  4. 如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行
  5. 优先级数字越小,优先级越高,越先被执行

了解了抢占与响应两个优先级的基本概念后再看上面的表就会发现,可以设置5中不同的优先级分组,每种都是4位也就是16种不同的优先级设置。

NVIC中断优先级设置

一般情况下,系统代码执行过程中,只设置一次中断优先级分组(并且是在main函数比较靠前的位置设置),设置好分组之后一般不会再改变分组。若是在多处进行了分组,程序会以最后一次的分组为准,并且之前设置的分组全部失效。随意改变分组会导致中断管理混乱,程序出现意想不到的执行结果。
在stm32中,关于NVIC优先级设置的函数都在misc.h里可以看到:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);

在main函数中通常使用一个中断优先级分组设置函数

NVIC_PriorityGroupConfig();

//函数的入口参数可以选择这些,也就是对应上表的几种分组
#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \
                                       ((GROUP) == NVIC_PriorityGroup_1) || \
                                       ((GROUP) == NVIC_PriorityGroup_2) || \
                                       ((GROUP) == NVIC_PriorityGroup_3) || \
                                       ((GROUP) == NVIC_PriorityGroup_4))

在单个中断设置抢占和响应优先级时通常用:

 NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

//入口参数有三个
  assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));		//中断使能
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); 		//抢占优先级设置 
  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));		//响应优先级设置

关于NVIC中断优先级分组的介绍就到这了,砰~,水遁消失。