STM32 中断非常强大,每个外设都可以产生中断,中断也是STM32非常重要的一个内容。

NVIC:嵌套向量中断控制器,属于内核外设,管理着包括内核和片上所有外设的中断相关的功能。

ARM cortex_m3 内核支持 256 个中断(16 个内核+240 外部)和可编程 256 级中断优先级的设置,与其相关的中断控制和中断优先级控制寄存器(NVIC、SYSTICK 等)也都属于cortex_m3 内核的部分。STM32 采用了 cortex_m3 内核,所以这部分仍旧保留使用,但 STM32并没有使用 cortex_m3 内核全部的东西(如内存保护单元 MPU 等),因此它的 NVIC 是cortex_m3 内核的 NVIC 的子集。

这篇文章主要记录我学习中断时关于NVIC的两个问题。

问题1:NVIC_Type和NVIC_InitTypeDef结构体的关系?

NVIC寄存器的定义是在core_cm3.h中:

typedef struct
{__IO uint32_t ISER[8];                      /*!< Offset: 0x000  Interrupt Set Enable Register 中断使能寄存器          */uint32_t RESERVED0[24];                                   __IO uint32_t ICER[8];                      /*!< Offset: 0x080  Interrupt Clear Enable Register 中断清除寄存器        */uint32_t RSERVED1[24];                                    __IO uint32_t ISPR[8];                      /*!< Offset: 0x100  Interrupt Set Pending Register 中断使能悬起寄存器         */uint32_t RESERVED2[24];                                   __IO uint32_t ICPR[8];                      /*!< Offset: 0x180  Interrupt Clear Pending Register 中断清除悬起寄存器       */uint32_t RESERVED3[24];                                   __IO uint32_t IABR[8];                      /*!< Offset: 0x200  Interrupt Active bit Register 中断有效位寄存器          */uint32_t RESERVED4[56];                                   __IO uint8_t  IP[240];                      /*!< Offset: 0x300  Interrupt Priority Register (8Bit wide)中断有效位寄存器 */uint32_t RESERVED5[644];                                  __O  uint32_t STIR;                         /*!< Offset: 0xE00  Software Trigger Interrupt Register 软件触发中断寄存器    */
}  NVIC_Type;

在配置中断的时候我们一般只用 ISER、ICER 和 IP 这三个寄存器,ISER 用来使能中断,ICER用来失能中断,IP 用来设置中断优先级。而初始化这个结构体的函数就是void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct),在misc.c中定义,比较复杂,有兴趣可以看看:

/*** @brief  Initializes the NVIC peripheral according to the specified*         parameters in the NVIC_InitStruct.* @param  NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains*         the configuration information for the specified NVIC peripheral.* @retval None*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;/* Check the parameters */assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE){/* Compute the Corresponding IRQ Priority --------------------------------*/    tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;tmppre = (0x4 - tmppriority);tmpsub = tmpsub >> tmppriority;tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;tmppriority = tmppriority << 0x04;NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;/* Enable the Selected IRQ Channels --------------------------------------*/NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);}else{/* Disable the Selected IRQ Channels -------------------------------------*/NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);}
}

NVIC初始化函数是通过传递的参数NVIC_InitTypeDef* NVIC_InitStruct来初始化NVIC_Type结构体的,而对NVIC_InitTypeDef结构体的初始化就要看具体情况,比如说普通的按键外部中断等等。

NVIC_InitTypeDef结构体结构体定义在misc.h中:

typedef struct
{uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.This parameter can be a value of @ref IRQn_Type (For the complete STM32 Devices IRQ Channels list, pleaserefer to stm32f10x.h file) */uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channelspecified in NVIC_IRQChannel. This parameter can be a valuebetween 0 and 15 as described in the table @ref NVIC_Priority_Table */uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specifiedin NVIC_IRQChannel. This parameter can be a valuebetween 0 and 15 as described in the table @ref NVIC_Priority_Table */FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannelwill be enabled or disabled. This parameter can be set either to ENABLE or DISABLE */
} NVIC_InitTypeDef;

NVIC_Type和NVIC_InitTypeDef这两个结构体就是通过NVIC_Init函数来联系起来的。即NVIC_Type和NVIC_InitTypeDef的关系就是:先在具体的外部中断里将NVIC_InitTypeDef结构体初始化完成,然后通过NVIC_Init函数,把NVIC_InitTypeDef作为参数,将NVIC_Type结构体初始化。

