stm32中断分组学习

发布者:RadiantSerenity最新更新时间:2024-10-12 来源: cnblogs关键字:stm32  中断 手机看文章 扫描二维码
随时随地手机看文章

STM32的中断优先级包括:抢占式优先级和响应优先级

具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。

 

当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之 后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。

 

STM32 可以支持的 68 个外部中断通道,已经固定的分配给相应的外部设备。每个中断通道都具备自己的中断优先级控制字节 PRI_n(8 位,但在 STM32 中只使用 4 位,高 4 位有效),每 4 个通道的 8 位中断优先级控制字(PRI_n)构成一个 32 位的优先级寄存器(Priority Register)。68 个通道的优先级控制字至少构成 17 个 32 位的优先级寄存器,它们是 NVIC寄存器中的一个重要部分。

 

对于这 4bit 的中断优先级控制位还必须分成 2 组看:从高位开始,前面是定义抢先式优先级的位,后面用于定义子优先级。4bit 的分组组合可以有以下几种形式:


第0组:所有4位用于指定响应优先级

第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级

第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级

第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级

第4组:所有4位用于指定抢占式优先级


注意:优先级数字越小,对应的优先级别越高。


由于我们使用STM32的库函数,所以这里介绍如何使用库函数设置需要的优先级。可以通过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()选择使用哪种优先级分组方式。

这个函数的参数有下列5种:


NVIC_PriorityGroup_0 => 选择第0组

NVIC_PriorityGroup_1 => 选择第1组

NVIC_PriorityGroup_2 => 选择第2组

NVIC_PriorityGroup_3 => 选择第3组

NVIC_PriorityGroup_4 => 选择第4组

注意:在系统复位初始化之后,默认使用的是第0组优先级分组。


接下来就是指定中断源的优先级,下面以一个简单的例子说明如何指定中断源的抢占式优先级和响应优先级:

如果应用程序储存在ROM中,并且不需要改变异常服务程序,则我们可以把整个向量表编码到ROM的起始区域(从0 地址开始的那段)。在这种情况下,向量表的偏移量将一直为0, 并且中断向量一直在ROM中,因此上例可以大大简化,只需3 步:

1. 建立优先级组

2. 为该中断指定优先级

3. 使能该中断

 

// 选择使用优先级分组第1组

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

 

// 使能EXTI0中断 初始化采用和GPIO一样的结构体形参

NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定抢占式优先级别1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 指定响应优先级别0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

 

// 使能EXTI9_5中断

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;//这里指的是外部中断9-5线

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定抢占式优先级别0

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 指定响应优先级别1

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

 

要注意的几点是:

 

1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;

这里的范围是指第4组抢占式优先级0~15, 第二组抢占式优先级范围0~3,响应优先级0~3;剩下几组同理

 

2)抢占式优先级别相同的中断源之间没有嵌套关系;

 

3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。也就是说抢占式优先级高的一定可以中断中断优先级低的.

开关总中断:

在STM32/Cortex-M3中是通过改变CPU的当前优先级来允许或禁止中断。

PRIMASK位:只允许NMI和hard fault异常,其他中断/异常都被屏蔽(当前CPU优先级=0)。

FAULTMASK位:只允许NMI,其他所有中断/异常都被屏蔽(当前CPU优先级=-1)。

 

在STM32固件库中(stm32f10x_nvic.c和stm32f10x_nvic.h) 定义了四个函数操作PRIMASK位和FAULTMASK位,改变CPU的当前优先级,从而达到控制所有中断的目的。

 

新库中下面两个函数等效于关闭总中断:

void__disable_irq (void);

void __disable_fault_irq (void);

 

下面两个函数等效于开放总中断:

void __enable_irq (void);

void __enable_fault_irq (void);

 

上面两组函数要成对使用,不能交叉使用。

例如:

第一种方法:

PRIMASK 用于除能在NMI 和硬fault 之外的所有异常,它有效地把当前优先级改为0(可编程优先级中的最高优先级)。

void__disable_irq (void);//关闭总中断

void __enable_irq (void);//开放总中断

__set_PRIMASK(1);

__set_PRIMASK(0); 

第二种方法:

FAULTMASK 更绝,它把当前优先级改为‐ 1 。这么一来,连硬fault 都被掩蔽了。使用方案与PRIMASK 的相似。但要注意的是,FAULTMASK 会在异常退出时自动清零。

void __disable_fault_irq (void); //关闭总中断

void __enable_fault_irq (void);//开放总中断

