初学stm32 --- NVIC中断

目录

STM32 NVIC 中断优先级管理

NVIC_Type:

ISER[8]:

ICER[8]:

ISPR[8]:

ICPR[8]:

IABR[8]:

IP[240]:

STM32 的中断分组:

中断优先级分组函数 NVIC_PriorityGroupConfig

中断初始化函数 NVIC_Init

总结


STM32 NVIC 中断优先级管理

        CM3 内核支持 256 个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有 256级的可编程中断设置。但 STM32 并没有使用 CM3 内核的全部东西,而是只用了它的一部分。STM32 有 84 个中断,包括 16 个内核中断和 68 个可屏蔽中断,具有 16 级可编程的中断优先级。

        而我们常用的就是这 68 个可屏蔽中断, 但是 STM32 的 68 个可屏蔽中断,在 STM32F103 系列上面,又只有 60 个(在 107 系列才有 68 个)。因为我们开发板选择的芯片是 STM32F103 系列的,所以我们就只针对 STM32F103 系列这 60 个可屏蔽中断进行介绍。

         在 MDK 内,与 NVIC 相关的寄存器, MDK 为其定义了如下的结构体:

NVIC_Type:

typedef struct
{
__IO uint32_t ISER[8]; /*!< Interrupt Set Enable Register */
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; /*!< Interrupt Clear Enable Register */
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; /*!< Interrupt Set Pending Register */
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; /*!< Interrupt Clear Pending Register */
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; /*!< Interrupt Active bit Register */
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; /*!< Interrupt Priority Register, 8Bit wide */
uint32_t RESERVED5[644];
__O uint32_t STIR; /*!< Software Trigger Interrupt Register */
} NVIC_Type;

        STM32 的中断在这些寄存器的控制下有序的执行的。 只有了解这些中断寄存器,才能方便的使用 STM32 的中断。下面重点介绍这几个寄存器:

ISER[8]:

        全称是: Interrupt Set-Enable Registers,这是一个中断使能寄存器组。上面说了 CM3 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。但是STM32F103 的可屏蔽中断只有 60 个,所以对我们来说,有用的就是两个(ISER[0]和 ISER[1]),总共可以表示 64 个中断。而 STM32F103 只用了其中的前 60 位。 ISER[0]的 bit0~bit31 分别对应中断 0~31。 ISER[1]的 bit0~27 对应中断 32~59;这样总共 60 个中断就分别对应上了。 你要使能某个中断,必须设置相应的 ISER 位为 1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、 IO 口映射等设置才算是一个完整的中断设置)。具体每一位对应哪个中断,请参考 stm32f10x.h 里面的第 140 行处(针对编译器 MDK5 来说)。       

