【STM32F4】三、NVIC中断优先级管理


注:本博文只是对正点原子课程的又一次重复,总结正点的教程、写一些自己的感悟,并非以原创之名做抄袭之事。

一、STM32F4中断的介绍

1. STM32F4的中断个数、类型

STM32F4的内核是ARM家的Cortex-M4,真正的Cortex-M4支持 256 个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有256 级的可编程中断设置

但是STM32F4并没有使用Cortex-M4的全部中断,而是只用了它的一部分,总共有 92 个中断,包含10个内核中断和82个可屏蔽中断,具有 16 级可编程的中断优先级,而我们常用的就是这 82 个可屏蔽中断

2. 什么是内核中断与外部中断?

参考:CSDN博主【dgergeg】的文章:外部中断和内部中断

外部中断是指由外部中断源执行的中断程序,主要是指INT0,INT1,通讯中断;内部中断主要是指定时器/计数器中断、装栈溢出后置位等相关特殊寄存器来执行的中断;

举一个例子,外部中断:你在吃饭,这时候电话响了,你暂时放下餐具去接听电话在这里吃饭是你目前正在执行的程序,电话响了,是一个中断源,他是随机的,不定时发生,接完电话(处理完中断事件)你回来继续吃,(继续执行中断点没有做处理完的程序)
内部中断:你正在吃饭,这时碗里的饭没有了,你要去盛饭,盛了饭回来继续吃,在这里吃饭依然是你目前正在处理的一个程序,碗里的饭没有了相当于是一个中断,这个中断是由你吃饭引起了,相当于系统中的标志位溢出;

3. 什么是不可屏蔽中断与可屏蔽中断?

参考:CSDN博主【lidandan2016】的文章:可屏蔽中断和非屏蔽中断区别

按照是否可以被屏蔽,可将中断分为两大类:不可屏蔽中断(又叫非屏蔽中断)和可屏蔽中断。

不可屏蔽中断源一旦提出请求,cpu必须无条件响应,而对于可屏蔽中断源的请求,cpu可以响应,也可以不响应

cup一般设置两根中断请求输入线:可屏蔽中断请求INTR(Interrupt Require)和不可屏蔽中断请求NMI(Nonmaskable Interrupt)。对于可屏蔽中断,除了受本身的屏蔽位的控制外,还都要受一个总的控制,即CPU标志寄存器中的中断允许标志位IF(Interrupt Flag)的控制,IF位为1,可以得到CPU的响应,否则,得不到响应。其中,IF位可以由用户控制

典型的非屏蔽中断源的例子是电源掉电,一旦出现,必须立即无条件地响应,否则进行其他任何工作都是没有意义的。典型的可屏蔽中断源的例子是打印机中断,CPU对打印机中断请求的响应可以快一些,也可以慢一些,因为让打印机等待会儿是完全可以的。

根据以上分类,STM32F4中共有10个内核中断和82个可屏蔽中断,具有 16 级可编程的中断优先级。至于什么是可编程的中断优先级,请往后文阅读。

二、如何配置STM32F4的中断?

1. 什么是NVIC?

NVIC的全称是Nested vectoredinterrupt controller,即嵌套向量中断控制器。对于Cortex-M3或M4内核的MCU,每个中断的优先级都是用寄存器中的8位来设置的。8位的话就可以设置2 ^ 8 =256级中断,实际中用不了这么多,所以芯片厂商根据自己生产的芯片做出了调整。比如STM32F4只使用了这个8位中的高四位[7:4],低四位取零,这样2 ^ 4=16,只能表示16级中断嵌套。对于这个NVIC,有个重要的知识点就是优先级分组抢占优先级响应优先级,下面就以STM32为例进行介绍。

2. NVIC中的优先级分组、抢占优先级和响应优先级

2.1 抢占优先级和响应优先级

首先明确一个概念,若程序A的抢占优先级为0程序B的抢占优先级为1,则程序A程序B的抢占优先级要。即,数字越小,优先级越高

下面来讲抢占优先级响应优先级

:若程序A已经在执行过程中,这时候程序B想要开始执行,那么,如果B的抢占优先级比A,则B可以打断A,使系统先执行B。

:若程序A和程序B同时想要开始执行,而B的响应优先级比A高,则系统先执行B。

2.2 优先级分组

优先级可有五种分组编号,即0、1、2、3、4,不同分组代表着抢占优先级和响应优先级可以细分成多少个等级,如分组0的意义是0:4,即0 位抢占优先级,4 位响应优先级。也就是说,对系统中的全部中断程序来说,抢占优先级都一样,都是0;而响应优先级可以有2 ^ 4 = 16种不同等级。

下面展示具体的分配关系表(来自正点原子):
在这里插入图片描述
在写程序时,我们应当配置优先级分组,再配置不同中断程序的抢占优先级和响应优先级。

三、如何在程序中配置STM32F4的中断?

1. 配置优先级分组

在程序中,应当先配置优先级分组,我们才能根据分组知道抢占优先级和响应优先级各有几个等级

通过如下函数来配置优先级分组

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

其中,由于优先级分组有0、1、2、3、4共五种不同选择,则参数NVIC_PriorityGroup有如下五种选择:

 NVIC_PriorityGroup_0
 NVIC_PriorityGroup_1
 NVIC_PriorityGroup_2
 NVIC_PriorityGroup_3
 NVIC_PriorityGroup_4

2. 配置抢占优先级和响应优先级

通过如下函数配置抢占优先级和响应优先级:

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)

其中,形参类型NVIC_InitTypeDef是一个结构体,它的定义如下所示:

typedef struct
{
    
    
uint8_t NVIC_IRQChannel; 
uint8_t NVIC_IRQChannelPreemptionPriority;
uint8_t NVIC_IRQChannelSubPriority; 
FunctionalState NVIC_IRQChannelCmd; 
} NVIC_InitTypeDef;

其中,NVIC_IRQChannel定义初始化的是哪个中断,这个我们可以在 stm32f10x.h 中找到每个中断对应的名字。例如USART1_IRQnNVIC_IRQChannelPreemptionPriority定义这个中断的抢占优先级NVIC_IRQChannelSubPriority定义这个中断的子优先级别,也叫响应优先级NVIC_IRQChannelCmd用来设置该中断通道的使能

比如我们要使能串口 1 的中断,同时设置抢占优先级为 1,响应优先级位 2,初始化的方法是:

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口 1 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 响应优先级位 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能

NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数,调用函数来初始化 NVIC 寄存器,达到对中断进行设置的目的

猜你喜欢

转载自blog.csdn.net/qq_39642978/article/details/111987713