作为一个小白,之前自己一直没想明白,为什么在使能一个中断的时候,既要使用 __HAL_UART_ENABLE_IT(),又要同时使用 HAL_NVIC_EnableIRQ(),这两者不都是使能中断吗,为什么要使能两次,这两者的差别又在哪里?

直到我在 STM32 参考手册中看到了下面这张图及其解释,再结合附件文档《STM32中断优先级与相关使用概念》,我才算弄明白其中的门道。
image.png

明确中断向量(通道)、中断事件(源)的概念

首先让我们明确两个概念:

  • 中断向量(通道)
  • 中断事件(源)

image.png
image.png
对于 cortex_m3 内核所支持的 240 个外部中断,我在这里使用了“中断通道”这个概念来帮助理解,在参考手册中使用的是中断向量(interrupt vector)。

因为尽管每个中断对应一个外围设备,但
一个外围设备通常具备若干个可以引起中断的中断源或中断事件(interrupt events)。而该设备的所有的中断都只能通过同一个指定的“中断向量”向内核申请中断,这个中断向量就是同一个外设下面所有中断事件向内核申请中断的「通道」**。

因此,关于中断优先级的概念都是针对“中断向量(通道)”的。当该中断通道的优先级确定后,也就确定了该外围设备的中断优先级,并且该设备所能产生的所有类型的中断,都享有相同的中断优先级。至于该设备本身产生的多个中断的执行顺序,则取决于用户的中断服务程序。

一个外设所有的中断事件,都是在同一个外设对应中断服务程序(Interrupt Service Routine,ISR)中完成的,所以进入中断程序后,中断服务程序需要首先判断是哪个具体事件的中断,然后再转移到相应的服务代码段去。

结合 USART 中断理解

以上图中的 USART 中断为例,USART 有以下各种中断事件:
● 发送期间:发送完成、清除发送、发送数据寄存器空。
● 接收期间:空闲总线检测、溢出错误、接收数据寄存器非空、校验错误、 LIN断开符号检测、噪音标志(仅在多缓冲器通信)和帧错误(仅在多缓冲器通信)。

这些中断事件和其对应的使能控制位是“”的关系,只有当设置了对应的使能控制位时,这些事件才可以产生各自的中断。

在 HAL 库中,使能控制位是通过宏 __HAL_UART_ENABLE_IT()__HAL_UART_DISABLE_IT()
来设置的。比如我想让 USART 在接收到数据时产生一个中断,那么就要通过下面的代码来使能 RXNE(接收数据就绪可读)中断。

  1. __HAL_UART_ENABLE_IT(UART_IT_RXNE);

后面我又在正点原子的参考资料中看到,后悔没有早点看到啊,就是被几个概念给混淆了

STM32中断优先级与相关使用概念.pdf