0

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

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

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

我可以将整个程序的其余部分放在用于按下开始按钮的 ISR 中,这样屏幕绘图基本上就不会返回,但这确实很混乱,编码不佳,并且会在以后引起很多问题。

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

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

有任何想法吗?任何建议表示赞赏。

4

2 回答 2

1

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

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

于 2016-01-19T23:19:34.093 回答
0

如果您将要求从“立即”放宽到“用户没有注意到的如此之快”,则可以将其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 密码,但即使发生这种情况,您也只是跳过了介绍图像。)

于 2016-01-20T07:59:23.750 回答