我可以像这样使用 cli() 和 sei() 吗:
ISR(EXT_INT0_vect)
{
cli();
MyFunction();
sei();
}
Run Code Online (Sandbox Code Playgroud)
听说是禁止的。或者我可以像上面那样使用 cli() 和 sei() 吗?
如果您想要正常的中断行为,则手动调用 cli() 和 sei() (如您的示例中)是多余的。也就是说,因为AVR在执行ISR之前会自动清除全局中断标志。嵌套中断的使用情况很少,您可能需要在 ISR 中使用 sei() 手动重新启用中断。
来自嵌套中断:
通常,AVR 硬件在进入中断之前会清除全局中断标志(在 SREG 中)。这意味着正在运行的处理程序内将禁用其他中断,直到处理程序完成并退出。
RETI 指令是中断处理程序的正常函数尾声,因此重新启用中断(就像执行 SEI 指令一样)。因此,通常情况下,中断处理程序不能嵌套。
对于大多数中断处理程序来说,这是所需的行为。对于某些人来说,甚至需要它来防止无限递归中断。递归很容易超出可用的堆栈空间并使正在运行的程序崩溃。在极少数情况下,可能需要在中断处理程序内尽早重新启用全局中断标志,从而允许递归中断处理。小心。
这可以通过在中断处理程序的开头插入 sei() 指令来完成,但这仍然会在(编译器生成的)中断序言中留下一些指令,以便在禁用全局中断的情况下运行。[...]