#ifdef STM32F10X_HDADC1_2_IRQn                 = 18,     /*!< ADC1 and ADC2 global Interrupt                       */USB_HP_CAN1_TX_IRQn         = 19,     /*!< USB Device High Priority or CAN1 TX Interrupts       */USB_LP_CAN1_RX0_IRQn        = 20,     /*!< USB Device Low Priority or CAN1 RX0 Interrupts       */CAN1_RX1_IRQn               = 21,     /*!< CAN1 RX1 Interrupt                                   */CAN1_SCE_IRQn               = 22,     /*!< CAN1 SCE Interrupt                                   */EXTI9_5_IRQn                = 23,     /*!< External Line[9:5] Interrupts                        */TIM1_BRK_IRQn               = 24,     /*!< TIM1 Break Interrupt                                 */TIM1_UP_IRQn                = 25,     /*!< TIM1 Update Interrupt                                */TIM1_TRG_COM_IRQn           = 26,     /*!< TIM1 Trigger and Commutation Interrupt               */TIM1_CC_IRQn                = 27,     /*!< TIM1 Capture Compare Interrupt                       */TIM2_IRQn                   = 28,     /*!< TIM2 global Interrupt                                */TIM3_IRQn                   = 29,     /*!< TIM3 global Interrupt                                */TIM4_IRQn                   = 30,     /*!< TIM4 global Interrupt                                */I2C1_EV_IRQn                = 31,     /*!< I2C1 Event Interrupt                                 */I2C1_ER_IRQn                = 32,     /*!< I2C1 Error Interrupt                                 */I2C2_EV_IRQn                = 33,     /*!< I2C2 Event Interrupt                                 */I2C2_ER_IRQn                = 34,     /*!< I2C2 Error Interrupt                                 */SPI1_IRQn                   = 35,     /*!< SPI1 global Interrupt                                */SPI2_IRQn                   = 36,     /*!< SPI2 global Interrupt                                */USART1_IRQn                 = 37,     /*!< USART1 global Interrupt                              */USART2_IRQn                 = 38,     /*!< USART2 global Interrupt                              */USART3_IRQn                 = 39,     /*!< USART3 global Interrupt                              */EXTI15_10_IRQn              = 40,     /*!< External Line[15:10] Interrupts                      */RTCAlarm_IRQn               = 41,     /*!< RTC Alarm through EXTI Line Interrupt                */USBWakeUp_IRQn              = 42,     /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */TIM8_BRK_IRQn               = 43,     /*!< TIM8 Break Interrupt                                 */TIM8_UP_IRQn                = 44,     /*!< TIM8 Update Interrupt                                */TIM8_TRG_COM_IRQn           = 45,     /*!< TIM8 Trigger and Commutation Interrupt               */TIM8_CC_IRQn                = 46,     /*!< TIM8 Capture Compare Interrupt                       */ADC3_IRQn                   = 47,     /*!< ADC3 global Interrupt                                */FSMC_IRQn                   = 48,     /*!< FSMC global Interrupt                                */SDIO_IRQn                   = 49,     /*!< SDIO global Interrupt                                */TIM5_IRQn                   = 50,     /*!< TIM5 global Interrupt                                */SPI3_IRQn                   = 51,     /*!< SPI3 global Interrupt                                */UART4_IRQn                  = 52,     /*!< UART4 global Interrupt                               */UART5_IRQn                  = 53,     /*!< UART5 global Interrupt                               */TIM6_IRQn                   = 54,     /*!< TIM6 global Interrupt                                */TIM7_IRQn                   = 55,     /*!< TIM7 global Interrupt                                */DMA2_Channel1_IRQn          = 56,     /*!< DMA2 Channel 1 global Interrupt                      */DMA2_Channel2_IRQn          = 57,     /*!< DMA2 Channel 2 global Interrupt                      */DMA2_Channel3_IRQn          = 58,     /*!< DMA2 Channel 3 global Interrupt                      */DMA2_Channel4_5_IRQn        = 59      /*!< DMA2 Channel 4 and Channel 5 global Interrupt        */
#endif /* STM32F10X_HD */ 

ICER[8]:

        全称是: Interrupt Clear-Enable Registers,是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和 ICER 一样。这里要专门设置一个 ICER 来清除中断位,而不是向 ISER 写 0 来清除,是因为 NVIC 的这些寄存器都是写 1 有效的,写 0 是无效的。具体为什么这么设计,请看《CM3 权威指南》第 125 页, NVIC 概览一章。

ISPR[8]:

        全称是: Interrupt Set-Pending Registers,是一个中断挂起控制寄存器组。每个位对应的中断和 ISER 是一样的。通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。

ICPR[8]:

         全称是: Interrupt Clear-Pending Registers,是一个中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。通过设置 1,可以将挂起的中断接挂。写 0 无效。

IABR[8]:

        全称是: Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。

IP[240]:

        全称是: Interrupt Priority Registers,是一个中断优先级控制的寄存器组。这个寄存器组相当重要 STM32 的中断分组与这个寄存器组密切相关。 IP 寄存器组由 240 个 8bit 的寄存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。 而 STM32 只用到了其中的前 60 个。 IP[59]~IP[0]分别对应中断 59~0。 而每个可屏蔽中断占用的 8bit 并没有全部使用,而是 只用了高 4 位。这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。

STM32 的中断分组:

        STM32 将中断分为 5 个组,组 0~4。该分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。具体的分配关系如表1 所示: 

表1 AIRCR 中断分组设置表

        通过这个表,我们就可以清楚的看到组 0~4 对应的配置关系,例如组设置为 3,那么此时所有的 60 个中断,每个中断的中断优先寄存器的高四位中的最高 3 位是抢占优先级,低 1 位是响应优先级。每个中断,你可以设置抢占优先级为 0~7,响应优先级为 1 或 0。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。

这里需要注意两点:

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

        第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断,当两个中断同时发生的时候响应优先级高的先执行中断。

结合实例说明一下:

        假定设置中断优先级组为 2,然后设置中断 3(RTC 中断)的抢占优先级为 2,响应优先级为 1。中断 6(外部中断 0)的抢占优先级为 3,响应优先级为 0。中断 7(外部中断 1) 的抢占优先级为 2,响应优先级为 0。那么这 3 个中断的优先级顺序为:中断 7>中断 3>中断 6。

        上面例子中的中断 3 和中断 7 都可以打断中断 6 的中断。而中断 7 和中断 3 却不可以相互打断!

        接下来我们介绍如何使用库函数实现以上中断分组设置以及中断优先级管理。 NVIC 中断管理函数主要在 misc.c 文件里面

