STM32第四章-外部中斷管理

STM32F4 的每個 IO 都可以作爲外部中斷的中斷輸入口,這點也是 STM32F4 的強大之處。STM32F429 的中斷控制器支持 22個外部中斷/事件請求。每個中斷設有狀態位,每個中斷/事件都有獨立的觸發和屏蔽設置。

STM32F429有22個外部中斷爲,我們這裏只看IO口的16個外部中斷:EXTI 線 0~15:對應外部 IO 口的輸入中斷

STM32F4 供 IO 口使用的中斷線只有 16 個,但是 STM32F4 的 IO 口卻遠遠不止 16 個,那麼 STM32F4 是怎麼把 16 箇中斷線和 IO 口一一對應起來的呢?於是 STM32就這樣設計,GPIO 的引腳 GPIOx.0-GPIOx.15(x=A,B,C,D,E,F,G,H,I)分別對應中斷線 0~15。這樣每個中斷線對應了最多 9 個 IO 口,以線 0 爲例:它對應了 GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0、GPIOG.0,GPIOH.0,GPIOI.0。而中斷線每次只能連接到 1 個 IO口上,這樣就需要通過配置來決定對應的中斷線配置到哪個 GPIO 上了。

我舉一個例子:我們一個學校(對應一個單片機)有16個老師(對應16根中斷線)。但是我們現在有9個班級(GPIOA.0-GPIOI)。每個班級有16個同學(GPIOA_0…GPIOA_15)。如何讓這16位老師負責9個班級一共9X16=144個學生呢?
現在的方法就是:讓第1個老師負責每個班級的第1位同學。讓第2個老師負責每個班級的第2位同學…,讓第16個老師負責每個班級的第16位同學這樣就可以了對吧。

下面我們看看 GPIO跟中斷線的映射關係圖就容易理解多了:
中斷線的映射關係圖
哈哈哈 是不是通俗易懂!!!

接下來就是寫程序了。

程序配置:

1.第一步當然是初始化你的IO口了對吧。比如我們開始寫按鍵的時候是這樣寫的。

void KEY_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能PA端口時鐘
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	           //端口配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;          //上拉輸入
  GPIO_Init(GPIOC, &GPIO_InitStructure);				 //根據設定參數初始化GPIOC 
} 

2.初始化了IO口,接下來我們要幹嘛呢?你不是要讓按鍵按下了之後去幹別的事嗎?那就打開IO口的複用功能
使能EXTI外設對應的時鐘----注意:當使用EXTI外設時,使能的是AFIO時鐘,而不是EXTI外設時鐘

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 

3.現在就是要把中斷線和對應的IO口的關係給連接上
打開stm32f4xx_gpio.h。就看到下面這每個班的16個學生了,整整齊齊的排在這裏。因爲每一個GPIO都有16個管腳,所以這裏最大是從GPIO_PinSource0到GPIO_PinSource15。
GPIO_PinSource0-15
利用**GPIO_EXTILineConfig()**將EXTI線0連接到端口GPIOA的第0個針腳上
具體代碼:

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);

注意:如果配置的針腳是4號,那麼參數必須是GPIO_PinSource4
如果配置的針腳是3號,那麼參數必須是GPIO_PinSource3

4.接下來就是初始化EXTI了:打開stm32f42x_exti.h。就看到這16個老師高興的站在那裏,等待着他的學生(還有幾個老師也站在那裏但是不是負責GPIO的我們先不管他們)。我們要做的就是讓第1個老師去負責第一個班級(GPIOA)的第一個同學(GPIOA_0)。因爲你是第一個老師要負責第1個班級自然就是負責班級1的第1個同學啦。

