關於MSP430中斷機制

中斷很大程度上體現了一款單片機的性能,從這一點將MSP430在中斷方面做得很不錯,主要是提供了非常豐富的中斷源,基本的有IO中斷,定時器中斷和一些接口中斷(SPI,UART,I2C)等等。
    現在我就談談關於MSP430中斷的一些特性,主要是在項目經歷中感覺比較有用的問題,跟大家分享下。
    第一,MSP430中斷的優先級。
    MSP430支持中斷優先級,但是優先級的高低怎麼獲知呢?它的用手手冊上有個很有意思的說法,我原文引用過來“The nearer a module is to the CPU/NMIRS, the higher the priority”,翻譯過來就是說離CPU/NMIRS越近,優先級就越高。那我們怎麼知道那個模塊離CPU近啊,看datasheet給的框圖?總覺得這不可能讓一個做電子的人放心,比如框圖在中距CPU一樣進,那怎麼區分呢?所以我們有另外一個更可靠的辦法,IAR爲每一款型號的430都提供了對應的頭問題,只靠看中斷向量地址就可以知道了。430的中斷向量表從地址值0xFFC0開始至0XFFFF結束,一共有32個表項(每個中斷向量對應2byte),0XFFCO對應的中斷向量的優先級是最頂的,0XFFFE對應的中斷向量的優先級是最高的,也就是從0xFFCO開始至0xFFFF,32箇中斷優先級由低至高。這樣就很容易弄清楚各中斷的優先級了。
  第二,MSP430中斷的響應過程。
  首先,當然是中斷髮生對應的標誌爲置1。這個時候的過程我詳述下,其實是翻譯的用戶手冊但是還是瞭解下好。
1.CPU會執行完當期的指令。
2.指向下一條指令的PC被壓棧。
3.狀態寄存器SR壓棧。
4.選擇最好優先級的中斷進行服務。
5.單源中斷的中斷標誌位會被自動清零,這個地方需要小心下P1,P2這樣的中斷標誌位不會自動清零,因爲P1、P2的IO中斷屬於多源中斷,就是說P1或者P2的8個IO對應到了一箇中斷向量上,單片機知道是P1或者P2發生了中斷,無論是P1的哪一個IO發生的都會指向P1的中斷向量,P2也是一樣的,所以需要在代碼中手動清零。6.狀態寄存器SR被清零,將會終止任何低功耗狀態,並且全局中斷使能被關閉(GIE)。這個地方與51很是有些不同,430響應了中斷後會關閉全局中斷使能,不會響應任何其他的中斷包括優先級高的,就是說默認狀態下是沒有中斷嵌套的,若用到中斷嵌套的話需要使用_EINT()打開全局中斷。
7.中斷向量被裝載到PC,開始執行中斷服務函數。


以上是整個中斷的接收過程,比較重要的地方我用彩色字體標出了。


    中斷返回就相對簡單些,中斷服務函數會由RETI這條指令返回,SR被彈出,單片機恢復到中斷前的狀態,PC也被彈出,繼續執行指令。


    第三,開中斷和中斷服務函數。
    這個是讓我在項目中糾結過的地方,也請各位小心。
    MSP430一旦開了外設的中斷,比如SPI的接收中斷。
    在SPI的接收中斷被使能,單片機一旦發現SPI接收標誌置位,就會裝載中斷向量,但是我們如果沒有用到SPI的接收中斷,會怎樣呢?由於沒用到,所有就沒有寫SPI接收中斷的服務函數,此時中斷向量裏指向中斷服務函數地址值是啥?是全0。CPU從0-01FFh取指令,只會發生一件事。PUC,上電清零。接着PC會裝載0xFFFE中斷向量的內容,也就是復位向量,程序會跳轉到給IAR我們做的啓動代碼。程序再往下執行會執行到我們編寫的代碼的main()的第一句。這樣悲劇就誕生了,蕩機了!!!!


   所以我在這希望初學430的朋友對於中斷,未使用的就不要使能。使能的就一定要寫中斷服務函數,哪怕是空函數!

1.中斷嵌套,優先級 

430總中斷的控制位是狀態寄存器內的GIE位(該位在SR寄存器內),該位在復位狀態下,所有的可屏蔽中斷都不會發生響應。可屏蔽中斷又分爲單中斷源和多中斷源的。單中斷源的一般響應了中斷服務程序中斷標誌位就自動清零,而多中斷源的則要求查詢某個寄存器後中斷標誌位纔會清零。由於大多數人接觸的第一款單片機通常是51,51單片機CPU在響應低優先級的中斷程序過程中若有更高優先級的中斷髮生,單片機就會去執行高優先級,這個過程已經產生了中斷嵌套。而430單片機則不同,如果在響應低優先級中斷服務程序的時候,即使來了更高優先級的中斷服務請求,430也會置之不理,直至低優先級中斷服務程序執行完畢,纔會去響應高優先級中斷。這是因爲430在響應中斷程序的時候,總中斷GIE是復位狀態的,如果要產生類似51的中斷嵌套,只能在中斷函數內再次置位GIE位。 