中断优先级分组函数 NVIC_PriorityGroupConfig

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

        这个函数的作用是对中断的优先级进行分组,这个函数在系统中只能被调用一次,一旦分组确定就最好不要更改。这个函数我们可以找到其实现:
 

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

        从函数体可以看出,这个函数唯一目的就是通过设置 SCB->AIRCR 寄存器来设置中断优先级分组。

#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))

        这也是我们上面表1 讲解的,分组范围为 0-4。比如我们设置整个系统的中断优先级分组值为 2,那么方法是:

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

        这样就确定了一共为“2 位抢占优先级, 2 位响应优先级”。

中断初始化函数 NVIC_Init

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_InitTypeDef 结构体中间有四个成员变量,这四个成员变量的作用是:

  • NVIC_IRQChannel:定义初始化的是哪个中断,这个我们可以在 stm32f10x.h 中找到每个中断对应的名字。例如 USART1_IRQn。
  • NVIC_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 寄存器

总结

  1. 系统运行开始的时候设置中断分组。 确定组号,也就是确定抢占优先级和子优先级的分配位数。 调用函数为 NVIC_PriorityGroupConfig();
  2. 设置所用到的中断的中断优先级别。 对每个中断调用函数为 NVIC_Init();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/494683.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

掌握命令行参数的艺术:Python的`argparse`库

文章目录 掌握命令行参数的艺术&#xff1a;Python的argparse库背景argparse库简介标准库中的重要性简单库函数使用方法场景应用常见Bug及解决方案总结 掌握命令行参数的艺术&#xff1a;Python的argparse库 背景 在Python编程中&#xff0c;我们经常需要从命令行接收参数来控…

如何根据一系列提交文件,匹配对应的git提交记录?用ai

显示提取提交文件记录的git历史&#xff08;用的豆包写一下&#xff09; 显示每次提交涉及的文件名及提交注释等基本信息 可以使用以下命令格式&#xff1a; git log --name-only --prettyformat:“%an - %s” myFolder/ –name-only选项的作用是在显示提交信息时&#xff0…

Redis篇--常见问题篇6--缓存一致性1(Mysql和Redis缓存一致,更新数据库删除缓存策略)

1、概述 在使用Redis作为MySQL的缓存层时&#xff0c;缓存一致性问题是指Redis中的缓存数据与MySQL数据库中的实际数据不一致的情况。这可能会导致读取到过期或错误的数据&#xff0c;从而影响系统的正确性和用户体验。 为了减轻数据库的压力&#xff0c;通常读操作都是先读缓…

探寻快速排序的局限性及其优化策略

一. 快速排序之局限 快速排序的平均时间复杂度为O(nlogn)。其核心步骤是&#xff1a;先从待排序数组中选定一个元素作为基准&#xff08;pivot&#xff09;&#xff0c;通过一趟排序将数组分成两部分&#xff0c;使得左边部分的元素都小于等于基准元素&#xff0c;右边部分的元…

CS!GO

CS&#xff08;computer science&#xff09;计算机科学&#xff0c;说实话&#xff0c;不是找工作面试&#xff0c;这些题谁会背啊&#xff0c;反正我不行&#xff0c;一问三不知。 咱也不管这些&#xff0c;这个系列&#xff0c;可能会时不时的给出一些计网和操作系统相关的东…

python 内存管理

Python中的内存管理涉及包含所有Python对象和数据结构的私有堆。Python内存管理器在内部确保对此私有堆的管理。需要注意的是&#xff0c;Python堆的管理是由解释器本身执行的&#xff0c;并且用户无法控制它。从源码来看&#xff0c;分为以下几层&#xff1a; level 3&#xf…

Matlab个性化绘图第6期—带标记面的三维折线图

带标记面的三维折线图本质上就是多组折线图&#xff1a; Matlab论文插图绘制模板第92期—折线图&#xff08;Plot&#xff09; 或者三维折线图&#xff1a; Matlab论文插图绘制模板第37期—三维折线图(plot3) 不同之处在于带标记面的三维折线图把每一组数据单独放在一个三维平…

C/C++圣诞树

系列文章 序号直达链接1C/C爱心代码2C/C跳动的爱心3C/C李峋同款跳动的爱心代码4C/C满屏飘字表白代码5C/C大雪纷飞代码6C/C烟花代码7C/C黑客帝国同款字母雨8C/C樱花树代码9C/C奥特曼代码10C/C精美圣诞树11C/C俄罗斯方块12C/C贪吃蛇13C/C孤单又灿烂的神-鬼怪14C/C闪烁的爱心15C…

【C++语言】多态

