HAL_NVIC

文章目录

  • 一、NVIC简介
    • [   NVIC 做什么?](#   NVIC 做什么?)
  • 二、NVIC模块详解
    • [   1、NVIC 寄存器](#   1、NVIC 寄存器)
    • [   2、优先级的定义](#   2、优先级的定义)
      • [     1.优先级寄存器NVIC_IPRx](#     1.优先级寄存器NVIC_IPRx)
      • [     2.优先级分组](#     2.优先级分组)
    • [   3、NVIC 工作完整流程](#   3、NVIC 工作完整流程)
    • [   4、F103中断向量表](#   4、F103中断向量表)
      • [     1.内核异常向量(固定,所有 CM3 通用)](#     1.内核异常向量(固定,所有 CM3 通用))
      • [     2.外部中断向量(STM32F103 专用)](#     2.外部中断向量(STM32F103 专用))
  • 三、CudeMx配置NVIC
    • [   1、NVIC配置界面](#   1、NVIC配置界面)
    • [   2、打开NVIC界面](#   2、打开NVIC界面)
    • [   3、NVIC 页面里有什么?](#   3、NVIC 页面里有什么?)
    • [   4、最重要一步:选择 优先级分组](#   4、最重要一步:选择 优先级分组)
  • 四、NVIC模块组成
    • [   1、数据结构](#   1、数据结构)
    • [   2、句柄](#   2、句柄)
    • [   3、API](#   3、API)
      • [     1. 设置中断优先级](#     1. 设置中断优先级)
      • [     2. 使能中断](#     2. 使能中断)
      • [     3. 禁止中断](#     3. 禁止中断)
      • [     4. 设置优先级分组](#     4. 设置优先级分组)
      • [     5. 挂起中断(手动触发)](#     5. 挂起中断(手动触发))
      • [     6. 清除挂起](#     6. 清除挂起)
      • [     7. 获取中断活动状态](#     7. 获取中断活动状态)
    • [   4、状态/错误](#   4、状态/错误)
      • [     1. 使能状态](#     1. 使能状态)
      • [     2. 优先级状态](#     2. 优先级状态)
      • [     3. 挂起状态(Pending)](#     3. 挂起状态(Pending))
      • [     4. 活动状态(Active)](#     4. 活动状态(Active))
  • 五、NVIC模块通用模版
    • [   1、NVIC配置](#   1、NVIC配置)
    • [   2、开启更新中断](#   2、开启更新中断)
    • [   3、中断服务(stm32f1xx_it.c)](#   3、中断服务(stm32f1xx_it.c))
    • [   4、中断回调函数(处理数据)](#   4、中断回调函数(处理数据))

一、NVIC简介

   NVIC:Nested Vectored Interrupt Controller嵌套向量中断控制器,整个芯片的中断管理员。

   NVIC 是 Cortex‑M3 内置的中断硬件管理器。

   NVIC 做什么?

     哪个中断可以触发。

     中断优先级谁高谁低。

     高优先级中断能不能打断低优先级(嵌套)。

     中断发生时,CPU 跳去执行哪个函数。

   所有中断(串口、定时器、EXTI、DMA...)都必须经过 NVIC 配置才能用。

二、NVIC模块详解

   1、NVIC 寄存器

     NVIC 寄存器定义在 core_cm3.h 文件中,CM3 内核支持 256 个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有 256 级的可编程中断设置。

     STM32F103xE芯片有 70 个中断,包括 10 个内核中断和 60 个可屏蔽中断,具有 16 级可编程的中断优先级,我们常用的就是这 60 个可屏蔽中断。

c 复制代码
		typedef struct {
		    __IO uint32_t ISER[8];       // 中断使能寄存器
		    uint32_t RESERVED0[24];
		    __IO uint32_t ICER[8];       // 中断清除寄存器
		    uint32_t RSERVED1[24];
		    __IO uint32_t ISPR[8];       // 中断使能悬起寄存器
		    uint32_t RESERVED2[24];
		    __IO uint32_t ICPR[8];       // 中断清除悬起寄存器
		    uint32_t RESERVED3[24];
		    __IO uint32_t IABR[8];       // 中断有效位寄存器
		    uint32_t RESERVED4[56];
		    __IO uint8_t  IP[240];       // 中断优先级寄存器(8Bit wide)
		    uint32_t RESERVED5[644];
		    __O  uint32_t STIR;          // 软件触发中断寄存器
		}  NVIC_Type;

     一般使用ISER、ICER和IP 三个寄存器,IESR用来使能中断,ICER用来失能中断,IP用来设置中断优先级。

     ISER8 :全称是:Interrupt Set-Enable Registers,这是一个中断使能寄存器组。

       CM3 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。

       但是 STM32F103 的可屏蔽中断只有 60 个,所以对我们来说,有用的就是两个(ISER0和 ISER1),总共可以表示 64 个中断。

     ICER8 :全称是:Interrupt Clear-Enable Registers,是一个中断除能寄存器组。

     ISPR8 :全称是:Interrupt Set-Pending Registers,是一个中断挂起控制寄存器组。

     ICPR8 :全称是:Interrupt Clear-Pending Registers,是一个中断解挂控制寄存器组。

     IABR8 :全称是:Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。

     IP240 :全称是:Interrupt Priority Registers,是一个中断优先级控制的寄存器组。

       IP 寄存器组由 240 个 8bit 的寄存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。

       而 STM32 只用到了其中的前 60 个。IP59~IP0分别对应中断 59~0。

   2、优先级的定义

     1.优先级寄存器NVIC_IPRx

      

       用于表达优先级的4bit,又被分组成抢占优先级和子优先级。

       如果有多个中断同时响应,抢占优先级高的就会抢占抢占优先级低的优先得到执行,

       如果抢占优先级相同,就比较子优先级。

       如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。

     2.优先级分组

      

       设置优先级分组可调用库函数NVIC_PriorityGroupConfig()实现,有关NVIC中断相关的库函数都在库文件misc.c和misc.h中。

       中断优先级分组库函数NVIC_PriorityGroupConfig()

c 复制代码
			/**
			* 配置中断优先级分组:抢占优先级和子优先级
			* 形参如下:
			* @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)
			{
			    // 设置优先级分组
			    SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
			}

   3、NVIC 工作完整流程

     外部 / 外设产生中断信号。

     中断挂起标志置 1。

     NVIC 读取该中断优先级。

     NVIC 比较:

       若比当前运行中断抢占优先级更高 → 打断!

       若相同 → 排队,按子优先级决定顺序。

     CPU 自动保存现场(入栈)。

     跳转到对应的 中断服务函数(ISR)。

     执行完后恢复现场,回到原来程序。

   4、F103中断向量表

     1.内核异常向量(固定,所有 CM3 通用)

      

     2.外部中断向量(STM32F103 专用)

      

三、CudeMx配置NVIC

   1、NVIC配置界面

    

   2、打开NVIC界面

     在 CubeMX 界面:

       左边 System Core

       点击 NVIC

     进入中断配置页面

   3、NVIC 页面里有什么?

     主要 3 块:

       Enable:是否打开中断(打勾 = 使能)

       Preemption Priority:抢占优先级

       Sub Priority:子优先级

   4、最重要一步:选择 优先级分组

     在 NVIC 页面上方:

       Priority Group (优先级分组)

     STM32F103 最常用、最稳妥的是:

       NVIC_PriorityGroup_2

       2 位抢占优先级(0~3)

       2 位子优先级(0~3)

     数字越小,优先级越高!

四、NVIC模块组成

   1、数据结构

c 复制代码
		typedef struct
		{
		  __IO uint32_t ISER[8];       // 中断使能
		  __IO uint32_t ICER[8];       // 中断禁止
		  __IO uint32_t ISPR[8];       // 挂起置位
		  __IO uint32_t ICPR[8];       // 挂起清除
		  __IO uint32_t IABR[8];       // 活动标志
		  __IO uint8_t  IP[240];       // 优先级寄存器(最重要)
		} NVIC_Type;

   2、句柄

     NVIC 没有句柄!

   3、API

    

     1. 设置中断优先级

       HAL_NVIC_SetPriority(IRQn, PreemptPriority, SubPriority);

       示例:

         HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);

     2. 使能中断

       HAL_NVIC_EnableIRQ(IRQn);

     3. 禁止中断

       HAL_NVIC_DisableIRQ(IRQn);

     4. 设置优先级分组

       HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);

       F103 最常用:GROUP_2(2 位抢占 + 2 位子优先级)

     5. 挂起中断(手动触发)

       NVIC_SetPendingIRQ(IRQn);

     6. 清除挂起

       NVIC_ClearPendingIRQ(IRQn);

     7. 获取中断活动状态

       uint32_t status = NVIC_GetActive(IRQn);

   4、状态/错误

       NVIC 有 4 种状态:

     1. 使能状态

       已使能|已禁止

       中断是否已使能:

         uint32_t en = NVIC_GetEnableIRQ(IRQn);

     2. 优先级状态

       抢占优先级|子优先级

       获取当前优先级分组:

         uint32_t pg = HAL_NVIC_GetPriorityGrouping();

     3. 挂起状态(Pending)

       中断触发了,但还没来得及处理。

       中断是否挂起:

         uint32_t pending = NVIC_GetPendingIRQ(IRQn);

     4. 活动状态(Active)

       正在执行中断服务函数。

       中断是否正在执行:

         uint32_t active = NVIC_GetActive(IRQn);

五、NVIC模块通用模版

   NVIC应用实例都与具体外设有关,请查看外设对应实例。

   1、NVIC配置

c 复制代码
		// 1. 分组(系统只一次)
		HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
		
		// 2. 设置优先级
		HAL_NVIC_SetPriority(XXX_IRQn, 抢占优先级, 子优先级);
		
		// 3. 使能中断
		HAL_NVIC_EnableIRQ(XXX_IRQn);
		

   2、开启更新中断

c 复制代码
		// 4. 开启外设中断
		__HAL_XXX_ENABLE_IT(...);

   3、中断服务(stm32f1xx_it.c)

c 复制代码
		//5.中断服务
		void XXX_IRQHandler(void)
		{
		  HAL_XXX_IRQHandler(&hxxx);
		}

   4、中断回调函数(处理数据)

c 复制代码
		//6.中断回调函数
		void HAL_XXX_Callback(XXXT_HandleTypeDef *hxxx)
		{
		  if(hxxx->Instance == ...)
		  {
		    // 接收到数据,在这里处理
		  }
		}
相关推荐
笨笨没好名字1 天前
怎么看懂51单片机电路图与功能实现的C语言编写(2-7入门篇)
c语言·嵌入式硬件·51单片机
项目題供诗1 天前
STM32-TIM输入捕获(十四)
stm32·单片机·嵌入式硬件
cpsss06811 天前
Freertos的Systick_Handler重定义
单片机·嵌入式硬件
国产电子元器件1 天前
电流传感器的输出可以直接接示波器吗?
stm32·单片机·嵌入式硬件
zlinear数据采集卡1 天前
SPI Flash存储电路深度解析:从芯片选型到ZLinear采集卡的实战设计
c语言·嵌入式硬件·自动化·硬件架构
m0_747124531 天前
单片机 VSCode 开发环境搭建
vscode·单片机·嵌入式硬件
嵌入式小站1 天前
STM32 零基础可移植教程 21:1602A 并口 4 位模式,先显示 Hello
stm32·单片机·嵌入式硬件
夜月yeyue1 天前
KCP 与 UDP 可靠传输
linux·网络·单片机·网络协议·udp·php
WIZnet1 天前
W55RP20-EVB-MKR MicroPython 实战(14):MQTT 协议与 OneNET 平台对接
单片机·网络协议·wiznet
三佛科技-187366133971 天前
AIP8P005B(SOP14)中微爱芯8位MCU用辉芒微FT60E112A SOP14替代
单片机·嵌入式硬件