STM32学习笔记5 --------- 外部中断

如何将STM32的IO口作为外部中断输入?

外部中断/事件控制器(EXTI)由19个产生事件/中断要求的边沿检测器组成。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以被独立的屏蔽。

EXTI控制器的主要特性:

  • 每个中断/事件都有独立的触发和屏蔽
  • 每个中断线都有专用的状态位
  • 支持多达19个中断/事件请求
  • 检测脉冲宽度低于APB2时钟宽度的外部信号。

STM32 IO口中断的基础概念:

中断代码主要分布在固件库的stm32f10x_exti.h和stm32f10x_exti.c文件中。

每个IO都可以作为外部中断的中断输入口,STM32F103的中断控制器支持19个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。

STM32F103的19个外部中断:
  • 线0~15:对应外部IO口的输入中断
  • 线16:连接到PVD输出
  • 线17:连接到RTC闹钟事件
  • 线18:连接到USB唤醒事件

GPIO的管脚GPIOx.0~GPIOx.15(A,B,C,D,E,F,G)分别对应中断线0~15。每个中断线对应最多7个IO口,中断线每次只能连接到1个IO口上,这样就需要通过配置来决定对应的中断线配置到哪个GPIO上了。

库函数GPIO配置中断

GPIO_EXTILineConfig() ---------配置GPIO与中断线的映射关系
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)

EXTI_Init() ----------- 中断线上中断的初始化

void  EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);

// eg: 设置中断线4上的中断为下降沿触发
EXTI_InitTypeDef   EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line4;                  //中断线的标号,EXTI_Line0~EXTI_Line15
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;         //中断模式,(中断EXTI_Mode_Interrupt和事件EXTI_Mode_Event)
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;     //触发方式(上升/下降/任意电平触发)
EXTI_InitStructure.EXTI_LineCmd=ENABLE;                   //使能中断线
EXTI_Init(&EXTI_InitStructure);

涉及到中断就还要设置NVIC中断优先级。

eg: 设置中断线2的中断优先级
NVIC_InitTypeDef   NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;          //使能按键外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;   //抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;     //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;       //使能外部中断通道

NVIC_Init(&NVIC_InitStructure);

配置完中断优先级后,编写中断服务函数。中断服务函数的名字是在MDK中事先有定义的。STM32的IO口外部中断函数只有6个:

EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI4_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler

中断线0-4没给中断线对应一个中断函数,中断线5~9共用中断函数EXPORT EXTI9_5_IRQHandler,中断线10~15共用中断函数EXPORT EXTI15_10_IRQHandler。

编写中断服务函数的时候经常使用到两个函数:
判断某个中断线上的中断是否发生(标志位是否置位):
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
清除某个中断线上的中断标志位:
void EXTI_ClearITPendingBit(uint32_t EXTI_LINE);

常用的中断服务函数格式:

void EXTI2_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line3) != RESET)
	{
		中断逻辑.....
		EXTI_ClearITPendingBit(EXTI_Line3);      
	}
}

ps:固件库还提供了两个函数来判断外部中断状态以及清除外部状态标志位的函数EXTI_GetFlagStatus和EXTI_ClearFlag,作用和前面的两个函数类似。 EXTI_GetFlagStatus函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而EXTI_GetITStatus直接用来判断状态标志位。

IO口外部中断的一般步骤:

  • 初始化IO口为输入;
  • 开启IO口复用时钟,设置IO口与中断线的映射关系;
  • 初始化线上中断,设置触发条件等;
  • 配置中断分组(NVIC),并使能中断;
  • 编写中断服务函数

你可能感兴趣的:(STM32)