多任务处理可以使一个或多个程序可以同时运行。在嵌入式系统中,微控制器还可以处理多任务处理并同时执行两个或多个任务,而无需停止当前指令。
通常在 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() 进行计时和延迟,就是要记录并存储操作开始时间的时间,然后定期检查定义的时间是否已过。 如上所述,将当前时间存储在变量中。
unsigned long currentMillis = millis();
我们还需要两个变量来确定是否已经过了所需的时间。 我们已将当前时间存储在 currentMillis 变量中,但我们还需要知道定时周期何时开始以及周期有多长。 因此声明了 Interval (下方为 Period ,即延迟周期。类似于 delay 函数括号中的时间)和 previousMillis。 Interval 将告诉我们时间延迟周期,单位为毫秒;previosMillis 将存储事件发生的最后时间:
unsigned long previousMillis;
unsigned long period = 1000;
但是如果同时有多个需要延迟的进程,那么需要定义多个 previousMillis,以便进行区分:
unsigned long previousMillisHeater = 0; //用来存时间
unsigned long previousMillisVentilateur = 0; //用来存时间
unsigned long previousMillisMoteur = 0; //用来存时间
const long period = 30000; // 周期,不中断正在进行的进程,单位为ms
举一个简单的闪烁LED示例。 period = 1000 将告诉我们 LED 将闪烁1秒:
const int ledPin = 4; // the LED pin number connected
int ledState = LOW; // used to set the LED state
unsigned long previousMillis = 0; //will store last time LED was blinked
const long period = 1000; // period at which to blink in ms
void setup() {
pinMode(ledPin, OUTPUT); // set ledpin as output
}
void loop() {
unsigned long currentMillis = millis(); // store the current time
if (currentMillis - previousMillis >= period) { // check if 1000ms passed
previousMillis = currentMillis; // save the last time you blinked the LED
if (ledState == LOW) { // if the LED is off turn it on and vice-versa
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);//set LED with ledState to blink again
}
}
这里,语句 if (currentMillis - previousMillis >= period)
检查是否已经过去了 1000ms 。如果超过1000ms,则LED闪烁并再次进入相同状态;此效果和 delay 函数相同,但是同时它不会暂停整个 Arduino 代码的运行。
Arduino 的中断与其他微控制器的工作方式相同。 Arduino UNO 板有两个独立的引脚,用于连接 GPIO 引脚 2和 3 上的中断,这可能会在之后的文章中提到。
使用的delay 函数 在阻塞的时候 如果发生中断事件 arduino会怎么处理呢?
您好 不好意思好久没看后台🤣我试了一下当使用delay的时候,使用attachInterrupt(interrupt, ISR, mode)函数没有效果,也就是说使用delay的时候arduino就不做别的事情了(也可能执行了中断,但是中断执行完毕继续执行delay),要么就是复位停止delay。另一种办法是
用while循环,将delay的值设小一点,当满足结束条件时跳出while,不满足条件就继续。