我一直在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.
}
答案 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正确指出的那样)
如果不是这种情况,有几个中断优先级会有什么意义?中断较低优先级的较高优先级中断处理程序的概念称为“中断嵌套”。