当前位置:网站首页>2021-06-16 STM32F103 EXTI 中斷識別 使用固件庫

2021-06-16 STM32F103 EXTI 中斷識別 使用固件庫

2022-06-21 07:40:00 DRMIVET Stone

本文展示了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

STM32 EXIT – LED 程序

STM32 EXIT – EXIT 程序

STM32 EXIT – Key 程序

STM32 RCC – 主程序

總結

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 相關參數配置,只是改為下降沿觸發方式
原网站

版权声明
本文为[DRMIVET Stone]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/172/202206210737470749.html