本文主要是为了记录自己对中断从不懂到皮毛到能够使用的过程,内容通俗易懂,主要为刚接触stm32的群众提供帮助少走弯路,对中断的配置有个大概的认知,文章图片主要来自网上或其它相关博文。
先理解一些关键词:
1.抢占优先级--PreemptionPriority
2.响应优先级--SubPriority
3.中断分组--NVIC_PriorityGroup_0(第0组)
4.中断通道--IRQChannel
1.有某个指定的事件发生将产生相关的中断(一个信号),从而并跳转到对应的中断处理程序中(一般自己写)。
2.事件可以触发中断,也可能不触发中断,有可能被更优先的中断屏蔽(优先级问题),
3.通俗点讲事件就是一个触发信号(脉冲),而中断则是一个固定的电平信号,从而开启指定的中断处理程序(就像点灯)
4.NVIC-中断向量控制器 (通过修改里面的参数来配置中断)
需要引入misc.c固件库文件,内含NVIC的外设驱动 ,代替原来的stm32f10x.nvic.c(旧版本,现在很少见)。外部中断是:stm32f10x_exti.c(如果插入固件库后程序没错但各种报错未定义(undefine)的可以参考USART配置博文)
首先,先理解抢占优先级和响应优先级:
1--顾名思义,抢占就是当多个中断同时存在(不一定是同时发生)时,抢占优先级别高的先抢得先机(先发生中断),所以它可以打断正在响应的低抢占优先级的中断(因此可以实现中断嵌套)。
2--但是,不能打断同抢占等级的中断,只能乖乖排队。
3--那么,若是抢占等级相同而又同时触发呢?这时候才看响应优先级,哪个优先级高,哪个先响应
4--总结:多个中断发生时,先看抢占优先级高低,抢占等级相同的看触发先后时间,先后顺序一样(同时)的看响应等级。
通俗的讲: 抢占 > 响应 (数值越小,等级越高)
先上图,大家大概思考一下
(感觉这是解释得最直观的一张图)
中断寄存器中有用于指定优先级的4个bits。这4个bits用于分配preemption抢占优先级和sub响应优先级
而分组方式则是规定这个4个bits的使能格式,即分组不同,数值的作用不同,从而实现中断的多样化,充分利用4个bits的空间。
类似于编码器的用法。
选择0组:可以配置0-15等级的响应优先级
选择2组:可以配置0-3等级的抢占优先级 和 0-3等级的响应优先级
.........
所以,分组与优先级无关,定义了优先级的配置格式,中断优先级取决于抢占优先级和响应优先级的参数
深入研究中断寄存器的可参考:【1】STM32 NVIC
(代码详解)
/*选择第0组中断方式配置*/
void TIM2_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure; //定义结构体
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // 选择使用第0组中断向量格式 初始化分组方式
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //中断通道--定时器TIM2通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级--无抢占优先级配置
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级 可配置0-15
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);//初始化参数
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //使能外部中断所在的通道 当时的IO口是PB1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级--无抢占优先级配
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //响应优先级 可配置0-15
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //初始化参数
}
/*选择第2组中断方式配置*/
void TIM2_NVIC_Configuration(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择第1组中断向量格式 初始化分组方式
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //中断通道--定时器TIM2通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级--可配置0-3等级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级 可配置0-3等级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);//初始化参数
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //使能外部中断所在的通道 当时的IO口是PB1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 可配置0-3等级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应优先级 可配置0-3等级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
}
至于中断通道--IRQChannel--则需要自己在固件库搜索,以下是常用的一些中断通道
GPIO引脚 | 中断标志位 | 中断处理函数 |
PA0~PG0 | EXTI0 | EXTI0_IRQHandler |
PA1~PG1 | EXTI1 | EXTI1_IRQHandler |
PA2~PG2 | EXTI2 | EXTI2_IRQHandler |
PA3~PG3 | EXTI3 | EXTI3_IRQHandler |
PA4~PG4 | EXTI4 | EXTI4_IRQHandler |
PA5~PG5 | EXTI5 | EXTI9_5_IRQHandler |
PA6~PG6 | EXTI6 | |
PA7~PG7 | EXTI7 | |
PA8~PG8 | EXTI8 | |
PA9~PG9 | EXTI9 | |
PA10~PG10 | EXTI10 | EXTI15_10_IRQHandler |
PA11~PG11 | EXTI11 | |
PA12~PG12 | EXTI12 | |
PA13~PG13 | EXTI13 | |
PA14~PG14 | EXTI14 | |
PA15~PG15 | EXTI15 |
参考:【2】STM32 GPIO外部中断总结
参考:【3】STM32的NVIC和中断的总结
到此为止应该对stm32中断原理有个初步的了解并能简单地设置一些简单地中断了。
提醒: 添加中断(外部中断)处理的库文件,设置中断后同时要编写 中断的Handler处理函数,类似上一篇博文的USART2的Handler函数,实际也是一个串口中断 。
若有错误,请指正~
内容粗糙,望能助人。
【1】STM32 NVIC
【2】STM32 GPIO外部中断总结
【3】STM32的NVIC和中断的总结