typedef enum
{
  EXTI_Mode_Interrupt = 0x00,  //中斷觸發
  EXTI_Mode_Event = 0x04       //事件觸發
}EXTIMode_TypeDef;
typedef enum
{
  EXTI_Trigger_Rising = 0x08,         //上升沿觸發
  EXTI_Trigger_Falling = 0x0C,        //下降沿觸發
  EXTI_Trigger_Rising_Falling = 0x10  //高低電平觸發
}EXTITrigger_TypeDef;
#define EXTI_Line0       ((uint32_t)0x00001)  /*!< External interrupt line 0 */
#define EXTI_Line1       ((uint32_t)0x00002)  /*!< External interrupt line 1 */
#define EXTI_Line2       ((uint32_t)0x00004)  /*!< External interrupt line 2 */
#define EXTI_Line3       ((uint32_t)0x00008)  /*!< External interrupt line 3 */
#define EXTI_Line4       ((uint32_t)0x00010)  /*!< External interrupt line 4 */
#define EXTI_Line5       ((uint32_t)0x00020)  /*!< External interrupt line 5 */
#define EXTI_Line6       ((uint32_t)0x00040)  /*!< External interrupt line 6 */
#define EXTI_Line7       ((uint32_t)0x00080)  /*!< External interrupt line 7 */
#define EXTI_Line8       ((uint32_t)0x00100)  /*!< External interrupt line 8 */
#define EXTI_Line9       ((uint32_t)0x00200)  /*!< External interrupt line 9 */
#define EXTI_Line10      ((uint32_t)0x00400)  /*!< External interrupt line 10 */
#define EXTI_Line11      ((uint32_t)0x00800)  /*!< External interrupt line 11 */
#define EXTI_Line12      ((uint32_t)0x01000)  /*!< External interrupt line 12 */
#define EXTI_Line13      ((uint32_t)0x02000)  /*!< External interrupt line 13 */
#define EXTI_Line14      ((uint32_t)0x04000)  /*!< External interrupt line 14 */
#define EXTI_Line15      ((uint32_t)0x08000)  /*!< External interrupt line 15 */
#define EXTI_Line16      ((uint32_t)0x10000)  /*!< External interrupt line 16 Connected to the PVD Output */
#define EXTI_Line17      ((uint32_t)0x20000)  /*!< External interrupt line 17 Connected to the RTC Alarm event */
#define EXTI_Line18      ((uint32_t)0x40000)  /*!< External interrupt line 18 Connected to the USB Device/USB OTG FS                                                  Wakeup from suspend event */                                    
#define EXTI_Line19      ((uint32_t)0x80000)  /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */

那具體的代碼就是下面這樣的:

void exti_Init(void)
{  
EXTI_InitTypeDef   EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //外部中斷,需要使能AFIO時鐘
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//將EXTI線連接到對應的IO端口上
EXTI_InitStructure.EXTI_Line  =   EXTI_Line0;  //常用的就是EXTI_Line0-EXTI_Line015負責gpio管腳的那幾個
EXTI_InitStructure.EXTI_Mode =    EXTI_Mode_Interrupt;	
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發
EXTI_InitStructure.EXTI_LineCmd = ENABLE;              //中斷線使能
EXTI_Init(&EXTI_InitStructure);	                      //初始化中斷
}

到此爲止外部中斷就寫好了。當然這些函數你可以放在一起,就是下面這樣:

void key_exti_init(void)
{  
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
	
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);  //外部中斷,需要使能AFIO時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	         //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;        //上拉輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);	//根據設定參數初始化GPIOA 

//注意:如果配置的針腳是0號,那麼參數必須是GPIO_PinSource0 如果配置的針腳是3號,那麼參數必須是GPIO_PinSource3	
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//將EXTI線連接到對應的IO端口上
//注意:如果配置的0號針腳,那麼EXTI_Line0是必須的  如果配置的針腳是3號,那麼參數必須是EXTI_Line3
EXTI_InitStructure.EXTI_Line = EXTI_Line0;  //常用的就是EXTI_Line0-EXTI_Line015負責gpio管腳的那幾個
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);	   //初始化中斷
}

你以爲到次就結束了嗎?當然沒有。既然有了中斷就要有中斷優先級。同一時間你爸爸叫你喫飯,正在這時候你女朋友給你打電話。你是先去喫飯了還是先接電話?當然是先接電話對吧。但是單片機可是不知道要先去幹嘛。你就必須給他配一下中斷優先級。所以就引出了NVIC中斷優先級。你要問我NVIC幹嘛的,我就告訴你NVIC就是你在同一時間有兩個事件來了先幹哪一個。這回就有人說了假如我現在有100個事件同時來了先幹哪一個呢?不要着急待我細細道來!!!

優先級的定義

