Wenn Sie eine Gleichung in C / C ++ schreiben, wirken sich die zu bearbeitenden Datentypen sehr real auf die Ausgabe der Gleichung aus.
Jeder Typ mag int
, float
und unsigned long
hat unterschiedliche Verhaltensweisen und benötigt eine bestimmte Menge an Speicherplatz zum Speichern.
int
(auf Arduino) wird in 16 Bit gespeichert, wobei die Hälfte seiner Werte für negative Zahlen, die Hälfte für positive Werte und ein Wert für 0 angegeben wird. Dies ergibt einen Bereich von -2 ^ 15 (-32.768) bis + 2 ^ 15-1 (32.767).
unsigned long
(auf Arduino) ist 32 Bit, aber keines wird als negativ bezeichnet. sein Bereich ist dann 0 bis 2 ^ 32-1 (4294967295).
Was für eine Art von Mathe? Welche andere Art der Verarbeitung ist bei der Arbeit mit Millis ausgeschlossen?
Der Kern des Problems ist, dass die Zeit, in der Millis zurückkehrt, immer über 32767 hinausgeht und Sie versucht haben, es in einem Int zu speichern. Das Arduino konnte es nicht, weil es eine int
so große Zahl nicht halten kann. Die Art der Mathematik, für die dies verboten ist, ist die Mathematik, die mit kleineren Datentypen geschieht, nicht mit bestimmten Operationen. Vielleicht helfen diese Beispiele:
int i = 32767;
Serial.println(i);
//No problems here; it fits just fine
32767
i = 32767 + 1;
Serial.println(i);
//Oh no, the value didn't fit
-32768
unsigned long fake_millis = 42000;
i = fake_millis;
Serial.println(i);
//This is an example of millis going past an int
-23536
i = -10;
unsigned int j = i;
Serial.println(j);
//no way to put a negative number in an unsigned value
65526
uint32_t k = fake_millis;
Serial.println(k);
//unsigned long is a uint32_t on arduino; this works great!
42000
Die Art und Weise, wie dies implementiert wird, ist wirklich ziemlich genial; Wenn Sie daran interessiert sind, woher diese Zahlen kommen und warum sie so übergreifen, wie sie es tun, sollten Sie sich die gleichen Erklärungen der Zweierkomplement-Zahlendarstellungen ansehen.
unsigned long
dass sich mit verschiedenen Plattformen (z. B. x86) ändern kann,uint32_t
immer 32 vorzeichenlose Bits überall sein werden.32767 + 1
) undefiniertes Verhalten liefert, was fast immer eine schlechte Sache ist . Ihre anderen Beispiele sind dokumentiertes Verhalten, auf das Sie sich verlassen können.millis()
Gibt a zurückunsigned long
, eine 32-Bit-Ganzzahl ohne Vorzeichen auf dem Arduino. Wenn Sie dann versuchen, so etwas zu tununsigned int time = millis() - 1000
, versuchen Sie, dies in einer 16-Bit-Ganzzahl ohne Vorzeichen zu speichernunsigned int
. Eine 16-Bit-Ganzzahl kann niemals einen 32-Bit-Wert enthalten.Gemäß der C-Spezifikation , Absatz 6.3.1.3, werden die oberen 16 Bits verworfen.
Behalten Sie die
millis()
Ausgabe nach Möglichkeit in aunsigned long
und verwenden Sie Datentypen mit weniger Bits nur, wenn Sie absolut sicher sind, dass Sie keine Bits verlieren.Weitere Informationen zu expliziten Casts in C finden Sie hier: https://stackoverflow.com/a/13652624/1544337
quelle
uint32_t
einunsigned long
On-Arduino zurückgibt?unsigned long
.int time = millis() - 1000
) erfolgt, ist das Ergebnis ähnlich: Die oberen 16 Bits werden verworfen. Diesmal sagt der C-Standard, dass das Ergebnis implementierungsdefiniert ist und das Verhalten in der gcc-Dokumentation zum implementierungsdefinierten Verhalten von Ganzzahlen angegeben ist (vierter Aufzählungspunkt).Wenn Sie mit millis () arbeiten möchten, denken Sie daran, Ihre Variable mit dem Typ "uint32_t" zu initialisieren.
Machen Sie also so etwas wie "uint32_t last_millis", wo Sie die Ausgabe der Funktion "millis ()" speichern.
Andernfalls würde es, wie die anderen sagten, überlaufen, wenn es über 31.000 hinausgeht, was ziemlich schnell passieren wird.
quelle