PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : uint16_t größte Variable?



Wsk8
06.09.2013, 19:52
Hallo,
heute war ich wieder fleißig am proggen, leider hab ich etwa 2h durch einen wirklich dummen Fehler verloren :(

Ich habe den Wert vom Timer1 eines Mega8 ausgelesen. Timer1 = 16bit. Gespeichert habe ich den Wert in uint32_t.
Warum jetzt 32bit? Ganz einfach, ich wollte noch einen festen Wert dazumultiplizieren und ein uint32_t sollte ja theoretisch über 4Mrd speichern können.

NOOOOP!!! Das Ding läuft genauso wie ein uint16_t bei 65535 über!!!

WAS SOLL DAS???

mfg

Klebwax
07.09.2013, 06:05
NOOOOP!!! Das Ding läuft genauso wie ein uint16_t bei 65535 über!!!

WAS SOLL DAS???

Wenn das wirklich so ist, arbeitet dein Compiler nicht standardkonform oder er hat einen kapitalen Bug. Um das erste auszuschließen, kannst du ja mal in die stdint.h schauen. Da muß so etwas drin stehen wie:


/* Maximum of unsigned integral types. */
# define UINT8_MAX (255)
# define UINT16_MAX (65535)
# define UINT32_MAX (4294967295U)

Wenn du das findest, sollte sich der Compiler an den C Standard halten und du hast einen Compiler-Bug gefunden.

MfG Klebwax

markusj
07.09.2013, 08:39
ich wollte noch einen festen Wert dazumultiplizieren und ein uint32_t sollte ja theoretisch über 4Mrd speichern können.

Ich habe die Regeln zur Typumwandlung nicht präsent, vermute aber folgendes: "Fester Wert" ist eine Konstante, damit int und 16-Bit breit. TCNT1 ist ebenfalls 16-Bit breit. Also bekommst du eine 16-Bit-Multiplikation, die läuft über und das Ergebnis landet in deiner 32-Bit-Variablen.

Grüße,
Markus

Wsk8
07.09.2013, 11:26
Ich arbeite mit dem Atmel Studio 6.1.2674 - SP1

In der stdint.h

#define INT32_MAX 0x7fffffffLL
#define INT32_MIN (-INT32_MAX - 1LL)
#define UINT32_MAX (__CONCAT(INT32_MAX, U) * 2ULL + 1ULL)

#else /* !__USING_MINT8 */
#define INT32_MIN (-INT32_MAX - 1L)



Ich habe die Regeln zur Typumwandlung nicht präsent, vermute aber folgendes: "Fester Wert" ist eine Konstante, damit int und 16-Bit breit. TCNT1 ist ebenfalls 16-Bit breit. Also bekommst du eine 16-Bit-Multiplikation, die läuft über und das Ergebnis landet in deiner 32-Bit-Variablen.
Ich habe die 32bit Variable extra mit 65500 initialisiert und dann hochgezählt und musste feststellen, dass diese bei 65535 überläuft. Also nur 16bit.

mfg

markusj
07.09.2013, 12:19
Ich habe die 32bit Variable extra mit 65500 initialisiert und dann hochgezählt und musste feststellen, dass diese bei 65535 überläuft. Also nur 16bit.

Quelltext bitte. Ich bin fast geneigt zu wetten, dass dein Debugging-Code einen Fehler hat. In der Größenordnung printInt(uint16_t) oder so ;)

Grüße,
Markus

Wsk8
07.09.2013, 12:25
Da ich es schon anders gelöst habe, habe ich den genauen nicht mehr, aber das Prinzip war genau so:

uint32_t myVar = 65500;
char tmp[12] = {0};


while(1) {
sprintf(tmp, "%u", myVar);
lcd_string(tmp);

myVar++;
}

EDIT: Ich verwende einen Mega8, falls das einen Unterschied macht.

mfg

markusj
07.09.2013, 13:50
sprintf(tmp, "%u", myVar);

%u ist 16 Bit breit, nimm Mal %uu ...

Grüße,
Markus

Wsk8
07.09.2013, 15:26
Die Ausgabe funktioniert jetzt, aber die anfängliche Berechnung ist immer noch falsch :(

Die sieht so aus:


#define TICK 32


uint32_t myVar = 0;


ISR(...) {
myVar = TCNT1;
TCNT1 = 0;

myVar *= TICK;

...
}

mfg

seite5
08.09.2013, 07:38
hi,
evtl.: myVar*=(uint32_t)TICK;
mfg
Achim

markusj
08.09.2013, 10:29
Die Ausgabe funktioniert jetzt, aber die anfängliche Berechnung ist immer noch falsch :(

Was passiert? Das myVar 32-Bit breit ist, muss die Multiplikation auch mit 32-Bit erfolgen. Das sollte so eigentlich stimmen ...
Du könntest Mal probieren, "#define TICK 32UL" zu schreiben (das hat die gleiche Wirkung wie der Vorschlag von Achim), ggf. bekommst du Probleme wegen unsigned*signed, aber ich bezweifle das.

Grüße,
Markus

SprinterSB
10.09.2013, 20:04
Einige von Atmel verbreitete Distributionen von avr-gcc enthalten fehlerhafte 32 = 16*16 routinen, siehe z.B.

http://gcc.gnu.org/PR52474