编程中经常出现计时问题。

一个众所周知的 Arduino 函数是 delay() ,它暂停程序数毫秒指定为参数。

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

您可能还喜欢:
学习爬行:我与阿杜伊诺的第一次体验

乍一看,您可能会怀疑此功能的用处。然而,事实上,它在许多情况下非常有用,通常 delay() 完全”替换”。让我们先来看看我们如何使用 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) 区别是,上述代码中的循环将每秒运行一次相当准确。具有 的 code 中的循环 delay(1000) 将稍微少一些运行频率,因为它执行还需要一 Serial.println("Hello") 些时间。

为什么要使用米米()而不是延迟()?

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

精确计时

我们将讨论的第一个好处是准确的时机。从代码上讲,我们在最后一节中介绍了这一点。使用 millis() ,我们可以确保循环运行尽可能频繁,而不考虑执行时间(很明显,只要执行时间比所需时间段的时间短)。使用 delay() 时,这是不可能的,因为我们不知道循环执行时间有多长。

像这样的精确计时在以特定频率采样或运行滤波器时非常有用。

非阻塞

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

假设我们要打印”你好”串行每秒一次,同时做其他的东西。这在 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 秒的外观:

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

微()和溢出

就像 delay() 有一个微秒版本 delayMicroseconds() 称为, millis()micros() 。如果你需要更好的解决方案, micros() 可能是要走的路。

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

总结

millis()micros()是处理计时任务时使用的非常方便的函数。如果您不知道这些,您可能会最终 delay() 使用,而不是,这并不总是工作得那么好(如果有的话)。

进一步阅读

学习爬行:我与阿杜伊诺的第一次体验

10 Arduino IDE 替代开始编程

Comments are closed.