STM32中断篇
STM32中每个外设均可以产生中断。
中断分类
大致可分为两类:
-
系统异常(异常可理解为中断)。
-
外部中断。
Table 61. Vector table for STM32F405xx/07xx and STM32F415xx/17xx In RM0090
NVIC(Nested Vectored Interrupt Controller)
NVIC,可从架构来理解它的名字:NVIC是M4内核里的一个外设,即为嵌套,由于它控制着整个芯片的中断,即为嵌套向量中断控制器。
- NVIC结构体定义:core_cm4.h
/**
\brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
*/
typedef struct
{
__IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24U];
__IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[24U];
__IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[24U];
__IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
uint32_t RESERVED4[56U];
__IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644U];
__OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
} NVIC_Type;
- 一般只用到:
- ISER[8U]: Interrupt Set Enable Register.
- ICER[8U]: Interrupt Clear Enable Register.
- IP[8U]: Interrupt Priority Register (8Bit wide).
-
CMSIS access NVIC function (Table 46 in PM0214)
以下函数只要是Cortex-M4均可使用。
中断优先级
优先级定义
中断优先级在Interrupt priority register x (NVIC_IPRx)中配置, IPR 宽度为8bit。原则上每个外部中断可配置的优先级为0~255,数值越小,优先级越高。在F407 中,只使用了高4bit,如下所示:
用于表达优先级的这 4bit,又被分组成抢占优先级和子优先级。如果有多个中断同时响应,抢占优先级高的就会 抢占 抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。
优先级分组
优先级的分组由内核外设SCB的Application interrupt and reset control register (AIRCR)的PRIGROUP[10:8]决定。
-
**Application interrupt and reset control register (AIRCR):**The AIRCR provides priority grouping control for the exception model, endian status for data accesses, and reset control of the system.
Table 51. Priority grouping in PM0214
- Group priority, 主(组)优先级,抢占优先级。
- Subpriority, 子优先级。
- 设置优先级分组可调用库函数 NVIC_PriorityGroupConfig()实现,有关NVIC 中断相关的库函数都在库文件 misc.c 和 misc.h 中。
void NVIC_PriorityGroupConfig(uint32_t PriorityGroup)
{
// 检查参数
assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
// 设置优先级分组
NVIC_SetPriorityGrouping(PriorityGroup);
}
中断编程
-
使用HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)函数配置中断优先级分组。一般默认是NVIC_PRIORITYGROUP_4 分组 4。
-
使用HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)函数配置具体外设中断通道的抢占优先级和子优先级。
-
使用HAL_NVIC_EnableIRQ 函数使能中断请求。
-
编写中断服务函数。【一定要在中断中清除中断标志位,不然会一直进入中断】
可以自行查阅启动文件startup_stm32f40xx.s中预先写好的一个个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,中断服务函数统一写在stm32f4xx_it.c 这个库文件中。关于中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量表中找不到中断服务函数的入口。
以下为部分截图: