1. 按鍵如何觸發(fā)中斷 我們用 Keil 打開下面這個(gè)工程: STM32Cube_FW_F0_V1.11.0ProjectsSTM32F030R8-NucleoExamplesGPIOGPIO_EXTIMDK-ARMProject.uvprojx 編譯下載運(yùn)行此代碼,然后按壓 B1 USER 這個(gè)按鍵,每一次按壓會(huì)觸發(fā)板上一個(gè)LED燈翻轉(zhuǎn)一次。這個(gè)功能也很簡單,但它牽涉到的東西卻不少??匆幌麓a: 上一篇文章講了如何翻轉(zhuǎn)GPIO引腳,所以現(xiàn)在我們只關(guān)注一下如何用一個(gè)引腳觸發(fā)中斷吧。main()函數(shù)里調(diào)用了一個(gè)外部中斷模塊(EXTI)初始化后就進(jìn)入while循環(huán)了。 我們在下面可以找到這個(gè)初始化函數(shù)的實(shí)現(xiàn)。它調(diào)用HAL庫函數(shù)對(duì)按鍵連接的引腳PC13做了初始化,把此引腳初始化為能觸發(fā)中斷的模式。 初始化函數(shù)的下面是一個(gè)回調(diào)函數(shù)(Callback Function)。在此函數(shù)中翻轉(zhuǎn)了連接LED的引腳。我們接下來分別講一下這個(gè)回調(diào)函數(shù)和如何把一個(gè)GPIO引腳初始化為中斷模式。 2. 回調(diào)函數(shù) 回調(diào)函數(shù)這個(gè)概念,解釋可以說五花八門,什么原因呢?因?yàn)檫@好像不是一句自然(人)語言(話)。咱們還是打個(gè)比方好理解一些。 好比你在廚房做菜,突然發(fā)現(xiàn)醬油沒了。你叫你兒子去給你打醬油,兒子就是你的驅(qū)動(dòng)。兒子聽到你的召喚,說:行啊,老爸,但你得先給我點(diǎn)錢??!你看,兒子這就是回調(diào)(Callback)。一會(huì)兒兒子打醬油回來了,然后把醬油交給你,這也是回調(diào)。 那我們回到程序,看一下應(yīng)用程序(Application),驅(qū)動(dòng)(Driver)和回調(diào)函數(shù)(Callback Function)是什么關(guān)系。如果應(yīng)用程序調(diào)用一個(gè)驅(qū)動(dòng),這個(gè)驅(qū)動(dòng)在執(zhí)行前先調(diào)用一個(gè)函數(shù)來獲取一些參數(shù),而這些參數(shù)需要由應(yīng)用程序提供,所以此函數(shù)位于應(yīng)用層,它就是一個(gè)回調(diào)函數(shù)。還有一種情況就是驅(qū)動(dòng)執(zhí)行完畢,通過調(diào)用應(yīng)用層的一個(gè)函數(shù)返回結(jié)果,或通知應(yīng)用層執(zhí)行完畢,此函數(shù)也是回調(diào)函數(shù)。 下面就是從中斷發(fā)生,一直到應(yīng)用層的回調(diào)路徑: HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) <-main.c 那么如何才能讓PC13觸發(fā)這個(gè)中斷呢? 3. GPIO中斷引腳配置 MCU是如何把一個(gè)引腳電平的變化和一個(gè)中斷聯(lián)系起來的呢?我們馬上想到給每個(gè)GPIO引腳分配一個(gè)中斷向量就好了。當(dāng)一個(gè)引腳電平變化,馬上就可以跳轉(zhuǎn)到自己對(duì)應(yīng)的中斷服務(wù)程序。這確實(shí)是最簡單的辦法,但MCU一般都有幾十個(gè)引腳,如果這樣做像M0這種內(nèi)核只支持32個(gè)外部中斷,根本就不夠用的。所以我們看STM32F030僅支持16個(gè)外部中斷,又在中斷向量表中進(jìn)一步縮減為3個(gè)中斷向量。 外部中斷0至15 0,1對(duì)應(yīng)一個(gè)中斷向量(5號(hào)中斷); 2,3對(duì)應(yīng)一個(gè)(6號(hào)中斷); STM32F030的16個(gè)外部中斷是如何對(duì)應(yīng)到各個(gè)引腳上的呢? 這就要通過 EXTI (Extended interrupts and events controller)這個(gè)模塊。它除了可以完成中斷引腳的選擇(映射),還可以配置是上升沿還是下降沿觸發(fā),也可以屏蔽(Mask)某個(gè)引腳。下面的示意圖簡要的顯示了這種關(guān)系。 大家注意,圖中這些模塊雖然都在一個(gè)芯片內(nèi),但是EXTI是芯片級(jí)模塊,NVIC是在M0內(nèi)核之中。 相關(guān)寄存器介紹: 一共有4個(gè)這樣的寄存器: SYSCFG_EXTICR1,SYSCFG_EXTICR2,SYSCFG_EXTICR3,SYSCFG_EXTICR4 EXTI_IMR (Interrupt mask register) 0: 屏蔽所對(duì)應(yīng)的中斷。1: 允許對(duì)應(yīng)中斷。 EXTI_RTSR (Rising trigger selection register) EXTI_FTSR (Falling trigger selection register) 如果上升沿和下降沿都設(shè)置為1,那么在上升沿和下降沿都會(huì)觸發(fā)中斷。 EXTI_PR (Pending register) 當(dāng)中斷發(fā)生使此寄存器某一位被置1后,在此位寫入1可以清除此標(biāo)志位。 現(xiàn)在大家再返回去,理解代碼就會(huì)容易一些了。 參考資料: PM0215 STM32F0xxx Cortex-M0 programming manual UM1785 Description of STM32F0 HAL and low-layer drivers STM32F030 Datasheet STM32F030 Reference Manual |
|