8051μCU - 如何处理并发中断?

时间:2012-09-07 06:37:28

标签: c microcontroller interrupt 8051

我一直在8051微控制器上进行编程,在处理中断时发现了一些奇怪的东西。假设发生了中断。在处理该中断时,正在发生另一个具有更高优先级的中断。控制器是否应该跳入为更高优先级的中断服务,然后返回到更低的中断?

以下说明了我的问题。连接键盘以触发外部中断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.
}

2 个答案:

答案 0 :(得分:3)

也许“同时”在这里是错误的词,因为这意味着他们在同一时间开始。鉴于此,优先级较高的人将获胜。我认为“并发”可能是一个更好的词。您会认为处理器会跳到更高优先级的处理器,但不会,这不是它的工作原理。实际处理器中只有一个中断线。因此,就处理器而言,它要么处理中断,要么不处理(线路发出信号或未发出信号)。有一个中断控制器可以帮助将多个中断复用到该单行,并且它是帮助确定优先级的中断控制器。在一个更大的微控制器中,中断控制器和处理器之间有一点点分离,但它仍然存在于8051 ......只是有点隐藏。无论如何,一旦中断处理开始,微控制器将处理该中断直到完成,然后被通知下一个中断,即使待处理的中断具有更高的优先级。

有关其工作原理的详细信息,请查看Atmel's Hardware Guide for the 8051。虽然它特定于它们的实现,但大多数实现都非常接近(它们都试图保持原始8051微处理器的原始语义)。在第2-112页,他们讨论了中断的处理方式。第2.16.1节说:

  

执行从该位置继续,直到遇到RETI指令。该   RETI指令通知处理器该中断例程不再存在   进度,然后从堆栈中弹出前两个字节并重新加载程序计数器。   中断程序的执行从中断处开始继续

这是第一行在这里很重要。在执行RETI指令之前,不会处理下一个中断。

答案 1 :(得分:3)

很抱歉这样说,但这里完全错误的答案被认为是最好的。与此同时,TurboJ给出了正确的答案(实际上多了一个),这只是作为评论可见。

8051 micro(或具有多个中断优先级的任何其他)将不执行中断,直到完成,如果更高级别中断挂起,如果所有相关中断都已启用,并且正确设置了优先级。优先级较高的中断处理程序将执行。将以预定顺序扫描相同的优先级中断,并且这些中断不会中断同一级别的中断。默认情况下,8051将所有中断设置为相同级别,这就是所示示例中的问题(正如@TurboJ正确指出的那样)

如果不是这种情况,有几个中断优先级会有什么意义?中断较低优先级的较高优先级中断处理程序的概念称为“中断嵌套”。