用millis() 這個函式來取得arduino執行程式到目前過了幾個milliseconds
但這個值是用unsign long (32bit) 儲存的,所以大概在約50天左右就會overflow,
從0開始,但是如果程式寫法是如下,那就好笑了。
unsigned long start=millis(); int delaytime=3000; void loop() { while (millis()<start+delaytime) { ; } sendData(); }
當五十天後,你就永遠不會傳送資料了,因為millis()可能會遠小於sendtime。等到大於sendtime時,差不多又overflow了。
但是以下的寫法是不會有問題的
unsigned long start=millis(); unsigned long delay=3000; if (millis()-start>delay) { sendData(); start=millis(); }
我們先來了解一下unsigned long 到底可以放的下什麼
0 to 4,294,967,295 (2^32 - 1)
那如果overflow 後會發生什麼事
unsigned long number=4294967295; void setup() { // put your setup code here, to run once: Serial.begin(9600); Serial.println("number is :"+String(number)); number+=1; Serial.println("number+1 is :"+String(number)); }
輸出結果如下,當大於2^32 -1 後,就會歸零。
number is :4294967295
number is :0
我們來模擬一下overflow之後的運算
unsigned long number=4294967295; unsigned long testNumber=4294967295; void setup() { // put your setup code here, to run once: Serial.begin(9600); Serial.println("number is :"+String(number)); number+=1; Serial.println("number+1 is :"+String(number)); Serial.println("number- 2^32-1 :"+String(number-testNumber)); }
number+1 is :0
number- 2^32-1 :1
所以0-(2^32-1) 會是1 ,
以此類推,當overflow後,即使millis()比較小,相滅之後仍然會是正值。
number is :4294967295
number+10000 is :9999
number- 2^32-1 :10000
我們來測試一下,若是millis()比較小時做相減會怎樣
number is :0
number+10000 is :10000
number- 2^32-1 :10001
所以2數運算時要考慮到unsigned long 能裝的下的空間,unsigned long 面對運算結果負值也會出現問題。
number is :0
number+10000 is :10000
number-10001 :4294967295
millis() 溢出(overflow)歸零(rollover)有沒問題?(教程)定时器相關http://www.arduino.cn/thread-12506-1-1.html
沒有留言:
張貼留言