__set_FAULTMASK(1);

__set_FAULTMASK(0); 

常常使用

void__disable_irq (void);//关闭总中断

void __enable_irq (void);//开放总中断

 

总结:

库函数中提到的PreemptionPriority含义是抢占式优先级,subPriority含义是响应优先级,也叫亚优先级。
何为抢占式优先级?顾名思义,是指在抢占式优先级不同时,抢占式优先级高的可以中断抢占式优先级低的,也就是所谓的嵌套!相同的抢占式优先级之间是不可以中断嵌套的。打个比方,如果系统采用的是第4组优先级分组方式,就意味着所有的4位都被用来指定抢占式优先级,也就是说,这样一来抢占式优先级就有16个等级,通过你对需要的中断源进行中断优先级赋值,就可以实现你所希望的高优先级中断函数在低优先级中断函数未执行完之前就开始执行,即中断嵌套,该分组方式最多可以完成1个中断和15级嵌套。

 

通过上面我们知道抢占式优先级高的可以中断优先级低的,但是响应优先级跟抢占式优先级有什么联系呢?这里我就打个可能不太形象的比喻,帮助大家理解一下,如果说抢占式优先级是某个等级的政府机关的话,那响应优先级就是这个政府机关里面的部门,政府机关权力有高低之分,同样每个部门之间也有权力大小之分。

 

打个比喻:

不同的政府机关(抢占式优先级)之间可以相互中断,但是同一个政府机关里面的不同部门(即抢占式中断优先级相同,响应优先级不同)之间不能相互中断,因为内部不能相互打架,即使响应优先级高的来了,如果此时有响应优先级低的中断服务程序正在执行,他一定要等到对方执行完之后才可以执行,但是要注意一点,虽然他不可以打断比他响应优先级低的中断服务函数,但是他有“插队”的特权,即当有多个相同抢占式优先级同时到来的时候,响应优先级高的虽然中断来的比较迟,但是他有优先执行的特权!问题又来了,如果抢占式优先级和响应优先级都相同的中断同时中断或是排队时孰先孰后呢,这就要看他们在中断向量表中的位置了,也就是说中断入口地址低的优先。


注意:中断通道数跟单片机引脚个数没有任何关系,目前M3内核无论多少引脚的单片机中断通 道数都是84个,而无论引脚有多少个,这些引脚只占用6个通道,即0~4线分别占用一个通道,5~9线10~15线占用两个中断通道,一个中断通道可能对应很多外设。


关键字:stm32  中断 引用地址:stm32中断分组学习

上一篇:stm32之SPI学习
下一篇:我的STM32从菜鸟到牛人的学习步骤

推荐阅读最新更新时间:2026-03-24 22:40

