Forum: Mikrocontroller und Digitale Elektronik ATMEGA: uint32_t* / Speicherstellen


von Marcel Pokrandt (Gast)


Lesenswert?

Morgen Jungs und Mädels... Klasse Seite die ihr da habt. Hat mir schon
oft weitergeholfen - jetzt hab ich aber ein kleines Problem.
Es geht mir um folgendes. Ich lese von meinem IPod über den UART eine 4
Byte lange Zahl ein.
Die berechne ich mir derzeit durch ne wilde Multiplikation in uint32_t
und funktioniert aus super - is aber natürlich lahmarschig! Hab jetzt
den Quellcode nicht da - sieht aber in etwa so aus:

(uint32_t) meineZahl = (uint8_t)byte[3] + (uint8_t)byte[2] * 255 +
(uint8_t)byte[3] * 16665[...]

Ich dachte mir da - eigentlich sollte es doch möglich sein, direkt in
die Datenstruktur uint32_t zu schreiben und mir dadurch die Berechnung
zu sparen. Also hab ich mir nen Zeiger gebastelt und die 4 Bytes
überprüft. Dummerweise hab ich nur die zwei niederwertigsten gefunden -
kann also nur Zahlen bis ~~16000 darstellen. Die Bytes scheinen
irgendwie nicht linear im Speicher angeordnet zu sein. In den
Quellcodes der libc hab ich da nur ne typedef von uint32_t gefunden,
die mir nicht weiterhilft.

Weiss da einer was zu??

von Ingo (Gast)


Lesenswert?

ja, das geht (ungefähr so, ist wohl nicht der schönste Code)

uint32_t meineZahl
uint8_t *meineZahlPointer = &meineZahl

for (int i = 0; i<4; i++)
{
    meineZahlPointer[i] = byte[i];
}

Du legst also ein Feld über Deinen 32bit int. Ginge auch mit einer
union:

union
{
    uint32_t zahl;
    uint32_t byte[4];
} meine;

Allerdings bekommst Du u.U. dann ein Problem mit der endianess der
Bytes, da der iPod möglicherweise big endian rechnet, der PC aber
little endian.

von Marcel Pokrandt (Gast)


Lesenswert?

Gerade so eine ähnliche Lösung hatte ich wie gesagt mit dem Zeiger schon
ausprobiert. Und da wunderte ich mich darüber, dass er nur die 2
niederwertigsten Bytes ausgewertet hat.

Aber ich muss zugeben: An eine Union-Struktur hatte ich noch gar nicht
gedacht. Das hat bedeutend mehr Stil als mein Gefrickel mit dem Zeiger,
Dereferenzierung etc.
Ich werd das nochmal testen und werde berichten, obs geklappt hat.

von Marcel Pokrandt (Gast)


Lesenswert?

PS.
Mit dem Endian-Problem hast du übrigens Recht. Die Reihenfolge der
Bytes mussten umgedreht werden. Das hatte ich aber schon
berücksichtigt. Zumindest die Bitreihenfolge innerhalb der Bytes ist
korrekt. Ist ja auch schonmal was wert.

von Rick Dangerus (Gast)


Lesenswert?

Mach doch statt der Multiplipation einen shift:

meineZahl = byte[1]<<24 + byte[2]<<16 + byte[3]<<8 + byte[4];

Rick

von Marcel Pokrandt (Gast)


Lesenswert?

Das mit dem Shift funktioniert nur, wenn ich die einzelnen Bytes
zunächst in ein uint32_t umwandel. Sonst hab ich nachher 4 Bytes mit
dem Wert 0. Aber die Idee ist gut... g

Wie gesagt. Ich werde heute abend oder die Tage mal das mit der
Union-Struct versuchen

von Marcel Pokrandt (Gast)


Lesenswert?

Oh mann oh mann... es war meine Blödheit.
Die Berechnung war wohl von Anfang an OK - .da ich aber das Ergebnis
mit der UTOA-Funktion ausgegeben habe und nicht wusste, dass die nur 16
Bit verarbeitet, hatte der das immer abgeschnitten. Für 32Bit Werte
gibts die UTLOA....
Habs jetzt jedenfalls mit deinem Vorschlag übernommen und sieht jetzt
so aus:

uint32_t char4ToUint32(char* c) {
  union byteUint32union {
      uint32_t zahl;
      uint8_t byte[4];
  } ;
  union byteUint32union unionzahl;

  unionzahl.byte[0] = c[3];
  unionzahl.byte[1] = c[2];
  unionzahl.byte[2] = c[1];
  unionzahl.byte[3] = c[0];

  return unionzahl.zahl;
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.