NVIC中断优先级管理

发布者:CreativeMind最新更新时间:2021-11-30 来源: eefocus关键字:NVIC  中断优先级  stm32 手机看文章 扫描二维码
随时随地手机看文章

一,STM32中断介绍

CM3内核支持256个中断,16个内核中断和240个外部中断,具有256级可编程中断设置


STM32只使用了CM3内核的一部分,84个中断:16个内核中断+68个可屏蔽中断(外部中断),具有16级可编程的中断优先级


STM32F103系列只有60个可屏蔽中断(F107系列有68个)


二,中断管理

STM32有如此多的中断,那么是如何进行管理的

这里写图片描述

中断优先级分组:


 SCB->AIRCR [10:8]3位寄存器 :


配置分组,确定中断具有几位抢占优先级和几位响应优先级


每一个中断都具有一个[7:4]4位IP寄存器,通过这4个位来设置抢占和响应优先级, 16级可编程中断优先级(2的4次方=16)


配置分组寄存器SCB->AIRCR之后,抢占优先级和响应优先级的位分配也对应完成


三,抢占优先级和响应优先级:

 优先级高低划分:0最高,4最低


 较高抢占优先级中断可以打断正在执行的较低抢占优先级的中断


 如:A的抢占优先级是4,B的抢占优先级是0

 A中断正在执行中,B中断发生,此时由于B的抢占优先级较高,会先暂停执行A的中断,先执行B的中断,待B中中断执行完成后,继续执行A的中断


 抢占优先级相同,且两个中断同时发生时,响应优先级较高的中断先执行


 如:A,B的抢占优先级是0,A的响应优先级是0,B的响应优先级是4

 A,B中断同时发生,此时由于A的响应优先级较高,A中断先执行


四,中断优先级分组函数

中断优先级分组函数:


void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);


在misc.c中找到NVIC_PriorityGroupConfig函数源码:


/**

  * @brief  Configures the priority grouping: pre-emption priority and subpriority.

  * @param  NVIC_PriorityGroup: specifies the priority grouping bits length.

  *   This parameter can be one of the following values:

  *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority

  *                                4 bits for subpriority

  *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority

  *                                3 bits for subpriority

  *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority

  *                                2 bits for subpriority

  *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority

  *                                1 bits for subpriority

  *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority

  *                                0 bits for subpriority

  * @retval None

  */

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寄存器

}


入参NVIC_PriorityGroup有效性判断:

在misc.h中找到IS_NVIC_PRIORITY_GROUP的声明


/** @defgroup Preemption_Priority_Group

  * @{

  */

#define NVIC_PriorityGroup_0         ((uint32_t)0x700) //0位抢占,1为响应

#define NVIC_PriorityGroup_1         ((uint32_t)0x600) //1位抢占,3为响应

#define NVIC_PriorityGroup_2         ((uint32_t)0x500) //2位抢占,2为响应

#define NVIC_PriorityGroup_3         ((uint32_t)0x400) //3位抢占,1为响应

#define NVIC_PriorityGroup_4         ((uint32_t)0x300) //4位抢占,0为响应


//有效性 分组0 - 分组4

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


设置分组:


NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组2

1

五,设置分组相关寄存器:

__IO uint8_t  IP[240]; //中断优先级控制的寄存器组


__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]; //中断激活标志位寄存器组


中断优先级分组属于内核级别,在core_cm3.h中找到NVIC_Type结构体


/** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC

  memory mapped structure for Nested Vectored Interrupt Controller (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  Software Trigger Interrupt Register     */

}  NVIC_Type;


1,中断优先级控制的寄存器组 IP[240]


 IP[240]寄存器组,对于每个中断都有一个IP寄存器,共240个8位寄存器


CM3内核最多有240个可屏蔽中断,所以有240个8位寄存器来配置240个中断的优先级

STM32F10x系列共60个可屏蔽中断,使用IP[59]-IP[0]

每个IP寄存器的高4位用于设置抢占和响应优先级.低4位没有用到


通过NVIC_Init()函数设置抢占和响应优先级

在misc.h中找到NVIC_Init()函数源码:


/**

  * @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_InitTypeDef*结构体指针,位于misc.h


typedef struct


{


  uint8_t NVIC_IRQChannel; //设置中断通道


  uint8_t NVIC_IRQChannelPreemptionPriority;//设置响应优先级


  uint8_t NVIC_IRQChannelSubPriority; //设置抢占优先级


  FunctionalState NVIC_IRQChannelCmd; //使能/使能


} NVIC_InitTypeDef;


/** @addtogroup STM32F10x_StdPeriph_Driver

  * @{

  */


/** @addtogroup MISC

  * @{

  */


/** @defgroup MISC_Exported_Types

  * @{

  */


/**

  * @brief  NVIC Init Structure definition

  */


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, please

                                                    refer to stm32f10x.h file) */

                                                  //通道

  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel

                                                   specified in NVIC_IRQChannel. This parameter can be a value

                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */

                                                  //抢占优先级

[1] [2]
关键字:NVIC  中断优先级  stm32 引用地址:NVIC中断优先级管理

上一篇:关于STM32 NVIC配置的解释
下一篇:按键输入-GPIO输入

推荐阅读最新更新时间:2024-11-04 16:28

