Spørgsmål:
Arduino - Miller ()
user3060854
2015-03-06 02:35:22 UTC
view on stackexchange narkive permalink

Kopieret fra Arduino-referencen - millis ()

Tip : Bemærk, at parameteren for millis er en usigneret længe kan der genereres fejl, hvis en programmør prøver at lave matematik med andre datatyper som f.eks. mellemrum.

Hvilken type matematik? Hvilken anden form for behandling er udelukket, når du arbejder med millis?

Kunne nogen præcisere denne erklæring og / eller give et eksempel?

Tre svar:
BrettAM
2015-03-06 04:09:33 UTC
view on stackexchange narkive permalink

Når du skriver en ligning i C / C ++, har de datatyper, der betjenes, en meget reel effekt på ligningens output.

Hver type som int , float og usigneret lang har forskellige adfærd og tager en vis plads i hukommelse, der skal gemmes.

int (på arduino) gemmes i 16 bits, hvor halvdelen af ​​dens værdier gives til negative tal, halv-1 gives til positive værdier og en værdi gives til 0 Det giver det et interval på -2 ^ 15 (-32,768) til + 2 ^ 15-1 (32,767).

usigneret lang (på arduino) er 32 bits, men ingen betegnes som negative. dens rækkevidde er så 0 til 2 ^ 32-1 (4294967295).

Hvilken slags matematik? Hvilken anden form for behandling er udelukket, når du arbejder med millis?

Kernen i problemet er, at det er tiden millis returnerer nogensinde er kommet forbi 32767, og du forsøgte at gemme det i en int , kunne arduinoen ikke gøre det, fordi en int ikke kan rumme så stort et nummer. Den type matematik, dette er uden for grænserne, er, at matematik sker for mindre datatyper, ikke for nogen specifikke operationer. Måske hjælper disse eksempler:

  int i = 32767; Serial.println (i); // Ingen problemer her; det passer fint  

32767

  i = 32767 + 1; Serial.println (i); // Å nej, værdien passede ikke  

-32768

  usigneret lang fake_millis = 42000; jeg = falske_millis; Serial.println (i); // Dette er et eksempel på, at millis går forbi en int  

-23536

  i = -10; usigneret int j = i; Serial.println (j); // ingen måde at placere et negativt tal i en usigneret værdi  

65526

  uint32_t k = fake_millis; Serial.println (k); // usigneret lang er en uint32_t på arduino; dette fungerer godt!  

42000

Den måde, dette implementeres på, er virkelig genialt; Hvis du er interesseret i, hvor disse numre kommer fra, og hvorfor de spreder sig på den måde, de gør, skal du se på de samme forklaringer på tos komplementære nummerrepræsentationer.

Bare et simpelt spørgsmål: At erklære _ "usigneret lang fake_millis;" _ svarer til _ "uint_32 fake_millis;" _?
Ja, de er lige på arduinoen. Forskellen er, at "usigneret lang" kan ændre sig med forskellige platforme (f.eks. X86), "uint32_t" vil altid være 32 usignerede bits overalt.
Det skal bemærkes, at dit andet eksempel (`32767 + 1`) giver udefineret adfærd, hvilket er [næsten altid en dårlig ting] (http://stackoverflow.com/questions/9024826). Dine andre eksempler er dokumenteret adfærd, du kan stole på.
user6971
2015-03-06 03:11:52 UTC
view on stackexchange narkive permalink

millis () returnerer en usigneret lang , som er et 32-bit usigneret heltal på Arduino. Når du derefter prøver at gøre noget som usigneret int tid = millis () - 1000 , prøver du at gemme det i et 16-bit usigneret heltal usigneret int . Et 16-bit heltal kan aldrig indeholde en 32-bit værdi.

I henhold til C-specifikationen, afsnit 6.3.1.3, kasseres de øverste 16 bit.

Hvis det er muligt, skal du gemme millis () i en usigneret lang og kun bruge datatyper med færre bits, når du er helt sikker på, at du ikke mister bits.

Der er flere oplysninger om eksplicitte rollebesætninger i C her: https://stackoverflow.com/a/13652624/1544337

Tak for redigeringen. Jeg fjernede henvisningen til uint32_t, da det er noget andet. uint32_t garanterer, at du har et 32-bit usigneret heltal, det har ikke signeret lang (selvom det er på Arduino). Jeg nævnte også allerede, at det er en 32-bit type.
Derefter ville du ikke sige, at det er mere korrekt at sige, at det returnerer en 'uint32_t', der tilfældigvis er en 'usigneret lang' på arduino?
@BrettAM ifølge [docs] (http://arduino.cc/da/Reference/Millis) returnerer denne funktion en `usigneret lang`.
Fjernede gamle kommentarer, da hele diskussionen giver ringe mening med den aktuelle version af svaret. Bare hold dette for posten: Hvis konverteringen er til et _signeret_ heltal (`int time = millis () - 1000`), er resultatet ens: de øverste 16 bits kasseres. Denne gang siger C-standarden, at resultatet er implementeringsdefineret, og adfærden er specificeret i [gcc-dokumentationen om implementeringsdefineret adfærd for heltal] (https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation .html) (fjerde punkt).
nemik
2015-03-06 02:52:51 UTC
view on stackexchange narkive permalink

Når du vil lave ting med millis (), skal du bare huske at initialisere din variabel med typen "uint32_t"

Så gør noget som "uint32_t last_millis", hvor du gemmer output fra "millis ( ) "funktion.

Ellers som de andre sagde, ville den løbe over, når den går forbi 31.000, hvilket vil ske temmelig hurtigt.



Denne spørgsmål og svar blev automatisk oversat fra det engelske sprog.Det originale indhold er tilgængeligt på stackexchange, som vi takker for den cc by-sa 3.0-licens, den distribueres under.
Loading...