一个众所周知的 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()
使用,而不是,这并不总是工作得那么好(如果有的话)。