【STM32 LL库编程】外部中断与中断管理

0x01 > 什么是中断

         所谓中断就是指CPU正处于工作状态时,外部发生了某一事件(按键按下),请求CPU进行处理,于是 CPU暂时中断当前的工作,转而处理所发生的的事件,处理完毕在回到原来被中断的地方继续工作,这样的过程被称为中断

中断示意图

中断包括以下几部分

  • 中断源
  • 中断申请
  • 开放中断
  • 保护现场
  • 中断服务
  • 恢复现场
  • 中断返回

我们知道 传统的51单片机一共有 5 个中断源,它们分别为:

  1. 外部中断0
  2. 定时器0
  3. 外部中断1
  4. 定时器1

现在正在学习的 STM32 有多少中断呢?

0x02 > STM32 中断基础知识

  • Cortex-m3支持256个中断,其中包含了16个内核中断,240个外部中断。
  • STM32 只有84个中断,包括16个内核中断和68个可屏蔽中断
  • STM32 上只有60个可屏蔽中断,f107上才有68个中断
  • 先占优先级也就是抢占优先级,概念等同于51单片机中的中断。假设有两中断先后触发,已经在执行的中断先占优先级如果没有后触发的中断 先占优先级更高,就会先处理先占优先级高的中断。也就是说又有较高的先占优先级的中断可以打断先占优先级较低的中断。这是实现中断嵌套的基础。
  • 次占优先级,也就是响应优先级,只在同一先占优先级的中断同时触发时起作用,先占优先级相同,则优先执行次占优先级较高的中断。次占优先级不会造成中断嵌套。 如果中断的两个优先级都一致,则优先执行位于中断向量表中位置较高的中断。

  0x001 >> 嵌套向量中断控制器 (NVIC)

    STM32 的中断既然有这么多,那么要怎么管理呢?
ST也给了我们一些解决方案就是 使用 嵌套中断向量控制器 NVIC,NVIC属于内核级的寄存器,所以当我们需要查询 NVIC 相关定义 应该到 core_cm3.h 中(这里讲解的芯片是 STM32F103ZE 是基于 Coretex-M3)

/* 访问嵌套向量中断控制器 (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];               /* 中断优先级寄存器(8Bit wide) */
        uint32_t RESERVED5[644U];
  __OM  uint32_t STIR;                   /* 软件触发中断寄存器 */
}  NVIC_Type;

  0x002 >> 中断优先级定义 ☆

中断优先级设定寄存器

coretex-M3 内核的中断定义寄存器的宽度是8位的,在上图中,我们能看到ST在设计中断的时候只使用了高4位 [7:4]

The processor implements only bits[7:4] of each field, bits[3:0] read as zero and ignore writes.
处理器只实现每个字段的位[7:4],位[3:0]读为零,忽略写。

ST在上述分组中,ST还将中断分成了主优先级(抢占优先级)和子优先级(响应优先级)。对应的寄存器


优先级分组寄存器

优先级组

上图就是,优先级分组寄存器和对应的优先级分组,下面来简单的总结一下优先级分组怎么用。


优先级分组
/* LL 库中断优先级分组,选项和实现 */

#define NVIC_PRIORITYGROUP_0         ((uint32_t)0x00000007) /*!< 0 bit  for pre-emption priority,
                                                                 4 bits for subpriority */
#define NVIC_PRIORITYGROUP_1         ((uint32_t)0x00000006) /*!< 1 bit  for pre-emption priority,
                                                                 3 bits for subpriority */
#define NVIC_PRIORITYGROUP_2         ((uint32_t)0x00000005) /*!< 2 bits for pre-emption priority,
                                                                 2 bits for subpriority */
#define NVIC_PRIORITYGROUP_3         ((uint32_t)0x00000004) /*!< 3 bits for pre-emption priority,
                                                                 1 bit  for subpriority */
#define NVIC_PRIORITYGROUP_4         ((uint32_t)0x00000003) /*!< 4 bits for pre-emption priority,
                                                                 0 bit  for subpriority */

/**
  \brief   Set Priority Grouping
  \details Sets the priority grouping field using the required unlock sequence.
           The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
           Only values from 0..7 are used.
           In case of a conflict between priority grouping and available
           priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
  \param [in]      PriorityGroup  Priority grouping field.
 */
__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
  uint32_t reg_value;
  uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL);             /* only values 0..7 are used          */

  reg_value  =  SCB->AIRCR;                                                   /* read old register configuration    */
  reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change               */
  reg_value  =  (reg_value                                   |
                ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
                (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) );               /* Insert write key and priority group */
  SCB->AIRCR =  reg_value;
} 

假设我们有两个外设 外设A 和外设B 我们将 两个外设的主优先级都配置为 0,将外设 A 的子优先级配置为 1,外设 B 的子优先级配置为 2,。当它们的中断请求同时到来时,内核将如何执行?

内核将比较两个外设的主优先级,如果外设的主优先级相等,就会对子优先级进行比较,子优先级越高,子优先级的数字就越小。

令人头痛的问题,如果外设的主优先级、子优先级都相同,怎么判断?

如果外设的主优先级和子优先级都相等,那么将会对硬件中断编号进行比较

硬件编号在哪?

硬件编号 位于 《STM32 中文参考手册_V10》第九章 中断和事件 第9.1.2小节 中断和异常向量表

0x03 > 总结

以上就是 关于 STM32F103ZE 的外部中断与中断管理的理论部分。这篇文章可能会让你感到晦涩难懂,或者有漏洞,那是在所难免的问题。
如有错误,欢迎指正,对您有帮助,点个赞再走 (>..<)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容