NVIC中断优先级管理示例解析

目录

NVIC中断优先级管理

STM32中断优先级简介

如何管理中断?

什么是“抢占优先级”和“响应优先级”呢?

优先级是如何定义的?

特别说明

函数介绍

中断优先级分组选择函数

对于每个中断怎么设置优先级?

如何理解中断挂起与解挂的含义?

获取中断状态的函数

清除/设置中断标志位的函数

针对于中断标志位的操作有什么用?

举例说明


NVIC中断优先级管理

STM32中断优先级简介

 

NVIC的缩写是“嵌套向量中断控制器(Nested Vectored Interrupt Controller)”。

如何管理中断?

STM32中断优先级管理采用“响应优先级和抢占优先级”结合的方法,并且进行了中断分组。

 

以第1组为例:1bit抢占优先级说明抢占优先级共有两级,3bits响应优先级说明响应优先级共有8级。我们可以看到无论如何分组,中断优先级总有16种。

 

什么是“抢占优先级”和“响应优先级”呢?

抢占优先级和响应优先级都是区分那个中断优先进行的标志,但是两者的含义去不尽相同。

抢占优先级从名字上就比响应优先级霸气一些,因此抢占优先级起决定作用,当抢占优先级相同时,响应优先级高的才会优先发生。

优先级是如何定义的?

值越小,优先级越大。

例如:假定设置中断优先级组为2,然后设置中断3(RTC中断)的抢占优先级为2,响应优先级为1。  中断6(外部中断0)的抢占优先级为3,响应优先级为0。中断7(外部中断1)的抢占优先级为2,响应优先级为0。

优先级顺序:中断7>中断3>中断6

结论:抢占优先级高的必定先抢占中断,如果抢占优先级相同,那就看响应优先级,此时谁的响应优先级高,谁就先发生。

除此之外,如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个,排序越考上,中断越优先。中断向量地址可以参考“STM32中文参考手册->中断->中断异常向量”部分的内容。部分示例:

 

特别说明

一般情况下,系统代码执行过程中,只设置一次中断优先级分组,比如分组2,设置好分组之后一般不会再改变分组。随意改变分组会导致中断管理混乱,程序出现意想不到的执行结果。

函数介绍

在操作函数的底层中,我们一般只用到ISER、ICER、IP这3个寄存器。ISER用于使能中断,ICER用来清除中断,IP用来设置中断优先级。

中断优先级分组选择函数

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

我们选择的是按照组2的方式进行分组,即抢占优先级总数为4级(0-3),响应优先级总级数为4级(0-3)。我们可以看到无论如何分组,中断优先级总有16种。

 

对于每个中断怎么设置优先级?

NVIC_InitTypeDef NVIC_InitStructure;  
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  // 2<3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //3<=3
NVIC_Init(&NVIC_InitStructure);  

 

如何理解中断挂起与解挂的含义?

中断的挂起与解挂针对的是中断标志位,也可以叫做允许中断发生的位。

获取中断状态的函数

函数原型

static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn);

函数应用

uint32_t IterruptFlag = NVIC_GetPendingIRQ(USART1_IRQn);

// 这个函数获取了串口1中断的状态

清除/设置中断标志位的函数

函数原型

static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn);

static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)

函数使用

NVIC_SetPendingIRQ(USART1_IRQn);

NVIC_ClearPendingIRQ(USART1_IRQn);

针对于中断标志位的操作有什么用?

1、一般来说单片机的中断发生有两个条件,一是中断标志位置位,二是中断允许,如果这两个条件都满足则进入中断,因为正常情况下中断一直是允许的,那么只能通过标志位来区分是否有中断挂起;

2、如果进入中断不清除标志位,那么这一中断服务程序结束后由于标志位还是置位的并且中断是允许的,那么还会再次进入该中断,就会发生一直在执行中断程序的情况。

举例说明

在A中断中设置B中断的中断标志位为1,那么当B中断条件满足时,B中断可以发生,但是如果清除A中B中断标志位,那么无论是否满足触发B中断的条件,A中断中永远不可能执行B中断,因为中断发生的条件是:“中断标志位有效+中断条件满足”。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
HC32F460PETB-LQFP100是一款基于ARM Cortex-M4架构的微控制器,它集成了一套串口通信模块,用于处理串行通信中断。在使用该芯片时,串口中断通常用于监控和响应串口接收或发送数据的状态变化。 以下是一个简单的HC32F460的串口中断代码示例,假设我们使用的是USART1中断: ```c // 包含必要的头文件 #include "HC32F4xx.h" // HC32系列MCU的头文件 // 定义串口初始化函数 void USART1_Init(void) { // 初始化串口配置,这里省略实际的配置代码 } // 串口中断服务函数 void USART1_IRQHandler(void) { __disable_irq(); // 先禁止中断,以防止中断嵌套 // 检查中断源 if (ITStatus & USART1_IT_RXNE) // 检查是否接收到新的数据 { // 接收数据,并根据需要处理(如保存到缓冲区或解析) uint8_t received_char = USART1_ReadData(); // 处理逻辑... } else if (ITStatus & USART1_IT_TC) // 检查发送完成标志 { // 发送完成,可能需要重新发送或进行其他操作 // 清除发送完成标志 USART1_ClearITPendingBit(USART1_IT_TC); } __enable_irq(); // 重新开启中断 // 中断处理结束,可选择返回主程序或继续执行中断处理任务 return; } // 在系统初始化中开启串口中断 void SystemInit(void) { USART1_Init(); // 初始化串口 NVIC_EnableIRQ(USART1_IRQn); // 开启USART1中断 NVIC_SetPriorityGrouping(0x07); // 设置优先级组 NVIC_SetPriority(USART1_IRQn, 2); // 设置串口中断优先级 } int main(void) { // ... 主程序初始化... // 开始串口中断 USART1_ITConfig(USART1_IT_RXNE | USART1_IT_TC, ENABLE); // 启用接收和发送完成中断 // 进入无限循环等待中断 while (1); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥肥胖胖是太阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值