1、目的
本篇學習筆記我們主要來了解ME32F030的中斷系統(tǒng),首先通過對ME32F030終端系統(tǒng)和中斷控制存器進行學習,最后通過實際的GPIO端口中斷實例掌握中斷函數(shù)的編程實現(xiàn)來加深掌握ME32F030中斷系統(tǒng)的編程方法。
2、ME32F030中斷概述
中斷是單片機系統(tǒng)重要的組成部分,使單片機能夠快速的對事件請求做出響應。ME32F030靠內(nèi)部的嵌套向量中斷控制器(NVIC)來進行中斷的調(diào)度,它是 Cortex?-M0 內(nèi)核的一部分。它可以讓 CPU 以最短的時間對中斷作出反應。主要的特征有:
? 較短的中斷響應延遲.
? 處理系統(tǒng)異常和外設(shè)中斷.
? 支持 32 個中斷向量.
? 四種可編程的中斷響應優(yōu)先級別.
? 產(chǎn)生軟件中斷.
? 可配置的不可屏蔽中斷源會有詳細的說明。
3、ME32F030嵌套向量中斷控制器(NVIC)
嵌套向量中斷控制器(NVIC)負責著整個MCU的中斷管理,除了管理我們常用的外設(shè)中斷源,還包括非屏蔽中斷源的管理。具體管理的中斷源及其中斷序號,其實在CMSDK_CM0.h中定義好了,通過程序定義對具體管理的中斷源一目了然,定義的內(nèi)容如下圖所示。
中斷源
ME32F030的中斷系統(tǒng)是由一系列的NVIC寄存器組成的,這些寄存器可用于中斷 IRQ0~IRQ31, 包括中斷使能,等待和優(yōu)先級等操作。如果中斷被允許,并且相應中斷掛起被設(shè)置,NVIC 將會根據(jù)中斷優(yōu)先級觸發(fā)中斷。反之,中斷被禁止,中斷源只會改變中斷掛起狀態(tài),而 NVIC 不會對中斷源信號采取任何動作,不論任何中斷優(yōu)先級。具體的NVIC寄存器組如表格所示:
NVIC寄存器列表
2-1 中斷允許寄存器
中斷允許寄存器(ISER)用于使能中斷設(shè)置,同時可返回當前允許中斷設(shè)置。需要注意的是,對該寄存器寫0是無效的,是不能禁止中斷的。要禁止中斷,就需要下面介紹的中斷禁止寄存器。
2-2 中斷禁止寄存器
有使能中斷的設(shè)置,相應的就會有禁止中斷設(shè)置,這就是中斷禁止寄存器的作用。對寄存器進行寫1操作,就可以禁止中斷設(shè)置。。需要注意的是,對該寄存器寫0是無效的。對寄存器進行讀操作,同返回當前禁止中斷設(shè)置。
2-3 中斷掛起寄存器
當有中斷事件發(fā)生時,中斷掛起寄存器(ISPR)中對應的中斷位就會置位 。此時讀取寄存器就可以判斷具體的中斷源。同時我們也可以向寄存器的中斷位寫1,來強制中斷進入掛起狀態(tài)。
2-4 清除中斷掛起寄存器
當MCU響應了中斷請求,并且執(zhí)行完對應的中斷子程序后,MCU便會返回斷點處繼續(xù)運行。但在返回前需要通過清除中斷掛起寄存器(ICPR),來清除對應的中斷掛起,這樣當次的中斷流程算是完整結(jié)束。
2-5 中斷優(yōu)先級寄存器
如同我們做事情有輕重緩急之分,單片機對中斷的處理也有“輕重緩急”。具體就是靠8組中斷優(yōu)先級寄存器IPR0~7來實現(xiàn)。每組寄存器對應4個中斷源的優(yōu)先級。這樣剛好決定了中斷0~中斷31的優(yōu)先級。
每一組的中斷優(yōu)先級寄存器IPRn的每個字節(jié)最高兩位決定優(yōu)先級,因此有0~3共4個優(yōu)先級可以選擇,越低的值表示優(yōu)先級越高,當優(yōu)先級更高的中斷發(fā)生時,高優(yōu)先級的中斷會打斷低優(yōu)先級中斷。如果是同優(yōu)先級中斷,則并不會打斷當前中斷,而是依次響應中斷。中斷優(yōu)先級寄存器IPRn如圖所示:
這里介紹個快速的方法來計算中斷 M 的 IPR 寄存器號:
? 計算對應的 IPR 寄存器號, N, N = M / 4
? 計算 IPR 寄存器內(nèi)的字節(jié)偏移量 M % 4, 其中:
– 字節(jié)偏移量 0 對應寄存器的位 7:0
– 字節(jié)偏移量 1 對應寄存器的位 15:8
– 字節(jié)偏移量 2 對應寄存器的位 23:16
– 字節(jié)偏移量 3 對應寄存器的位 31:24
4、ME32F030端口中斷例程
本篇中我們首先講解了ME32F030的GPIO中斷系統(tǒng),然后又介紹了嵌套向量中斷控制器(NVIC)的原理。
最后,我們還是要通過具體的實例來把我們學到的理論知識應用到實際的例子中。我們將兩者結(jié)合起來做個小實驗,測試程序的代碼如下:
unsignedintuiCnt=0;//端口反轉(zhuǎn)次數(shù) intmain(void) { PA->DIR_b.DIR0=1;//PA_0設(shè)置為輸出口 PA->IS_b.ISENSE0=0;//PA_0設(shè)置為沿觸發(fā) PA->IBE_b.IBE0=1;//PA_0上升沿和下降沿都觸發(fā)中斷 PA->IC_b.CLR0=1;//PA_0中斷標志位清除 PA->IE_b.MASK0=1;//PA_0中斷使能 PB->DIR_b.DIR9=1;//PB_9設(shè)置為輸出口 NVIC_EnableIRQ(PA_IRQn);//使能PA_IRQ中斷 lcd_init();//LCD液晶初始化 while(1) { uiCnt++;//端口反轉(zhuǎn)次數(shù)加1 PA->NOT_b.NOT0=1;//PA_0輸出取反 SYS_DelaymS(500); if(uiCnt==20)//當反轉(zhuǎn)20次時 { PA->IE_b.MASK0=0;//PA_0中斷關(guān)閉 } } } //PA_IRQ中斷子程序 voidPA_IRQHandler(void) { PB->NOT_b.NOT9=1;//PB_9(LED燈)輸出取反 PA->IC_b.CLR0=1;//清除PA_0中斷位 //LCD顯示中斷發(fā)生的次數(shù) LCD->MEMMAP1=lcd[uiCnt/10]|(lcd[uiCnt%10]<<16); }
測試程序是通過PA_0端口輸出反轉(zhuǎn),來產(chǎn)生下降沿和上升沿。但同時它的端口中斷功能是被使能的,因此可以通過輸出電平來“觸發(fā)”自己的中斷。在中斷服務子程序中,LED小燈端口輸出取反來進行點亮和熄滅,同時加入了LCD段碼液晶來顯示中斷發(fā)生的次數(shù)。在程序全速運行的過程中,當端口輸出反轉(zhuǎn)20次之后,會關(guān)閉端口的中斷功能。接下來下載并仿真例程來進行說明。
程序下載并仿真后,先在程序這兩處打上斷點。然后用快捷鍵F5全速運行,程序首先會運行到第78行處的斷點,這時端口還沒有進行輸出反轉(zhuǎn)。接下來用快捷鍵F10單步運行觀察。
仿真1
F10單步運行后,發(fā)現(xiàn)程序已經(jīng)跳轉(zhuǎn)到了PA_IRQ中斷服務子程序中,繼續(xù)F10單步運行并觀察執(zhí)行每一步的現(xiàn)象,直到把中斷服務子程序走完。
仿真2
中斷服務子程序內(nèi)的代碼全部運行后的效果如圖所示,首先LED小燈的端口輸出取反,把LED小燈給點亮后(下次再進中斷會輸出取反熄滅,依次往復)。LCD段碼液晶顯示01,這說明發(fā)生了1次中斷。
仿真結(jié)果
通過單步仿真我們清楚了中斷發(fā)生后的處理流程,接下來就可以把之前打的兩個斷點取消掉,然后在83行的位置打上一個斷點,隨后F5全速運行程序,等待程序停到斷點處。在等待的過程中,LED小燈保持閃爍,LCD段碼液晶上的數(shù)字一直在自加。當程序停到斷點處后,LCD段碼液晶顯示為20。繼續(xù)單步運行后,端口PA_0的中斷功能就被關(guān)閉了。
仿真3
關(guān)閉中斷后,再次全速運行程序。我們發(fā)現(xiàn)小燈不再閃爍了,段碼液晶顯示的數(shù)字也不再自加。這是因為我們已經(jīng)把端口中斷關(guān)閉掉了,雖然uiCnt還在自加。但是已經(jīng)進不了中斷子程序去更新顯示。因此依舊停留顯示在20。我們不妨把uiCnt添加到Watch窗口中來看一下,添加方法如圖所示。雙擊ucCnt變量名,選中后右鍵選擇“Add uiCnt to”,“Watch 1”,這樣就添加到Watch1窗口中了。
仿真4
通過Watch1窗口看到端口已經(jīng)反轉(zhuǎn)37次了,但LCD液晶已經(jīng)停留在20。這也說明中斷確實被關(guān)閉了,因此液晶一直沒能更新顯示。
仿真5
仿真結(jié)果2
來源:敏矽MCU
-
控制器
+關(guān)注
關(guān)注
112文章
16361瀏覽量
178046 -
端口
+關(guān)注
關(guān)注
4文章
964瀏覽量
32079 -
Cortex-M0
+關(guān)注
關(guān)注
4文章
124瀏覽量
38692 -
外部中斷
+關(guān)注
關(guān)注
1文章
131瀏覽量
15824
發(fā)布評論請先 登錄
相關(guān)推薦
評論