凡從事過ST MCU應(yīng)用開發(fā)的人往往會遇到事件、中斷事件 中斷三個概念或術(shù)語。這三個概念彼此關(guān)聯(lián),有時會讓人有點混淆或犯迷糊。 先拿一件生活中的事情打比方對上述三個概念做個基本的粗略理解,之后再分享一個STM32 GPIO外部中斷配置案例。 比如一老師在教室里給學(xué)生們上課。課堂上的學(xué)生可能做出各種行為動作,比方做筆記、打哈氣、翻書包、講小話等,我們把這些行為統(tǒng)稱為事件,其中有些行為老師往往只是視而不見,繼續(xù)他的上課;而有些行為可能導(dǎo)致老師的上課中止,比方講小話,并對學(xué)生的相關(guān)行為予以警告、批評或糾正等,然后繼續(xù)上課。我們把老師因為學(xué)生的某些行為而中止授課,并產(chǎn)生后續(xù)動作,之后接著上課的這個過程理解為中斷或中斷響應(yīng)。我們把可能導(dǎo)致老師上課中斷的學(xué)生行為理解為中斷事件。
結(jié)合上面的比方,不難理解中斷事件是一種可以導(dǎo)致中斷發(fā)生的事件,中斷則是因為中斷事件的發(fā)生而導(dǎo)致的后續(xù)行為過程。事件與中斷事件是包含關(guān)系,即事件可分為中斷事件或非中斷事件。而中斷事件與中斷之間屬于前后關(guān)聯(lián)的因果關(guān)系,雖有關(guān)聯(lián),但二者在時序上、行為上并不一樣。
結(jié)合具體的ST MCU運行過程,其中會有許多各種各樣的事件,比方管腳電平變化、計數(shù)器溢出、DMA空、FIFO非空、AD轉(zhuǎn)換結(jié)束、超時、外設(shè)使能、初始化等等,其中有些事件是不會導(dǎo)致中斷產(chǎn)生的,比方外設(shè)使能或部分初始化動作是不會導(dǎo)致中斷發(fā)生的,有些事件就可能導(dǎo)致中斷發(fā)生,比方計數(shù)器溢出,AD轉(zhuǎn)換結(jié)束等,這些就是中斷事件。當然這些中斷事件最終能否觸發(fā)后續(xù)中斷,得看是否開啟了該中斷事件的中斷使能,相關(guān)中斷矢量控制器【NVIC】是否配置,最終讓CPU內(nèi)核參與進來,并完成后續(xù)的中斷服務(wù)動作。
不妨借助STM32 MCU的GPIO的外部事件與中斷控制器的框圖來理解上述概念。
從上圖可以看出,不論外部電平變化成為中斷事件還是非中斷事件,綠色方框部分都是一樣的,即具有相同的觸發(fā)源。差別就在后面。一般性事件要變?yōu)橹袛嗍录?,得有相關(guān)中斷使能位的允許。中斷事件再向CPU激活相關(guān)中斷請求,在NVIC配置相應(yīng)中斷矢量后,CPU便參與進行后續(xù)的中斷響應(yīng)服務(wù)【如保存現(xiàn)場、執(zhí)行中斷服務(wù)程序、恢復(fù)現(xiàn)場并返回】,而非中斷事件就沒有中斷事件后續(xù)的流程,只是有些硬件觸發(fā)信號或標志的產(chǎn)生。當然非中斷事件的形成也是可控的。
既然一個可以觸發(fā)中斷的事件可能被配置中斷事件或非中斷事件,那么在相關(guān)事件的觸發(fā)配置時就出現(xiàn)兩種可能,即允許產(chǎn)生中斷或禁止產(chǎn)生中斷。于是乎,ST MCU參考手冊里在談到事件的觸發(fā)方式時就引出了事件模式和中斷模式兩個概念。
比方STM32的GPIO口的電平跳變基本都是可以觸發(fā)外部中斷的。但在具體配置時,可以根據(jù)需要來決定啟用還是禁用相關(guān)腳的中斷功能,從而選擇不同的事件觸發(fā)方式,即事件模式和中斷模式。如果不希望電平跳變事件觸發(fā)中斷,就配置為事件模式,反之,配置為中斷模式。
好,我們一起來看看一個具體的案例。 某工程師做了一塊STM32F407的工程樣板,利用ST官方推出的STM32配置工具STM32CubeMx做MCU基本管腳和外設(shè)的軟硬件配置并生成相關(guān)代碼。令他郁悶的是,竟然在做某GPIO做按鍵中斷時卡殼了,發(fā)現(xiàn)不論怎么按鍵就是不進中斷程序。
經(jīng)溝通了解,他用到的的那個GPIO是個很普通的腳,并非什么特別功能腳。按鍵電路也很常規(guī)簡單。順便看了下的相關(guān)配置代碼??吹狡銰PIO初始化代碼時,發(fā)現(xiàn)有關(guān)GPIO模式的地方有問題,也就是如下紅色標注的代碼行的地方。
void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */ __GPIOE_CLK_ENABLE();
/*Configure GPIO pin : PE2 */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_EVT_FALLING; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* EXTI interrupt init*/ HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI2_IRQn);
} 紅色語句代碼是將該GPIO配置為下降沿觸發(fā)的事件模式了,而不是中斷模式。在利用STM32CubeMx對GPIO管腳進行模式配置時往往有很多選項,這些選項又可分為2大類。分別是中斷模式和事件模式?!緄nterrupt mode / event mode】
既然配置成了事件模式,按鍵自然沒法觸發(fā)中斷及相關(guān)服務(wù)程序。讓其修改為中斷模式,即將上面配置修改為下面語句后即OK. GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
在STM32相關(guān)參考手冊里,涉及中斷【INTERRUPT】和事件【EVENT】二詞表述的地方比較多,加上這兩個詞的含義比較寬泛。手冊里可能會用interrupt或interrupt event表述同一東西,或者說interrup泛指中斷事件及后續(xù)中斷響應(yīng)全過程。比方類似下面語句的地方:
有時用Interrupt event明確出來。比方下面表格中提到interrupt event.
|
|
來自: rookie > 《技術(shù)帖》