STM32 外部中断

摘要

本文介绍STM32配置的步骤以及相关的步骤,通过触发按键外部中断实现摁键点灯操作,即摁下摁键,触发中断,LED灯亮,松开LED灯灭。

STM32外部中断简介

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

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

线 16:连接到 PVD 输出。

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

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

所以STM32可以作为GPIO外部中断的线路共有16个,其具体的映射关系如下:

STM32F1外部中断配置的一般步骤如下:

1)将对应的GPIO口初始化维输入模式

2)开启AFIO时钟,开启端口的复用

3)根据GPIO和中断的映射关系配置IO口与中断的映射关系

4)初始化GPIO外部中断线,并设置触发条件等内容

5)配置中断,包括使能中断和为中断分组等

6)根据项目需求配置中断服务程序

预实现的功能

摁下UP_LED对应的按键,点亮UP引脚连接的LED灯,松开UP_LED按键,熄灭LED引脚连接的LED灯。

程序代码

端口宏定义:、

/*配置GPIO输入模式*/

#define UP_LED_PORT                        GPIOB

#define UP_LED_PIN                        GPIO_Pin_3

#define UP_LED_RCC                        RCC_APB2Periph_GPIOB

#define UP_LED_Mode                        GPIO_Mode_IPU                //上拉输入

#define UP_LED_Speed                GPIO_Speed_50MHz

   

/*配置GPIO外部中断相关的信息 按键接在PB3,对应的3号中断线和USART3_IRQ中断*/

#define UP_LED_EXTI_PORT        GPIO_PortSourceGPIOB

#define UP_LED_EXTI_Source        GPIO_PinSource3

#define UP_LED_EXTI_LINE        EXTI_Line3

#define UP_LED_EXTI_MODE        EXTI_Mode_Interrupt

#define UP_LED_EXTI_TRIGGER        EXTI_Trigger_Rising_Falling        //上升下降沿触发

   

#define UP_LED_NVIC_IRQChannel        EXTI3_IRQn

   

/*配置UP对应的LED状态,推挽输出*/

#define UP_PORT                                GPIOD

#define UP_PIN                                GPIO_Pin_2

#define UP_RCC                                RCC_APB2Periph_GPIOD

#define UP_Mode                                GPIO_Mode_Out_PP        //push pull

#define UP_Speed                        GPIO_Speed_50MHz

/*宏定义LED灯电平状态*/

#define UP(x)        x?GPIO_SetBits(UP_PORT,UP_PIN):GPIO_ResetBits(UP_PORT,UP_PIN)

#define UP_Elevator_LED_ON        UP(0)                //电梯按钮亮

#define UP_Elevator_LED_OFF        UP(1)                //电梯按钮灭

/*宏定义UP_LED 读取电平状态*/

#define READ_UP_LED        GPIO_ReadInputDataBit(UP_LED_PORT,UP_LED_PIN)

   

LED对应的引脚功能初始化: 推挽输出模式

void Elevator_LED_Configuration(void)

{

   

GPIO_InitTypeDef Elevator_GPIO_InitStruct;

   

RCC_APB2PeriphClockCmd(UP_RCC,ENABLE);        //ENABLE the CLOCK

/*初始化UP的引脚功能,推挽输出模式*/

Elevator_GPIO_InitStruct.GPIO_Pin = UP_PIN;

Elevator_GPIO_InitStruct.GPIO_Mode = UP_Mode;

Elevator_GPIO_InitStruct.GPIO_Speed = UP_Speed;

GPIO_Init(UP_PORT,&Elevator_GPIO_InitStruct);

/*设置默认输出状态*/

UP_Elevator_LED_OFF;

}

   

按钮对应的引脚功能初始化,上拉输入

void Elevator_Key_Configuration(void)

{

GPIO_InitTypeDef Elevator_GPIO_InitStruct;

   

RCC_APB2PeriphClockCmd(UP_LED_RCC,ENABLE);        //ENABLE the CLOCK

/*初始化UP_LED的引脚功能,输入模式*/

Elevator_GPIO_InitStruct.GPIO_Pin = UP_LED_PIN;

Elevator_GPIO_InitStruct.GPIO_Mode = UP_LED_Mode;

Elevator_GPIO_InitStruct.GPIO_Speed = UP_LED_Speed;

GPIO_Init(UP_LED_PORT,&Elevator_GPIO_InitStruct);

}

按键对应的引脚外部中断初始化配置。

void Elevator_Key_EXTI_Configuration(void)

{

EXTI_InitTypeDef Elevator_Key_EXTI_InitStructure;

NVIC_InitTypeDef Elevator_Key_NVIC_InitStructure;

   

Elevator_Key_Configuration();        //初始化电梯按钮为输入模式

   

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);        //开始AFIO时钟

   

   

/*配置UP_LED对应的电梯按钮中断线*/

GPIO_EXTILineConfig(UP_LED_EXTI_PORT,UP_LED_EXTI_Source);

   

Elevator_Key_EXTI_InitStructure.EXTI_Line = UP_LED_EXTI_LINE;

Elevator_Key_EXTI_InitStructure.EXTI_Mode = UP_LED_EXTI_MODE;

Elevator_Key_EXTI_InitStructure.EXTI_Trigger = UP_LED_EXTI_TRIGGER;        //配置触发方式,下降沿触发

Elevator_Key_EXTI_InitStructure.EXTI_LineCmd = ENABLE;

   

EXTI_Init(&Elevator_Key_EXTI_InitStructure);

   

Elevator_Key_NVIC_InitStructure.NVIC_IRQChannel = UP_LED_NVIC_IRQChannel;        //使能外部中断通道

Elevator_Key_NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;

Elevator_Key_NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;

Elevator_Key_NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

   

NVIC_Init(&Elevator_Key_NVIC_InitStructure);

   

}

中断服务程序,本次项目中需要同时检测摁下和松手,所以配置成上升下降沿触发,所以无论是摁下还是松开均会触发中断服务函数,通过以下中断服务程序的处理便实现当按键摁下时,对应的LED灯亮,松开即关闭的效果。

void EXTI3_IRQHandler(void)

{

if(READ_UP_LED==RESET)                //检测到下降沿,即摁键摁下

{

UP_Elevator_LED_ON;                //点亮内部LED

UP_KeyMode = 1;                        //摁下标志位置1

}

else                                                //检测到上升沿,即摁键弹起

{

UP_Elevator_LED_OFF;        //熄灭内部LED

UP_KeyMode = 0;                        //复位摁下标志位

}

EXTI_ClearITPendingBit(UP_LED_EXTI_LINE);//清除中断线路

}

 

虽然本文所提的控制目标也可以使用扫描的方式实现,但是在实际项目中,为了提高系统响应的灵敏度,通常建议使用触发中断的方式检测按键。

posted @ 2020-07-02 21:51  LivingTowardTheSun  阅读(1271)  评论(0编辑  收藏  举报