stm32-afio的使用
1. AFIO的功能 为了优化64脚或100脚封装的外设数目,可以把一些复用功能重新映射到其他引脚上。设置复用重映射和调试I/O配置寄存器(AFIO_MAPR)实现引脚的重新映射。这时,复用功能不再映射到它们的原始分配上。 简言之,AFIO实现了复用功能的重新映射。 2. 在什么情况下,需要开启AFIO时钟? 参考手册中写道:对寄存器AFIO_EVCR, AFIO_MAPR和AFIO_EXTICRX进行读写操作前,应当首先打开AFIO的时钟。 在数据手册的引脚定义中(pin definitions),复用功能 Alternate functions 栏下分为两栏:默认 Default 和重映射 R
[单片机]
stm32-afio的使用
STM32的PWM的频率和占空比设定
在TEC控温项目中用到PWM的占空比来控制温度,这就需要占空比是连续可以变化的。 最开始也是到处找资料,找现成的例程,发现大家各说风云,最后还是没有建设性的结果。所以又请教了官方的固件库“STM32最新固件库v3.5”(存到百度网盘- 开发应用- stm32目录下了)呵呵,有现成的demo。开始好像是懂了也没有过多的去研究,也没有备份,就没去管他了。后来具体用的时候发现没有想象的那么简单,又倒腾了好久才搞清楚,问了不走弯路。这次决定用博客来记录一下现在的成果。配置文件如下: void TIME_ini(uint16_t Channel4Pulseset) { TIM_TimeBaseInitTypeDef TIM_Time
[单片机]
STM32_USART输入输出讲解
今天总结STM32F103串口,以工程实例来讲述。 工程现象: 1.间断发送字符 2.接收中断(接收字符,并发送该字符) 软件工程下载地址(360云盘): https://yunpan.cn/cPEI3zyQ7UqJv 访问密码ee52 讲述分如下几点: 一、初始化始终 这里的“时钟配置”函数在bsp.c文件下面; 使能串口1(RCC_APB2Periph_USART1)时钟。 二、USART1引脚配置 这里的“USART1引脚配置”函数在usart.c文件下面; 初始化串口使用引脚, 包含端口引脚、频率、输出类型。 三、串口配置 这里的“串口配置”函数在usart.c文件下面; 详见
[单片机]
STM32_USART输入输出讲解
STM32 FSMC学习笔记+补充(LCD的FSMC配置)
FSMC全称 静态存储器控制器 。 使用FSMC控制器后,可以把FSMC提供的FSMC_A 作为地址线,而把FSMC提供的FSMC_D 作为数据总线。 (1)当存储数据设为8位时,(FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b) 地址各位对应FSMC_A ,数据位对应FSMC_D (2)当存储数据设为16位时,(FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b) 地址各位对应FSMC_A ,数据位对应FSMC_D FSMC 包括4个
[单片机]
<font color='red'>STM32</font> FSMC学习笔记+补充(LCD的FSMC配置)
stm32快速学习7——LED闪烁(TIM2查询)
#include stm32f10x_gpio.h #include stm32f10x_rcc.h #include stm32f10x_flash.h #include stm32f10x_tim.h #include misc.h void RCC_Configuration(void); void GPIO_Configuration(void); void TIM_Configuration(void); int main(void) { RCC_Configuration(); GPIO_Configuration(); TIM_Configuration(); while(1)
[单片机]
STM32下载出现no target connect
今天焊好了一个STM32F107VCT6的板子,一开始芯片可以下载进去程序。 然后过了5分钟,程序突然下载不进去了。然后就是一顿分析。当然分析的过程很复杂。 前前后后焊了3个芯片。STlink和Jlink都试过还是不能下载程序。 分析了一下,是芯片写保护了。 至于为什么写保护,是STlink供电不稳定, 当时引脚没有焊上去。供电断断续续的,芯片就被写保护了。解决办法在下面。 下两个图是我用STlink做的。 然后查资料将复位引脚拉低以后,然后在设备里面出现了 但是现在是下载不进去程序的。 然后继续看资料,将BOOT0引脚拉高使用ISP下载模式(就是直接下载就行了), 如果出现
[单片机]
<font color='red'>STM32</font>下载出现no target connect
STM32驱动DP83848注意事项
检查STM32的MAC时钟是否已开启。 检查以太网50M的时钟是否正确配置。 检查STM32的以太网复用IO是否连接到重映射端口上。 检查STM32的以太网RMII端口是否已正确初始化,IO端口的时钟是否已开启。 检查连接DP83848的RST引脚的IO是否已初始化。 检查DP83848的CONFIG引脚在复位状态下的电平是否正确。 检查DP83848的地址引脚配置是否与STM32中初始化定义的地址一致。 检查DP83848的时钟接法,如果是外接晶振,检查晶振是否起振,否则查看是否接到STM32的MOC脚,如果是,检查STM32是否已配置MOC脚输出50M时中。。。。。。。。。。。
[单片机]
STM32启动流程
1、stm32初始化流程 void RCC_Configuration(void) { /* RCC system reset(for debug purpose) */ RCC_DeInit(); //时钟控制寄存器全部恢复默认值 /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); //外部高速时钟源开启(8M晶振) /* Wait till HSE is ready */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部时钟HSE就绪 if(HSEStartUpStatus == SUCCESS) //如果时钟启动成功 {
[单片机]
<font color='red'>STM32</font>启动流程
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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