一、多态的概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某种行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 我们可以举一个例子&#xff1a; 比如买票这种行为&#xff0c;当普通人买票时&#xff0c;是全价买票&am…

GitCode 光引计划投稿|MilvusPlus:开启向量数据库新篇章

在人工智能和大数据时代&#xff0c;向量数据库作为处理非结构化数据的核心技术&#xff0c;正变得越来越重要。MilvusPlus&#xff0c;作为「光引计划」的一部分&#xff0c;应运而生&#xff0c;旨在提供一个高性能、易扩展、全功能的向量数据库解决方案。项目背景根植于对现…

Java设计模式 —— 【结构型模式】外观模式详解

文章目录 概述结构案例实现优缺点 概述 外观模式又名门面模式&#xff0c;是一种通过为多个复杂的子系统提供一个一致的接口&#xff0c;而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口&#xff0c;外部应用程序不用关心内部子系统的具体的细节&#xff0c;这…

Gin-vue-admin(1):环境配置和安装

目录 环境配置如果443网络连接问题&#xff0c;需要添加代理服务器 后端运行前端运行 环境配置 git clone https://gitcode.com/gh_mirrors/gi/gin-vue-admin.git到server文件目录下 go mod tidygo mod tidy 是 Go 语言模块系统中的一个命令&#xff0c;用于维护 go.mod 文件…

浅谈算法交易

本文想基于我的简单理解说说什么是算法交易&#xff0c;或者说是量化交易。 原文地址请访问&#xff1a;浅谈算法交易 什么是算法交易&#xff1f; 刚开始接触算法交易的时候&#xff0c;对它的理解&#xff0c;它就是把我平时的交易规则搬进计算机里自动执行。这个理解也没…

《点点之歌》“意外”诞生记

世界是“点点”的&#xff0c;“点点”是世界的。 (笔记模板由python脚本于2024年12月23日 19:28:25创建&#xff0c;本篇笔记适合喜欢诗文的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 …

项目代码第6讲:UpdownController.cs;理解 工艺/工序 流程、机台信息;前端的“历史 警报/工艺 记录”

一、UpdownController.cs 1、前端传入 当用户在下图的“记录查询”中的 两个界面选项 中,点击“导出”功能时,向后端发起请求,请求服务器下载文件的权限 【权限是在Program.cs中检测的,这个控制器里只需要进行“谁在哪个接口下载了文件”的日志记录】 【导出:是用户把…

Docker 技术系列之安装多版本Mysql5.6和Mysql5.7

image 大家好&#xff0c;后面的就不是关于MAC专有的内容&#xff0c;基本是跟Java环境&#xff0c;基础技术方面有关。所以这个教程对于在linux系统还是macOS都是通用的&#xff0c;不用担心。 上一篇&#xff0c;我们安装好对应的Docker之后&#xff0c;感受到了它的便利。接…

机器学习04-为什么Relu函数

机器学习0-为什么Relu函数 文章目录 机器学习0-为什么Relu函数 [toc]1-手搓神经网络步骤总结2-为什么要用Relu函数3-进行L1正则化修改后的代码解释 4-进行L2正则化解释注意事项 5-Relu激活函数多有夸张1-细数Relu函数的5宗罪2-Relu函数5宗罪详述 6-那为什么要用这个Relu函数7-文…

【GO环境安装】mac系统+GoLand使用

文章目录 下载安装包环境配置GoLandGo Modules 下载安装包 地址&#xff1a;GO下载地址 下载好后直接进行安装&#xff1a; 进入terminal&#xff0c;查看是否安装成功&#xff1a; 环境配置 在文稿下面创建工作目录&#xff1a; 在文稿下新建Go_Works文件夹&#xff0c;在…

京东大数据治理探索与实践 | 京东零售技术实践

01背景和方案 在当今的数据驱动时代&#xff0c;数据作为关键生产要素之一&#xff0c;其在商业活动中的战略价值愈加凸显&#xff0c;京东也不例外。 作为国内领先的电商平台&#xff0c;京东在数据基础设施上的投入极为巨大&#xff0c;涵盖数万台服务器、数 EB 级存储、数百…

Day13 苍穹外卖项目 工作台功能实现、Apache POI、导出数据到Excel表格

目录 1.工作台 1.1 需求分析和设计 1.1.1 产品原型 1.1.2 接口设计 1.2 代码导入 1.2.1 Controller层 1.2.2 Service层接口 1.2.3 Service层实现类 1.2.4 Mapper层 1.3 功能测试 1.4 代码提交 2.Apache POI 2.1 介绍 2.2 入门案例 2.2.1 将数据写入Excel文件 2.2.2 读取Excel文…