本文展示了STM32 外部中断EXTI的 识别操作
内容涉及 :
外部中断EXTI的识别
IO口输入输出
按键的外部中断处理
外部中断捕捉方法
文章目录
前言
这里只讲解核心部分的代码,有些变量的设置,头文件的包含等可能不会涉及到,完整的代码请参考本章配套的工程。 为了使工程更加有条理,我们把 LED 灯控制相关的代码独立分开存储,方便以后移植。 在“工程模板”之上新建“RCC_book.c”及“RCC_book.h”文件以及之前的 “Led_book.c”及“Led_book.h”文件: Git 代码
一、 编程要点
外部中断:1) 初始化用来产生中断的 GPIO ,使能外设某个中断
2) 初始化 EXTI
a:初始化 NVIC_InitTypeDef 结构体,配置中断优先级分组,设置抢占优先级和子优先级,使能中断请求
b:NVIC_IROChannel:用来设置中断源
c:NVIC_IRQChannelPreemptionPriority:抢占优先级
d:NVIC_IRQChannelSubPriority
e:NVIC_IRQChannelCmd:中断使能(ENABLE)或者失能(DISABLE)
3) 配置 NVIC
4) 编写中断服务函数
二、使用步骤
1.理解原理图
、
代码如下:
: STM32F103ZET6 输出口为PB5低电平点有效
: STM32F103ZET6 Key检测脚为PA8
2.建立EXTI 键盘中断的 头文件 Exit_book.h
代码如下(示例):
#ifndef __EXIT_BOOK_H_
#define __EXIT_BOOK_H_
#include "stm32f10x.h"
#define _KEY_EXTI_IN_GPIO_Port GPIOA
#define _KEY_EXTI_IN_GPIO_Pin GPIO_Pin_0
#define _EXTI_IN_GPIO_PortSource GPIO_PortSourceGPIOA
#define _EXTI_IN_GPIO_PinSource GPIO_PinSource0
#define _EXTI_IN_EXTI_Line EXTI_Line0
#define _EXTI_IN_EXTI_Trigger EXTI_Trigger_Rising
#define _EXTI_IN_GPIO_Clock RCC_APB2Periph_AFIO
#define _EXTI_IN_EXTI_Mode EXTI_Mode_Interrupt
#define _EXTI_IN_EXTI_LineCmd ENABLE
#define _NVIC_IN_EXTI_IRQChannel EXTI0_IRQn
#define _NVIC_IN_EXTI_IRQChannelCmd ENABLE
#define _KEY2_EXTI_IN_GPIO_Port GPIOC
#define _KEY2_EXTI_IN_GPIO_Pin GPIO_Pin_13
#define _EXTI_IN2_GPIO_PortSource GPIO_PortSourceGPIOC
#define _EXTI_IN2_GPIO_PinSource GPIO_PinSource13
#define _EXTI_IN2_EXTI_Line EXTI_Line13
#define _EXTI_IN2_EXTI_Trigger EXTI_Trigger_Falling
#define _EXTI_IN2_GPIO_Clock RCC_APB2Periph_AFIO
#define _EXTI_IN2_EXTI_Mode EXTI_Mode_Interrupt
#define _EXTI_IN2_EXTI_LineCmd ENABLE
#define _NVIC_IN2_EXTI_IRQChannel EXTI15_10_IRQn
#define _NVIC_IN2_EXTI_IRQChannelCmd ENABLE
void fn_EXTI_GPIO_Config(void);
void fn_NVIC_Config(void);
void EXTI0_IRQHandler(void);
#endif
3.建立EXTI 键盘中断的 头文件 Exit_book.c
代码如下(示例):
#include "Exit_book.h"
#include "Led_book.h"
/**************************************************************
* @brief
* void fn_EXTI_GPIO_Config(void)
* @param
*
* #define _KEY_EXTI_IN_GPIO_Port GPIOA
* #define _KEY_EXTI_IN_GPIO_Pin GPIO_Pin_0
* #define _EXTI_IN_GPIO_PortSource GPIO_PortSourceGPIOA
* #define _EXTI_IN_GPIO_PinSource GPIO_PinSource0
* #define _EXTI_IN_EXTI_Line EXTI_Line0
* #define _EXTI_IN_EXTI_Trigger EXTI_Trigger_Rising
* #define _EXTI_IN_GPIO_Clock RCC_APB2Periph_AFIO
* #define _EXTI_IN_EXTI_Mode EXTI_Mode_Interrupt
* #define _EXTI_IN_EXTI_LineCmd ENABLE
*
* #define _KEY2_EXTI_IN_GPIO_Port GPIOC
* #define _KEY2_EXTI_IN_GPIO_Pin GPIO_Pin_13
* #define _EXTI_IN2_GPIO_PortSource GPIO_PortSourceGPIOC
* #define _EXTI_IN2_GPIO_PinSource GPIO_PinSource13
* #define _EXTI_IN2_EXTI_Line EXTI_Line13
* #define _EXTI_IN2_EXTI_Trigger EXTI_Trigger_Falling
* #define _EXTI_IN2_GPIO_Clock RCC_APB2Periph_AFIO
* #define _EXTI_IN2_EXTI_Mode EXTI_Mode_Interrupt
* #define _EXTI_IN2_EXTI_LineCmd ENABLE
* @retval
*************************************************************/
void fn_EXTI_GPIO_Config(void){
EXTI_InitTypeDef EXIT_InitStruck;
RCC_APB2PeriphClockCmd(_EXTI_IN_GPIO_Clock , ENABLE);
//注意:我们除了开 GPIO 的端口时钟外,我们还打开了 AFIO 的时钟
GPIO_EXTILineConfig(_EXTI_IN_GPIO_PortSource | _EXTI_IN2_GPIO_PortSource , _EXTI_IN_GPIO_PinSource | _EXTI_IN2_GPIO_PinSource);
/* 选择 EXTI 的信号源 */
// GPIO_EXTILineConfig 函数用来指定中断/事件线的输入源,它实际是设定外部中断配
// 置寄存器的 AFIO_EXTICRx 值,该函数接收两个参数,第一个参数指定 GPIO 端口源,第
// 二个参数为选择对应 GPIO 引脚源编号。
EXIT_InitStruck.EXTI_Line = _EXTI_IN_EXTI_Line ; /* 选择 EXTI 的信号源 */
EXIT_InitStruck.EXTI_Mode = _EXTI_IN_EXTI_Mode; /* EXTI 为中断模式 */
EXIT_InitStruck.EXTI_Trigger = _EXTI_IN_EXTI_Trigger ; /* 上升沿中断 */
EXIT_InitStruck.EXTI_LineCmd = _EXTI_IN_EXTI_LineCmd; /* 使能中断 */
EXTI_Init(&EXIT_InitStruck);
// EXTI初始化配置的变量
// fn_NVIC_Config();
// 调用 NVIC_Configuration函数完成对按键 1、按键 2 优先级配置并使能中断通道
EXIT_InitStruck.EXTI_Line = _EXTI_IN2_EXTI_Line; /* 选择 EXTI 的信号源 */
EXIT_InitStruck.EXTI_Mode = _EXTI_IN2_EXTI_Mode; /* EXTI 为中断模式 */
EXIT_InitStruck.EXTI_Trigger = _EXTI_IN2_EXTI_Trigger; /* 下降沿中断 */
EXIT_InitStruck.EXTI_LineCmd = _EXTI_IN_EXTI_LineCmd;/* 使能中断 */
EXTI_Init(&EXIT_InitStruck);
fn_NVIC_Config();
}
/**************************************************************
* @brief
* void fn_NVIC_Config(void)
* @param
* #define _NVIC_IN_EXTI_IRQChannel EXTI0_IRQn
* #define _NVIC_IN_EXTI_IRQChannelCmd ENABLE
* #define _NVIC_IN2_EXTI_IRQChannel EXTI15_10_IRQn
* #define _NVIC_IN2_EXTI_IRQChannelCmd ENABLE
* @retval
*************************************************************/
void fn_NVIC_Config(void){
NVIC_InitTypeDef NVIC_InitStruct;
/* 配置 NVIC 为优先级组 1 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* 配置中断源: */
NVIC_InitStruct.NVIC_IRQChannel = _NVIC_IN_EXTI_IRQChannel; //EXTI0_IRQn;
/* 配置抢占优先级:1 */
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
/* 配置子优先级:1 */
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
/* 使能中断通道 */
NVIC_InitStruct.NVIC_IRQChannelCmd = _NVIC_IN_EXTI_IRQChannelCmd; //ENABLE
NVIC_Init(&NVIC_InitStruct);
/* 配置中断源: */
NVIC_InitStruct.NVIC_IRQChannel = _NVIC_IN2_EXTI_IRQChannel; //EXTI0_IRQn;
NVIC_Init(&NVIC_InitStruct);
}
/**************************************************************
* @brief
* void fn_NVIC_Config(void)
* @param
* #define _KEY_EXTI_IN_GPIO_Port GPIOA
* #define _KEY_EXTI_IN_GPIO_Pin GPIO_Pin_0
* @retval
*************************************************************/
void EXTI0_IRQHandler(void){
// EXTI_GetITStatus 函数用来获取 EXTI 的中断标志位状态,如果 EXTI 线有中断发生函
//数返回“SET”否则返回“RESET”。实际上,EXTI_GetITStatus 函数是通过读取
//EXTI_PR寄存器值来判断 EXTI线状态的。
if(EXTI_GetITStatus(_EXTI_IN_EXTI_Line)!= RESET){
if(GPIO_ReadInputDataBit(_KEY_EXTI_IN_GPIO_Port, _KEY_EXTI_IN_GPIO_Pin)==1){
__LED_Change__;
}
}
EXTI_ClearITPendingBit(_EXTI_IN_EXTI_Line); // 重要的清除中断标志位
}
void EXTI15_10_IRQHandler(void){
if(EXTI_GetITStatus(_EXTI_IN2_EXTI_Line)!= RESET){
if(GPIO_ReadInputDataBit(_KEY2_EXTI_IN_GPIO_Port, _KEY2_EXTI_IN_GPIO_Pin)==0){
__LED_Change__;
}
}
EXTI_ClearITPendingBit(_EXTI_IN2_EXTI_Line); // 重要的清除中断标志位
}
4.建立Key采集的 头文件 Key_book.h
代码如下(示例):
#ifndef __KEY_BOOK_H_
#define __KEY_BOOK_H_
#include "stm32f10x.h"
#include "Led_book.h"
#define KEY_IN_GPIO_Port GPIOA
#define KEY_IN_GPIO_Clock RCC_APB2Periph_GPIOA
#define KEY_IN_GPIO_Pin GPIO_Pin_0
#define KEY_IN_GPIO_Pin_Bit 0
#define Key_IN_GPIO_Modle GPIO_Mode_IN_FLOATING //浮空输入
#define KEY2_IN_GPIO_Port GPIOC
#define KEY2_IN_GPIO_Clock RCC_APB2Periph_GPIOC
#define KEY2_IN_GPIO_Pin GPIO_Pin_13
#define KEY2_IN_GPIO_Pin_Bit 13
#define Key2_IN_GPIO_Modle GPIO_Mode_IN_FLOATING //浮空输入
typedef union {
struct{
unsigned char BIT0:1;unsigned char BIT1:1;unsigned char BIT2:1;unsigned char BIT3:1;
unsigned char BIT4:1;unsigned char BIT5:1;unsigned char BIT6:1;unsigned char BIT7:1;
//unsigned char BIT8:1;unsigned char BIT9:1;unsigned char BIT10:1;unsigned char BIT11:1;
//unsigned char BIT12:1;unsigned char BIT13:1;unsigned char BIT14:1;unsigned char BIT15:1;
}DATA_BIT;
uint8_t DATA_BYTE;
}Per_key_type;
extern volatile Per_key_type key_flag;
#define bkey_10ms key_flag.DATA_BIT.BIT0
#define bkey_judge key_flag.DATA_BIT.BIT1
#define bkey_judge_long key_flag.DATA_BIT.BIT2
#define bkey_Effect key_flag.DATA_BIT.BIT3
#define bkey_LongEffect key_flag.DATA_BIT.BIT4
#define bkey_Effect_Lose key_flag.DATA_BIT.BIT5
#define bkey_Effect_LLose key_flag.DATA_BIT.BIT6
void fn_Key_GPIO_Config( GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock , uint16_t _GPIO_Pin_x , GPIOMode_TypeDef _GPIOMode_TypeDef );
void fn_Key_Init(void);
void fn_key_judge(void);
void fn_key_Effect(void);
void fn_key_Check(void);
#endif
5.建立Key采集的 头文件 Key_book.c
代码如下(示例):
#include "Key_book.h"
volatile Per_key_type key_flag;
/**************************************************************
* @brief
* void fn_Key_GPIO_Config( GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock ,
* uint16_t _GPIO_Pin_x , GPIOMode_TypeDef _GPIOMode_TypeDef );
* @param
* #define KEY_IN_GPIO_Port GPIOA
* #define KEY_IN_GPIO_Clock RCC_APB2Periph_GPIOA
* #define KEY_IN_GPIO_Pin GPIO_Pin_0
* #define KEY_IN_GPIO_Pin_Bit 0
* #define Key_IN_GPIO_Modle GPIO_Mode_IN_FLOATING //浮空输入
*
* #define KEY2_IN_GPIO_Port GPIOC
* #define KEY2_IN_GPIO_Clock RCC_APB2Periph_GPIOC
* #define KEY2_IN_GPIO_Pin GPIO_Pin_13
* #define KEY2_IN_GPIO_Pin_Bit 13
* #define Key2_IN_GPIO_Modle GPIO_Mode_IN_FLOATING //浮空输入
* @retval
*************************************************************/
void fn_Key_GPIO_Config( GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock , uint16_t _GPIO_Pin_x , GPIOMode_TypeDef _GPIOMode_TypeDef ){
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = _GPIOMode_TypeDef;
GPIO_InitStruct.GPIO_Pin = _GPIO_Pin_x;
RCC_APB2PeriphClockCmd(_GPIO_Clock,ENABLE);
GPIO_Init(_GPIO_x , &GPIO_InitStruct);
}
/**************************************************************
* @brief
* void fn_Key_Init(void);
* @param
* @retval
*************************************************************/
void fn_Key_Init(void){
fn_Key_GPIO_Config(KEY_IN_GPIO_Port,KEY_IN_GPIO_Clock,KEY_IN_GPIO_Pin,Key_IN_GPIO_Modle);
fn_Key_GPIO_Config(KEY2_IN_GPIO_Port,KEY2_IN_GPIO_Clock,KEY2_IN_GPIO_Pin,Key2_IN_GPIO_Modle);
}
/************************************************************
* @brief
* void fn_key_judge(void);
* @param
* @retval
**************************************************************/
#define _LONG_key 30
static uint16_t count_key ;
void fn_key_judge(void){
if(!bkey_10ms){return;}
bkey_10ms = 0;
if(GPIO_ReadInputDataBit(KEY_IN_GPIO_Port,KEY_IN_GPIO_Pin)){
if(count_key++<3){return;}
if(!bkey_judge){
bkey_judge = 1;
bkey_Effect = 1;
}else{
if(count_key>_LONG_key){
bkey_judge_long = 1;
bkey_LongEffect = 1;
}
}
}
else{
count_key = 0;
if(bkey_judge){
bkey_judge = 0;
if(bkey_judge_long){
bkey_judge_long = 0;
bkey_Effect_LLose = 1;
}else{
bkey_judge_long = 0;
bkey_Effect_Lose = 1;
}
}else{
bkey_judge = 0;
}
}
}
/************************************************************
* @brief
* void fn_key_Effect(void);
* @param
* @retval
*************************************************************/
void fn_key_Effect(void){
if(bkey_Effect){
bkey_Effect = 0;
fn_LED_Corporate(LED_OUT_GPIO_Port,LED_OUT_GPIO_Pin,LED_Corporate_Toggle);
}
}
/**************************************************************
* @brief
* void fn_key_Check(void);
* @param
* @retval
*************************************************************/
void fn_key_Check(void){
fn_key_judge();
fn_key_Effect();
}
6.利用之前的LED输出的 头文件 Led_book.h
代码如下(示例):
#ifndef __LED_BOOK_H_
#define __LED_BOOK_H_
#include "stm32f10x.h"
#define LED_OUT_GPIO_Port GPIOB //GPIO Point
#define LED_OUT_GPIO_Clock RCC_APB2Periph_GPIOB //GPIO clock
#define LED_OUT_GPIO_Pin GPIO_Pin_5
#define LED_OUT_GPIO_Pin_Bit 5
#define LED_OUT_GPIO_Modle GPIO_Mode_Out_PP
typedef enum {
LED_Corporate_On = 1,
LED_Corporate_OFF = 2,
LED_Corporate_Toggle = 3,
} LED_Corporate_state_t;
void fn_LED_GPIO_Config(GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock ,\
uint16_t _GPIO_Pin_x , GPIOMode_TypeDef _GPIOMode_TypeDef);
void fn_Led_Init(void);
void fn_LED_Corporate(GPIO_TypeDef* _GPIO_x , uint16_t _GPIO_Pin_x , \
LED_Corporate_state_t _LED_Corporate_state_t );
#define __LED_Change__ fn_LED_Corporate(LED_OUT_GPIO_Port,LED_OUT_GPIO_Pin,LED_Corporate_Toggle)
#endif
7.利用之前的LED输出的 头文件 Led_book.c
代码如下(示例):
#include "Led_book.h"
/**************************************************************
* @brief
* void fn_LED_GPIO_Config(GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock ,
* uint16_t _GPIO_Pin_x , GPIOMode_TypeDef _GPIOMode_TypeDef);
* @param
* @retval
*************************************************************/
#define LED_GPIO_Speed GPIO_Speed_10MHz
void fn_LED_GPIO_Config(GPIO_TypeDef* _GPIO_x , uint32_t _GPIO_Clock ,uint16_t _GPIO_Pin_x , GPIOMode_TypeDef _GPIOMode_TypeDef){
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = _GPIOMode_TypeDef;
GPIO_InitStruct.GPIO_Pin = _GPIO_Pin_x;
GPIO_InitStruct.GPIO_Speed = LED_GPIO_Speed;
RCC_APB2PeriphClockCmd(_GPIO_Clock ,ENABLE);
GPIO_Init(_GPIO_x , &GPIO_InitStruct) ;
GPIO_SetBits(_GPIO_x,_GPIO_Pin_x);
}
/**************************************************************
* @brief
* void fn_Led_Init(void);
* @param
* @retval
*************************************************************/
void fn_Led_Init(void){
fn_LED_GPIO_Config (LED_OUT_GPIO_Port,LED_OUT_GPIO_Clock,LED_OUT_GPIO_Pin,LED_OUT_GPIO_Modle);
}
/**************************************************************
* @brief
* void fn_LED_Corporate(GPIO_TypeDef* _GPIO_x , uint16_t _GPIO_Pin_x ,
* LED_Corporate_state_t _LED_Corporate_state_t );
* @param
* @retval
*************************************************************/
void fn_LED_Corporate(GPIO_TypeDef* _GPIO_x , uint16_t _GPIO_Pin_x , LED_Corporate_state_t _LED_Corporate_state_t ){
switch(_LED_Corporate_state_t){
case LED_Corporate_On :
GPIO_SetBits(_GPIO_x,_GPIO_Pin_x);
break;
case LED_Corporate_OFF:
GPIO_ResetBits(_GPIO_x,_GPIO_Pin_x);
break;
case LED_Corporate_Toggle:
GPIO_ReadOutputDataBit(_GPIO_x,_GPIO_Pin_x)?GPIO_ResetBits(_GPIO_x,_GPIO_Pin_x):GPIO_SetBits(_GPIO_x,_GPIO_Pin_x);
break;
}
}
//practice
//fn_LED_GPIO_Config (LED_OUT_GPIO_Port,LED_OUT_GPIO_Clock,LED_OUT_GPIO_Pin,LED_OUT_GPIO_Modle);
// while(1){
// delay(10000);
// fn_LED_Corporate(LED_OUT_GPIO_Port,LED_OUT_GPIO_Pin,LED_Corporate_Toggle);
// }
8.建立Systicks Key输出的 主程序 main.c
代码如下(示例):
/**
******************************************************************************
* @file GPIO/JTAG_Remap/main.c
* @author MCD Application Team
* @version V3.5.0
* @date 08-April-2011
* @brief Main program body
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "PROJ_book.h"
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
void delay(int x);
void fn_Main_Init(void);
int main(void)
{
fn_Led_Init();
fn_Key_Init();
fn_Main_Init();
fn_EXTI_GPIO_Config();
while(1){
// fn_key_Check();
delay(10000);
}
}
void fn_Main_Init(void){
uint16_t count_Init = 2;
while(count_Init-->0){
__LED_Change__;
fn_Systick_Delay(500,_Systick_ms);
__LED_Change__;
fn_Systick_Delay(100,_Systick_ms);
__LED_Change__;
fn_Systick_Delay(100,_Systick_ms);
__LED_Change__;
fn_Systick_Delay(500,_Systick_ms);
}
}
void delay(int x){
int y = 0xFFFFF;
while((x--)>0){
while((y--)>0){
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
}
}
}
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
www.firebbs.cn。
参考笔记。
_STM32f103 中断 以及 EXT
总结
EXTI(External interrupt/event controller)—外部中断/事件控制器,管理了控制器的 20
个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿
检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为
中断或者事件,以及触发事件的属性。
EXTI 的功能框图包含了 EXTI 最核心内容,掌握了功能框图,对 EXTI 就有一个整体
的把握,在编程时思路就非常清晰。EXTI 功能框图见图 18-1。 在图 18-1 可以看到很多在信号线上打一个斜杠并标注“20”字样,这个表示在控制器
内部类似的信号线路有 20 个,这与 EXTI 总共有 20 个中断/事件线是吻合的。所以我们只
要明白其中一个的原理,那其他 19 个线路原理也就知道了
EXTI0 至 EXTI15 用于 GPIO,通过编程控制可以实现任意一个 GPIO 作为 EXTI 的输
入源。由表 18-1 可知,EXTI0 可以通过 AFIO 的外部中断配置寄存器 1(AFIO_EXTICR1)的
EXTI0[3:0]位选择配置为 PA0、PB0、PC0、PD0、PE0、PF0、PG0、PH0 或
EXTI 初始化结构体详解
标准库函数对每个外设都建立了一个初始化结构体,比如 EXTI_InitTypeDef,结构体
成员用于设置外设工作参数,并由外设初始化配置函数,比如 EXTI_Init()调用,这些设定
参数将会设置外设相应的寄存器,达到配置外设工作环境的目的
typedef struct {
2 uint32_t EXTI_Line; // 中断/事件线
3 EXTIMode_TypeDef EXTI_Mode; // EXTI 模式
4 EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
5 FunctionalState EXTI_LineCmd; // EXTI 使能
6 } EXTI_InitTypeDef;
1. 首先进行 按键和 EXTI 宏定义使用宏定义方法指定与硬件电路设计相关配置,这对于程序移植或升级非常有用的。在上面的宏定义中,我们除了开 GPIO 的端口时钟外,我们还打开了 AFIO 的时钟,这 是 因 为 等 下 配 置 EXTI 信号源的时候需要用到 AFIO 的外部中断控制寄存器AFIO_EXTICRx
2. 嵌套向量中断控制器 NVIC 配置,配置两个的中断软件优先级
3. EXTI 中断配置
4. 使用 GPIO_InitTypeDef 和 EXTI_InitTypeDef 结构体定义两个用于 GPIO 和EXTI 初始化配置的变量,关于这两个结构体前面都已经做了详细的讲解。
使用 GPIO 之前必须开启 GPIO 端口的时钟;用到 EXTI 必须开启 AFIO 时钟。
调用 NVIC_Configuration 函数完成对按键优先级配置并使能中断通道。
作为中断/事件输入线时需把 GPIO 配置为输入模式,具体为浮空输入,由外部电路完全决定引脚的状态。GPIO_EXTILineConfig 函数用来指定中断/事件线的输入源,它实际是设定外部中断配置寄存器的 AFIO_EXTICRx 值,该函数接收两个参数,第一个参数指定 GPIO 端口源,第二个参数为选择对应 GPIO 引脚源编号。
我们的目的是产生中断,执行中断服务函数,EXTI 选择中断模式,按键 1 使用上升沿触发方式,并使能 EXTI 线。按键 2 基本上采用与按键 1 相关参数配置,只是改为下降沿触发方式