在 NVIC 有一個專門的寄存器:中斷優先級寄存器 NVIC_IPRx(在 F429 中,x=0…90)用來配置外部中斷的優先級,IPR寬度爲 8bit,原則上每個外部中斷可配置的優先級爲0~255,數值越小,優先級越高。但是絕大多數 CM4芯片都會精簡設計,以致實際上支持的優先級數減少,在 F429 中,只使用了高 4bit,就是每個外部中斷可配置的優先級爲0-16。如下所示:
優先級的定義
用於表達優先級的這 4bit,又被分組成搶佔優先級子優先級。如果有多箇中斷同時響應,搶佔優先級高的就會 搶佔 搶佔優先級低的優先得到執行,如果搶佔優先級相同,就比較子優先級。如果搶佔優先級和子優先級都相同的話,就比較他們的硬件中斷編號,編號越小,優先級越高。

優先級的分組

優先級分組
這裏我們用階級來表示搶佔優先級用階層來表示子優先級,通常我們響應優先級也叫做子優先級。
1.如果我們按照NVIC_PriorityGroup_4這樣分組的話,系統就分配了4位搶佔優先級。0位響應優先級。就分了16個階級(2^4=16),0個階層。
比如我來了一箇中斷叫做外部中斷1(EXTI1_IRQn)。他的搶佔優先級就可以設置爲0-15.響應優先級就只能設置爲0,假如在這個時候又來了一箇中斷叫做外部中斷2(EXTI2_IRQn)。他的搶佔優先級就可以設置爲0-15.響應優先級就只能設置爲0。這個箇中斷可以設置爲一樣的,也可以設置爲不一樣的。如果假如夠設置搶佔優先級爲4,那麼系統就看哪一個中斷縣發生,先發生就先執行。

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);	 //設置NVIC中斷分組4:4位搶佔優先級,0位響應優先級
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//使能外部中斷通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;	//搶佔優先級4  因爲爲分組爲4 這裏可以設置爲0-15
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	//響應優先級0 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	//使能外部中斷通道
NVIC_Init(&NVIC_InitStructure);  	  //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器

2.如果我們按照NVIC_PriorityGroup_2這樣分組的話,系統就分配了2位搶佔優先級。2位響應優先級。就分了4個階級(2^2=4),4個階層。

比如我來了一箇中斷叫做外部中斷1(EXTI1_IRQn)。他的搶佔優先級就不能設置爲0-15,範圍應該是0-3,響應優先級就只能設置爲0,假如在這個時候又來了一箇中斷叫做外部中斷2(EXTI2_IRQn)。他的搶佔優先級就設置範圍爲0-3.響應優先級範圍也是0-3。同樣的他們的優先級可以設置爲一樣的,也可以設置爲不一樣的。如果外部中斷1的搶佔優先級爲2,響應優先級爲1,外部中斷2的搶佔優先級爲2,響應優先級爲0。那麼當兩個中斷同時發生的時候就會首先響應外部中斷2,因爲外部中斷2響應優先級高於外部中斷1.數值越小優先級越高.

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //設置NVIC中斷分組2:2位搶佔優先級,2位響應優先級
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//使能外部中斷通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	//搶佔優先級2  因爲爲分組爲2 這裏可以設置爲0-3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;	//響應優先級0 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	//使能外部中斷通道
NVIC_Init(&NVIC_InitStructure);  	  //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器

NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;         //使能外部中斷通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//搶佔優先級2  因爲爲分組爲4 這裏可以設置爲0-3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	   //響應優先級0 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	//使能外部中斷通道
NVIC_Init(&NVIC_InitStructure);  	  //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器

一般情況下,系統代碼執行過程中,只設置一次中斷優先級分組,比如分組2,設置好分組之後一般不會再改變分組。
隨意改變分組會導致中斷管理混亂,程序出現意想不到的執行結果。換句話說NVIC_PriorityGroupConfig();這個函數在你的整個程序中只能設置一次,這個要切記!!!

