【Arduino 教程】使用 millis() 函数实现多任务处理

多任务处理可以使一个或多个程序可以同时运行。在嵌入式系统中,微控制器还可以处理多任务处理并同时执行两个或多个任务,而无需停止当前指令。

通常在 Arduino 中使用 delay() 函数来执行 LED 闪烁等周期性任务,但是 delay() 函数会暂停程序一段时间,并且不允许执行其他操作。因此,在 Arduino 中将 delay 替换为 millis() 函数可以同时执行多个任务,并使 Arduino 成为多任务控制器

为什么不用 Arduino 中的 delay()

在 Arduino 的参考文档中有两种类型的延迟函数,第一种是 delay() ,第二种是 delayMicroseconds()。两个函数在产生延迟时间方面是相同的。唯一的区别在于,在 delay() 函数中,传递的参数整数是以毫秒为单位,即如果我们写入 delay(1000) 则延迟将是1000毫秒,即1秒。类似地,在 delayMicroseconds() 函数中,传递的参数是微秒,即如果我们写 delayMicroseconds(1000),则延迟将是1000微秒,即1毫秒。

重点是,两个函数都会暂停程序延迟函数传递的时间。因此,如果我们给出1秒的延迟,则处理器在1秒钟之前不能进入下一条指令。类似地,如果延迟是10秒,则程序将停止10秒,并且处理器将不允许进行下一指令,直到10秒过去。这妨碍了微控制器在速度和执行指令方面的性能。

解释延迟函数缺点的最好例子是使用两个按钮:比如使用两个按钮切换两个LED。如果按下一个按钮,则相应的LED发光2秒;如果按下第二个,则LED应该发光4秒。但是当我们使用 delay() 时,如果用户按下第一个按钮,程序将停止2秒,如果用户在2秒延迟之前按下第二个按钮,则微控制器将不接受输入,因为程序是在停止阶段。

Arduino的官方文档在其delay()函数描述的注释和警告中明确提到了这一点。

为什么要使用 millis()

为了克服使用 delay() 函数引起的问题,我们可以使用 millis() 函数,这个函数在习惯使用后很容易使用,它将使用100%的 CPU 性能而不会在执行指令时产生任何延迟。 millis() 函数只返回自 Arduino 开发板开始运行当前程序以来没有冻结程序所经过的毫秒数。大约50天后,这个时间数将溢出(即回到零)。

就像 Arduino 有 delayMicroseconds() 一样,它也有微型版本的 millis(),那就是 micros()。 micros 和 millis 之间的差异是,micros() 在大约70分钟后会溢出,而millis()则是50天。

使用 millis() 而不是 delay()

要使用 millis() 进行计时和延迟,就是要记录并存储操作开始时间的时间,然后定期检查定义的时间是否已过。 如上所述,将当前时间存储在变量中。

我们还需要两个变量来确定是否已经过了所需的时间。 我们已将当前时间存储在 currentMillis 变量中,但我们还需要知道定时周期何时开始以及周期有多长。 因此声明了 Interval (下方为 Period ,即延迟周期。类似于 delay 函数括号中的时间)和 previousMillis。 Interval 将告诉我们时间延迟周期,单位为毫秒;previosMillis 将存储事件发生的最后时间:

但是如果同时有多个需要延迟的进程,那么需要定义多个 previousMillis,以便进行区分:

举一个简单的闪烁LED示例。 period = 1000 将告诉我们 LED 将闪烁1秒:

这里,语句 if (currentMillis - previousMillis >= period) 检查是否已经过去了 1000ms 。如果超过1000ms,则LED闪烁并再次进入相同状态;此效果和 delay 函数相同,但是同时它不会暂停整个 Arduino 代码的运行。

Arduino 的中断与其他微控制器的工作方式相同。 Arduino UNO 板有两个独立的引脚,用于连接 GPIO 引脚 2和 3 上的中断,这可能会在之后的文章中提到。

参考资料

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注