首先感谢 xvb*** 坛友 帮忙发现这个问题 !
什么问题 ? 就是 delay( ) "看起来" 好像不准的问题, 请看:
unsigned long st = millis( );
delay(1000);
unsigned long et = millis( );
Serial.println(et - st); // 差距多少个 ms
结果印出 999,
你不相信对不对 !? 一开始我也不相信 !
如果印出的是 1000 或 1001 应该大家都会相信,
但是, 999 怎么可能呢 ?!
要感谢坛友问了这个问题 :-)
一开始打死我也不相信会有这种事,
因为我明明看过 delay( ) 的程序源码:
(注意 delay 是以 ms(millis second)为最小单位, 1 ms = 1000 us)
void delay( unsigned long ms ){
unsigned long start = millis();
while (millis() - start < ms) {
// do nothing here
} // while(
} // delay(
你会发现,这 delay( ) 的代码很简单,
它就是不断的调用 millis( ) 看看时间到了没?
时间没到就不返回,
一点学问都没吧 :-)
这样看来 delay(1000)前后一定至少差 1000 啊, 偶而差 1001 也是正常,
因可能被中断导致 loop 做完回到我们调用 millis( ) 又多跳了一 ms,
但是, 说要得到 999 是绝对不可能的事 !
问题是, 事实摆在眼前, 由图片有证据 !
所以, 我重新去看源代码,
啥 !? 是我脑筋停留在四年前看的 :-)
原来 delay( ) 早就改写了,
查看 Arduino Release Note:
http://arduino.cc/en/Main/ReleaseNotes
发现 Arduino 从 2010/09/03 之后版本就改用这新版本的 delay( ) :
void delay(unsigned long ms) {
uint16_t start = (uint16_t)micros();
while (ms > 0) {
if (((uint16_t)micros() - start) >= 1000){
ms--;
start += 1000;
} // if
}//while(
}// delay(
靠餐ㄟ, 这就难怪囉 ..
这样写法当然有可能发生上述说的:
在 delay(1000); 之后却只有差 999ms 的情形,
不过好处是,
它这种新的写法误差在应该在 7us 以內,
可是以前旧版delay( ) 的误差可能高达1ms;
通常有好处就有坏处,
延迟的误差是变小了,
但是,
本来旧版本的写法不会有前后查看 millis( ) 发现结果怪怪的问题,
新写法却会有这种感觉似乎少 delay 1 milli second, 但其实並没有喔 !
会这样, 这也是没办法的事 !
delay( ms )前后各调用一次 millis( )相减竟然小於 delay( )的 ms 数!
怎会这样呢?
这其实是 millis( ) 本身的问题 !
因为 millis( ) 本身就会有 1 ms 的误差 !!
|