通过间歇或类似方式异步退出环路 (MSP430/C)



我遇到了一个我相当难倒的问题,因为我能想到的每个解决方案都有一个问题,使它无法完全工作。我正在开发一款MSP430FF529游戏,当第一次通电时,使用循环和循环延迟无限地将两个图像绘制到屏幕上。我希望它能够使用户按下开始按钮(端口上的简单高边触发器)时,程序立即停止绘制这些屏幕,无论进程的哪个部分,并开始执行运行游戏的其余代码。

我可以将将屏幕上的图像放在 do while 循环中的函数,但它不会是异步的,因为当前正在绘制的图像必须在继续之前完成。

我会使用 break 命令,但我认为这在 ISR 中不起作用,并且只有在它直接在循环中时才有效。

我可以将程序的整个其余部分放在我用于按下开始按钮的 ISR 中,这样屏幕绘图基本上永远不会返回,但这真的很混乱,编码很差,以后会导致很多问题。

从本质上讲,我想这样做,这样当按下按钮时,程序将立即跳转到程序的实际游戏部分,而忘记在屏幕上绘制这些图像。是否有可能以某种方式拥有一个 ISR,在执行例程中的代码后不会返回到当前发生的情况?基本上,一旦程序开始向前移动(按下开始按钮),我不想回到绘制图像的函数,除非我再次显式调用它。

我唯一能想到的是 goto 命令,我觉得在这种特殊情况下它实际上不会太糟糕,尽管我想避免使用它,因为担心它在大多数情况下是一个糟糕的解决方案而成为一种习惯。但是,这甚至可能不起作用,因为我有一种感觉,在 ISR 中使用 goto 真的会弄乱堆栈。

有什么想法吗?任何建议不胜感激。

你想要的基本上是一个"上下文切换"。您应该修改程序计数器指针和堆栈指针,当您从 ISR 返回时,它们将被恢复,然后执行正常的 ISR 返回,以便清除中断掩码、恢复堆栈等。如您的问题的评论中所述,这可能需要一些手动汇编代码。

我不熟悉 MSP430,但在其他架构上,这是在内核堆栈或中断上下文堆栈(或者可能只是某些微控制器上的"堆栈")上保存的寄存器结构中,或者它可能在某些特殊寄存器中,当它跳转到您的 ISR 时,它由 CPU 自动保存。因此,您必须将这些寄存器指针更改为它们所在的位置。

如果您将要求从"立即"放宽到"如此之快以至于用户没有注意到",则可以将if (button_pressed)放入图像绘制例程中的某个循环中。


如果您确实想立即中止图像绘制,可以通过重置 MCU 来实现(例如,通过将错误的密码写入 WDT)。在应用程序初始化代码中,检查重置的原因之一是否是您自己的软件:

bool start_button = false;
for (;;) {
    int cause = SYSRSTIV;
    if (cause == SYSRSTIV_WDTKEY)
        start_button = true;
    if (cause == SYSRSTIV_NONE)
        break;
    // you might handle debugging of other reset causes here ...
}
if (!start_button)
    draw_images();
else
    actual_game();

(这假定您的代码从未意外写入错误的 WDT 密码,但即使发生这种情况,您也只会跳过介绍图像。

最新更新