2012-09-07 52 views
3

我一直在編程8051微控制器,並且在處理中斷時發現了一些奇怪的東西。假設發生了中斷。服務該中斷時,會發生另一個具有較高優先級的中斷。控制器不應該跳轉到服務於較高優先級的中斷,然後返回到較低優先級的中斷嗎?8051μCU - 如何處理併發中斷?

以下說明我的問題。連接鍵盤以觸發外部中斷1(低優先級),並啓用定時器0中斷(高優先級)。


// With this snippet, the LED-s are blinking as expected. 
#include <8051.h> 
#include <stdint.h> 
#include <stdbool.h> 

__xdata __at (0x9000) uint8_t KEYPAD; 
__xdata __at (0xA000) uint8_t LED; 

uint8_t LedState = 0x00; 
bool Running = false; 

void StopperIsr() __interrupt TF0_VECTOR 
{ 
    LedState = ~LedState; 
    LED  = LedState; 
    TR0  = 0; // Prevent the timer restating right away. 
    Running = false; 
} 

void StopperStart() 
{ 
    TL0 = 0; 
    TH0 = 0; 
    TR0 = 1;  // Start timer 0 
    Running = true; 
} 

void main() 
{ 
    ET0 = 1;  // Enable timer 0 interrupt. 
    EA = 1;  // Enable global interrupts. 
    TMOD = T0_M0; // Set timer 0 to 16-bit mode. 

    while(1) { 
     if (false == Running) { 
     StopperStart(); 
     } 
    } 
} 

// The stopper is used inside external interrupt 1 ISR and since timer 0 has 
// higher priority, the LED-s should be blinking just like in the previous snippet. 
// This is not the case. Instead, on keypress, the ISR is called (LED gets 0xFF), 
// but timer 0 ISR is never entered. 
#include <8051.h> 
#include <stdint.h> 
#include <stdbool.h> 

__xdata __at (0x9000) uint8_t KEYPAD; 
__xdata __at (0xA000) uint8_t LED; 

uint8_t LedState = 0x00; 
bool Running = false; 

void StopperStart() 
{ 
    TL0 = 0; 
    TH0 = 0; 

    TR0 = 1;  // Start timer 0. 
    Running = true; 
} 

void StopperIsr() __interrupt TF0_VECTOR 
{ 
    LedState = ~LedState; 
    LED  = LedState; 

    TR0  = 0; // Stop the timer. 
    Running = false; 
} 

void KeypadIsr() __interrupt IE1_VECTOR 
{ 
    LedState = 0xFF; 
    LED  = LedState; 

    while(1) { 
     if (!Running) { 
     StopperStart(); 
     } 
    } 
} 

void main() 
{ 
    EX1 = 1;  // Enable keypad interrupt on external interrupt 1. 
    ET0 = 1;  // Enable timer 0 interrupt. 
    TMOD = T0_M0; // Set timer 0 to 16-bit mode. 
    EA = 1;  // Enable global interrupts. 
    KEYPAD = 0; // Reset the keypad to its initial state. 
} 
+0

第二個示例缺少while(1);'main() –

+1

而且它也缺少中斷優先級設置。 –

+0

@TurboJ我可以在星期一到達控制器,但我相信優先級設置是我錯過的。出於某種原因,我有一個印象,優先號碼確定。諮詢數據表讓我意識到情況並非如此。謝謝! – gilden

回答

3

也許「同時」是錯詞這裏,因爲這意味着對我說,他們開始在同一時間。鑑於此,較高優先級的將獲勝。我認爲「併發」可能是一個更好的詞。你會認爲處理器會跳到更高優先級的處理器,但不會,這並不完全如此。中斷線只有一個進入實際處理器。所以就處理器而言,它要麼處理中斷,要麼不處理(線路被髮信號或不發信號)。有一箇中斷控制器可以幫助將多箇中斷複用到單個線路上,並且它是幫助確定優先級的中斷控制器。在一個更大的微控制器中,中斷控制器和處理器之間還有一點距離,但它仍然存在於8051中......只是有點隱藏。無論如何,一旦中斷處理開始,微控制器將處理該中斷直至完成,然後通知下一個中斷,即使該中斷具有更高優先級。

有關如何工作的詳細信息,您可以查看Atmel's Hardware Guide for the 8051。雖然具體到它們的實現,但大多數實現都非常接近(它們都試圖保持原始8051 micro的原始語義)。在第2-112頁,他們討論了處理中斷的問題。第2.16.1節說:

執行從該位置繼續進行,直到遇到RETI指令。 RETI指令通知處理器該中斷程序不再處於 進程中,然後從堆棧中彈出前兩個字節並重新裝載程序計數器。 中斷程序的執行繼續從停止的地方開始

這是第一行,這裏很重要。在執行RETI指令之前,不會處理下一個中斷。

3

很抱歉這麼說,但這裏完全錯誤的答案被認爲是最好的。與此同時,TurboJ已經給出了正確的答案(實際上多於一個答案),這隻能作爲評論可見。

如果所有相關的中斷都被使能並且優先級設置正確,那麼8051微控制器(或者具有多箇中斷優先級的任何其他中斷)將不會執行中斷直到完成。較高優先級的中斷處理程序將執行。相同的優先級中斷將以預定的順序掃描,並且這些中斷不會中斷同一級別的中斷。默認情況下,8051的所有中斷都設置在同一級別,這就是所示檢驗問題(正如@TurboJ已經正確指出的那樣)

如果這不是中斷優先級,案子?更高優先級中斷處理程序中斷較低優先級中斷處理程序的概念被稱爲「中斷嵌套」。