一、简介
中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后有返回原来的被暂停的位置继续运行;
中断优先级:当有多个中断源同事申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先相应更加紧急的中断源;
中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回;
STM32具有68个可屏蔽中断,每一个中断具有16个可编程的优先等级;
1.EXTI:外部中断
EXTI可以检测指定的GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC裁决后即可中断CPU主程序,使CPU执行EXT对应的中断程序
支持的触发方式:上升沿/下降沿/双边沿/软件触发
支持的GPIO口:所有的GPIO口,但相同的Pin不能同时触发中断(比如:PB0和PA0就不能同时触发)
通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
触发响应方式:中断响应/事件响应
2.AFIO:复用引脚重映射、中断引脚选择
什么时候需要用外部中断呢?
对于STM32来说:先要获取的信号是外部驱动的很快的突发信号。
3.中断分组:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
中断分组决定了中断优先级的结构(中断优先级有抢占优先级和响应优先级构成),中断分组决定了这两部分优先级占用的位数;
NVIC_PriorityGroup_0
:所有的位都分配给抢占优先级,没有响应优先级。即,只有抢占优先级,没有响应优先级。NVIC_PriorityGroup_1
:抢占优先级和响应优先级各占 4 位。NVIC_PriorityGroup_2
:抢占优先级占 3 位,响应优先级占 5 位。NVIC_PriorityGroup_3
:抢占优先级占 2 位,响应优先级占 6 位。NVIC_PriorityGroup_4
:抢占优先级占 1 位,响应优先级占 7 位。NVIC_PriorityGroup_5
-NVIC_PriorityGroup_7
:将中断优先级的分配根据不同需要进一步调整
4.抢占优先级
抢占优先级决定了一个中断是否可以打断另一个正在执行的中断;
抢占优先级越低,表示优先级越高;
5.响应优先级
响应优先级是指在抢占优先级相同的情况下,哪个中断先执行。
响应优先级数值越低,优先级越高;
6.总结
- 中断分组:决定了优先级配置的结构,分配了多少位用于抢占优先级和响应优先级。
- 抢占优先级:决定了中断能否打断正在执行的其他中断或主程序。数值越小,优先级越高。
- 响应优先级:在抢占优先级相同的情况下,决定了哪个中断先执行。数值越小,优先级越高。
二、工程源码
配置中断流程:
1.打开相应时钟;
2.GPIO初始化;
3.AFIO映射(外部中断需要打开AFIO映射并配置EXTI);
4.中断配置:
中断分组:
中断源;
抢占优先级和响应优先级;
5.中断服务函数:
获取中断状态;
清除中断标志位;
EXTI.c
#include "stm32f10x.h" // Device header
#include "exti.h"void Key_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;EXTI_InitTypeDef EXTI_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //打开引脚时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //打开外设时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 下拉输入GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5); //外部中断引脚选择配置EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //外部中断线将被配置为触发中断。另一种可能的配置是 EXTI_Mode_Event,用于事件触发 EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //触发方式EXTI_InitStruct.EXTI_Line = EXTI_Line5; //需要配置的中断线EXTI_InitStruct.EXTI_LineCmd = ENABLE; //启用该中断线EXTI_Init(&EXTI_InitStruct);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;//中断通道 中断通道在stm32f10x.h里面NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 3; //抢占优先级NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3; //子优先级NVIC_Init(&NVIC_InitStruct);
}//中断函数在启动文件startup——stm32f10x_hds.s里面
void EXTI9_5_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line5) == SET) // 检查 EXTI Line 5 是否触发了中断{EXTI_ClearITPendingBit(EXTI_Line5); // 清除 EXTI Line 5 的中断挂起位,防止中断一直触发}
}
EXTI.h
#ifndef __EXTI_H
#define __EXTI_H#include "stm32f10x.h" // Device header
#include "sys.h"void Key_Init(void);#endif