我知道这听起来非常简单。但我想不出,也没有充分的定义来搜索,如何让C中的代码在程序的其余部分运行时以恒定的频率闪烁。设置和忘记的事情。我今天看到了线程,尽管对我的基本理解来说似乎有点复杂。
我在Windows上开发,并在MikroC上运行PIC18,但当我在Arduino上进行另一个项目时,我也有同样的想法。
查看PIC18 上使用C的多线程的答案
对于标准的C开发,这将需要多线程,但这个答案建议使用事件循环。
只需使用微控制器硬件即可。输出比较定时器、PWM硬件等。如果您没有任何此类硬件,在大多数情况下,从中断切换I/O端口应该足够准确。
大多数微控制器都有可用的硬件定时器,可用于此类目的。因此,你在计时器中的代码将切换闪烁,主软件可以设置变量,告诉计时器代码是否应该闪烁
int shouldblink = 0;
int ledstatus = 0;
void OnTimer(void) /* configure your microcontroller to call this on timer */
{
if (ledstatus)
{
turnoffLED();
ledstatus = 0;
}
else {
if (shouldblink)
{
turnonLED();
ledstatus = 1;
}
}
}
int main()
{
configure_timer();
shouldblink = 1;
do_slow_work();
shouldblink = 0;
}
在PIC上,您不一定会像一些评论中所建议的那样,直接从繁忙等待循环这样简单的东西跳到多线程库这样复杂的东西。
让我们假设你在一个循环中每秒钟闪烁一次LED——这让该循环中的代码(或从该循环内部调用的代码)在不同的东西上执行将近1秒。如果你能把这些任务分成小块,使它们适合"当你需要回来时"闪烁LED的时间间隔,那就是一个开始。
显然,如果你在闪烁循环中执行任意代码,你的闪烁频率将受到其他代码部分用完的时间的影响,你不能再使用CPU作为时基-你需要一些不同的东西来检查是否应该闪烁。大多数MCU都有一个计时器,可以让你做到这一点——读取一个免费运行的计时器来检查你是否"需要眨眼"将是第一个简单的步骤。参见以下伪代码:
while (1){
if (((time = readTimer()) - oldTime) > INTERVAL){
/* Timer run-around ignored for reasons of simplicity */
oldTime = time;
blink();
}
else
doSomethingElse();
}
请注意,somethingElse()
必须在尽可能短的时间内完成,因为它的运行时间会影响闪烁的精度。
如果你仍然希望闪烁的时间间隔准确,你应该研究一下中断服务例程。了解如何使计时器以闪烁频率触发中断,并在中断服务例程中执行闪烁。这就释放了主循环,您可以在那里执行任何需要长期运行的任务。计时器将以您想要的频率触发中断,中断服务程序将切换指示灯。