如何处理 Arduino micros() 函数的微秒溢出0条评论

作者:学长   发布于:2013年9月3日 23:41:35 周二    分类: Arduino    7096 人浏览

How To Handle Microsecond Rollover With Arduino’s micros() Function 

如何处理 Arduino micros() 函数的微秒溢出 

When timing on the Arduino, it’s common to use the millis() function, 

which counts the milliseconds the current program has been running. 

But sometimes you need to do things smaller – enter the microsecond timing function, micros().

当arduino 须要计时的时候, 一般是使用 millis() 函数, 

millis() 计算目前程序所已经过的 毫秒(ms) 时间. 

但有时候, 需要更细微的计时, 就是使用 micros(us) 计算 微秒 时间。 

However, there’s a big problem: its maximum size ends up being too small for long-term programs! 

然而, 有一个大问题, 就是对一个长时间执行的程序来说计时的最大值太小了。

To see how that works, consider: 

the largest value that micros() can produce is 2^32-1, or 4,294,967,295. At one million ‘ticks’ per second,

we can do 


试想: micros() 能处理的最大值是 2^32-1 (4,294,967,295). 一秒钟 1,000,000 次的计数可得以下结果 

4,294,967,295 / 1,000,000 = 4294.967295 seconds 

Before we overflow (about 71 minutes and 35 seconds). 


However, what do we do then? 

For example, what if we need to keep track,

and our last count was 4,294,967,000, and our new count is 250. 

How do we figure out the change? 


举例, 需要持续追踪最后的计次是否超过 4,294,967,000 又 250 次? 


In a nutshell – the same way we always did! 

简言之, 跟一般我们处理计时没什么不同! 

To see how that works, consider code to check the change in time, or delta: 

来看这样的情况, 让 程序代码去检查时间的变化或增量: 

unsigned long oldTime=micros(); 
...later on... 
unsigned long newTime=micros()-oldTime; 

So if oldTime is 500, and newTime is 750, we have (750-500=250), which is fine. But look at our earlier example:

如果 oldTime 是 500, 並且 newTime 是 750 , 得到(750-500=250), 這樣很好. 


         decimal          hexadecimal

            250                   FA
- 4,294,967,000           - FFFFFED8
----------------     ----------------
- 4,294,966,750             00000222 (decimal 546)

What happened? In our world, we have negative numbers, so the result is negative. 

But we’re working with unsigned longs – there’s only 32 bits, and no negative.

So the value rolls over like an old-fashioned odometer, and we get 546. 

发生了什么事? 在 arduino 的世界里有负数, 所以结果是负数.

但是我们定义 unsigned long , 只有32位而且没有负数。 

所以数值就溢出了, 像是旧式的里程表, 得到了 546 这个数值。

To see if this is right, let’s do some math: 

为了确定这是正确的, 我们来算一下数学题: 

  • From 4,294,967,000 to 4,294,967,295 (hexadecimal FFFFFFFF) is 295
  • From 4,294,967,295 to 4,294,967,296 is 1 
  • But 4,294,967,296 doesn’t exist in an unsigned long, 
  • so it rolls over to zero So, from 0 to 250 is 250 
  • 295 + 1 + 250 is 546 – the result we expect! 

  • 从 4,294,967,000 到 4,294,967,295 (十六进制 FFFFFFFF) 是 295 
  • 从 4,294,967,295 到 4,294,967,296 是 1 
  • 但 4,294,967,296 不存在于 unsigned long, 
  • 所以就溢出为 0 所以, 从 0 到 250 是 250 
  • 295 + 1 + 250 是 546 – 我们得到的结果 

So it would seem we can ignore rollover when we do time calculations, and use the result no matter what. 

看起来当计算时间的时候可以忽略溢出, 不管如何都能直接使用结果。

Not quite: 


For this to work, we MUST have an ‘oldTime’ that occurred in the last 71.5 minutes. 

If we cycle over two or more times, the difference is meaningless; 

since we can’t ‘hold’ multiple 71.5 minutes cycles in an unsigned long, we can’t figure out the whole time interval. 

The value as mentioned must be an unsigned long, which rolls over after FFFFFFFF. 

这能正常工作,必须 有个 'oldTime' 变量在上一个 71.5 分钟内.

如果我们在多于两个以上的循环, 就变得无意义了 

因为我们不能用同一个 unsigned long 处理多个71.5 分钟的循环, 无法确定这样的时间间隔。 

之前提到的值必要是 unsigned long, 在 FFFFFFFF 之后溢出.

However, if we keep this in mind, this means that as long as we time frequently enough, code like 

unsigned long newTime=micros()-oldTime; 

will work! 

然而, 如果我们记得这些限制, 表示只要我们时间频率是足够的, 程序代码 

unsigned long newTime=micros()-oldTime;





How To Handle Microsecond Rollover With Arduino’s micros() Function


Arduino问答实验室- 本站版权
继续查看有关 arduino micros 的文章