问题2:关于中断优先级和中断优先级分组的问题,这两个有什么区别?

中断优先级分组的设定是在NVIC_Type和NVIC_InitTypeDef结构体初始化的前面。

中断优先级的设定是NVIC->IPRx寄存器(共8bit,只使用高4bit):

       相关函数:NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) // core_cm3.h 1586行

/*** @brief  Set the priority for an interrupt** @param  IRQn      The number of the interrupt for set priority* @param  priority  The priority to set** Set the priority for the specified interrupt. The interrupt * number can be positive to specify an external (device specific) * interrupt, or negative to specify an internal (core) interrupt.** Note: The priority cannot be set for every core interrupt.*/
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{if(IRQn < 0) {SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */else {NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */
}

即就是上面函数中的NVIC->IP。

中断优先级分组的设定是SCB->AIRCR:PRIGROUP[10:8]

       优先级分组是由3个bit来控制,所以可以有2 ^ 3 = 8 个分组,但是STM32只用了五组(即0~4),如下图:

相关函数:void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{/* Check the parameters */assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));/* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

所以中断优先级和中断优先级分组有什么区别或关系呢?SCB->AIRCR:PRIGROUP[10:8]设置的是中断优先级分组,也就是它的值是NVIC_PriorityGroup_0、NVIC_PriorityGroup_1、NVIC_PriorityGroup_2、NVIC_PriorityGroup_3、NVIC_PriorityGroup_4这五个值,而NVIC->IP设置的是分组中主优先级和子优先级的值,STM32使用高四位,根据不同的分组,主优先级和子优先级占用这四位中不同的位数。
       要注意的就是:中断优先级的设置和中断优先级分组的设置是在不同寄存器中设置的,前者是NVIC->IPRx,后者是SCB->AIRCR。

以上就是我遇到的两个问题及其答案,如有错误,欢迎指正。

中断编程的顺序有四个步骤:
       ①使能中断请求;
       ②配置中断优先级分组;
       ③配置NVIC寄存器,初始化NVIC_InitTypeDef;
       ④编写中断服务函数。

第一个步骤,使能中断请求是配置外设相应的寄存器,配置好外设的中断使能寄存器后,外设就可以触发中断,即可以向CPU发送中断请求,但是要让CPU接受中断请求,还需要配置NVIC(嵌套向量中断控制器)的中断使能位,这个使能位是NVIC结构体的一个成员,即上面结构体中的__IO uint32_t ISER[8]。可以说,外设的中断请求使能是小门,而NVIC(嵌套向量中断控制器)的中断使能是大门,一个大门对应多个小门。

第二个步骤,配置中断优先级分组,为什么要配置中断优先级分组呢?因为STM32有多个外设,所以就有可能产生多个中断请求,这时候就需要解决先处理哪个中断请求这个问题,所以就要配置中断优先级分组,优先级高的先处理。

第三个步骤,当中断优先级分组配置完了,就要配置具体的外部中断了,除了要初始化NVIC_InitTypeDef结构体,还要配置EXTI_InitTypeDef结构体。

第四个步骤,中断服务函数也是在具体的外部中断中配置的,比如EXTI0_IRQHandler函数,具体问题具体分析,这里不再多说。

STM32中断笔记——关于NVIC的两个问题相关推荐

  1. STM32学习笔记(四)丨TIM定时器及其应用(定时中断、内外时钟源选择)

    本篇文章包含的内容 一.TIM 定时器 1.1 TIM 定时器简介 1.2 TIM 定时器类型及其工作原理简介 1.2.1 基本定时器工作原理及其结构 1.2.2 通用定时器工作原理及其结构 1.2. ...

  2. STM32入门笔记(02):定时器之定时器中断、输入捕获和PWM输出(SPL库函数版)

    目录 定时器 8个定时器 定时器功能 定时器中断 常用通用定时器的寄存器 定时器中断实验目的: 定时器库函数及步骤 实验程序讲解 PWM 简介 STM32 PWM工作过程 PWM模式1 与 PWM模式 ...

  3. STM32中断回调函数定时器-STM32电控学习笔记06

    STM32中断&定时器-STM32电控学习笔记06 day6:2022/9/24 [中断概述] 在 STM32 中,对信号的处理可以分为轮询方式和中断方式,轮询方式就是不断去访问一个信号的端口 ...

  4. STM32学习笔记(三)丨中断系统丨EXTI外部中断(对射式红外传感器计次、旋转编码器计次)

    本篇文章包含的内容 一.中断系统 1.1 中断的定义 1.2 中断优先级 1.3 中断的嵌套 1.4 STM32中的中断系统 1.4.1 STM32的中断资源 1.4.2 嵌套中断向量控制器 NVIC ...

  5. STM32笔记之 NVIC(嵌套向量中断控制器)

    写在前面: 本文章旨在总结备份.方便以后查询,由于是个人总结,如有不对,欢迎指正:另外,内容大部分来自网络.书籍.和各类手册,如若侵权请告知,马上删帖致歉. 目录 一.NVIC简单解释 二.抢占优先级 ...

  6. 009 - STM32学习笔记 - 中断

    009 - STM32学习笔记 - 中断 这节的内容,野火的官方视频我反复看了好几次,但是感觉火哥在这块讲解的特别绕,理解起来很吃力,后来在看了一下其他老师的视频,结合一些书本资料和官方手册,才搞清楚 ...

  7. 【STM32学习笔记】(13)——外部中断详解

    EXTI 简介         EXTI(External interrupt/event controller)-外部中断/事件控制器,管理了控制器的 20 个中断/事件线.每个输入线可以独立地配置 ...

  8. stm32学习笔记-中断系统

    文章目录 问题引入 1.中断系统概述. 1.1 为什么要中断(中断意义) 中断和轮询比较: 1.2 中断处理过程 1.3 中断笔试题 1.4 中断服务函数 2.STM32中断的体系结构. 2.1 结构 ...

  9. STM32学习笔记——EXTI外部中断,光敏传感器控制LED灯

    中断系统 中断:在主程序运行过程中,当出现了特定的中断触发条件,CPU就可以暂停当前正在运行的程序去处理中断程序,并把当前程序的地址压入堆栈,中断程序处理完成后把地址弹出堆栈,回到刚刚暂停的位置继续执 ...

最新文章

  1. 如何成立一家私募基金公司
  2. C#面向对象设计模式纵横谈——6.Prototype 原型模式(创建型模式)
  3. android面试自定义view,资深面试官:自定义View的实现方式,你知道几种?
  4. 文献学习(part19)--Graph Connectivity In Sparse Subspace Clustering
  5. (5)呼吸灯systemverilog与VHDL编码
  6. 引导页的圆点滑动效果
  7. 连接svn认证失败有那些原因_SVN下载安装及使用教程(一)
  8. 了解Hadoop数据类型,输入输出格式及用户如何自定义。
  9. C#之向ListView视图插入数据...
  10. idea断点的几个意思_你真的理解Intellij IDEA的Debug技巧吗?这篇文章全部教给你...
  11. [远程桌面]程mstsc连接Windows Server2008 未安装任何音频输出设备 启用声音音频解决
  12. 个人信息安全规范----8、组织的个人信息安全管理要求
  13. 三小时学会HTML(菜鸟教程精华版)
  14. 计算机组装专周实训心得,电脑组装实训心得3篇
  15. python小程序源码合集
  16. 联邦学习:加密算法Paillier,Affine,IterativeAffine
  17. 高数 03.02洛必达法则
  18. Java实验06-GUI文件加解密软件,ScrollPanel嵌套Boxlayout,DES分组加密算法,进度条控制
  19. Python 获取 网易云音乐热门评论(python2/python3代码)
  20. After Effects for Graphic Design After Effects for Graphic Design Lynda课程中文字幕

热门文章

  1. PPT之如何一键删除所有幻灯片备注?
  2. 用户增长:增长黑客——Growth Hacking
  3. (转载)程序员各种网站收藏
  4. Service简单介绍
  5. 【Skywalking】集成Sl4fj2报错:NoClassDefFoundError,com/lmax/disruptor/TimeoutBlockingWaitStrategy
  6. Linux系统操作(3):ubuntu安装使用tmux的详细教程
  7. 贝索斯登顶世界首富告诉我们什么?
  8. 手机ppi排行测试软件,国产机最顶级屏幕!一加7 Pro屏幕测试出炉:色准、亮度无敌...
  9. 关闭iTunes的强制自动文件备份 -(电脑空间不足,无法升级iPhone)
  10. vue项目里面使用video.js视频播放插件