3.上面我們說到來了一個外部中斷1(EXTI1_IRQn)和外部中斷2(EXTI2_IRQn)。根據我在最前面講的一個故事也就是說,用到的管腳與中斷線的序號是要一一對應的,,不管A–H用的哪一組的管腳,PIN1就要對應EXTI1…PIN15就要對應EXTI15。同時也要對應相應的中斷函數,在庫函數中EXTI0_IRQn,EXTI1_IRQn,EXTI2_IRQn,EXTI3_IRQn,EXTI4_IRQn,EXTI9_5_IRQn(EXTI5-EXTI9都對應這個中斷),EXTI15_10_IRQn(EXITI10-EXTI15都對應這個中斷函數)。這些中斷通道全都在stm32f4xx.h中用了一個枚舉結構體包起來了。想用哪一個找到對應的通道寫上就可以了。

typedef enum IRQn
{
/******  Cortex-M4處理器異常數 ****************************************************************/
  NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                                          */
  MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M4 Memory Management Interrupt                           */
  BusFault_IRQn               = -11,    /*!< 5 Cortex-M4 Bus Fault Interrupt                                   */
  UsageFault_IRQn             = -10,    /*!< 6 Cortex-M4 Usage Fault Interrupt                                 */
  SVCall_IRQn                 = -5,     /*!< 11 Cortex-M4 SV Call Interrupt                                    */
  DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M4 Debug Monitor Interrupt                              */
  PendSV_IRQn                 = -2,     /*!< 14 Cortex-M4 Pend SV Interrupt                                    */
  SysTick_IRQn                = -1,     /*!< 15 Cortex-M4 System Tick Interrupt                                */
/******  STM32 特定的中斷數量 **********************************************************************/
  WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                                         */
  PVD_IRQn                    = 1,      /*!< PVD through EXTI Line detection Interrupt                         */
  TAMP_STAMP_IRQn             = 2,      /*!< Tamper and TimeStamp interrupts through the EXTI line             */
  RTC_WKUP_IRQn               = 3,      /*!< RTC Wakeup interrupt through the EXTI line                        */
  FLASH_IRQn                  = 4,      /*!< FLASH global Interrupt                                            */
  RCC_IRQn                    = 5,      /*!< RCC global Interrupt                                              */
  EXTI0_IRQn                  = 6,      /*!< EXTI Line0 Interrupt                                              */
  EXTI1_IRQn                  = 7,      /*!< EXTI Line1 Interrupt                                              */
  EXTI2_IRQn                  = 8,      /*!< EXTI Line2 Interrupt                                              */
  EXTI3_IRQn                  = 9,      /*!< EXTI Line3 Interrupt                                              */
  EXTI4_IRQn                  = 10,     /*!< EXTI Line4 Interrupt                                              */
  DMA1_Stream0_IRQn           = 11,     /*!< DMA1 Stream 0 global Interrupt                                    */
  DMA1_Stream1_IRQn           = 12,     /*!< DMA1 Stream 1 global Interrupt                                    */
  DMA1_Stream2_IRQn           = 13,     /*!< DMA1 Stream 2 global Interrupt                                    */
  DMA1_Stream3_IRQn           = 14,     /*!< DMA1 Stream 3 global Interrupt                                    */
  DMA1_Stream4_IRQn           = 15,     /*!< DMA1 Stream 4 global Interrupt                                    */
  DMA1_Stream5_IRQn           = 16,     /*!< DMA1 Stream 5 global Interrupt                                    */
  DMA1_Stream6_IRQn           = 17,     /*!< DMA1 Stream 6 global Interrupt                                    */
  ADC_IRQn                    = 18,     /*!< ADC1, ADC2 and ADC3 global Interrupts                             */    
#if defined(STM32F429_439xx)
  CAN1_TX_IRQn                = 19,     /*!< CAN1 TX Interrupt                                                 */
  CAN1_RX0_IRQn               = 20,     /*!< CAN1 RX0 Interrupt                                                */
  CAN1_RX1_IRQn               = 21,     /*!< CAN1 RX1 Interrupt                                                */
  CAN1_SCE_IRQn               = 22,     /*!< CAN1 SCE Interrupt                                                */
  EXTI9_5_IRQn                = 23,     /*!< External Line[9:5] Interrupts                                     */
  TIM1_BRK_TIM9_IRQn          = 24,     /*!< TIM1 Break interrupt and TIM9 global interrupt                    */
  TIM1_UP_TIM10_IRQn          = 25,     /*!< TIM1 Update Interrupt and TIM10 global interrupt                  */
  TIM1_TRG_COM_TIM11_IRQn     = 26,     /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */
  TIM1_CC_IRQn                = 27,     /*!< TIM1 Capture Compare Interrupt                                    */
  TIM2_IRQn                   = 28,     /*!< TIM2 global Interrupt                                             */
  TIM3_IRQn                   = 29,     /*!< TIM3 global Interrupt                                             */
  TIM4_IRQn                   = 30,     /*!< TIM4 global Interrupt                                             */
  I2C1_EV_IRQn                = 31,     /*!< I2C1 Event Interrupt                                              */
  I2C1_ER_IRQn                = 32,     /*!< I2C1 Error Interrupt                                              */
  I2C2_EV_IRQn                = 33,     /*!< I2C2 Event Interrupt                                              */
  I2C2_ER_IRQn                = 34,     /*!< I2C2 Error Interrupt                                              */
  SPI1_IRQn                   = 35,     /*!< SPI1 global Interrupt                                             */
  SPI2_IRQn                   = 36,     /*!< SPI2 global Interrupt                                             */
  USART1_IRQn                 = 37,     /*!< USART1 global Interrupt                                           */
  USART2_IRQn                 = 38,     /*!< USART2 global Interrupt                                           */
  USART3_IRQn                 = 39,     /*!< USART3 global Interrupt                                           */
  EXTI15_10_IRQn              = 40,     /*!< External Line[15:10] Interrupts                                   */
  RTC_Alarm_IRQn              = 41,     /*!< RTC Alarm (A and B) through EXTI Line Interrupt                   */
  OTG_FS_WKUP_IRQn            = 42,     /*!< USB OTG FS Wakeup through EXTI line interrupt                     */
  TIM8_BRK_TIM12_IRQn         = 43,     /*!< TIM8 Break Interrupt and TIM12 global interrupt                   */
  TIM8_UP_TIM13_IRQn          = 44,     /*!< TIM8 Update Interrupt and TIM13 global interrupt                  */
  TIM8_TRG_COM_TIM14_IRQn     = 45,     /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */
  TIM8_CC_IRQn                = 46,     /*!< TIM8 Capture Compare Interrupt                                    */
  DMA1_Stream7_IRQn           = 47,     /*!< DMA1 Stream7 Interrupt                                            */
  FMC_IRQn                    = 48,     /*!< FMC global Interrupt                                              */
  SDIO_IRQn                   = 49,     /*!< SDIO global Interrupt                                             */
  TIM5_IRQn                   = 50,     /*!< TIM5 global Interrupt                                             */
  SPI3_IRQn                   = 51,     /*!< SPI3 global Interrupt                                             */
  UART4_IRQn                  = 52,     /*!< UART4 global Interrupt                                            */
  UART5_IRQn                  = 53,     /*!< UART5 global Interrupt                                            */
  TIM6_DAC_IRQn               = 54,     /*!< TIM6 global and DAC1&2 underrun error  interrupts                 */
  TIM7_IRQn                   = 55,     /*!< TIM7 global interrupt                                             */
  DMA2_Stream0_IRQn           = 56,     /*!< DMA2 Stream 0 global Interrupt                                    */
  DMA2_Stream1_IRQn           = 57,     /*!< DMA2 Stream 1 global Interrupt                                    */
  DMA2_Stream2_IRQn           = 58,     /*!< DMA2 Stream 2 global Interrupt                                    */
  DMA2_Stream3_IRQn           = 59,     /*!< DMA2 Stream 3 global Interrupt                                    */
  DMA2_Stream4_IRQn           = 60,     /*!< DMA2 Stream 4 global Interrupt                                    */
  ETH_IRQn                    = 61,     /*!< Ethernet global Interrupt                                         */
  ETH_WKUP_IRQn               = 62,     /*!< Ethernet Wakeup through EXTI line Interrupt                       */
  CAN2_TX_IRQn                = 63,     /*!< CAN2 TX Interrupt                                                 */
  CAN2_RX0_IRQn               = 64,     /*!< CAN2 RX0 Interrupt                                                */
  CAN2_RX1_IRQn               = 65,     /*!< CAN2 RX1 Interrupt                                                */
  CAN2_SCE_IRQn               = 66,     /*!< CAN2 SCE Interrupt                                                */
  OTG_FS_IRQn                 = 67,     /*!< USB OTG FS global Interrupt                                       */
  DMA2_Stream5_IRQn           = 68,     /*!< DMA2 Stream 5 global interrupt                                    */
  DMA2_Stream6_IRQn           = 69,     /*!< DMA2 Stream 6 global interrupt                                    */
  DMA2_Stream7_IRQn           = 70,     /*!< DMA2 Stream 7 global interrupt                                    */
  USART6_IRQn                 = 71,     /*!< USART6 global interrupt                                           */
  I2C3_EV_IRQn                = 72,     /*!< I2C3 event interrupt                                              */
  I2C3_ER_IRQn                = 73,     /*!< I2C3 error interrupt                                              */
  OTG_HS_EP1_OUT_IRQn         = 74,     /*!< USB OTG HS End Point 1 Out global interrupt                       */
  OTG_HS_EP1_IN_IRQn          = 75,     /*!< USB OTG HS End Point 1 In global interrupt                        */
  OTG_HS_WKUP_IRQn            = 76,     /*!< USB OTG HS Wakeup through EXTI interrupt                          */
  OTG_HS_IRQn                 = 77,     /*!< USB OTG HS global interrupt                                       */
  DCMI_IRQn                   = 78,     /*!< DCMI global interrupt                                             */
  CRYP_IRQn                   = 79,     /*!< CRYP crypto global interrupt                                      */
  HASH_RNG_IRQn               = 80,     /*!< Hash and Rng global interrupt                                     */
  FPU_IRQn                    = 81,     /*!< FPU global interrupt                                              */
  UART7_IRQn                  = 82,     /*!< UART7 global interrupt                                            */
  UART8_IRQn                  = 83,     /*!< UART8 global interrupt                                            */
  SPI4_IRQn                   = 84,     /*!< SPI4 global Interrupt                                             */
  SPI5_IRQn                   = 85,     /*!< SPI5 global Interrupt                                             */
  SPI6_IRQn                   = 86,     /*!< SPI6 global Interrupt                                             */
  SAI1_IRQn                   = 87,     /*!< SAI1 global Interrupt                                             */
  LTDC_IRQn                   = 88,     /*!< LTDC global Interrupt                                             */
  LTDC_ER_IRQn                = 89,     /*!< LTDC Error global Interrupt                                       */
  DMA2D_IRQn                  = 90      /*!< DMA2D global Interrupt                                            */
#endif /* STM32F429_439xx */
} IRQn_Type;

