STM32中断使用NVIC

抢占优先级和响应优先级

值越小优先级越高,抢占优先级高就可以的打断抢占优先级低的;但同一个抢占优先级,高响应优先级并不能打断低响应优先级;当然中断同时发生的响应优先级高的先执行。简单理解为: 抢占优先级能控制中断的绝对打断,同级抢断优先级没有打断的功能

分组配置是在寄存器SCB->AIRCR中配置:

SCB: System Control Block; AIRCR : Application Interrupt / Reset Control Register

STM32中断使用NVIC

; 常用寄存器解释

typedef struct
{
  __IOM uint32_t ISER[8U];
         uint32_t RESERVED0[24U];
  __IOM uint32_t ICER[8U];
         uint32_t RSERVED1[24U];
  __IOM uint32_t ISPR[8U];
         uint32_t RESERVED2[24U];
  __IOM uint32_t ICPR[8U];
         uint32_t RESERVED3[24U];
  __IOM uint32_t IABR[8U];
        uint32_t RESERVED4[56U];
  __IOM uint8_t  IP[240U];
         uint32_t RESERVED5[644U];
  __OM  uint32_t STIR;
}  NVIC_Type;

ISER[8]

ISER 全称是:Interrupt Set-Enable Registers,这是一个中断使能寄存器组。CM3 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制(32 _8=256),但103系列的芯片只有60个所以只需要两个32位中断(2_32=64),也就是ISER[0]和ISER[1]

ICER

ICER[8]:全称是:Interrupt Clear-Enable Registers,是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。

ISPR

ISPR[8]:全称是:Interrupt Set-Pending Registers,是一个中断挂起控制寄存器组。每个位对应的中断和 ISER 是一样的。

ICPR

ICPR[8]:全称是:Interrupt Clear-Pending Registers,是一个中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。

IABR

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

IP

IP[240]:全称是:Interrupt Priority Registers,是一个中断优先级控制的寄存器组。这个寄存器组相当重要!STM32 的中断分组与这个寄存器组密切相关。IP 寄存器组由 240 个 8bit 的寄存器组成,每个可屏蔽中断占用 8bit。想要设置某个序号的中断,最终是通过修改IP中某个序号8位的值。例如IP[37]=

程序设置中断过程

typedef struct
{
  uint8_t NVIC_IRQChannel;
  uint8_t NVIC_IRQChannelPreemptionPriority;
  uint8_t NVIC_IRQChannelSubPriority;
  FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;

系统运行后先设置中断优先级分组。调用函数:
1.void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
 整个系统执行过程中,只设置一次中断分组。
针对每个中断,设置对应的抢占优先级和响应优先级:
2.void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
NVIC_InitTypeDef   NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
③ 如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。

STM32中断使用NVIC

库函数中的中断初始化函数分析

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
  uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;

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

    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;

    NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
  else
  {

    NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
}

中断函数的命名,不能随意命名

参考:https://www.cnblogs.com/zzdbullet/p/9949742.html,https://blog.csdn.net/c_kongfei/article/details/124724844
在keil建立工程时,都会有一个启动文件,是对应每个硬件的启动文件例如 startup_stm32f10x_hd.s,这是一个汇编语言的文件。其中已经定义了不同中断触发后进入那个函数执行。其中很多以IRQ(Interupt ReQuest)有关的DCD定义, DCD表示定义一个字的空间(32位bit’),就是对应中断的执行函数名称。Cortex-M3使用了”向量表查表机制”。

Original: https://blog.csdn.net/weixin_43794311/article/details/128420515
Author: MAR-Sky
Title: STM32中断使用NVIC

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/793233/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球