【STM32学习笔记】(12)——NVIC(嵌套向量中断控制器)详解
NVIC(嵌套向量中断控制器)简介
在讲如何配置中断优先级之前,我们需要先了解下 NVIC。NVIC 是嵌套向量中断控制器,控制着整个STM32芯片中断相关的功能,它跟Cortex-M3 内核紧密联系,是内核里面的一个外设。但是各个芯片厂商在设计芯片的时候会对Cortex-M3内核里面的 NVIC 进行裁剪,把不需要的部分去掉,所以说 STM32 的 NVIC 是 Cortex-M 3 的 NVIC 的一个子集。
NVIC 寄存器简介
/**中断 NVIC 结构体定义*/
typedef struct
{__IO uint32_t ISER[8]; /*!<Offset: 0x000 中断使能寄存器 */uint32_t RESERVED0[24]; __IO uint32_t ICER[8]; /*!<Offset: 0x080 中断清除寄存器 */uint32_t RSERVED1[24]; __IO uint32_t ISPR[8]; /*!<Offset: 0x100 中断使能悬起寄存器 */uint32_t RESERVED2[24]; __IO uint32_t ICPR[8]; /*!<Offset: 0x180 中断清除悬起寄存器 */uint32_t RESERVED3[24]; __IO uint32_t IABR[8]; /*!<Offset:0x200 中断有效位寄存器 */uint32_t RESERVED4[56]; __IO uint8_t IP[240]; /*!< Offset: 0x300 中断优先级寄存器 (8Bit wide) */uint32_t RESERVED5[644]; __O uint32_t STIR; /*!< Offset: 0xE00 软件触发中断寄存器 */
} NVIC_Type;
在配置中断的时候我们一般只用 ISER、ICER 和 IP 这三个寄存器,ISER 用来使能中断,ICER 用来清除中断,IP 用来设置中断优先级。
NVIC 中断配置固件库
固件库头文件 core_cm3.h 中,提供了 NVIC 的一些函数,这些函数遵循 CMSIS 规则,只要是 Cortex-M3 的处理器都可以使用,具体如下:
优先级的介绍
优先级的分组由内核外设SCB 的应用程序中断及复位控制寄存器 AIRCR 的 PRIGROUP[10:8] 位决定,F103 分为了 5 组,具体如下:主优先级 = 抢占优先级。
设置优先级分组可调用库函数 NVIC_PriorityGroupConfig() 实现,有关 NVIC 中断相关的库函数都在库文件 misc.c 和 misc.h 中。
/**
* 配置中断优先级分组:抢占优先级和子优先级
* 形参如下:
* @arg NVIC_PriorityGroup_0: 0bit for 抢占优先级
* 4 bits for 子优先级
* @arg NVIC_PriorityGroup_1: 1 bit for 抢占优先级
* 3 bits for 子优先级
* @arg NVIC_PriorityGroup_2: 2 bit for 抢占优先级
* 2 bits for 子优先级
* @arg NVIC_PriorityGroup_3: 3 bit for 抢占优先级
* 1 bits for 子优先级
* @arg NVIC_PriorityGroup_4: 4 bit for 抢占优先级
* 0 bits for 子优先级
* @ 注意 如果优先级分组为 0,则抢占优先级就不存在,优先级就全部由子优先级控制
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{/* 检查参数*/assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));/* 设置优先级分组*/ SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
具有高抢占式优先级的中断可以在具有低抢占式优先级的中断服务程序执行过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以抢占低抢占式优先级的中断的执行。在抢占式优先级相同的情况下,有几个子优先级不同的中断同时到来,那么高子优先级的中断优先被响应。
在抢占式优先级相同的情况下,如果有低子优先级中断正在执行,高子优先级的中断要等待已被响应的低子优先级中断执行结束后才能得到响应,即子优先级不支持中断嵌套。Reset、NMI、Hard Fault 优先级为负数,高于普通中断优先级,且优先级不可配置。
NVIC中断编程步骤
在配置每个中断的时候一般有 3 个编程步骤:
1、使能外设某个中断,这个具体由每个外设的相关中断使能位控制。比如串口有发送完成中断,接收完成中断,这两个中断都由串口控制寄存器的相关中断使能位控制。
2、初始化 NVIC_InitTypeDef 结构体,配置中断优先级分组,设置抢占优先级和子优先级,使能中断请求。NVIC_InitTypeDef 结构体在固件库头文件 misc.h 中定义。
typedef struct
{uint8_t NVIC_IRQChannel; /*!< 中断源 */uint8_t NVIC_IRQChannelPreemptionPriority; /*!< 抢占优先级 */uint8_t NVIC_IRQChannelSubPriority; /*!< 子优先级*/FunctionalState NVIC_IRQChannelCmd; /*!< 中断使能或者失能 */
} NVIC_InitTypeDef;
a. NVIC_IROChannel:用来设置中断源,不同的中断中断源不一样,且不可写错,即使写错了程序 也不会报错,只会导致不响应中断。具体的成员配置可参考 stm32f10x.h 头文件里面的 IRQn_Type 结构体定义,这个结构体包含了所有的中断源。
typedef enum IRQn
{
/****** Cortex-M3 处理器异常编号 ***********/NonMaskableInt_IRQn = -14, /*!< 2 不可屏蔽中断*/MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 内存管理中断*/BusFault_IRQn = -11, /*!< 5 Cortex-M3 总线故障中断*/UsageFault_IRQn = -10, /*!< 6 Cortex-M3 使用故障中断*/SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV 呼叫中断*/DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 调试监视器中断*/PendSV_IRQn = -2, /*!< 14 Cortex-M3挂起 SV 中断*/SysTick_IRQn = -1, /*!< 15 Cortex-M3 系统滴答中断*//****** STM32 特定中断号码*******/WWDG_IRQn = 0, /*!< 窗口看门狗中断*/PVD_IRQn = 1, /*!< PVD 通过 EXTI 线路检测中断*/TAMPER_IRQn = 2, /*!< 篡改中断*/RTC_IRQn = 3, /*!< RTC 全局中断*/FLASH_IRQn = 4, /*!< 闪存全局中断*/RCC_IRQn = 5, /*!< RCC 全局中断*/EXTI0_IRQn = 6, /*!< EXTI Line0 中断*/EXTI1_IRQn = 7, /*!< EXTI Line1 中断*/EXTI2_IRQn = 8, /*!< EXTI Line2 中断*/EXTI3_IRQn = 9, /*!< EXTI Line3 中断*/EXTI4_IRQn = 10, /*!< EXTI Line4 中断*/DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 全局中断*/DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 全局中断*/DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 全局中断*/DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 全局中断*/DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 全局中断*/DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 全局中断*/DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 全局中断*/ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 全局中断*/USB_HP_CAN1_TX_IRQn = 19, /*!< USB 设备高优先级或 CAN1 TX 中断*/USB_LP_CAN1_RX0_IRQn = 20, /*!< USB 设备低优先级或 CAN1 RX0 中断*/CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 中断*/CAN1_SCE_IRQn = 22, /*!< CAN1 单片机中断*/EXTI9_5_IRQn = 23, /*!< External Line[9:5] 中断*/TIM1_BRK_IRQn = 24, /*!< TIM1 打破 中断*/TIM1_UP_IRQn = 25, /*!< TIM1 更新 中断*/TIM1_TRG_COM_IRQn = 26, /*!< TIM1 触发和换向中断*/TIM1_CC_IRQn = 27, /*!< TIM1 捕获比较中断*/TIM2_IRQn = 28, /*!< TIM2 全局中断*/TIM3_IRQn = 29, /*!< TIM3 全局中断*/TIM4_IRQn = 30, /*!< TIM4 全局中断*/I2C1_EV_IRQn = 31, /*!< I2C1 事件中断*/I2C1_ER_IRQn = 32, /*!< I2C1 错误中断*/I2C2_EV_IRQn = 33, /*!< I2C2 事件中断*/I2C2_ER_IRQn = 34, /*!< I2C2 错误中断*/SPI1_IRQn = 35, /*!< SPI1 全局中断*/SPI2_IRQn = 36, /*!< SPI2 全局中断*/USART1_IRQn = 37, /*!< USART1 全局中断*/USART2_IRQn = 38, /*!< USART2 全局中断*/USART3_IRQn = 39, /*!< USART3 全局中断*/EXTI15_10_IRQn = 40, /*!< External Line[15:10] 中断*/RTCAlarm_IRQn = 41, /*!< 通过 EXTI 线路中断发出 RTC 报警*/USBWakeUp_IRQn = 42, /*!< USB 设备通过 EXTI 线路中断从挂起状态唤醒*/TIM8_BRK_IRQn = 43, /*!< TIM8 打破中断*/TIM8_UP_IRQn = 44, /*!< TIM8 更新中断*/TIM8_TRG_COM_IRQn = 45, /*!< TIM8 触发和换向中断*/TIM8_CC_IRQn = 46, /*!< TIM8 捕获比较中断*/ADC3_IRQn = 47, /*!< ADC3 全局中断*/FSMC_IRQn = 48, /*!< FSMC 全局中断*/SDIO_IRQn = 49, /*!< SDIO 全局中断*/TIM5_IRQn = 50, /*!< TIM5 全局中断*/SPI3_IRQn = 51, /*!< SPI3 全局中断*/UART4_IRQn = 52, /*!< UART4 全局中断*/UART5_IRQn = 53, /*!< UART5 全局中断*/TIM6_IRQn = 54, /*!< TIM6 全局中断*/TIM7_IRQn = 55, /*!< TIM7 全局中断*/DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 全局中断*/DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 全局中断*/DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 全局中断*/DMA2_Channel4_5_IRQn = 59 /*!< DMA2 Channel 4 and Channel 5 全局中断*/
} IRQn_Type;
b. NVIC_IRQChannelPreemptionPriority:抢占优先级,具体的值要根据优先级分组来确定,具体参考下图。
c. NVIC_IRQChannelSubPriority:子优先级,具体的值要根据优先级分组来确定,具体参考下图。
d. NVIC_IRQChannelCmd:中断使能(ENABLE)或者失能(DISABLE)。操作的是 NVIC_ISER 和 NVIC_ICER 这两个寄存器。
代码举例:
在配置中断优先级的函数中需要这样写:
NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure);//⑤初始化 NVIC
在main.c中需要调用此函数:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//抢占优先级可选0~3,响应优先级可选0~3;
3、编写中断服务函数。
在启动文件 startup_stm32f10x_hd.s 中我们预先为每个中断都写了一个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,为了方便管理我们把中断服务函数统一写在 stm32f10x_it.c 这个库文件中。
【STM32学习笔记】(12)——NVIC(嵌套向量中断控制器)详解相关推荐
- ios学习笔记3--导航控制器详解
前言: 导航控制器和标签控制器是ios中常用的两个控件.因此,特意写一篇文章记录一下,自己对导航控制器的理解,持续更新中. 导航条UINavigationBar介绍 容器UINavigationIte ...
- STM32笔记 (七)中断系统与NVIC嵌套向量中断控制器
简介 STM32拥有一个强大的中断系统,几乎所有外设都能产生中断,对于F103系列的单片机,ARM公司在Cortex‐M3 的内核水平上搭载了一个异常响应系统(异常就是中断), 支持为数众多的系统异常 ...
- 【相机标定与三维重建原理及实现】学习笔记1——相机模型数学推导详解
目录 前言 一.小孔成像模型 二.坐标系的变换 1.世界坐标系到相机坐标系的变换(刚体变换)[xw^→xc^\boldsymbol {\hat{x_{w}}}\rightarrow \boldsymb ...
- NVIC嵌套向量中断控制器
首先区分一下中断和异常的关系,其实中断和异常时有差异也有关联的,我们常常所说的中断其实也包含了异常.中断是指系统停止当前正在运行的程序转而其他服务,可能是程序接收了比自身高优先级的请求,或者是人为设置 ...
- SNMP学习笔记之SNMP 原理与实战详解
原文地址:http://freeloda.blog.51cto.com/2033581/1306743 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...
- 【学习笔记】sed 命令及参数详解
sed 命令及参数详解 标签:Sed 文章目录 sed 命令及参数详解 一.简介 二.基本用法 2.1. 三种方式 2.2. 常用选项 2.3. 命令体的组成 2.3.1. 定位文本部分 2.3.2. ...
- RT-Thread学习笔记|TCS34725 RGB 颜色识别传感器详解
rt-thread是什么? RT-Thread 是一个集实时操作系统(RTOS)内核.中间件组件和开发者社区于一体的技术平台,组件完整丰富.高度可伸缩.简易开发.超低功耗.高安全性的物联网操作系统.R ...
- 吴恩达深度学习笔记(114)-RNN梯度消失问题详解
https://www.toutiao.com/a6652968074712449550/ 2019-02-10 14:34:53 循环神经网络的梯度消失(Vanishing gradients wi ...
- HTML学习笔记3:HTML基本骨架详解
在HTML笔记1中,我简单介绍了HTML抽象的基本框架,其实,HTML的基本骨架部分还有更多内容需要了解,这一节,咱们就详细学习HTML的基本骨架. 打开sublime编辑器,输入html:xt 图1 ...
- pytorch学习笔记(十二):详解 Module 类
Module 是 pytorch 提供的一个基类,每次我们要 搭建 自己的神经网络的时候都要继承这个类,继承这个类会使得我们 搭建网络的过程变得异常简单. 本文主要关注 Module 类的内部是怎么样 ...
最新文章
- shell实例第21讲:定时清空文件内容,定时记录文件大小
- 每天睡4小时上7门课
- java聚水潭_聚水潭.sln · killvs/jusuitan - Gitee.com
- Wordpress不同页面显示不同小工具
- golang sql注入问题
- Ubuntu 打开 initramfs
- Hadoop_28_MapReduce_自定义 inputFormat
- readonly(C# 参考)
- HTML5_2(视频)
- Android studio开发Android图灵智能聊天机器人,课程设计报告
- linux运行speex,linux 用speex库压缩音频
- Go语言开发第1课-环境搭建及简单程序入门
- dll注入失败原因总结
- pion ice项目源码分析
- Eclipse 版本对应的 JDK版本要求
- ArcGIS教程:最小值和最大值条形图
- 【Servlet】servlet上传文件
- Ruby on Rails 之旅(七)—— Ruby on Rails 入门(5)
- 基于微信小程序的校园二手物品交易平台的设计与实现-计算机毕业设计源码+LW文档
- (zhuan) 126 篇殿堂级深度学习论文分类整理 从入门到应用