STM32单片机的中断机制
- STM32单片机开发
- 6天前
- 54热度
- 0评论
在前面进行按键控制LED灯的实验中,程序采用轮询方式判断按键是否被按下,程序运行效率非常低下,若需要高效率运行单片机程序,就要摆脱轮询方式,使用中断来提高程序的运行效率。本文主要讲述STM32的外部中断机制,掌握外部中断寄存器的配置方式。
中断向量
STM32的所有GPIO都可以用做外部中断源的输入端,STM32通过一个中断向量表来管理中断事件,中断向量表有256条记录,这说明STM32可以支持256个中断,下表是中断向量表的一部分,完整的中断向量表见《技术参考手册》表55。
中断向量表虽然可以从《技术参考手册》找到,但我们最好从启动文件startup_stm32f10x_hd.s查找,因为不同型号的STM32芯片,中断向量表稍微有点区别,在启动文件中,已经有相应芯片可用的全部中断向量,而且在编写中断服务函数时,需要从启动文件中定义的中断向量表查找中断服务函数名。
上图是startup_stm32f10x_hd.s启动文件内定义中断向量表的部分代码,开发者可以通过DCD指令后面的标号名称与《技术参考手册》的中断向量表项对应起来。ARM汇编指令DCD,分配存储单元并初始化,存储单元的访问可通过DCD命令后面的程序标号进行。
NVIC中断控制器
中断向量表描述了中断配置方式和中断入口函数,但开发者并不能通过中断向量表来配置中断。STM32提供了NVIC向量中断控制器来配置中断,配置中断要使用到NVIC寄存器组和EXTI寄存器。NVIC中断控制器是属于Cortex内核的器件,因此关于NVIC寄存器组的编程请参考《STM32F10xxx Cortex-M3编程手册》。
NVIC中断使能寄存器NVIC_ISERx
NVIC_ISERx(x=0.....7)中断使能寄存器共有8个,ISER0设置0~31号中断的使能,ISER1设置32~63号中断的使能,如此类推。要使能ISER0的1号中断,就需要向ISER0寄存器的第2位写入1,这里的中断号与中断向量表“位置列”从序号0开始对应,例如中断号6对应中断向量表的EXTI0中断,STM32只有60个中断,因此NVIC_ISERx我们只用前两个 ISER0 和 ISER1。
我们现在关心的是GPIOx分别对应哪几个中断号?因为我们的目标是让按键连接到GPIOx端口,按键按下时,通过GPIOx端口触发外部中断。
STM32的所有GPIOx都引入到EXTI外部中断线上,所有的GPIO端口都能作为外部中断的输入源,GPIO与EXTI的连接方式见下图。
观察GPIO与EXT1的连接图可知,PA0~PG0连接到EXTI0,PA1~PG1连接到EXTI1,……,PA15~PG15连接到EXTI15。
看到这里有的同学可能会产生疑问,为什么在中断向量表中看不到EXTI5~EXTI15中断项呢?中断开发我们还是要参考startup_stm32f10x_hd.s文件内的中断向量表,在startup_stm32f10x_hd.s文件内定义了EXTI5~EXTI15中断项。
从启动文件内的中断向量表可以看出,EXTI5~EXTI9共用一个中断处理函数,EXTI10~EXTI15共用一个中断处理函数。
NVIC_IPRx(中断优先级控制寄存器组)
该寄存器组配置中断的优先级,STM32将中断优先级分为主优先级和次优先级,两个中断先比较主优先级,再比较次优先级。假设有两个中断A、B同时到达:若A的主优先级高于B的主优先级,则先响应A的中断;若A、B的主优先级相同,再比较它们的次优先级,执行次优先级高的中断;若次优先级也相同,就根据向量表中断的位置,谁的中断号小就先执行谁。
主优先级可以嵌套,但次优先级不能嵌套,假设有A、B两个中断,B先发生中断,在B中断执行过程中,A又发生中断,在此种情况下:若A的主优先级高于B的主优先级,B会被挂起,先执行A的中断请求,A中断执行完成后,再继续执行B中断。
NVIC_IPRx寄存器组用来配置中断的优先级,寄存器结构如下图所示:
从图中可以看出,IPRx是一个32位的寄存器,每个IPRx寄存器拆分成四个8位的寄存器IP,用来配置中断的优先级,每个IP寄存器配置一个中断,中断向量表的中断号与IPx一一对应,例如:IP0对应中断号0,IP8对应中断号8。IP寄存器长度是8位,8位可以表示256种优先级,但实际上STM只用了IP寄存器的高4位,因此可以配置16种优先级,配置的数值越小,其优先级越高。
SCB_AIRCR寄存器(应用程序中断及复位控制寄存器)
SCB_AIRCR是一个32位的寄存器,用于配置中断优先级分组、系统复位等控制。寄存器结构如下图所示。
寄存器8~10位用来配置中断优先级分组,配置该寄存器时需要在寄存器的16~31位写入密钥,密钥的值为0x5FA。
优先级分组主要是解决抢占优先级和响应优先级的调度问题。抢占优先级是指当前处理的中断被立即挂起并执行较高优先级的中断;响应优先级是指一个中断在在挂起后能够在最短时间内得到响应并恢复执行的优先级,响应优先级就是次优先级。
优先级分组决定了IPx寄存器高4位配置优先级的方式,配置方式见下表。
表中的0b是二进制数字的前缀,STM设置了五个分组,分组值分别为011、100、101、110、111,分组值设置到SCB_AIRCR寄存器的8~10,可以确定中断优先级采用哪个分组,确定优先级分组后,再配置IPx寄存器的高4为。
例如:假设中断优先级分组使用0b101组,将SCB_AIRCR寄存器的8~10位设置为101,IPx寄存器6~7位配置抢占优先级,4~5位配置响应优先级,配置的数值越低,优先级越高。
EXTI寄存器组
EXTI寄存器组用于配置外部中断的工作模式,EXTI 即 Extern Interrupt,外部中断,它是一个可以触发中断的片上外设。外部中断控制器结构如下图所示。
从图中可以看出,外设接口通过控制中断屏蔽寄存器、请求挂起寄存器、软件中断事件寄存器、上升沿触发选择寄存器、下降沿触发选择寄存器进行中断处理。
EXTI_IMR(中断屏蔽寄存器)
EXTI_IMR是一个32位的寄存器,用来开放和屏蔽来自线x的中断请求。寄存器结构如下图所示。
EXTI_IMR寄存器使用了0~19位,分别为MR0~MR19,MRx(x=0~19)置1,开放x线的中断请求,MRx置0,屏蔽该线的中断请求。这里的线指外部中断请求线。
为什么会有20条外部中断线呢?
GPIOx有16个端口,GPIOx相同的端口号共用一条外部中断线,一共需要16条中断线,另外还有4条特殊的外部中断线(PVD、RTC、USB、ETC),用于芯片的唤醒功能。
EXTI_RTSR(上升沿触发选择寄存器)
EXTI_RTSR是一个32位的寄存器,0~19位有效,对应20条外部中断线,用于配置相应中断线采用上升沿触发。寄存器结构如下图所示。
EXTI_FTSR(下降沿触发选择寄存器)
EXTI_FTSR用于配置相应中断线采用下降沿触发,寄存器结构如下图所示。
EXTI_SWIER(软件中断事件寄存器)
EXTI_SWIER用于配置是否启用软件中断,0~19位有效,SWIERx(x=0~19)位置1,可以在对应的中断线上允许软件中断。寄存器结构如下图。
EXTI_PR(挂起寄存器)
EXTI_PR是一个32位的寄存器,0~19位有效,PRx(x=0~19)位为0表示对应线路没有触发请求,1表示有触发请求。中断请求发生后,对应线的处理程序将改位写入“1”,以清除该位的中断状态。
AFIO_EXTRCRx(外部中断配置寄存器)
AFIO_EXTRCRx(x=1~4)为四个寄存器,用于配置GPIOx的中断引脚。我们知道GPIOx的同一端口(引脚)共用一条中断线,配置中断时我们需要确定具体使用GPIOx的哪个引脚。例如:AFIO_EXTRCR1寄存器的0~15位值为0000时,PA[x]引脚有效;值为0001时PB[x]引脚有效。寄存器结构如下图所示。
AFIO_EXTICR1管理0—3号中断线;
AFIO_EXTICR2管理4—7号中断线;
AFIO_EXTICR3管理8—11号中断线;
AFIO_EXTICR4管理12—15号中断线。
外部中断的具体配置步骤
假设我们使用GPIOC的第8个引脚作为中断源,具体中断配置工作如下所述。
1、查找中断向量表,确定中断源所在的中断号和中断处理函数名称,建议使用启动文件内的中断向量表。经查表可知GPIOC第8个引脚的中断号为23,中断处理函数名称为EXTI9_5_IRQHandler;
2、配置中断使能寄存器NVIC_ISER0,向NVIC_ISER0寄存器的第23位写入1,启用23号中断;
3、配置中断优先级分组,操作的寄存器为SCB_AIRCR;
4、配置中断优先级,操作的寄存器为NVIC_IPRx;
5、开放中断线8,操作的寄存器为EXTI_IMR;
6、配置中断线8采用下降沿触发,操作的寄存器为EXTI_FTSR;
7、配置PC[8]引脚有效,操作的寄存器为AFIO_EXTICR3;
8、使能GPIOC,操作的寄存器为RCC_APB2ENR;
9、配置GPIOC的第8个引脚为上拉输入模式;
10、编写中断处理函数EXTI9_5_IRQHandler。