Arduino教程:使用millis()代替delay()

众所周知的Arduino里的delay()将程序暂停指定为毫秒数的参数。

millis()另一方面,是一个返回自程序启动以来经过的毫秒数的函数。

乍一看,您可能会怀疑此功能的实用性。事实是,它在许多情况下非常有用,通常会完全“替换”delay() 。首先让我们看一下如何使用millis()几乎完全像delay()

时序问题经常出现在编程中。

使用像millis()这样的delay()

unsigned long time_now = 0;
 
void setup() {
    Serial.begin(115200);
}
 
void loop() {
    time_now = millis();
   
    Serial.println("Hello");
   
    while(millis() < time_now + period){
        //wait approx. [period] ms
    }
}

如果您希望代码在每次循环迭代结束时仅暂停1000 ms,则上面的代码有点愚蠢。您可以  delay(1000)改用。上面的代码和delay(1000)结尾的代码之间的唯一区别是,上面的代码中的循环每秒非常准确地运行一次。代码中的循环delay(1000)会减少运行的频率,因为它也需要一些时间执行Serial.println("Hello")

为什么使用millis()而不是delay()?

现在,我们将millis()比较与相比的两个优势delay()

准确的时间

我们将讨论的第一个优点是准确的时间安排。在代码方面,我们在上一章中进行了介绍。有了millis()我们,我们可以确保循环执行所需的次数,而与执行时间无关(显然,只要执行时间短于所需的时间,就可以执行)。随着delay()这是不可能的,因为我们不知道循环执行的时间有多长。

当以一定频率采样或运行滤波器时,此类精确定时非常有用。

不阻塞

另一个好处millis()是它不会阻止我们在“等待”时运行代码。

unsigned long time_now = 0;
 
void setup() {
    Serial.begin(115200);
}
 
void loop() {
    if(millis() > time_now + period){
        time_now = millis();
        Serial.println("Hello");
    }
   
    //Run other code
}

假设我们要每秒打印一次“ Hello”,同时还要做其他事情。这是不可能的,delay()因为它会暂停整个代码。这是我们可以执行此操作的一种方法:
该代码块与第一个代码块非常相似,不同之处在于,当不通过串行打印时,它不会阻塞程序的其余部分。

示例:一个简单的调度程序

让我们写一个简单的示例,在该示例中,我们创建一个调度程序,该调度程序以不同的间隔打印某些文本位。

#define INTERVAL_MESSAGE2 7000
#define INTERVAL_MESSAGE3 11000
#define INTERVAL_MESSAGE4 13000
 
unsigned long time_1 = 0;
unsigned long time_2 = 0;
unsigned long time_3 = 0;
unsigned long time_4 = 0;
 
void print_time(unsigned long time_millis);
 
void setup() {
    Serial.begin(115200);
}
 
void loop() {
    if(millis() > time_1 + INTERVAL_MESSAGE1){
        time_1 = millis();
        print_time(time_1);
        Serial.println("I'm message number one!");
    }
   
    if(millis() > time_2 + INTERVAL_MESSAGE2){
        time_2 = millis();
        print_time(time_2);
        Serial.println("Hello, I'm the second message.");
    }
   
    if(millis() > time_3 + INTERVAL_MESSAGE3){
        time_3 = millis();
        print_time(time_3);
        Serial.println("My name is Message the third.");
    }
   
    if(millis() > time_4 + INTERVAL_MESSAGE4){
        time_4 = millis();
        print_time(time_4);
        Serial.println("Message four is in the house!");
    }
}
 
void print_time(unsigned long time_millis){
    Serial.print("Time: ");
    Serial.print(time_millis/1000);
    Serial.print("s - ");
}

这是串行监视器中前60秒的样子:

这是一种同步代码中执行的好方法。您也可以同时运行其他代码。

micros()和溢出

就像delay()有一个微秒版本称为delayMicroseconds()millis()具有micros()。如果您需要更好的分辨率,micros()则可以采用。

但是,要知道,micros()会后溢出约70分钟,比millis()50天。这意味着函数的返回值将从零开始。

摘要

millis()并且micros()是非常方便的功能,具有定时任务处理时使用。如果您不了解这些内容,则可能最终只会使用delay(),但这种方式可能不会总是那么好。

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论