STM32-外部中断

外部中断概述

STM32的每个IO都可以作为外部中断输入

STM32F1的中断控制器支持19个外部中断/事件请求:

线0 ~ 15:对应外部IO口的输入中断。

线16:连接到PVD输出。

线17:连接到RTC闹钟事件。

线18:连接到USB唤醒事件。

每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发(上升沿和下降沿都可)),触发/屏蔽,专用的状态位。

从上面可以看出,STM32供IO使用的中断线只有16个,但是STM32F10x系列的IO口多达上百个,STM32F103ZET6(112),STM32F 103RCT6(51),那么中断线怎么跟IO口对应呢?

GPIO 的管脚 GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 0~15。这样每个中断线对应了最多 7 个 IO 口,以线 0 为例:它对应了 GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、 GPIOE.0、GPIOF.0、GPIOG.0。而中断线每次只能连接到 1 个 IO 口上,这样就需要通过配置来决定对应的中断线配置到哪个 GPIO 上了。

STM32-外部中断_第1张图片

是不是16个中断线就可以分配16个中断服务函数呢?

不是的,IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数

在STM32中文参考手册9.1.2 中断和异常向量这一章,可以查看到STM32F10XXX产品的中断向量表

其中EXTI的中断向量在表中可以找到,从表中可以看出,外部中断线5 ~ 9分配一个中断向量,共用一个服务函数,外部中断线10~15分配一个中断向量,共用一个中断服务函数。

STM32-外部中断_第2张图片

中断服务函数列表

EXTIO_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler

外部中断常用库函数

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);	//设置IO口与中断线的映射关系
exp:GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);		//初始化中断线:触发方式等
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);			//判断中断线中断状态,是否发生
void EXTL_ClearITPendingBit(uint32_t EXTI_Line);		//清除中断线上的中断标志位

EXTI_Init函数解析

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);		//类似于GPIO_Init函数的用法,参数是一个结构体类型指针

结构体类型

typedef struct
{
    uint32_t EXTI_Line;					//指定要配置的中断线
    EXTIMode_TypeDef EXTl_Mode;			//模式:事件OR中断
    EXTITrigger_TypeDefEXTI_Trigger;	//触发方式:上升沿/下降沿/双边沿触发
    FunctionalState EXTI_LineCmd;		//使能OR/失能OR
}EXTI_InitTypeDef;

初始化示例

EXTI_InitStructure.EXTI_Line = EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

外部中断的一般配置步骤

1.初始化IO口为输入。

​ GPIO_Init();

2.开启IO口复用时钟。

​ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

3.设置IO口与中断线的映射关系。

​ void GPIO_EXTILineConfig(); ——stm32f10x_gpio.h

4.初始化线上中断,设置触发条件等。

​ EXTl_Init(); ——stm32f10x_exti.h

5.配置中断分组(NVIC),并使能中断。

​ NVIC_Init();

6.编写中断服务函数。

​ EXTIx_IRQHandler();

7.清除中断标志位

​ EXTI_ClearlTPendingBit(); ——在中断服务函数中软件清除标志位

代码示例

外部中断初始化

/**
* @name 	EXTIx_Init
* @brief	外部中断初始化,使用按键所接的引脚PA8
* @param	None
* @retval	None
*/
void EXTIx_Init(void)
{
  EXTI_InitTypeDef EXTI_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  //按键初始化
  KEY_Init();

  //开启IO口复用时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

  //PA8中断线初始化
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource8);

  //外部中断初始化配置
  EXTI_InitStructure.EXTI_Line = EXTI_Line8;                //KEY对应中断线
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       //中断模式
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;   //下降沿触发

  EXTI_Init(&EXTI_InitStructure);

  //NVIC中断向量设置
  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;    //使能按键KEY的外部中断通道
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;       //使能外部中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;   //2级抢占优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;          //2级子优先级

  NVIC_Init(&NVIC_InitStructure);
}

外部中断服务函数

一定要记得最后清除中断标志位,不然外部中断触发后回不到main函数中继续执行

/**
* @name 	EXTI9_5_IRQHandle
* @brief	外部中断服务函数
* @param	None
* @retval	None
*/
void EXTI9_5_IRQHandler(void)
{
  delay_ms(10);   //消抖
  if(KEY == 0)    //如果按键被按下
  {
    GPIO_ResetBits(GPIOA,GPIO_Pin_1);   //点亮LED灯
  }
  EXTI_ClearITPendingBit(EXTI_Line8);   //清除LINE8上的中断标志位
}

主函数

在主函数中通过串口不断发送 “外部中断实验…\r\n” 提示信息,当按键被按下,外部中断触发后,KEY_FLAG被置位,翻转LED灯状态,清零标志位,并在串口发送外部中断触发信息

#include "LED.h"
#include "delay.h"
#include "KEY.h"
#include "EXTI.h"
#include "USART1.h"

u8 KEY_FLAG = 0;		//按键标志位

int main()
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//NVIC初始化分组
	LED_Init();		//LED初始化
	delay_init();	//延时初始化
	KEY_Init();		//按键初始化
	EXTIx_Init();	//外部中断初始化
	USART1_Init(9600);	//串口初始化
	while(1)
	{
		//检测到按键被按下
		if(KEY_FLAG == 1)
		{
			GPIOA->ODR ^= 0x01 << 1;	//翻转LED灯
			KEY_FLAG = 0;
			printf("按键按下,外部中断触发\r\n");
		}
		printf("外部中断实验...\r\n");
		delay_ms(1000);
	}
}

你可能感兴趣的:(STM32,stm32,单片机,arm,嵌入式硬件,学习)