Arduino中使用millis()代替delay()

在您的Arduino项目中使用delay()函数? 在许多情况下,最好将millis()用作更准确的非阻塞替代方法。

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

著名的Arduino函数是delay(),它可以将程序暂停指定为参数的毫秒数。
另一方面,millis()是一个函数,它返回自程序启动以来经过的毫秒数。

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

像millis()一样使用delay()

int period = 1000;
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()相比有两个优点。

1.精准的时间

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

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

2.非阻塞

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

假设我们要每秒打印一次“ Hello”,同时还要做其他事情。 使用delay()不可能做到这一点,因为它会暂停整个代码。 这是我们执行此操作的一种方法:

int period = 1000;
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
}

该代码块与第一个代码块非常相似,不同之处在于,当不通过串行打印时,它不会阻塞程序的其余部分。

一个简单的调度程序示例

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

#define INTERVAL_MESSAGE1 5000
#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()。

但是,请注意,与millis()的50天相比,micros()将在大约70分钟后溢出。 这意味着函数的返回值将从零开始。

总结

millis()和micros()是处理计时任务时真正方便使用的函数。 如果您不了解这些内容,则可能最终会使用delay()来代替,它可能不会总是那么好用(如果有的话)。

SO资源郑重声明:
1. 本站所有资源来源于用户上传和网络,因此不包含技术服务请大家谅解!如有侵权请邮件联系客服!3187589@qq.com
2. 本站不保证所提供下载的资源的准确性、安全性和完整性,资源仅供下载学习之用!如有链接无法下载、失效或广告,请联系客服处理,有奖励!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!

SO资源 » Arduino中使用millis()代替delay()