一、中断简介

  在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。

图1 中断示意图

  STM32有68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设。使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级

二、NVIC简介

  NVIC是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设计芯片的时候会对Cortex-M3内核里面的NVIC进行裁剪,把不需要的部分去掉,所以说STM32的NVIC是Cortex-M3的NVIC的一个子集。

图2 NVIC基本结构

图3 NVIC优先级分组

  NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级。
  抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队。

三、EXTI简介

  EXTI(External interrupt/event controller)——外部中断/事件控制器,管理了控制器的 20个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。

图4 EXTI基本结构

3.1 AFIO复用I/O口

图5 EXTI中断/事件线

图6 EXTx输入源选择

  在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择。

3.2 EXTI功能框图

图7 EXTI 功能框图

  EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件.
  图7中红色虚线是一个产生中断的线路,最终信号流入到NVIC控制器内。

  1. 编号1是输入线,EXTI控制器有19个中断/事件输入线,这些输入线可以通过寄存器设置为任意一个 GPIO,也可以是一些外设的事件。
  2. 编号 2是一个边沿检测电路,它会根据上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)对应位的设置来控制信号触发。如果检测到有边沿跳变就输出有效信号 1给编号 3电路,否则输出无效信号0。
  3. 编号 3电路实际就是一个或门电路,它一个输入来自编号 2电路,另外一个输入来自软件中断事件寄存器(EXTI_SWIER)。EXTI_SWIER 允许我们通过程序控制就可以启动中断/事件线,即只要有一个中断请求进入就响应。
  4. 编号 4电路是一个与门电路,它一个输入是编号 3电路,另外一个输入来自中断屏蔽寄存器(EXTI_IMR)。只有当中断屏蔽寄存器输出1时,才会响应。
  5. 编号5是将EXTI_PR寄存器内容输出到NVIC内,从而实现系统中断事件控制。

  图7中绿色虚线是一个产生事件的线路,最终输出一个脉冲信号。

  1. 编号6 电路是一个与门,它一个输入来自编号 3 电路,另外一个输入来自事件屏蔽寄存器(EXTI_EMR)。只有当中断屏蔽寄存器输出1时,才会响应。
  2. 编号 7是一个脉冲发生器电路,当它的输入端,即编号 6电路的输出端,是一个有效信号1时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。
  3. 编号 8是一个脉冲信号,就是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器 TIM、模拟数字转换器 ADC 等等,这样的脉冲信号一般用来触发TIM或者ADC开始转换。

  EXTI是在APB2总线上的。

四、EXTI库函数代码实现

4.1 EXTI初始化结构体

typedef struct { 
    uint32_t EXTI_Line;                 // 中断/事件线 
    EXTIMode_TypeDef EXTI_Mode;         // EXTI模式 
    EXTITrigger_TypeDef EXTI_Trigger;   // 触发类型 
    FunctionalState EXTI_LineCmd;       // EXTI使能 
} EXTI_InitTypeDef;

4.2 配置

  根据EXIT基本结构框图可知,需要配置RCC、GPIO、AFIO、EXTI、NVIC。

4.2.1 配置RCC

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

4.2.2 配置GPIO

GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = ;
GPIO_InitStruct.GPIO_Pin = ;
GPIO_InitStruct.GPIO_Speed = ;
GPIO_Init(GPIOA,&GPIO_InitStruct);

4.2.3 配置AFIO

void GPIO_AFIODeInit(void); //清除AFIO外设配置
//配置AFIO事件输出
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);//引脚重映射
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);//配置AFIO的数据选择器,选择中断引脚
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface); //与以太网相关
GPIO_EXTILineConfig(GPIO_PortSourceGPIOx,GPIO_PinSourcex);

4.2.4 配置EXTI

4.2.4.1 EXTI配置相关函数介绍
void EXTI_DeInit(void); //清除EXTI配置
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);//配置EXTI外设
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);//软件触发中断
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);//获取状态寄存器标志位
void EXTI_ClearFlag(uint32_t EXTI_Line);//清除状态寄存器标志位
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);//获取状态寄存器中断标志位
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);//清除状态寄存器中断标志位
4.2.4.2 初始化
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Linex;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//EXTI_Mode_Interrupt or EXTI_Mode_Event
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//EXTI_Trigger_Rising、EXTI_Trigger_Falling、EXTI_Trigger_Rising_Falling
EXTI_Init(&EXTI_InitStruct);

4.2.4 配置NVIC

4.2.4.1 NVIC相关函数介绍
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);//配置中断分组方式,即抢占优先组和响应优先组
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);//NVIC初始化
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);//设置中断向量表
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);//系统低功耗配置
4.2.4.2 初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd =ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);

4.3 中断函数

void EXTI9_5_IRQHandler(void)  //中断函数名在startup_stm32f10x_md.s文件查看
{
	//中断标志位判断
	if(EXTI_GetFlagStatus(EXTI_Line5) == SET)
	{
		//中断函数功能
		
		//清除标志位
		EXTI_ClearFlag(EXTI_Line5);
	}
};

作者:猪猪长

物联沃分享整理
物联沃-IOTWORD物联网 » STM32 EXTI外部中断

发表回复