Piszę funkcję licznika czasu, która używa funkcji micros (), która generuje wartość typu unsigned long. Aby zrekompensować warunek przewrócenia, chciałbym użyć maksymalnej wartości dla tego typu zmiennej. Mam liczbę 4 294 967 295, ale spodziewałem się, że gdzieś będzie stała.
Czy gdzieś w plikach kompilatora Arduino znajduje się stała MAX_UNSIGNED_LONG?
Wypróbowałem tę nazwę i wiem, że prawdopodobnie to nie jest to. Nadal się rozglądam.
Odpowiedź
Różne limits.h
pliki w hierarchii avr-gcc
definiują ULONG_MAX
, co może być wartością Na przykład w moim systemie takie pliki mają ścieżki kończące się na hardware/tools/avr/lib/gcc/avr/4.8.1/include-fixed/limits.h
lub na hardware/tools/avr/lib/gcc/avr/4.8.1/install-tools/include/limits.h
i zawierają definicje takie jak poniżej.
/* Maximum value an `unsigned long int" can hold. (Minimum is 0). */ #undef ULONG_MAX #define ULONG_MAX (LONG_MAX * 2UL + 1UL)
Uwaga, LONG_MAX
jest również zdefiniowane w limits.h
.
Uwaga, arytmetyka wykonana w formie takiej jak
timeDelta = micros() - prevTime;
będzie poprawna (niezależnie od tego, czy micros()
przepełniony) przez okres do 2³² mikrosekund, czyli około 4295 sekund.
Odpowiedź
Nie musisz zrekompensować przewinięcie ”.
Zobacz moją odpowiedź: https://arduino.stackexchange.com/a/33577/10794
w kompilatorze Arduino?
Kompilator „Arduino” jest kompilatorem C ++. To jest punkt wyjścia dla większości pytań. Jeśli wyszukujesz w Google:
maximum unsigned long in c++
Pierwszy link prowadzi do:
http://www.cplusplus.com/reference/climits/
W tym jest napisane:
ULONG_MAX Maximum value for an object of type unsigned long int
Odpowiedź
Czy próbowałeś to zrobić ?:
unsigned long maxUnsignedLong = 0UL - 1UL;
lub:
const unsigned long ULONG_MAX = 0UL - 1UL;
Odpowiedź
Wydaje mi się, że z sieci nie jest łatwo znajdź właściwą odpowiedź maksymalną wartość micros () również moich własnych tablic arduino.
W moim przypadku , wygląda na to, że funkcja micros () przewija się co około 17 sekund. Na koniec napisałem Setup () dla siebie, aby wychwycić 0x1111111 jako maksymalną wartość micros () w następujący sposób.
void setup () { Serial.begin( 115200 ); // set the baud rate for writing messages. int go = 1; // set the flag to continue do-while loop; int n, nMin = 0, nMax = 0; // see how many more the numbers of calling micros() to get different value; int d, dMin, dMax; // see the time interval of micros() having different values; unsigned long currT; // the time of current micros() calling unsigned long lastT = micros(); // the time of last micros() calling unsigned long T[200]; // keep tracking 200 different lastT values int it = 0; // use T[it%200] to keep each lastT (circular buffer) do { n = 0; while( (currT=micros()) == lastT ) n++; // get a different value T[ (it++) % 200 ] = currT; // save the value d = currT - lastT; // get the difference if ( d<0 ) { // if micros() rolls over go = 0; // stop this do-while loop Serial.println(); // print new line for ( int i=it-200, j=0; i<it; i++ ) { Serial.printf( "%9x", T[i%200] ); // the last 200 different lastT values if ( ++j%5==0 ) Serial.println(); // } Serial.printf("\nat %d ms lastT 0x%x currT 0x%x n=[%d..%d] d=[%d..%d]\n", millis(), lastT, currT, nMin, nMax, dMin,dMax); } if ( !nMin && !nMax ) nMin = nMax = n, dMin = dMax = d; if ( nMin>n ) { PRINTF( "\nat %d ms nMin %d > n %d ", millis(), nMin, n); nMin = n; } else if ( nMax<n ) { PRINTF( "\nat %d ms nMax %d < n %d", millis(), nMax, n ); nMax = n; } if ( dMin>d ) dMin = d; else if ( dMax<d ) dMax = d; lastT = currT; } while( go ); }
Komentarze
- doprecyzuj komentarz " int n, nMin = 0, nMax = 0; "
- Nie, to jest całkowicie błędne . Zobacz arduino.cc/en/Reference/Micros , gdzie podano czas przewijania wynoszący około 70 minut, który odpowiada maksymalnemu długości bez znaku w mikrosekundach, przekonwertowanym na minut (właściwie 71 i pół minuty)
- Cóż, ' widziałem czas przewijania wynoszący około 70 minut. Ale naprawdę nie ' nie wiem, dlaczego na mojej płycie wifi boy esp32 połączenie micros () przewija się co 17 sekund. Czy możesz to sobie wyobrazić?
- Ten rodzaj eksperymentu " złapać go w akcie " jest błędny , ale potem ulega dalszemu pomieszaniu w różnicach między AVR a ESP – na przykład ten kod nie byłby ' t nawet poprawny na AVR, gdzie% d błędnie zinterpretowałby długość bez znaku – mógłby " prawie " działa na ESP32, ale nadal pomieszałby bit znaku. Naprawdę powinieneś przeczytać dokumentację lub kod źródłowy rdzenia.
- Odkryłem, że w rzeczywistości mój wifiboy esp32 działa z częstotliwością 240 MHz. Zatem maksymalna wartość typu long unsigned long w makrach () 0xffffffff / 240 to 0x1111111. To jest dokładnie to, co dostałem. Bardzo dziękuję!