C比较可以溢出的时间

时间:2014-05-15 07:45:46

标签: time arduino overflow

我需要检测unsigned long的溢出。

此变量保存自设备运行以来的毫秒数(它是Arduino)。做sizeof(unsigned long),我发现它确实是一个32位的数字。现在,因为它每毫秒递增一次,这意味着设备将在此值溢出之前运行大约49天。

由于它适用于家庭系统,因此不太可取。现在我正在使用的数字是,比较当前时间是否大于前一次加上去抖动量。

if(timeChanged + amountOfMs < currentTime){ ... }

毋庸置疑,一旦发生溢出,这就不再适用了。什么是解决这个问题的有效方法?我已经考虑过还有一个二次计时器来检查是否有一个溢出的毫秒,但最后我会遇到同样的问题。

4 个答案:

答案 0 :(得分:2)

似乎你已经得到了两个非常糟糕的答案......

正确的答案是,只要您正确进行计算,就不必担心millis()翻转。

这很糟糕:

if (timeChanged + amountOfMs < currentTime) { ... }

这很好(翻滚安全):

if (currentTime - timeChanged > amountOfMs) { ... }

它起作用的原因是具有无符号整数的算术(在你的情况下为unsigned long)可靠地以模数max + 1工作(ULONG_MAX+1是2 ^ 32)。因此,currentTimetimeChanged及其差异始终具有正确的值,模2 ^ 32。只要您每49天测试一次按钮的频率超过一次(很可能),差异将在unsigned long的范围内,您的测试将是正确的。

换句话说:如果millis()在timeChangedcurrentTime之间滚动,则差异currentTime - timeChanged将为负数。但由于差异实际上是用无符号数计算的,因此它会下溢并翻转到正确的结果。我不喜欢这个解释,因为它听起来像是一个补偿另一个错误的错误。事实是:如果你在模块化算术中考虑无符号数,那么任何地方都没有错误。

答案 1 :(得分:-1)

这是一个常见的错误(也是我自己创造的一个错误),Arduino游乐场有一个很好,彻底,正确的答案。见https://playground.arduino.cc/Code/TimingRollover

答案 2 :(得分:-3)

您可以创建一个新的if循环来检查条件:if(currentTime == 0xFFFFFFFE)

如果这是条件,则下一毫秒将溢出您的变量。所以在这一点上你可以手动将它重置为零并转到从零开始的循环。

这可能会或可能不会对您的情况有所帮助。我无法肯定地说,因为您还没有分享有关您的代码的任何进一步细节。

答案 3 :(得分:-3)

定义两个变量,我将把它们称为'now'和'lastNow'。

unsigned long now;
unsigned long lastNow = 0;

在循环中,您现在可以执行此操作:

now = millis();
if (now < lastNow) {
    // rollover!
}
lastNow = now;

无论您多久(或不经常)循环,都很好而且可靠。