Hey Zusammen :) Es ist spät, ich habe mir lang den Kopf zerbrochen und nun hoffe ich von Euch auf nen kleinen Tip :) Ich habe ein Array data[8]. Dies ist gefüllt mit ( 0x01, 0x00, 0x0, 0x50, 0x00, 0x00, 0x00, 0x00). data[0] ist also 0x01, data[3] ist 0x50. In einem Fall stellt data[0...3] den Inhalt eines uint32_t dar. Mein Gedanke: Die Daten liegen ja im RAM hintereinander, sollte doch ein leichtes sein. uint32_t test; test = data[0]; ->> warn versucht, klappt natürlich nicht test = (uint32_t){data[0]}; ->> auch nicht uint32_t* ptr = data[0]; test = *prt --> test wird mit (0x75, 0x01, 0x00, 0x00) geladen. uint32_t* ptr = data[1]; test = *prt --> test wird endlich mit (0x01, 0x00, 0x00, 0x50) geladen. Dann resetet der µC uint32_t* ptr = &data[0]; test = *prt --> test ist nun (0x50, 0x00, 0x00, 0x01) und ab diesem Moment bin ich total durcheinander... evt ist es auch einfach zu spät... Aber evt habt Ihr nen Rat/Vorschlag für mich? Danke und Gruß Danny
Integers werden auf dem von dir benutzten Prozessor little-endian, d.h. beginnend mit dem niederwertigsten Byte im Speicher abgelegt. 0x01 wird somit als das niedrigstwertige und 0x50 als das höchstwertige Byte betrachtet, so das die gelesene uint32_t-Wert 0x50000001 ist.
Vielen Dank für die schnellen Antworten! Ich bin grad völlig verblüfft, bislang war für mich "big-endian" die einzig denkbarer Art und ich bin jahrelang damit in kein Problem gelaufen... Das muss ich mir ausgeruht morgen früh nochmal selbst verdeutlichen :)
Danny schrieb im Beitrag #3367193: > Ich bin grad völlig verblüfft, bislang war für mich "big-endian" die > einzig denkbarer Art und ich bin jahrelang damit in kein Problem > gelaufen... Was für Exoten-Prozessoren hast du denn jahrelang benutzt? Oliver
Oliver S. schrieb: > Was für Exoten-Prozessoren hast du denn jahrelang benutzt? Also, vor 20 Jahren war mal der Motorola 68000 (Atari, Amiga, Mac usw.) sehr populär (grad bei Assembler Programmierer). Der hatte Big-Endian.
Oliver S. schrieb: > Was für Exoten-Prozessoren hast du denn jahrelang benutzt? Sehr gebräuchliche Prozessoren mit Big Endian sind: - 68000 - PowerPC - SPARC Viele ARM-Prozessorkerne lassen sich wahlweise als Big oder Little Endian konfigurieren, teilweise per externem Endianess-Pin. Beispiel Alcatel MTC-20285. Auch StrongARM- und Xscale-Prozessoren werden oft in Big Endian verwendet, gerade in Netzwerkkomponenten, da die Header von TCP/IP-Paketen auch in Big Endian (sog. Network Byte Order) spezifiziert sind. Bei einigen MIPS-Prozessoren kann die Endianess sogar für jeden Prozess separat eingestellt werden, z.B. Toshiba TX39. Nachtrag: Auch aktuelle ARM-Kerne beherrschen beide Betriebsarten, exemplarisch für den Cortex-A9: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0407e/BABCIEHF.html
:
Bearbeitet durch User
DirkB schrieb:
1 | > uint32_t test; |
2 | > test = *(uint32_t*)(&data[0]); |
Weil noch keiner darauf eingegangen ist: DirkB hat hier völlig recht. Ganz unabhängig davon ob der TE einen kleinen oder großen Indianer programmiert, hat er auch Daten und Adressen durcheinandergewürfelt. So hat er z.B. hier: Danny schrieb: > uint32_t* ptr = data[1]; > test = *prt den Inhalt von data[1] (also vermutlich ein uint_8t) als Adresse eines uint32_t interpretiert. Und das geht in jedem Fall in die Hose. Wenn es das erwartete Ergebnis geliefert hat, dann auf jeden Fall nur zufällig. XL
Mensch, da habe ich ja etwas losgetreten :) Obwohl ich mir fest vornahm den Ziel-µC zu nennen, hab' ich's doch vergessen... Es ging/geht um einen Atmel AVR (Mega8 / Mega 128)... Und tatsächlich hatte ich diese Probleme in den ganzen letzten Jahren nicht, aber meiner Recherche nach kann das auch gut sein, denn Probleme treten ja nur auf wenn Daten zwischen zwei Unterschiedlichen Systemen getauscht werden. Auch dieses Mal wäre ich sicher nicht darüber gefallen, wenn ich mich nicht zu Testzwecken einmal als "fremdes System (big-endian-denkend)" eingemischt hätte :) einmal noch für mein Verständnis Dirk's Lösung: uint32_t test; test = *(uint32_t*)(&data[0]); mit (uint32_t*)(&data[0]); lade ich einen pointer auf einen uint32_t mit der Startadresse von data[0]. Durch den * vor dem ganzen wird der Ausdruck zum 32 Bit breiten Inhalt, auf den der Pointer zeigt. Um das big/little-endian muss ich mich dann zu Fuß kümmern. Hab ich das soweit richtig verstanden? Danke nochmal
vergessen: Dirk's Lösung ist also mein letzter geschriebener Schritt uint32_t test; uint32_t* ptr = &data[0]; test = *prt in einer Zeile, richtig?
Danny schrieb: > uint8_t Dann wirst du wohl mindestens ein Warning bekommen. Und dann wird sich das ganze nicht so verhalten, wie du dir das (wahrscheinlich) vorstellst. Benutze doch einen Pointer vom selben Typ.
:
Bearbeitet durch User
dann liest er aber kein 32bit-Wert aus 4 hintereinander liegenden 8bit-Werten
Danny schrieb: > dann liest er aber kein 32bit-Wert aus 4 hintereinander liegenden > 8bit-Werten Ah ja, mein Fehler. Klar, deshalb ja auch die Frage nach Endianess. Ziehe meinen Klugschiss zurück :)
Ro B. schrieb: > Danny schrieb: >> dann liest er aber kein 32bit-Wert aus 4 hintereinander liegenden >> 8bit-Werten > > Ah ja, mein Fehler. Klar, deshalb ja auch die Frage nach Endianess. > Ziehe meinen Klugschiss zurück :) Würds dann aber eher sauber coden und dann shiften/adden. Oder siehst du deine Vorgehensweise als optimiert?
Danny schrieb: > in einer Zeile, richtig? Ja. Mehr wollte ich auch nicht machen. Damit änderst du noch nichts an der Bytereihenfolge. Wenn du zwischen verschiedenen Systemen die Werte austauschen willst, solltest du dir mal die Funktionen wie htonl oder ntohl ansehen.
@Dirk: danke für den Tip, da werde ich mal vor dem schlafen gehen nach schauen :) für den Moment habe ich mir geholfen, indem ich nicht die Bytes selbst "errechnet" habe sondern per (uint32_t[]){ 200 } eingefügt...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.