一、什么是中斷
首先介紹一下什么是中斷。在實(shí)際開發(fā)過程中,中斷是很有必要的。比如需要針對某種特殊情況進(jìn)行快速響應(yīng),單純的使用一個while輪詢似乎并不能滿足。中斷的概念非常好理解,舉個經(jīng)典例子。比如你在家里看電視,忽然有人敲門,你臨時把電視暫停了,轉(zhuǎn)去開門。開完門之后再次回來繼續(xù)看電視。
中斷也就是這種流程??措娨暤男袨榫皖愃朴诔绦蛑衜ain函數(shù)的while,輪詢執(zhí)行業(yè)務(wù)。忽然有人敲門,對應(yīng)程序運(yùn)行過程中忽然產(chǎn)生了一個中斷請求。此時暫停電視,對應(yīng)于此時程序中斷當(dāng)前的業(yè)務(wù),轉(zhuǎn)而去處理中斷業(yè)務(wù)(開門)。最后,中斷業(yè)務(wù)處理完成后,再繼續(xù)執(zhí)行main函數(shù)while輪詢中的業(yè)務(wù)。簡單用一個圖來表示一下
中斷概念示意圖
根據(jù)中文參考手冊的介紹,STM32F103ZET6除了一些特殊的中斷外,常用的中斷有60個,這些中斷是通過中斷控制器來有條不紊地分配執(zhí)行的。
二、中斷的相關(guān)概念
2.1 中斷優(yōu)先級
從字面意思來講,優(yōu)先級用來區(qū)分中斷的響應(yīng)順序。當(dāng)同時接收到多個中斷請求時,中斷控制器會根據(jù)中斷優(yōu)先級來決定中斷處理的順序,優(yōu)先級高的會先被處理。如果在處理某個中斷請求時又來了一個中斷,這時會根據(jù)兩個中斷的中斷優(yōu)先級來確定處理方式。
如果新來的中斷優(yōu)先級比當(dāng)前中斷的優(yōu)先級高,則會停止對當(dāng)前中斷的處理,轉(zhuǎn)而處理新的中斷。反之,如果新來的中斷優(yōu)先級比當(dāng)前中斷的優(yōu)先級低,則需要等到當(dāng)前中斷處理完成后,再去處理新來的中斷。
中斷優(yōu)先級有兩種,一種是搶占優(yōu)先級,一種是響應(yīng)優(yōu)先級。響應(yīng)優(yōu)先級通常又被稱為“亞優(yōu)先級”或者“副優(yōu)先級”。當(dāng)兩個中斷的搶占優(yōu)先級相同時,用相應(yīng)優(yōu)先級來決定中斷的處理順序。
如果兩個中斷的搶占優(yōu)先級和相應(yīng)優(yōu)先級相同,則根據(jù)芯片手冊中的中斷向量號來決定中斷的處理順序。比如同時來了兩個中斷請求,在搶占優(yōu)先級和響應(yīng)優(yōu)先級均相同時,中斷向量號為41的中斷會比中斷向量號為42的中斷先被處理。
STM32提供了16個可編程的優(yōu)先等級(使用了4位中斷優(yōu)先級),優(yōu)先級分組可以使用庫函數(shù)提供的NVIC_PriorityGroupConfig()
設(shè)置。
2.2 中斷嵌套
一些低優(yōu)先級的中斷可以被高優(yōu)先級中斷打斷,這種情況叫做中斷嵌套。
2.3 中斷服務(wù)函數(shù)
中斷服務(wù)函數(shù)就是在進(jìn)入中斷后需要執(zhí)行的內(nèi)容。
中斷服務(wù)函數(shù)有特定的函數(shù)名,可以在下圖文件中搜索“IRQ”找到。
中斷服務(wù)函數(shù)名
2.4 中斷標(biāo)志位
不同的中斷會有對應(yīng)的中斷標(biāo)志位,通常標(biāo)志位默認(rèn)值為0。當(dāng)產(chǎn)生中斷請求時,標(biāo)志位被置1。比如設(shè)置一個串口接收完成中斷,串口接收完成標(biāo)志位初始值為0。當(dāng)串口接收完成后對應(yīng)的串口接收完成標(biāo)志位會被置1。
在中斷服務(wù)函數(shù)中檢測該標(biāo)志位的值,來確定是否是串口接收完成中斷產(chǎn)生了。每次中斷服務(wù)函數(shù)執(zhí)行結(jié)束后,需要清除一下對應(yīng)的中斷標(biāo)志位。
三、外部中斷EXIT
STM32F103ZET6有一個外部中斷控制器(EXIT),可以支持20個軟件的中斷/事件請求,其中外部中斷的EXIT0~EXIT15同坐IO中斷。
外部中斷IO對應(yīng)
其他詳細(xì)的介紹這里就不再說明。
四、中斷程序配置
這里以配置PA0(按鍵WK UP)的外部中斷為例,展示一下庫函數(shù)開發(fā)時,外部中斷的配置流程。關(guān)于其他中斷的配置,后續(xù)使用其他外設(shè)時會單獨(dú)介紹。
想要實(shí)現(xiàn)的效果是,利用外部中斷實(shí)現(xiàn)按下WK UP,LED1點(diǎn)亮。
4.1 設(shè)置中斷分組并使能中斷
這里使用外部中斷,需要開啟AFIO時鐘,設(shè)置IO與外部中斷線的映射關(guān)系。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 開啟AFIO時鐘
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //選擇GPIO管腳用作外部中斷線路
設(shè)置中斷分組并使能中斷時,庫函數(shù)提供了一個結(jié)構(gòu)體,我們直接配置這個結(jié)構(gòu)體就可以了。
//EXTI0 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //EXTI0中斷通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; //搶占優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
需要注意的是,配置優(yōu)先級時,數(shù)值越大,優(yōu)先級越低。
4.2 初始化EXIT
初始化EXIT時,庫函數(shù)也提供了一個結(jié)構(gòu)體,其中包括中斷線,EXIT模式,觸發(fā)方式以及EXIT使能或者失能。由按鍵檢測一節(jié)了解到,WK UP按下時,會產(chǎn)生一個上升沿。因此觸發(fā)方式我們選擇上升沿觸發(fā)。
EXTI_InitStructure.EXTI_Line=EXTI_Line0; // EXIT0
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; // 中斷
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising; // 上升沿觸發(fā)
EXTI_InitStructure.EXTI_LineCmd=ENABLE; // 使能
EXTI_Init(&EXTI_InitStructure);
整體配置函數(shù)如下
/*
*==============================================================================
*函數(shù)名稱:Exit_Init
*函數(shù)功能:初始化外部中斷
*輸入?yún)?shù):無
*返回值:無
*備 注:無
*==============================================================================
*/
void Exit_Init (void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 開啟AFIO時鐘
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //選擇GPIO管腳用作外部中斷線路
//EXTI0 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //EXTI0中斷通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; //搶占優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
EXTI_InitStructure.EXTI_Line=EXTI_Line0; // EXIT0
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; // 中斷
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising; // 上升沿觸發(fā)
EXTI_InitStructure.EXTI_LineCmd=ENABLE; // 使能
EXTI_Init(&EXTI_InitStructure);
}
4.3 編寫中斷服務(wù)函數(shù)
上面介紹了如何找中斷服務(wù)函數(shù)的函數(shù)名,這里直接開始寫中斷服務(wù)函數(shù)。這里的中斷服務(wù)函數(shù)比較簡單,直接點(diǎn)亮LED1即可。
/*
*==============================================================================
*函數(shù)名稱:EXTI0_IRQHandler
*函數(shù)功能:外部中斷0中斷服務(wù)函數(shù)
*輸入?yún)?shù):無
*返回值:無
*備 注:無
*==============================================================================
*/
void EXTI0_IRQHandler(void)
{
// 如果EXIT0中斷標(biāo)志位被置1
if(EXTI_GetITStatus (EXTI_Line0)==1)
{
Med_Led_StateCtrl (LED1,LED_ON); // 點(diǎn)亮LED1
}
EXTI_ClearITPendingBit (EXTI_Line0); // 清除中斷標(biāo)志位
}
至此,按下WK UP后,LED1會點(diǎn)亮。這種方法與之前的按鍵點(diǎn)亮LED有什么區(qū)別?之前的按鍵點(diǎn)亮LED是在main函數(shù)的while中實(shí)現(xiàn)的,而利用外部中斷的方法,是在外部中斷的中斷服務(wù)函數(shù)中實(shí)現(xiàn)的。即使main函數(shù)的while輪詢業(yè)務(wù)中沒有按鍵業(yè)務(wù),按鍵依舊可以起作用。
五、注意事項
- ? 中斷服務(wù)函數(shù)無需在.h文件中聲明
- ? 中斷服務(wù)函數(shù)中不要有過長的業(yè)務(wù)
- ? 中斷服務(wù)函數(shù)最后需要清除中斷標(biāo)志位
-
GPIO
+關(guān)注
關(guān)注
16文章
1189瀏覽量
51850 -
中斷控制器
+關(guān)注
關(guān)注
0文章
59瀏覽量
9432 -
串口中斷
+關(guān)注
關(guān)注
0文章
64瀏覽量
13848 -
STM32F103ZET6
+關(guān)注
關(guān)注
9文章
67瀏覽量
21069 -
AFIO
+關(guān)注
關(guān)注
0文章
6瀏覽量
2939
發(fā)布評論請先 登錄
相關(guān)推薦
評論