STM32学习:EXIT外部中断配置与应用实战指南
💭简要说明:本文记录stm32学习总结,专栏持续更新中,如有错误欢迎各位大佬指正。
目录
一、EXIT 简介
二、EXTI控制器框图分析
首先是产生中断部分:
之后是产生事件部分:
关于外部中断/事件线路映像(输入源设置):
三、NVIC与中断
四、EXTI外部中断配置
一、EXIT 简介
①.外部中断的本质是某中断线得到信号触发,进入对应的中断服务函数的过程
②EXTI外部中断可检测外部信号变化,当中断线上GPIO口电平信号变化时,EXTI将立即向NVIC(中断管理系统)发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。
③EXTI外部中断是stm32 68个可屏蔽中断(包含EXTI、SPI、USART等)中的一种。根据参考手册一般来说stm32的EXTI有20 个中断/事件线,共用一套寄存器,这就相当于stm32有20个EXTI结构。
④EXTI支持所有的GPIO,但是相同的Pin(如PA0,PB0…)不能同时触发中断,不同Pin口可以同时配置外部中断,这与AFIO有关。
⑤触发响应方式有中断/事件响应,支持的触发方式有上升沿/下降沿/双边沿/软件触发。
二、EXTI控制器框图分析
掌握了EXTI功能框图,就掌握了EXTI的核心内容。
框图中的20即代表着20条信号线。此框图可分为产生中断和产生事件两部分。
首先是产生中断部分:
①输入线信号来到边沿检测电路 ,通过设置上升沿触发选择器和下降沿触发选择寄存器,可以选择上升沿/下降沿/双边沿触发,寄存器对应数据位x置1为允许输入线x上的上/下升沿触发。当检测到所需信号变化时输出高电平1到下面或门的一端否则输出0。
②之后是来到一个或门,一个输入来自上部分边沿检测电路一部分来自软件中断/事件寄存器,只要有高电平或门就输出高电平1,作为后面电路的输入。因此特别时候可以利用软件模拟产生一个中断。
③当在外部中断线上发生了选择的边沿事件,或门输入高电平,该位被置’1’。在该位中写入’1’可以清除它,也可以通过改变边沿检测的极性清除。中断后软件将对应位置1只会清除相应位的挂起状态,硬件电路会执行清除操作,将该位重置为0,表示该中断请求已经处理完毕。
④请求挂起寄存器和中断屏蔽寄存器输入信号经过一个与门输出信号。若中断屏蔽寄存器对应位置0则对应通道中断被屏蔽。若没被屏蔽,则来自请求挂起寄存器的信号通过与门且与门输出内容保存到请求挂起寄存器内——即请求挂起寄存器信号通过与门,若与门输出为 1 就会把 EXTI_PR 对应位置 1。
⑤之后请求挂起寄存器信号来到NVIC中断处理。
此处对中断屏蔽寄存器的控制相当于控制中断使能,而请求挂起寄存器相当于中断标志,表示有中断,“正在执行中断函数”。中断标志在中断服务函数中进行清除,若不清除,将会一直进入中断,从而导致许多问题。
之后是产生事件部分:
事件部分在框图下面,有一部分与产生中断部分进行共用。
事件屏蔽寄存器与中断屏蔽寄存器类似,可以简单的控制 EXTI_EMR 来实现是否产生事件的目的。当事件屏蔽寄存器置1,同时触发事件,通过与门来到脉冲发生器,有效信号1时产生一个脉冲,否则不会产生。
最终产生的脉冲信号 可以给其他外设电路使 用,比如定时器 TIM、模拟数字转换器 ADC 等等,这样的脉冲信号一般用来触发 TIM 或者 ADC 开始转换。
产生中断线路的目的:输入信号输入到 NVIC,进一步会运行中断服务函数实现功能。
产生事件线路的目的:是传输一个电路级别的脉冲信号给其他外设使用。
中断线路是软件级的,事件线路是硬件级的。
关于外部中断/事件线路映像(输入源设置):
EXTI0 至 EXTI15 用于 GPIO,另外几位用于其他外设。GPIO的不同Pin口通过AFIO的寄存器配置,最终确定其中的一个PIN口为输出源。所以我们之后还需使能AFIO的时钟。
三、NVIC与中断
中断信号进入NVIC中断处理系统进行处理,NVIC 是嵌套向量中断控制器,属于STM32内核,但一般厂家设计时会对NVIC进行裁剪只用Cortex-M3 NVIC的一部分。
NVIC根据每个中断的优先级分配中断的先后顺序,告诉CPU先执行哪个中断。NVIC有专门的寄存器中断优先级寄存器 NVIC_IPRx,用其中的四位划分优先级。
优先级分为抢占优先级和响应优先级(子优先级),数值越小,优先级越高。调用函数可设置优先级分组方式。优先级分为n位的抢占优先级和4-n位的响应优先级,选定分组方式后取值不能超过对应范围。
如果有多个中断,抢占优先级高的比低的先执行,如果抢占优先级相同则比较响应优先级,若是都相同的话则比较中断号,中断号越小,优先级越高。
同时抢占优先级高的可以中断嵌套,打断其他正在执行的中断。
中断处理时NVIC对照向量表进入中断服务函数。在启动文件 startup_stm32f103xe.s 中每个中断都写了一个中断服务函数。中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量 表中找不到中断服务函数的入口,直接跳转到启动文件里面预先写好的空函数,并且在里面无限循环,实现不了中断。
向量表部分内容
注意:10-15的中断线共用EXTI15_10。
四、EXTI外部中断配置
①EXTI响应的是外部信号的边沿或电平触发,而这种响应不依赖于时钟,只依赖于信号本身的变化。故只需要配置GPIO时钟。同时AFIO寄存器用于配置输入源,故需要配置AFIO时钟。
②选择中断源,配置EXTI初始化,使能中断。
③配置中断优先级,初始化NVIC
④编写中断函数,结束中断时清除中断标志位
///以下面代码为例
#include "stm32f10x.h"
uint16_t cnt;
void EXTI_Init(void) ///外部中断配置
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); ///开启GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); ///开启AFIO时钟
GPIO_InitTypeDef GPIO_InitStructure; ///GPIO结构体配置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14;
GPIO_Init(GPIOB,&GPIO_InitStructure); ///调用GPIO初始化函数
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14); ///选择中断源 选择 GPIO 管脚
///用作外部中断线路
EXTI_InitTypeDef EXTI_InitStruct; ///EXTI结构体配置
EXTI_InitStruct.EXTI_Line=EXTI_Line14; ///选择中断线 ///若有多个中断线可用|操作
/// 如(Line1|Line14)
EXTI_InitStruct.EXTI_LineCmd=ENABLE; ///中断线使能
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt; ///选择模式(中断/事件)
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; 选择触发方式
EXTI_Init(&EXTI_InitStruct); ///调用初始化函数
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); ///选择优先级分组方式
NVIC_InitTypeDef NVIC_InitStruct; ///NVIC结构体配置
NVIC_InitStruct.NVIC_IRQChannel=EXTI15_10_IRQn; ///选择通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; 配置优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStruct);
}
uint16_t Countsensor_getcnt(void)
{
return cnt;
}
void EXTI15_10_IRQHandler(void) ///编写中断服务函数
{
if(EXTI_GetFlagStatus(EXTI_Line14)==SET) //判断中断标志位
{
cnt++;
EXTI_ClearITPendingBit(EXTI_Line14); ///清除中断标志位————重要
}
}
以下为相关固件库函数的介绍:
函数名 描述
NVIC_PriorityGroupConfig 设置优先级分组:先占优先级和从优先级
NVIC_Init 根据 NVIC_InitStruct 中指定的参数初始化外设 NVIC 寄存器
在启动文件中可查看中断函数名
作者:xx1mika