我遇到了一个我很难过的问题,因为我能想到的每个解决方案都存在一个问题,导致它无法完全发挥作用。我正在研究MSP430FF529上的游戏,当第一次启动时,使用循环和循环延迟无限地将两个图像绘制到屏幕上。我想拥有它,以便当用户按下开始按钮(端口上的一个简单的高边触发器)时,程序立即停止绘制这些屏幕,无论进程的哪个部分进入,并开始执行其余的运行游戏的代码。
我可以把把图像放在屏幕上的函数放在do while循环中但是它不会是异步的,因为当前正在绘制的图像必须在它移动之前完成。
我会使用break命令,但我认为这不适用于ISR,只有直接在循环中才有效。
我可以将整个程序的其余部分放在我用于启动按钮按下的ISR中,这样屏幕绘图基本上永远不会返回,但那真的很混乱,编码很差,以后会引起很多问题。 / p>
基本上,我想做到这一点,当按下按钮时,程序将立即跳转到实际游戏的程序部分,忘记在屏幕上绘制这些图像。在执行例程中的代码之后,是否有可能以某种方式使ISR无法返回当前正在发生的情况?基本上,一旦程序开始向前移动(按下开始按钮),我不想回到绘制图像的功能,除非我再次明确地调用它。
我唯一能想到的是goto命令,我觉得在这个特定的例子中实际上并不会太糟糕,尽管我想避免使用它,因为它害怕因为它是一个糟糕的解决方案而成为习惯在多数情况下。然而,这可能甚至不起作用,因为我觉得在ISR中使用goto会使堆栈陷入困境。
有什么想法吗?任何建议都表示赞赏。
答案 0 :(得分:1)
你想要的基本上是“上下文切换”。您应该修改程序计数器指针和堆栈指针,当您从ISR返回时将返回该指针,然后执行正常的ISR返回,以便清除中断屏蔽,恢复堆栈等。如您对问题的评论中所述,这可能需要一些手动汇编代码。
我不熟悉MSP430,但在其他架构上,这是在内核堆栈或中断上下文堆栈中保存的寄存器结构(或者可能只是某些微控制器上的“堆栈”),或者它可能是在一些特殊的寄存器中,它在跳转到ISR时由CPU自动保存。所以你必须改变它们所在的寄存器指针。
答案 1 :(得分: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密码,但即使发生这种情况,您也只是跳过介绍图像。)