使用 IO 口外部中斷的一般步驟:
1)初始化 IO 口為輸入。
2)開啟 IO 口復用時鍾,設置 IO 口與中斷線的映射關系。
3)初始化線上中斷,設置觸發條件等。
4)配置中斷分組(NVIC),並使能中斷。
5)編寫中斷服務函數。
//初始化 EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //開啟復用時鍾 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //外部中斷,需要使能 AFIO 時鍾 KEY_Init();//初始化按鍵對應 io 模式 //初始化線上中斷,設置觸發條件 //GPIOC.5 中斷線以及中斷初始化配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5); EXTI_InitStructure.EXTI_Line=EXTI_Line5; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿觸發 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //根據 EXTI_InitStruct 中指定的參數初始化外設 EXTI 寄存器 //配置中斷分組,並使能中斷 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按鍵所在的外部中斷通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //搶占優先級 2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子優先級 1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道 NVIC_Init(&NVIC_InitStructure); //編寫中斷服務函數 void EXTI0_IRQHandler(void) { delay_ms(10); //消抖 if(WK_UP==1) { LED0=!LED0; LED1=!LED1; } EXTI_ClearITPendingBit(EXTI_Line0); //清除 EXTI0 線路掛起位 } //根據 NVIC_InitStruct 中指定的參數初始化外設 NVIC 寄存器
STM32供IO口使用的中斷線只有16個,映射關系如下圖所示
配置GPIO與中斷線的映射關系的函數: GPIO_EXTILineConfig()來實現的:
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
例子:該函數將 GPIO 端口與中斷線映射起來,使用范例是:GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
中斷線上中斷的初始化是通過函數 EXTI_Init()實現的。EXTI_Init()函數的定義是:
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
typedef struct { uint32_t EXTI_Line;//中斷線的標號,取值范圍0~5 EXTIMode_TypeDef EXTI_Mode; //中斷模式: EXTI_Mode_Interrupt 和事件 EXTI_Mode_Event EXTITrigger_TypeDef EXTI_Trigger; //觸發方式:下降沿觸發 EXTI_Trigger_Falling //上升沿觸發 EXTI_Trigger_Rising, //任意電平(上升沿和下降沿)觸發EXTI_Trigger_Rising_Falling FunctionalState EXTI_LineCmd; //使能 }EXTI_InitTypeDef;
例子
EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line=EXTI_Line4; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //根據 EXTI_InitStruct 中指定的 //參數初始化外設 EXTI 寄存器
配置完中斷優先級后,要編寫中斷服務函數。
而中斷函數只用6個
EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI4_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler
在編寫中斷函數時會經常使用到兩個函數,
第一個函數是判斷某個中斷線上的中斷是否發生(標志位是否置位):
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
這個函數一般使用在中斷服務函數的開頭判斷中斷是否發生。
另一個函數是清除某個中斷上的中斷標志位:
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
這個函數一般應用在中斷服務函數結束之前,清除中斷標志位。
常用的中斷函數格式
void EXTI2_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line2)!=RESET)//判斷某個線上的中斷是否發生 { 中斷邏輯… EXTI_ClearITPendingBit(EXTI_Line2); //清除 LINE 上的中斷標志位 } }