STM32定时器中断详解(HAL库实战讲解)
1、定时器简单介绍 以STM32F103C8T6中几个定时器为例: TIM1:这是一个高级定时器,不仅具备基本的定时中断功能,还拥有内外时钟源选择、输入捕获、输出比较、编码器接口以及主从触发模式等多种功能。这使得TIM1能够适用于各种复杂的应用场景,为开发者提供强大的时间控制和信号处理能力。 TIM2、TIM3和TIM4:这些是通用定时器,同样具有定时功能,但在功能上与高级定时器有所区别。通用定时器通常用于实现一些基本的定时任务,如LED闪烁、脉冲宽度测量等。 每个定时器都由一个**16位计数器、预分频器和自动重装寄存器的时基单元组成。**预分频器可以对时钟进行分频,计数器则对预分频后的时钟进行计数。当计数器的值达到设定值时,
[单片机]
<font color='red'>STM32</font>定时器<font color='red'>中断</font>详解(HAL库实战讲解)
STM32的NVIC嵌套向量中断控制器与外部中断应用案例分析详解
前言   本文并不是简单介绍一下外部中断的使用和NVIC浅层的内容,而是从内核角度,深入剖析中断的内涵,中断向量表和MVIC内部机理,最后以外部中断使用案例结束。相信会给你带来惊喜。   对于嵌套向量中断控制器,也就是Nested vectored interrupt controller,缩写为NVIC,在所有的ARM Cortex-M3和Cortex-M4系列的所有芯片都适用,因为NVIC是内核层面的东西,不是一个外设,所以凡是这个内核的芯片,都有NVIC。于是本文虽从STM32F4入手讲解和使用案例分析,但对于其他芯片同样适用。本文具体参考的文档《The definitive guide to Arm Cortex-M3 a
[单片机]
<font color='red'>STM32</font>的NVIC嵌套向量<font color='red'>中断</font>控制器与外部<font color='red'>中断</font>应用案例分析详解
STM32串口中断实例二
int main(void) { uint8_t a=0;//LED高低电压控制 /* System Clocks Configuration */ RCC_Configuration(); //系统时钟设置 /*嵌套向量中断控制器 说明了USART1抢占优先级级别0(最多1位) ,和子优先级级别0(最多7位) */ NVIC_Configuration(); //中断源配置 /*对控制LED指示灯的IO口进行了初始化,将端口配置为推挽上拉输出,口线速度为50Mhz。PA9,PA10端口复用为串口1的TX,
[单片机]
<font color='red'>STM32</font>串口<font color='red'>中断</font>实例二
STM32单片机串口中断+DMA使用(含CUBE配置)
最近又要重新用32做点东西,发现一两年没怎么碰的结果就是,曾经熟得不行的东西都变得极度陌生,这种重新学习记忆的过程过于痛苦,果然还是要留下一些记录给之后失忆的自己的。 1.STM32CUBE配置 1.1 pinout设置 找到想要用的串口,配置模式,正常情况是Asyn(异步)和Disable。 关于mode的几个选项: Asyn 异步 Syn同步 Single Wire单工 后面几个没有太多的了解惹 1.2 configuration设置 Parameter Settings可以设置:波特率/字长/奇偶校验/停止位/收发模式 DMA Settings中添加接收DMA的流 NVIC Setti
[单片机]
<font color='red'>STM32</font>单片机串口<font color='red'>中断</font>+DMA使用(含CUBE配置)
STM32外部中断原理与配置
STM32-外部中断原理与配置 IO口外部中断原理概述 STM32控制器支持的外部中断/事件请求 中断线 M3 M4 M7 EXTI线0~15:对应外部IO口的输入中断。 √ √ √ EXTI线16:连接到PVD输出。 √ √ √ EXTI线17:连接到RTC闹钟事件。 √ √ √ EXTI线18:连接到USB OTG FS唤醒事件。 √ √ √ EXTI线19:连接到以太网唤醒事件。 √ √ EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件 √ √ EXTI线21:连接到RTC入侵和时间戳事件。 √ √ EXTI线22:连接到RTC唤醒事件。 √ √ EXSTI线23
[单片机]
STM32 串口接收流程-串口接收中断
串口接收 串口接收流程 编程USARTx_CR1的M位来定义字长。 编程USARTx_CR2的STOP位来定义停止位位数。 编程USARTx_BRR寄存器确定波特率。 使能USARTx_CR1的UE位使能USARTx。 如果进行多缓冲通信,配置USARTx_CR3的DMA使能(DMAT)。 使能USARTx_CR1的RE位为1使能接收器。 如果要使能接收中断(接收到数据后产生中断),使能USARTx_CR1的RXNEIE位为1。 当串口接收到数据时 USARTx_SR(ISR)的RXNE位置1。表明移位寄存器内容已经传输到RDR(DR)寄存器。已经接收到数据并且等待读取。 如果开启了接收数据中断(USART
[单片机]
STM32 HAL库使用中断实现串口接收不定长数据
以前用DMA实现接收不定长数据,DMA的方法接收串口助手的数据,全部没问题,不过如果接收模块返回的数据,而这些数据如果包含回车换行的话就会停止接收,例如接收:ATrnOKrn,就只能接收到ATr,导致没有接收完成,具体原因还没搞懂,有了解的,希望可以告知一下,DMA不定长接收方法传输门:https://www.cnblogs.com/xingboy/p/9714907.html。 好了,不多说了,现在进入正文。首先建立一个STM32Cumebx的工程,打开串口中断,完成配置,具体的配置流程就不细说了,没什么难度就只是打开串口跟中断而已。 生成工程代码后,先定义好一些变量: //串口4中断接收定义 #define MAX
[单片机]
<font color='red'>STM32</font> HAL库使用<font color='red'>中断</font>实现串口接收不定长数据
stm32中断与事件
事件:是表示检测有一某件触发事件发生了。 中断:有某个事件发生并产生中断,并跳转到对应的中断处理程序中。 事件可以触发中断,也可以不触发 中断有可能被更优先的中断屏蔽,事件不会 事件本质上就是一个触发信号,是用来触发特定的外设模块或核心本身(唤醒). 事件只是一个触发信号(脉冲),而中断则是一个固定的电平信号
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved