開發板芯片:STM32F407ZGT6
硬件連接:PE3-KEY1
一、STM32F4的中斷介紹
STM32F4的每個IO都可以作為外部中斷輸入,很強大的功能吧!以前學習的51只有兩個外部中斷。
STM32F4的中斷控制器支持22個外部中斷/事件請求:
EXTI線0~15:對應外部IO口的輸入中斷。即GPIOx.0—EXTI0,GPIOx.a—EXTIa如下圖所示

EXTI線16:連接到PVD輸出。
EXTI線17:連接到RTC鬧鍾事件。
EXTI線18:連接到USB OTG FS喚醒事件。
EXTI線19:連接到以太網喚醒事件。
EXTI線20:連接到USB OTG HS(在FS中配置)喚醒事件。
EXTI線21:連接到RTC入侵和時間戳事件。EXTI線22:連接到RTC喚醒事件。
對於每個中斷線0我們可以設置相應的觸發方式(上升沿觸發,下降沿觸發,邊沿觸發)以及使能。
中斷服務函數又是如何分配的呢?
其中中斷線0-4有單獨的中斷向量,即單獨的中斷服務函數。
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
中斷線5-9共用一個中斷服務函數
EXTI9_5_IRQHandler
中斷線10-15共同一個中斷服務函數
EXTI15_10_IRQHandler
二、中斷優先級的管理
嵌套向量中斷控制器NVIC (Nested vectored interrupt controller)
中斷優先級分組的是在SCB->AIRCR寄存器中設置的,具體設置情況如下:

選擇不同的分組可以設置不同的優先級等級,例如選擇分組2,分配結果為2位搶占,2位響應,既然是兩位,所以優先級可以設置為0-3,要注意的是,設置好分組之后不要再改變分組,隨意改變分組會導致中斷管理混亂。
關於搶占優先級和響應優先級的說明
-
- 高優先級的搶占優先級可以打斷正在進行的低搶占優先級中斷的。
- 搶占優先級相同的中斷,高響應優先級不可以打斷低響應優先級的中斷。
- 搶占優先級相同的中斷,當兩個中斷同時發生的情況下,哪個響應優先級高,哪個先執行。
- 如果兩個中斷的搶占優先級和響應優先級都是一樣的話,則看哪個中斷先發生就先執行;
例如:

這里要注意的是,搶占優先級設置的越小,則優先級越高,0最高
則這三個優先級的順序為:中斷7>中斷3>中斷6。
三、程序設計
1.初始化PF3中斷,即EXTI3中斷的過程:
1.1.使能GPIO時鍾,注意:模式設置為輸入
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //使能GPIOA,GPIOE時鍾
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //普通輸入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOE, &GPIO_InitStructure);
1.2.使能SYSCFG時鍾。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //使能SYSCFG時鍾,必須的
1.3.設置GPIO和中斷線的映射關系
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3); //PF3,中斷線映射,line3-Pin3
1.4.中斷初始化,包括設置觸發方式,指定中斷線,使能中斷,設置中斷模式等
EXTI_InitTypeDef EXTI_InitStructure; //中斷方式初始化
EXTI_InitStructure.EXTI_Line = EXTI_Line3; //指定中斷線3
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中斷線
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中斷模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發方式,必須的,上升沿不靈敏
EXTI_Init(&EXTI_InitStructure);
1.5.中斷分組和優先級設置
NVIC_InitTypeDef NVIC_InitStructure; //優先級初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置中斷分組為2:2,優先級范圍0-3
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //指定中斷線3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占優先級0,可以設置0-3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應優先級0,可以設置0-3
NVIC_Init(&NVIC_InitStructure);
2.中斷服務函數
中斷初始化完畢后,就可以編寫相應的中斷服務函數了,我們使用的是中斷線3,所以對應的中斷服務函數名稱為void EXTI3_IRQHandler(void),注意在執行完后要將標志位清零,
void EXTI3_IRQHandler(void) //中斷線3服務函數,發生中斷時,自動執行
{
delay_ms(10); //消抖,很有必要,增加識別的准確度
if(KEY1 == 0) //用EXTI_GetITStatus(EXTI_Line3)!=RESET來判斷不是很靈敏,快速按時不准確
LED0 = !LED0;
EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中斷標志位,以備下一次使用
}
根據手冊可以通過EXTI_GetITStatus(EXTI_Line3)來判斷中斷標志位的狀態,實際運行時發現這種方式並不是很有效,可能是我的用法不對吧!
這個中斷服務函數還是很簡單的,就是按下按鍵時,將LED的狀態反轉
3.主函數
主函數的執行部分可以不寫,這里寫了 LED 的閃爍用來指示程序的運行
int main(void)
{
delay_init(168);
LED_Init();
IT_Init(); //中斷初始化
LED0_OFF;
LED1_OFF;
while(1)
{
LED1_ON;
delay_ms(500); //LED1閃爍提醒程序運行狀態
LED1_OFF;
delay_ms(500);
}
}
總結:
從以上過程可以看出STM32F4的外部中斷的配置和使用方法還是很簡單清晰的。雖然比51要復雜一些,但是畢竟功能那么強大,復雜一些也是可以理解的。
參考資料:
STM32F4xx中文參考手冊
STM32F4開發指南-庫函數版本_V1.1
以上是我學習過程的一些個人理解,有不對或不准確的地方,歡迎各位大神指正。
2017年4月17日22:01:43
歡迎大家關注我的個人博客
微信掃碼關注我的公眾號

不定期更新個人學習筆記和技術總結,歡迎大家互相學習交流!
