One of the requested items I found was handling 'rollover' from 'millis()' and also, 'micros()'. This is actually not a very difficult matter to deal with, and it's something I've needed to address a lot of times in various contexts, from kernel drivers to applications, and of course, micro-controllers.
First, I shall explain two's complement mathematics, and signed vs unsigned integers.
Two's complement is a way to represent negative numbers in binary. It requires that you sacrifice one bit of precision (the most significant bit), to handle negative values.
For a 16-bit integer, a two's complement value can represent any number between -32768 and 32767, inclusive. For now, this is what I will focus on.
By definition, if you subtract a binary 1 from a binary zero, you should end up with a binary -1. Conversely, if you add a binary 1 to a binary -1, you should get zero.
???????????????? + 0000000000000001 = 0000000000000000
Doing a little atmospheric extrapolation, it's pretty obvious that the following is true.
1111111111111111 + 0000000000000001 = 0000000000000000
If there were another bit shown (i.e. the 'carry' bit) you would see a 17-bit number with the high bit set. But this is the consequence of using a fixed-length binary value. You get 'rollover'.
Consequently to adding binary 1 to "all 1's" to get zero, the following will also be true:
0000000000000000 - 0000000000000001 = 1111111111111111
So the representation of a -1 must be 'all 1 bits' for any two's complement integer, given a fixed-length integer size in bits.
Now it is important to distinguish 'unsigned' from 'signed' integer math. If you want to subtract two unsigned values, and have a negative result if the second is larger, you have to cast the result to a signed integer. This will treat the unsigned result as if it were two's complement, like so:
unsigned int i,j;
...
if( (int)(i - j) < 0 ) { do something }
And, this is the heart of the solution to 'rollover'. In the case where the value of 'i' has not yet 'crossed' the value of 'j', the result of 'i - j' (cast to a signed integer) will be NEGATIVE. If 'i' crosses 'j', the result will be POSITIVE.
Example: Assuming that 'millis()' returned a 16-bit integer (for simplicity), if the current 'millis()' time is 65500 and you want to wait for 1000 milliseconds, you can use unsigned math to add 1000 to 65500 and get a result of 964 (rolling over to zero at what would be 65536). When the '16-bit' millis() 'rolls over' to zero, it will continue to increment until it, too, reaches the value 964. At that point, your timer code can recognize the 'crossing' by subtracting the wait time from millis(), converting it to a signed integer, and checking that it's greater than or equal to zero.
The following code checks to see if you have 'crossed' a 1000 millisecond 'delay point', and initiate's another timer delay of 1000 milliseconds after some kind of periodic processing.
The same kind of code can be applied to 'micros()' as well.
static unsigned long lWaitMillis;
void setup()\
{
lWaitMillis = millis() + 1000; // initial setup
}
void loop()\
{
if( (long)( millis() - lWaitMillis ) >= 0)
{
// millis is now later than my 'next' time
{ do something }
lWaitMillis += 1000; // do it again 1 second later
}
else
{
// millis is still 'before' my 'next' time
// so I continue waiting
delay(1); // one possible thing you can do
}
}
[Get Code]
Solving the rollover with register arithmetic
The sketch below shows how to use unsigned variables, using the register arithmatic to overcome the rollover problem. The result it send to the serial monitor.
If the calculation for millis() and micros() is done with unsigned long, the difference between the new time and the old time is always valid, even in case of a rollover.
Remember to always use unsigned long variables to make this work.
// -------------------------------------------------------
//
// Rollover demonstration sketch
// Solving the rollover with register arithmetic
//
// Another test sketch for:
// http://playground.arduino.cc/Code/TimingRollover
//
// Using parts of:
// http://arduino.cc/en/Tutorial/BlinkWithoutDelay
//
// public domain
//
// Variables for the demonstration in the setup() function.
// The variables are "volatile" to force the calculation
// in the Arduino microcontroller for this test only.
// You don't need "volatile" in your sketch.
//
volatile byte p, q, r;
volatile unsigned long ulNew, ulOld, ul;
// Variables for the blinking led.
// Created according to:
// http://arduino.cc/en/Tutorial/BlinkWithoutDelay
// But updated to solve the rollover problem.
//
const int ledPin = 13;
int ledState = LOW;
unsigned long ul_PreviousMillis = 0UL;
unsigned long ul_Interval = 500UL;
void setup()
{
Serial.begin( 9600);
// If the Leonardo or Micro is used,
// wait for the serial monitor to open.
while (!Serial);
Serial.println( F("Rollover demonstration sketch."));
Serial.print( F("Solving the rollover problem"));
Serial.println( F(" with register arithmetic."));
Serial.println( "");
Serial.println( F("Test with unsigned 8-bit."));
p = 150;
q = 140;
r = p - q;
Serial.print( F("150 - 140 = "));
Serial.println( r, DEC);
p = 4; // rollover of value 260
q = 250;
r = p - q; // valid for unsigned variables
Serial.print( F("260 (=4) - 250 = "));
Serial.println( r, DEC);
Serial.println( "");
Serial.println( F("Test with unsigned long."));
// http://arduino.cc/en/Reference/UnsignedLong
ulNew = 3000000000UL;
ulOld = 2000000000UL;
ul = ulNew - ulOld;
Serial.print( F("3,000,000,000 - 2,000,000,000 = "));
Serial.println( ul, DEC);
ulNew = 705032704UL; // rollover of value 5,000,000,000
ulOld = 4000000000UL;
ul = ulNew - ulOld; // valid for unsigned long
Serial.print( F("5,000,000,000 (=705,032,704) - 4,000,000,000 = "));
Serial.println( ul, DEC);
Serial.println( "");
// The loop() function contains an example with millis()
Serial.print( F("A led at pin 13 will blink"));
Serial.println( F(" without rollover error"));
pinMode( ledPin, OUTPUT);
ul_PreviousMillis = millis();
}
void loop()
{
// Here is where you put your code
// that needs to be running all the time.
// Blink the LED.
unsigned long ul_CurrentMillis = millis();
// The next lines are very important
// Since the millis() is unsigned long, also the testing
// and updating the time must be done with unsigned long.
if( ul_CurrentMillis - ul_PreviousMillis > ul_Interval)
{
// Update the last time you blinked the LED
// This update with the interval
// must also be done with unsigned long.
// Option 1:
// Set the previous time to the current time.
// A delay by code will shift everyting further in time.
ul_PreviousMillis = ul_CurrentMillis;
// Option 2:
// Increment the previous time with the interval.
// The timing stays in pace.
// A delay by code, will shorten the next interval.
// If two intervals are missed, the next interval
// will be very short, since it is trying to catch up
// with the time.
// ul_PreviousMillis += ul_Interval;
// if the LED is off, turn it on and vice-versa:
if( ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}
[Get Code]
The result of the sketch is:
Rollover demonstration sketch.
Solving rollover with register arithmetic.
Test with unsigned 8-bit.
150 - 140 = 10
260 (=4) - 250 = 10
Test with unsigned long.
3,000,000,000 - 2,000,000,000 = 1000000000
5,000,000,000 (=705,032,704) - 4,000,000,000 = 1000000000
A led at pin 13 will blink without rollover error
พบรายการที่ร้องขออย่างใดอย่างหนึ่งถูกจัดการ 'โรลโอเวอร์' จาก 'millis()' และยัง 'micros()' ไม่จริงเป็นเรื่องยากมากที่จะจัดการกับ และมันเป็นสิ่งผมเคยต้องอยู่มากในบริบทต่าง ๆ จากโปรแกรมควบคุมเคอร์เนลเพื่อใช้งาน และ ไมโครคอนโทรลเลอร์ครั้งแรก ฉันจะอธิบายคณิตศาสตร์ส่วนเติมเต็มของสอง และลงนามกับไม่เต็มส่วนเติมเต็มของสองวิธีการแทนตัวเลขลบในไบนารีได้ มันต้องมีที่คุณเสียสละหนึ่งบิตของความแม่นยำ (สำคัญที่สุดบิต), การจัดการค่าลบสำหรับจำนวนเต็มแบบ 16 บิต ค่าเสริมสองของสามารถแสดงหมายเลขใด ๆ ระหว่าง-32768 ถึง 32767 รวม สำหรับตอนนี้ นี่คือสิ่งที่ผมจะมุ่งเน้นในจากคำนิยาม ถ้าคุณลบ 1 จากศูนย์ไบนารี ไบนารีคุณควรจบลง ด้วย -1 ไบนารี ในทางกลับกัน ถ้าคุณเพิ่ม 1 ไบนารีไบนารี -1 คุณควรได้รับเป็นศูนย์???????????????? + 0000000000000001 = 0000000000000000ทำ extrapolation บรรยากาศเล็กน้อย ได้สวยชัดว่า ต่อไปนี้เป็นจริง1111111111111111 + 0000000000000001 = 0000000000000000ถ้ามีบิตอื่นแสดง (เช่น 'ยก' บิตจ) คุณจะเห็นหมายเลข 17 บิต มีการตั้งค่าบิตสูง แต่เป็นผลมาจากการใช้ค่าไบนารียาว- คุณได้รับ 'โรลโอเวอร์'ดังนั้น การเพิ่มไบนารี 1 "ทั้งหมด 1" จะเป็นศูนย์ ต่อไปนี้จะเกิดขึ้น:0000000000000000 - 0000000000000001 = 1111111111111111ดังนั้น การแสดงของ -1 ต้องเป็น 'ทั้งหมด 1 บิต' สำหรับใด ๆ สองของเสริมจำนวนเต็ม กำหนดขนาดความยาวคงที่จำนวนเต็มในบิตขณะนี้ เป็นสิ่งสำคัญที่จะแยกแยะความแตกต่าง 'รับรอง' จาก 'เซ็น' จำนวนเต็มคณิตศาสตร์ ถ้าคุณต้องการลบค่ารับรองที่สอง และมีผลเชิงลบที่สองขนาดใหญ่ คุณต้องโยนผลลัพธ์จำนวนเต็มที่เซ็นชื่อ นี้จะเก็บผลการรับรองนั้นเป็นสองส่วนเติมเต็ม เช่นนั้น:รับรอง int i, j...ถ้า ((int)(i-j) < 0) {ทำบางสิ่ง}ก เป็นหัวใจของการแก้ปัญหาเพื่อ 'โรลโอเวอร์' ในกรณีที่ค่าของ 'ฉัน' มีไม่ได้ 'ข้าม' ของ 'เจ' ผลลัพธ์ของ ' ฉัน - j' (โยนให้เป็นจำนวนเต็มที่เซ็นชื่อ) จะเป็นค่าลบ 'ฉัน' ข้าม 'เจ' ผลลัพธ์จะเป็นบวกตัวอย่าง: สมมติว่า 'millis()' กลับเป็นจำนวนเต็มแบบ 16-บิต (ในความเรียบง่าย), ถ้าเวลาปัจจุบันของ 'millis()' เป็น 65500 และต้องรอ 1000 มิลลิวินาที คุณสามารถใช้คณิตศาสตร์รับรองเพิ่ม 1000-65500 และได้รับผลของ 964 (กลิ้งผ่านศูนย์ที่ไหนจะ 65536) เมื่อ ' 16 บิต ' millis() 'กลิ้งผ่าน' ศูนย์ จะยังคงเพิ่มจนกว่าจะ เกินไป ถึงค่า 964 ณ รหัสของคุณสามารถจดจำ 'ข้าม' โดยหักจาก millis() รอเวลา แปลงเป็นจำนวนเต็มที่เซ็นชื่อ และตรวจสอบว่า มันมีค่ามากกว่า หรือเท่ากับศูนย์รหัสต่อไปนี้เพื่อดูว่า คุณมี 'ข้าม' 1000 มิลลิวินาที 'เลื่อนจุด' และเริ่มต้นของตัวจับเวลาหน่วงเวลาที่อื่นของ 1000 มิลลิวินาทีหลังบางชนิดของการประมวลผลประจำงวดนั้นสามารถใช้รหัสชนิดเดียวกันกับ 'micros()' เป็นอย่างดีlWaitMillis ไม่นานคงยกเลิกการตั้งค่า() \{ lWaitMillis = millis() + 1000 ตั้งค่าเริ่มต้น}วนโมฆะ() \{ ถ้า ((ยาว) (millis() - lWaitMillis) > = 0) { millis จะช้ากว่าเวลาของฉัน 'ถัดไป' {ทำบางสิ่ง} lWaitMillis += 1000 ทำได้อีก 1 วินาทีต่อมา } อื่น { millis จะ 'ยังก่อน' เวลา 'ถัดไป' ดังนั้น ฉันยังคงรอคอย delay(1) เป็นสิ่งหนึ่งที่คุณสามารถทำได้ }}[รับโค้ด]แก้โรลโอเวอร์กับทะเบียนเลขคณิตร่างด้านล่างแสดงวิธีการใช้ตัวแปรไม่ ใช้ arithmatic ทะเบียนเพื่อเอาชนะปัญหาโรลโอเวอร์ ผลจะส่งไปยังจอภาพพอร์ตอนุกรมถ้าการคำนวณสำหรับ millis() และ micros() จะทำด้วยไม่นาน ความแตกต่างระหว่างเวลาใหม่และเวลาเก่าถูกต้องเสมอ แม้ในกรณีโรลโอเวอร์จำไว้ว่า ต้องใช้ตัวแปรยาวรับรองเพื่อทำให้งานนี้เสมอ// -------------------------------------------------------//โรลโอเวอร์สาธิตร่างแก้โรลโอเวอร์กับทะเบียนเลขคณิต//ร่างระดับอื่นทดสอบสำหรับ:http://playground.arduino.cc/Code/TimingRollover//ใช้ส่วนของ:http://arduino.cc/en/Tutorial/BlinkWithoutDelay//โดเมนสาธารณะ//ตัวแปรสำหรับการสาธิตในฟังก์ชัน setup()ตัวแปรคือ "ระเหย" เพื่อบังคับการคำนวณในไมโครคอนโทรลเลอร์สืบสำหรับการทดสอบนี้เท่านั้นคุณไม่จำเป็น "ระเหย" ในร่างของคุณ// ไบต์ระเหย p, q, r ระเหยไม่ยาว ulNew, ulOld, ulตัวแปรสำหรับการกะพริบไฟ ledสร้างตาม:http://arduino.cc/en/Tutorial/BlinkWithoutDelayแต่ปรับปรุงแก้ปัญหาโรลโอเวอร์//ledPin int ค่า const = 13int ledState =ต่ำรับรองยาว ul_PreviousMillis = 0ULรับรองยาว ul_Interval = 500ULยกเลิก setup(){ Serial.begin (9600); ถ้า Leonardo หรือไมโครใช้ รอตรวจสอบลำดับการเปิด ในขณะที่ (!ประจำ); Serial.println (F ("โรลโอเวอร์สาธิตร่าง")); Serial.print (F ("แก้ปัญหาโรลโอเวอร์")); Serial.println (F ("พร้อมทะเบียนเลขคณิต")); Serial.println (""); Serial.println (F ("ทดสอบ ด้วยรับรอง 8 บิต")); p = 150 q = 140 r = p - q Serial.print (F (" 150-140 =")); Serial.println (r, DEC); p = 4 โรลโอเวอร์มูลค่า 260 q = 250 r = p - q สำหรับตัวแปรไม่ถูกต้อง Serial.print (F (" (= 4) 260 - 250 =")); Serial.println (r, DEC); Serial.println (""); Serial.println (F ("ทดสอบ ด้วยไม่นาน")); http://arduino.cc/en/Reference/UnsignedLong ulNew = 3000000000UL ulOld = 2000000000UL ul = ulNew - ulOld Serial.print (F (" 3,000,000,000-2,000,000,000 =")); Serial.println (ul, DEC); ulNew = 705032704UL โรลโอเวอร์ค่า 5,000,000,000 ulOld = 4000000000UL ul = ulNew - ulOld ไม่ถูกต้องสำหรับระยะยาว Serial.print (F (" (= 705,032,704) 5,000,000,000 - 4,000,000,000 =")); Serial.println (ul, DEC); Serial.println (""); ฟังก์ชัน loop() ประกอบด้วยตัวอย่าง ด้วย millis() Serial.print (F ("A ไฟ led ที่ขา 13 จะกะพริบ")); Serial.println (F ("โดยโรลโอเวอร์ข้อผิดพลาด")); pinMode (ledPin แสดงผล), ul_PreviousMillis = millis()}ยกเลิก loop(){ ที่นี่เป็นที่ที่คุณใส่รหัสของคุณ ที่ต้องทำงานตลอดเวลา กะพริบไฟ LED รับรองยาว ul_CurrentMillis = millis() บรรทัดถัดไปมีความสำคัญมาก เนื่องจาก millis() การรับรองยาว นอกจากนี้ การทดสอบ และปรับปรุงเวลาต้องทำด้วยไม่นาน ถ้า (ul_CurrentMillis - ul_PreviousMillis > ul_Interval) { ปรับปรุงครั้งล่าสุดที่คุณคันนั้นกะพริบไฟ LED ปรับปรุงนี้กับช่วงเวลา ต้องทำด้วยไม่นาน ตัวเลือกที่ 1: ตั้งเวลาก่อนหน้าเวลาปัจจุบัน ความล่าช้า โดยรหัสจะเปลี่ยนซักคืนเพิ่มเติมในเวลา ul_PreviousMillis = ul_CurrentMillis แบบที่ 2: เพิ่มค่าเวลากับช่วงก่อนหน้านี้ เข้าพักช่วงเวลาในจังหวะนั้น เลื่อนตามรหัส จะย่นช่วงถัดไป ถ้าช่วงที่สองจะพลาด ช่วงถัดไป จะสั้นมาก เนื่องจากจะพยายามให้ทัน มีเวลาการ ul_PreviousMillis += ul_Interval ถ้า LED ถูกปิด เปิดบนและกลับ: ถ้า (ledState ==ต่ำ) ledState =สูง อื่น ledState =ต่ำ ชุด LED ที่ มี ledState ของตัวแปร: digitalWrite (ledPin, ledState); }}[รับโค้ด]ผลของการร่างคือ:โรลโอเวอร์สาธิตร่างแก้โรลโอเวอร์กับทะเบียนเลขคณิตทดสอบกับรับรอง 8 บิต150 - 140 = 10(= 4) 260 - 250 = 10ทดสอบกับไม่นาน3,000,000,000 - 2,000,000,000 = 10000000005,000,000,000 (= 705,032,704) - 4,000,000,000 = 1000000000ไฟ led ที่ขา 13 A จะกะพริบไม่พลาดโรลโอเวอร์
การแปล กรุณารอสักครู่..

หนึ่งในรายการที่ร้องขอผมพบว่าได้รับการจัดการแบบโรลโอเวอร์ '' จาก 'MILLIS ()' และ 'Micros ()' นี้เป็นจริงไม่ได้เป็นเรื่องยากมากที่จะจัดการกับและมันเป็นสิ่งที่ฉันได้จำเป็นเพื่อที่อยู่หลายครั้งในบริบทต่าง ๆ จากคนขับรถเคอร์เนลเพื่อการใช้งานและแน่นอนไมโครคอนโทรลเลอร์. ครั้งแรกผมจะอธิบายเติมเต็มสอง คณิตศาสตร์และลงนาม vs จำนวนเต็มไม่ได้ลงนาม. เติมเต็มสองเป็นวิธีที่จะแสดงตัวเลขติดลบในไบนารี มันต้องมีที่คุณเสียสละหนึ่งบิตของความแม่นยำ (บิตที่สำคัญที่สุด) ในการจัดการค่าลบ. สำหรับจำนวนเต็ม 16 บิตค่าเติมเต็มสองสามารถแทนจำนวนใด ๆ ระหว่าง -32768 ถึง 32767 รวม สำหรับตอนนี้เป็นสิ่งที่ผมจะเน้น. ตามคำนิยามถ้าคุณลบไบนารี 1 จากศูนย์ไบนารีที่คุณควรจะจบลงด้วยไบนารี -1 ตรงกันข้ามถ้าคุณเพิ่มไบนารี 1 ถึงไบนารี -1, คุณควรจะได้เป็นศูนย์. ???????????????? + 0000000000000001 = 0000000000000000 ทำอนุมานบรรยากาศเล็ก ๆ น้อย ๆ ก็สวยเห็นได้ชัดว่าต่อไปนี้เป็นความจริง. 1111111111111111 + 0000000000000001 = 0000000000000000 ถ้ามีบิตอื่นแสดง (เช่น 'ดำเนินการ' บิต) คุณจะเห็นเลขที่ 17 บิตบิตสูง ชุด แต่นี้เป็นผลมาจากการใช้ความยาวคงที่ค่าไบนารี . คุณจะได้รับ 'โรลโอเวอร์' ดังนั้นการเพิ่ม 1 ไบนารี "ทั้งหมด 1" ที่จะได้รับเป็นศูนย์ต่อไปนี้จะสามารถเป็นจริง: 0000000000000000-0000000000000001 = 1111111111111111 ดังนั้นการเป็นตัวแทนของ -1 จะต้องเป็น 'ทั้งหมด 1 บิต' สำหรับส่วนประกอบใด ๆ ของทั้งสอง จำนวนเต็มได้รับความยาวคงที่ขนาดจำนวนเต็มในบิต. ตอนนี้มันเป็นสิ่งสำคัญที่จะแยกแยะความแตกต่าง 'ได้รับการรับรอง' จาก 'ลงนาม' คณิตศาสตร์จำนวนเต็ม ถ้าคุณต้องการที่จะลบสองค่าไม่ได้ลงนามและมีผลเชิงลบหากที่สองมีขนาดใหญ่คุณต้องโยนผลการจำนวนเต็มลงนาม นี้จะรักษาผลที่ไม่ได้ลงชื่อราวกับว่ามันเป็นส่วนเติมเต็มสองเช่นดังนั้น: ลงนาม int ฉัน j; ... ถ้า ((int) (i - ญ) <0) {} ทำอะไรบางอย่างและนี่คือหัวใจของ วิธีการแก้ 'โรลโอเวอร์' ในกรณีที่มูลค่าของ 'i' ยังไม่ได้ 'ข้าม' ค่าของ 'J' ผลมาจาก 'i - J' (นักแสดงที่จะลงนามในจำนวนเต็ม) จะเป็นลบ หาก 'i' ข้าม 'J' ผลจะเป็นบวก. ตัวอย่าง: สมมติว่า 'MILLIS () กลับจำนวนเต็ม 16 บิต (สำหรับความเรียบง่าย) ถ้าปัจจุบัน' MILLIS () เวลาเป็น 65500 และคุณต้องการ รอ 1000 มิลลิวินาทีคุณสามารถใช้คณิตศาสตร์ที่ไม่ได้ลงชื่อเพื่อเพิ่ม 1,000-65,500 และได้รับผลของ 964 (กลิ้งไปยังศูนย์ที่สิ่งที่จะเป็น 65536) เมื่อ '16 บิต 'MILLIS ()' ม้วนไปที่รายการเพื่อเป็นศูนย์ก็จะยังคงเพิ่มขึ้นจนเกินไปถึง 964. ค่า ณ จุดที่รหัสจับเวลาของคุณสามารถรับรู้ 'ข้าม' โดยการลบเวลารอ จาก MILLIS () แปลงไปเป็นจำนวนเต็มลงนามและตรวจสอบว่ามันเป็นมากกว่าหรือเท่ากับศูนย์. ตรวจสอบรหัสต่อไปนี้เพื่อดูว่าคุณได้ 'ข้าม' 1000 มิลลิวินาทีจุดล่าช้า 'และเริ่มต้นการเป็นตั้งเวลา 1000 อีก . มิลลิวินาทีตามชนิดของการประมวลผลเป็นระยะ ๆ บางชนิดเดียวกันของรหัสสามารถนำไปใช้ 'Micros ()' เช่นกัน. คงไม่ได้ลงนาม lWaitMillis ยาวติดตั้งเป็นโมฆะ () \ { lWaitMillis = MILLIS () + 1000; // ตั้งค่าเริ่มต้น} ห่วงเป็นโมฆะ () \ { ถ้า ((ยาว) (MILLIS () - lWaitMillis)> = 0) { // MILLIS ตอนนี้ช้ากว่า 'ต่อไป' ฉันเวลาทำบางสิ่งบาง {} lWaitMillis + = 1000; // ทำมันอีกครั้ง 1 วินาทีต่อมา} อื่น{ // MILLIS ยังคง 'ก่อนที่จะถึงเวลาของฉันต่อไป' // ดังนั้นฉันยังคงรอความล่าช้า (1); // สิ่งที่เป็นไปได้อย่างใดอย่างหนึ่งที่คุณสามารถทำได้} } [รับรหัส] แก้โรลโอเวอร์กับเลขคณิตทะเบียนร่างด้านล่างแสดงให้เห็นว่าการใช้ตัวแปรที่ไม่ได้ลงชื่อใช้ arithmatic ลงทะเบียนที่จะเอาชนะปัญหาแบบโรลโอเวอร์ ผลที่ได้ก็ส่งไปยังจอภาพอนุกรม. หากคำนวณ MILLIS () และไมโคร () จะกระทำด้วยความที่ไม่ได้ลงชื่อยาวแตกต่างระหว่างเวลาใหม่และเก่าเวลาที่ถูกต้องอยู่เสมอแม้ในกรณีของโรลโอเวอร์. จำไว้เสมอ ใช้ตัวแปรยาวไม่ได้ลงนามเพื่อให้งานนี้. // --------------------------------------- ---------------- // // โรลโอเวอร์ร่างสาธิต// แก้โรลโอเวอร์กับเลขคณิตทะเบียน// // ร่างทดสอบอีก: // http: //playground.arduino ซีซี / รหัส / TimingRollover // // การใช้ชิ้นส่วนของ: // http://arduino.cc/en/Tutorial/BlinkWithoutDelay // // โดเมนสาธารณะ// // ตัวแปรสำหรับการสาธิตในการตั้งค่า () ฟังก์ชัน. / / ตัวแปรคือ "ความผันผวน" ที่จะบังคับให้คำนวณ// ในไมโครคอนโทรลเลอร์ Arduino สำหรับการทดสอบนี้เท่านั้น. // คุณไม่จำเป็นต้อง "ผันผวน" ในร่างของคุณ. // ระเหย P ไบต์, Q, R; ระเหยที่ไม่ได้ลงชื่อยาว ulNew , ulOld, UL; // ตัวแปรสำหรับกระพริบนำ. // สร้างตาม: // http://arduino.cc/en/Tutorial/BlinkWithoutDelay // แต่การปรับปรุงเพื่อแก้ปัญหาแบบโรลโอเวอร์. // const int ledPin = 13; int ledState = ต่ำลงนามยาว ul_PreviousMillis = 0UL; ยาว unsigned ul_Interval = 500UL; การติดตั้งเป็นโมฆะ () { Serial.begin (9600); // ถ้าเลโอนาร์โดหรือ Micro จะใช้// รอการตรวจสอบอนุกรมเพื่อเปิด . ในขณะที่ (อนุกรม); Serial.println (F ("ร่างสาธิตแบบโรลโอเวอร์.")); Serial.print (F ("การแก้ปัญหาแบบโรลโอเวอร์")); Serial.println (F (". กับเลขคณิตลงทะเบียน") ); Serial.println (""); . Serial.println (F ("การทดสอบที่มีการลงนาม 8 บิต")); p = 150; q = 140; r = p - Q; Serial.print (F ("150 - 140 = ")); Serial.println (R, ธันวาคม); p = 4; // โรลโอเวอร์มูลค่า 260 q = 250; r = p - Q; // ที่ถูกต้องสำหรับตัวแปรที่ไม่ได้ลงชื่อSerial.print (F ("260 (= 4) - 250 =")); Serial.println (R, ธันวาคม); Serial.println (""); Serial.println (F ("การทดสอบ ที่มีการลงนามยาว "));. // http://arduino.cc/en/Reference/UnsignedLong ulNew = 3000000000UL; ulOld = 2000000000UL; ul = ulNew - ulOld; Serial.print (F ("3,000,000,000 - 2,000,000,000 =") ); Serial.println (UL, ธันวาคม); ulNew = 705032704UL; // โรลโอเวอร์ของมูลค่า 5,000,000,000 ulOld = 4000000000UL; ul = ulNew - ulOld; // ถูกต้องสำหรับการลงนามยาวSerial.print (F ("5000000000 (= 705,032,704) - 4,000,000,000 =")); Serial.println (UL, ธันวาคม); Serial.println (""); // ห่วง () ฟังก์ชันที่มี เช่นกับ MILLIS () Serial.print (F ("นำที่ขา 13 จะกระพริบ")); Serial.println (F ("โดยไม่มีข้อผิดพลาดแบบโรลโอเวอร์")); pinMode (ledPin, OUTPUT); ul_PreviousMillis = MILLIS () ; } ห่วงเป็นโมฆะ () { // นี่เป็นที่ที่คุณใส่รหัสของคุณ// ที่ต้องทำงานตลอดเวลา. // Blink LED. ยาว unsigned ul_CurrentMillis = MILLIS (); // บรรทัดต่อไปมีความสำคัญมาก/ / ตั้งแต่ MILLIS () เป็นที่ไม่ได้ลงชื่อยาวยังทดสอบ// และการปรับปรุงเวลาที่จะต้องทำด้วยความที่ไม่ได้ลงชื่อยาว. ถ้า (ul_CurrentMillis - ul_PreviousMillis> ul_Interval) { // อัพเดทครั้งสุดท้ายที่คุณกระพริบตา LED // ปรับปรุงด้วยนี้ ช่วง// ยังจะต้องทำด้วยความที่ไม่ได้ลงชื่อยาว. // ตัวเลือกที่ 1: // ตั้งเวลาก่อนหน้านี้กับเวลาปัจจุบัน. // ล่าช้าโดยรหัสจะเปลี่ยน everyting ต่อไปในเวลา. ul_PreviousMillis = ul_CurrentMillis; // ตัวเลือกที่ 2: // เพิ่มขึ้นครั้งก่อนหน้านี้ที่มีช่วงเวลา. // ช่วงเวลาที่อยู่ในก้าว. // ล่าช้าโดยรหัสจะร่นช่วงต่อไป. // ถ้าสองช่วงเวลาจะพลาดช่วงเวลาต่อไป// จะสั้นมากเนื่องจาก มันพยายามที่จะจับขึ้น// กับเวลา. // ul_PreviousMillis + = ul_Interval; // ถ้า LED ปิดเปิดและในทางกลับกัน: ถ้า (ledState == ต่ำ) ledState = สูงอื่นledState = LOW ; // ตั้ง LED ที่มี ledState ของตัวแปร: digitalWrite (ledPin, ledState); } } [รับรหัส] ผลของร่างคือร่างแบบโรลโอเวอร์สาธิต. แก้โรลโอเวอร์กับเลขคณิตลงทะเบียน. ทดสอบกับที่ไม่ได้ลงชื่อ 8 บิต150-140 = 10 260 (= 4) - 250 = 10 ทดสอบกับที่ไม่ได้ลงชื่อยาว. 3,000,000,000 - 2,000,000,000 = 1000000000 5000000000 (= 705,032,704) - 4,000,000,000 = 1000000000 นำที่ขา 13 จะกระพริบไม่มีข้อผิดพลาดแบบโรลโอเวอร์
การแปล กรุณารอสักครู่..
