在没有运行任何操作系统的微控制器上,当它进入一个例程并忙于在那里执行一些冗长的循环时,我怎样才能让微控制器过早地从这个例程中止(即返回到调用例程)作为对中断的响应(例如,当用户按下按钮时生成的)?
有没有比以下更好的解决方案:1)在循环之间轮询按钮或共享变量,2)手动修改堆栈中的返回地址,3)使用操作系统,以及 4)在 ISR 中硬编码 POP 和 JUMP 指令?
非常感谢!
在没有运行任何操作系统的微控制器上,当它进入一个例程并忙于在那里执行一些冗长的循环时,我怎样才能让微控制器过早地从这个例程中止(即返回到调用例程)作为对中断的响应(例如,当用户按下按钮时生成的)?
有没有比以下更好的解决方案:1)在循环之间轮询按钮或共享变量,2)手动修改堆栈中的返回地址,3)使用操作系统,以及 4)在 ISR 中硬编码 POP 和 JUMP 指令?
非常感谢!
如果您希望一个冗长的函数通过中断成为快捷方式,并且以干净的方式完成,那么实际上只有一种方法需要在函数中构建干净的返回。您如何告诉该函数返回可以让中断设置一个共享资源(例如一个变量)并且前台循环/函数可以返回。或者您可以让前台循环轮询某些东西(例如 gpio 引脚、计时器等)。
通常你想做的是不同的事情。您允许前台任务执行低优先级的事情,例如更新显示或处理用户输入或类似的事情,并且您不会强制它过早退出功能,而是在 isr 中处理需要作为优先。
那或者你可以制作一个迷你操作系统,如果你愿意并且有不同的线程,捕获需要处理的硬件事件的中断会留下该信息和/或交换线程(保存当前运行代码使用的所有寄存器的副本,用处理程序代码替换所有寄存器并返回处理程序代码)。如果 isr 没有交换,那么周期性计时器将出现,查看优先级事件并交换,然后当优先级处理程序空闲时,周期性计时器将交换回来。或者优先级处理程序可以在它空闲之前调用一个函数以导致切换回前台线程。不复杂,比简单的 isrs 更复杂,是的,但仍然不是很复杂。
对于 PIC 或 AVR,无论如何,所有操作系统都倾向于使用堆栈,所以我认为 2 - 4 是相同的选项(除了其他人已经实现并测试了堆栈操作的操作系统。)
我推荐选项 1,因为它是最便携的。在您的代码中执行此操作的一种非常快速的方法:
//Consider using static int if all the code is in one file
int WasButtonPressed;
//Change this to match your complier for interrupts
void __attribute__((__interrupt__,no_auto_psv)) _Interrupt
{
//Rewrite this to use whatever button polling method
if (PORTAbits.RA0) {
WasButtonPressed = 1;
}
}
//Testing to see if the interrupt fired and then get out of the function
#define HANDLE_BUTTON() { if (WasButtonPressed) return; }
然后你可以在你的循环中加入HANDLE_BUTTON();
调用。
微控制器利用通常在代码的第一部分中配置的硬件中断。可以将单个引脚配置为外部中断,并可以创建相关函数。
为我们提供:
然后我们可以为您的问题提供更具体的解决方案