2.定時器TA 
TimerA有2箇中斷向量。TIMERA0,TIMERA1 
TIMERA0只針對CCR0的計數溢出 
TIMERA1再查詢TAIV後可知道是CCR1,還是CCR2,亦或TAIFG引起的,至於TAIFG是什麼情況下置位的,則要看TA工作的模式 
具體看用戶手冊。還有一點TA本身有PWM輸出功能,無須借用中斷功能。在這個問題上經常出現應用彎路的是如何結合TA和AD實行定時採樣的問題,很多人都是在TA中斷裏打開AD這樣來做。這是不適宜的,因爲430 的ADC10,ADC12(SD16不熟悉,沒發言權)模塊均有脈衝採樣模式和擴展采樣模式。只要選擇AD是由TA觸發採樣,然後把TA設置成PWM輸出模式,當然輸出PWM波的都是特殊功能腳,但是在這裏它是不需要輸出的,所以引腳設置不必理會。值得關心的就是PWM的頻率,也就是你AD的採樣率。 

3.看門狗復位 
看門狗有2種工作模式:定時器 ,看門狗 
定時器工作模式下WDTIFG在響應中斷服務程序有標誌位自動復位,而在看門狗模式下,該標誌位只能軟件清零。但是怎麼判斷復位是由於WDT工作在看門狗模式下的定時溢出引起的,還是看門狗寫密鑰錯誤引起的呢?……………………………… 
答案是沒有方法,至少我沒見過有什麼方法,也沒見過周邊的人有什麼方法。若有人知道方法謝謝分享。 
4.經常有人會問這個語句的MOV.B  #LPM0,0(SP)的作用。假如你在進入中斷函數之前,430是在LPM0下待機,若要求執行完中斷函數之後進入LPM3待機,在中斷函數裏寫MOV.B  #LPM3,SR是無效的。因爲在進入中斷時430會把PC,SR壓棧,( SR內保存着低功耗模式的設置)即使你寫了MOV.B  #LPM3,SR,在退出中斷出棧時SR會被重新設置成低功耗0,要達到這樣的目的,只能更改堆棧內SR的設置:MOV.B  #LPM0,0(SP)。 

5中斷向量: 
430的中斷向量是FFE0H—FFFFH,一共32個字節也就是FLASH的最後一段,430的FLASH有大有小,但是最後地址肯定是FFFFH(大FLASH超過64K的除外)所以它們的起始地址是不一樣的,而一般IAR默認編譯都是把程序放在FLASH開始的位置(不包括信息段)。 
有個值得弄清楚的問題是:什麼是中斷向量?中斷向量實際就是保存中斷函數入口地址的存儲單元空間。就像FFFEH+FFFFH這2個字節是復位中斷向量,那麼它存儲的就是主函數在FLASH內的起始地址,假如主函數保存在以0x1100爲起始地址的FLASH塊內 ,那麼你會發現FFFFH 內保存的是0x11, FFFE內保存的是0x00.其他什麼TimerA,ADC12,所有的都一樣。只是你每次寫的程序長短不一,中斷函數放的位置不一樣。IAR編譯器都會給你定好,然後在你用JTAG燒寫程序的時候,把這個地址,燒寫到相應的中斷向量。因爲中斷函數所處地址可以由用戶自定義,也可以讓IAR自動編譯,所以這個地址除了源代碼開發人員知道,其他人是不知道的,BSL就是應用這32個字節的中斷向量內的內容的特殊性設置的密碼。但是有幾個東西在430是不變的,就是觸發中斷的條件滿足後,它到哪個地方去尋址中斷服務函數的入口地址,是TI 在做430時就固化好,定死的。比方說上電覆位的時候,它知道去FFFE,FFFF單元找地址,而不去FFE0,FFE2找地址,這個映射關係是430固化不變的。可有的時候你就是需要改變“中斷向量”,這怎麼辦?430FLASH程序自升級裏有時就會碰到這個問題,方法是在430原來默認的中斷向量表內做一個跳轉操作,同樣以上電覆位爲例: 
ORG  0x2345 
PowerReset: mov.w  &0xFCFE,PC 
………………………… 
………………………… 
ORG  0xFFFE 
DW   PowerReset 
這樣的話0xFCFE就相當是0xFFFE的映射了。這個在430程序自升級的TI應用報告裏就有。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章