• STM32 中断和事件


    中断和事件(Interrupts and events)

    嵌套向量中断控制器(Nested vectored interrupt controller -NVIC)

    • 中断是相对CPU而言的,因此例如IIC、定时器这些芯片内产生的中断也被称为外部中断,不能狭隘的理解为由芯片外的信号触发

    • EXTI被称为外部中断/事件控制器(External interrupt/event controller)

    • 什么是中断?什么是事件

    • EXTI的23个中断事件线与中断的关系? 在同一时刻每个中断线只能相应一个GPIO端口的中断,不能够同时相应所有端口的中断事件

    • 优先级定义

      NVIC有一个专门的寄存器:中断优先级寄存器NVIC_IPRx用来配置外部中断的优先级,IPR宽度为8bit,原则上每个外部中断可配置的优先级为0~255,数值越小,优先级越高。在STM32F4中使用了高4位设置中断优先级,也就是有16个可编程优先级。
      中断优先级被分组为抢占优先级子优先级。如果有多个中断同时响应,抢占优先级高的就会抢占抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。

    寄存器介绍

    上面说到 NVIC 控制着芯片的中断相关功能, 那么肯定有很多对应的寄存器,在固件库 core_cm3.h 文件内定义了一个 NVIC 结构体,里面定义了相关寄存器,如下:

    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]; //中断优先级寄存器
        uint32_t RESERVED5[644];
        __O uint32_t STIR; //软件触发中断寄存器
    } NVIC_Type;
    

    在配置中断时,我们通常使用的只有 ISER、 ICER 和 IP 这三个寄存器,ISER是中断使能寄存器,ICER是中断清除寄存器,IP 是中断优先级寄存器。在固件库 core_cm3.h文件后面,还提供了一些对 NVIC 操作的库函数,这些函数都是遵循 CMSIS 标准, 所以只要是基于 Cortex-M3 内核的芯片都可以用这些函数来操作 NVIC,只不过我们很少这样做,甚至不使用这些函数,因为在后面我们会有更简单的办法来配置中断。至于这些函数内容,大家如果有兴趣的话,可以打开我们库函数版本任意程序,找到 core_cm3.h 文件查看即可。

    这里多提一点__IO的用法:

    /* IO definitions (access restrictions to peripheral registers) */
    #ifdef __cplusplus
      #define __I  volatile         /*!< defines 'read only' permissions                 */
    #else
      #define __I  volatile const   /*!< defines 'read only' permissions                 */
    #endif
    #define   __O  volatile         /*!< defines 'write only' permissions                */
    #define   __IO volatile         /*!< defines 'read / write' permissions              */ 
    

    其实就是将volatile关键字进行了重定义,用来区分读写,仅仅是语法提醒层面,并不强制。

    中断配置

    前面讲解了那么多中断知识, 如果大家不理解也没有关系, 我们会应用即可,等到后面 STM32 熟练了,再回过头深入了解自然就会明白。要使用中断我们就需要先配置它,通常都需经过这几步:

    (1)使能外设某个中断,这个具体是由外设相关中断使能位来控制,比如

    定时器有溢出中断,这个可由定时器的控制寄存器中相应中断使能位来控制。

    (2)设置中断优先级分组,初始化 NVIC_InitTypeDef 结构体,设置抢占

    优先级和响应优先级,使能中断请求。

    NVIC_InitTypeDef 结构体如下:

    typedef struct
    {
      uint8_t NVIC_IRQChannel; //中断源
      uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级
      uint8_t NVIC_IRQChannelSubPriority; //响应优先级
      FunctionalState NVIC_IRQChannelCmd; //中断使能或失能
    } NVIC_InitTypeDef;
    

    下面我们对 NVIC_InitTypeDef 结构体成员进行一下简单介绍。

    1.NVIC_IRQChannel:中断源的设置,不同的外设中断,中断源不一样,自

    然名字也不一样,所以名字不能写错,否则不会进入中断。中断源放在stm32f10x.h 文件的 IRQn_Type结构体内,由于内容太多,这里就不复制所有中断源,只截取一部分,如下:

    
    typedef enum IRQn
    {
      //Cortex-M3 处理器异常编号
      NonMaskableInt_IRQn = -14,
      MemoryManagement_IRQn = -12,
      BusFault_IRQn = -11,
      UsageFault_IRQn = -10,
      SVCall_IRQn = -5,
      DebugMonitor_IRQn = -4,
      PendSV_IRQn = -2,
      SysTick_IRQn = -1,
      //STM32 外部中断编号
      WWDG_IRQn = 0,
      PVD_IRQn = 1,
      TAMP_STAMP_IRQn = 2,
      // 限于篇幅,中间部分代码省略,具体的可查看库文件 stm32f10x.h
      DMA2_Channel2_IRQn = 57,
      DMA2_Channel3_IRQn = 58,
      DMA2_Channel4_5_IRQn = 59
    }IRQn_Type;
    

    2.NVIC_IRQChannelPreemptionPriority:抢占优先级,具体的值要根据优先级分组来确定,可以参考前面中断优先级分组内容。

    3.NVIC_IRQChannelSubPriority:响应优先级,具体的值要根据优先级分组

    来确定,可以参考前面中断优先级分组内容。

    4.NVIC_IRQChannelCmd:中断使能/失能设置,使能配置为 ENABLE,失能配置为 DISABLE。

  • 相关阅读:
    经典测试面试题一
    自定义函数实现字符串数组互转
    php 实现密码错误三次锁定账号10分钟
    HTTP状态码
    Linux知识点
    慢查日志
    curl 采集
    HTTP协议
    docker配置
    mysql数据库索引、存储引擎、事务
  • 原文地址:https://www.cnblogs.com/RegressionWorldLine/p/12203676.html
Copyright © 2020-2023  润新知