STM32笔记 (七)中断系统与NVIC嵌套向量中断控制器
简介
STM32拥有一个强大的中断系统,几乎所有外设都能产生中断,对于F103系列的单片机,ARM公司在Cortex‐M3 的内核水平上搭载了一个异常响应系统(异常就是中断), 支持为数众多的系统异常和外部中断。对于每一种中断都有一个编号,其中,编号为 1-15 的对应系统异常,大于等于 16 的则全是外部中断
Cortex-M3系统异常清单:
Cortex-M3外部中断清单:
Cortex-M3提供了两百多种异常类型,但在STM32中并没有这么多,STM32的中断系统是被阉割裁剪过的,只有六十多个,但相比于51单片机也已经是十分强大了
NVIC嵌套向量中断控制器
NVIC嵌套向量中断控制器,控制着整个芯片中断相关的功能,相当于中断系统的大脑,是内核里面的一个外设,但由于ST官方在设计芯片的时候对Cortex-M3的中断系统进行了裁剪,把不需要用到的部分给去掉。
NVIC的寄存器
寄存器的结构体定义位于core_cm3.h中
typedef struct
{
__IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644];
__O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */
} NVIC_Type;
其中
ISER是中断使能寄存器,ICER是中断清除寄存器,IP是八位8bit中断优先级寄存器,我们在配置中断的时候一般只会用到这三个寄存器。
中断优先级
前面的寄存器中有出现IP八位中断优先级寄存器,但在STM32中实际只用了4个bit用于优先级的设置
用于表达的优先级还分为
- 抢占优先级(pre-emotion priority)
-
子优先级(subpriority)
在比较优先级的时候会先比较抢占优先级,之后再比较子优先级,抢占优先级相同时比较子优先级,子优先级和抢占优先级都相同时比较中断编号
优先级分组
由于优先级中有抢占优先级和子优先级之分,因此需要对这四个位进行分组,分出对应的bit用于两种优先级的表达
控制优先级分组的是内核外设SCB中的AIRCR寄存器,有五种分配选择
中断的初始化编程
中断初始化函数为:void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
NVIC_InitTypeDef初始化结构体:
typedef struct {
uint8_t NVIC_IRQChannel; // 中断源
uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
uint8_t NVIC_IRQChannelSubPriority; // 子优先级
FunctionalState NVIC_IRQChannelCmd; // 中断使能或者失能
} NVIC_InitTypeDef;
这里边就已经说明了中断编程的一些要点,由于STM32几乎每一个外设都能产生中断,因此使用哪一个外设的中断的时候
-
需要把对应外设的负责中断的寄存器给使能
-
配置中断源NVIC_IRQChannel
中断源可以在stm32f10x.h头文件中找到 -
配置抢占优先级与子优先级
NVIC_IRQChannelPreemptionPriority:抢占优先级
NVIC_IRQChannelSubPriority:子优先级
在这之前还需要设置优先级分组
用void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
函数配置,具体使用方法可以去msic.h和msic.c查询 -
使能中断或失能中断
NVIC_IRQChannelCmd:中断使能( ENABLE)或者失能( DISABLE) -
编写中断服务函数
需要注意的是,STM32的中断服务函数名字不能随意取,51中用编号区分,STM32中就没有,需要严格按照头文件中所声明的名称编写,如果函数名称与头文件定义的不一样,在执行中断的时候会跳转到启动文件中的空函数,从而进入死循环