NVIC嵌套向量中断控制器

        首先区分一下中断和异常的关系,其实中断和异常时有差异也有关联的,我们常常所说的中断其实也包含了异常。中断是指系统停止当前正在运行的程序转而其他服务,可能是程序接收了比自身高优先级的请求,或者是人为设置中断,中断是属于正常现象。 异常可以理解为MCU或者程序处于某种异常状态,异常属于不正常现象。注意一下:CM3的外部中断和STM32的外部中断不是一个概念。CM3:除了内核异常之外的都是外部中断;STM32:外部中断EXTI只有6个。所以如果在CM3角度看,像USART这类中断是属于外部中断;若在STM32角度看,EXTI外部引脚中断才属于中断。

我们刚开始接触单片机的时候都大致了解了中断的大致流程:

        中断响应和处理流程:处理器接受到中断信号之后,立即停止当前正在执行的程序,并且保存当前处理器状态,程序指针等,然后进入中断服务程序;完成中断处理之后即可返回原程序继续执行。一个中断服务程序对应于一个中断源,每个中断源都有其特定的中断服务程序。在中断服务程序中,处理器一般需要做3部分工作:一是保护现场,即保存执行中断源请求的特别任务之前的处理器状态,程序指针等,以便中断处理之后能正确返回;二是解析当前中断,执行相应动作;三是恢复现场,再返回到中断前的程序。

那么在STM32的中断与51单片机的中断有什么不一样呢?

STM32F103 中断讲解

由于 STM32F103 是基于 ARM Cortex M3 内核设计的,因此我们先了解一下 ARM Cortex M3 的中断,M3 内核的中断分为两大部分,第一部分是系统中断,一共有 16 个,第二部分是 留给芯片厂家的 240 的外设中断(这两部分加起来一共有 256 个中断)。但是芯片厂家可能 用不上 240 个外设中断,因此会对其进行裁剪,STM32F103 只是用了 60 个外设中断。 下面看一下 STM32F103 这 76 个中断(16 个系统中断有些是预留的,有意义的系统中断为 10 个。另外中断优先级数越小优先级别越高):

在STM32官方文档手册中有对STM32F10XX参考手册中的中断事件描述:

        其中灰色部分是系统的16个中断,其余 60 个为外设中断。另外除了三个中断优先级固定外,剩余的中断优先级都是可以通过程序设置的,STM32 支持 16 个可编程优先级。

在MDK中,有标准的异常和中断向量表文件可以使用(startup_stm32f10x_hd.s),在其中标明了中断处理函数的名称,不能随意定义。而中断通道NVIC_IRQChannel(即IRQn_Type类型)是在stm32f10x.h文件中进行了宏定义。

这里说一下和中断设置有关的名词: 

中断使能/失能:中断使能的意思是让中断有效或者说是开中断,失能则是关闭 中断。

中断挂起/解挂:当一个中断发生时,此时单片机正在执行和该中断同优先级或者更高 优先级的另外一个中断时,该中断将被挂起,直到另一个中断执行完才可解挂并执行,其实 就是根据中断优先级排队。

中断嵌套:一个高优先级的中断打断了低优先级的中断的过程 就是中断嵌套,这样做使得不同优先级的中断能够按照优先级的大小依次执行,可以理解为 VIP 插队。 接下来我们看一下 STM32F103 中断的相关寄存器(这些寄存器是用于设置 STM32F103 的 60 个外设中断的)

该段代码位于 core_cm3.h 文件中,它定义的是就是 STM32 的中断相关寄存器。

⚫ 中断使/失能寄存器(ISER/ICER)

ISER 用于使能某个中断,寄存器中的一个位对应着一个中断,写 1 就使能,写 0 被忽略。由于 CM3 内核最多支持 240 个外设中断,因此 ISER 是由 8 个 32 位的寄存器组成(只不 过剩余的最高 16 位没有用到),而 STM32F103 只有 60 个中断,因此只用到了 ISER[0]和 ISER[1]的低 28 位。 同理,ICER 用于设置 STM32 的中断失能,写 1 失能,写 0 忽略。

⚫ 中断挂起/解挂寄存器(ISPR/ICPR)

这两组寄存器用于设置中断挂起和解挂,操作和中断使/失能寄存器一致。

⚫ 活动中断标志寄存器 (IABR)

字面理解就是用于记录此时正在执行中断的寄存器,如果一个中断被执行,那么该中断 对应位就会被置 1,即使该中断被其他更高优先级的中断打断,只要该中断没有执行完就一 直保持 1 的状态,直到中断服务函数执行完才会被硬件自动清零。 

⚫ 中断优先级寄存器(IP)

中断优先级寄存器用于设置每个中断的优先级,CM3 内核最大支持 240 个外设中断并为 每个中断分配了 8 位可编程优先级,但是 STM32F103 只用到了 60 个中断优先级寄存器,而 且每个中断只用到了高四位来设置中断优先级。这高四位又被分组为两部分优先级:抢占优先级和子优先级。一个中断是否需能够抢占其他中断 由三个因素决定:抢占优先级,子优先级,中断编号。 

STM32的NVIC分组

        STM32将中断分为0-4组,假设设置为组2,则此时抢占优先级的取值范围是 0~3,子优先级取值范围也是 0~3,那么此时所有的 60 个中断,每个中断的中断优先寄存器的高四位中的最高 3 位是抢占优先级,较低 1 位是响应优先级。

这里需要注意两点:

第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;

第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。

(先看抢占优先级,再看响应优先级。按小的排,越小的先执行。)

假设现在有4个中断,中断1-4,设置此时的优先级分组3;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);

中断1:抢占优先级5,子优先级0;

中断2:抢占优先级6,子优先级1;

中断3:抢占优先级5,子优先级1;

中断4:抢占优先级6,子优先级0;

那么这四个中断的顺序为:中断1>中断3>中断4>中断2

        我们在配置中断的时候,一般要做两个工作:(1)设置分组,(2)初始化NVIC 

以USART为例:

static void NVIC_Configuration(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 嵌套向量中断控制器组选择 */

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  /* 配置USART为中断源 */

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  /* 抢断优先级*/

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  /* 子优先级 */

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  /* 使能中断 */

    NVIC_Init(&NVIC_InitStructure);  /* 初始化配置NVIC */

}

此函数可以就可已在串口中断配置的时候调用了。以上就是有关NVIC中断的配置。

更多参考资料参考链接:https://blog.csdn.net/m0_53095678/article/details/122706116

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值