Arduino教程:避免在使用millis()和micros()时出现溢出问题

在这里,我们讨论如何使用millis()和micros()与他们的主要优势相比delay()。

与C / C ++中的变量溢出不是一个很好的类比,但是您知道了…

我们提到的一点需要注意这些功能,那就是millis()和micros()溢出后50天左右70分钟,分别。从上次对代码进行很小的改动就可以很容易地避免这个潜在的问题。

millis()贯穿本帖子的用法与可以互换micros()。

简易修复

让我们看一下我们以前的文章中包含的简单非阻塞示例:

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
}

在大约50天后,当millis()我们从返回一个非常高的数字(接近(2 ^ 32)-1)到一个非常小的数字时,我们将得到一个溢出行为。这称为溢出或翻转。

现在,让我们看看如何解决此问题:

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
}

我们基本上只是移到time_now不等式运算符的另一端。为了使方程仍然有意义,我们必须更改变量的符号,因此要减去。您可以将持续时间与我们的period变量进行比较,而不是使用时间戳来查看。

稍安毋躁!

您可能想知道:“这怎么工作?” 这不是一个愚蠢的问题。这看起来很容易,因为我们只是在解决问题而不是解决问题。

从数学上看这没有多大意义,因为当millis()溢出发生时,左侧将变为负数(非常小的整数减去很大的整数的结果)。

起作用的原因

令人高兴的是,我们完全不必为此担心。由于计算的两个输入均为unsigned long数据类型,因此答案也将为unsigned long,因此结果将溢出,且返回值为millis()。记住两者millis()和micros()返回unsigned long:

当前内容已被隐藏,您需要登录才能查看

这将打印2到串行监视器。Serial.print()在这种情况下,该功能不会以任何方式修改答案。

附加信息

为确保此方法可跨多个平台和体系结构使用,您可以将计算结果显式转换为正确的数据类型,如下所示:

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

不同的数据类型

在Arduino Uno(及想同类型产品)上,您必须在进行处理时显式强制转换计算uint8_t。否则,如果输入正确,则减法的结果将变为负数。

uint16_t和uint32_t(与unsigned long Arduino Uno和等效版本相同)具有不需要显式强制转换的行为。处理millis()或micros()时,除unsigned long(uint32_t)以外的其他数据类型均不相关。

摘要

如前所述,这是在处理millis()或时潜在问题的真正简单“解决方案” micros()(我们并没有真正解决问题,只是避免了它)。

如果您不确定数据类型和溢出,我们建议您尝试一下,看看在使用不同数据类型的不同边缘情况下会发生什么。确保打印功能不会以任何方式影响您的结果(有时会)。请记住,这种行为在不同的平台,编译器和/或体系结构上可能有所不同。

「点点赞赏,手留余香」

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