所以我們結合EXTI和NVIC的代碼,就可以整理爲

void key_exti_init(void)
{  
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;	
NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);  //外部中斷,需要使能AFIO時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	         //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;        //上拉輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);	//根據設定參數初始化GPIOA 

//注意:如果配置的針腳是0號,那麼參數必須是GPIO_PinSource0 如果配置的針腳是3號,那麼參數必須是GPIO_PinSource3	
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//將EXTI線連接到對應的IO端口上
//注意:如果配置的0號針腳,那麼EXTI_Line0是必須的  如果配置的針腳是3號,那麼參數必須是EXTI_Line3
EXTI_InitStructure.EXTI_Line = EXTI_Line0;  //常用的就是EXTI_Line0-EXTI_Line015負責gpio管腳的那幾個
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);	   //初始化中斷

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //設置NVIC中斷分組2:2位搶佔優先級,2位響應優先級
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//使能外部中斷通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	//搶佔優先級2  因爲爲分組爲2 這裏可以設置爲0-3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;	//響應優先級0 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	//使能外部中斷通道
NVIC_Init(&NVIC_InitStructure);  	  //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器
}

當然爲了代碼的美觀,你可以那關於NVIC的代碼,放到一起便於管理。就像這樣,就可以清楚的看到響應的順序

以上就是所有關於中斷和中斷管理知識了。這方面不是很難理解,在遇到問題時對看看對應芯片的中文參考手冊就可以了。

上一篇:STM32第三章-系統時鐘配置
下一篇:STM32第五章-串口通訊詳解
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章