STM32第四章-外部中斷管理

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

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 上了。ui

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

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

接下來就是寫程序了。3d

程序配置

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

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外設時鐘orm

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_PinSource3ip

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的代碼,放到一塊兒便於管理。就像這樣,就能夠清楚的看到響應的順序 以上就是全部關於中斷和中斷管理知識了。這方面不是很難理解,在遇到問題時對看看對應芯片的中文參考手冊就能夠了。

相關文章
相關標籤/搜索