Hi Community, ich hab folgendes Problem: Ich habe eine 8Bit AVR MCU und wenn ich nun eine Variable vom Typ uint32_t habe und sowas mache: uint32_t counter = 0x1a2b3c4d; dann legt er es so im Speicher ab: 4d3c2b1a Also ist das wohl Little Endian. Das Problem ist aber, dass ich ein Netzwerkprotokoll implementiere und da brauche ich Big Endian. Gibt es da jetzt einen einfachen Weg um das zu erreichen? Ich könnte jetzt zwar statt eines uint32_t einfach ein Array mit vier uint8_t nehmen, aber wenn ich dann z.b. nen Counter habe und den erhöhen will, muss ich den Counter ja dann "manuell" implementieren, also etwa so: counter[0]++; if(counter[0] == 0) counter[1]++; if(counter[1] == 0) counter[2]++; if(counter[2] == 0) counter[3]++; Alternativ könnte ich natürlich erst mal mit nem uint32_t arbeiten und ganz normal inkrementieren und damit rechnen und muss es dann umkopieren nach dem Motto: counter_8[0] = (counter_32 >> 24); counter_8[1] = (counter_32 &0xFF0000) >> 16; counter_8[2] = (counter_32 &0xFF00) >> 8; counter_8[3] = (counter_32 &0xFF); aber das finde ich auch unschön. Gibt es da noch nen eleganteren Weg?
An den Code aus dem uIP-Stack angelehnt:
1 | #if BYTE_ORDER == BIG_ENDIAN
|
2 | #define HTONS(n) (n)
|
3 | #define HTONL(n) (n)
|
4 | #else
|
5 | #define HTONS(n) ((uint16_t)((((uint16_t) (n)) << 8) | (((uint16_t) (n)) >> 8)))
|
6 | #define HTONL(n) (((uint32_t)HTONS(n) << 16) | HTONS((uint32_t)(n) >> 16))
|
7 | #endif
|
8 | |
9 | #define NTOHS(n) HTONS(n)
|
10 | #define NTOHL(n) HTONL(n)
|
HTONS steht für Host to Network Short (16 Bit) HTONL steht für Host to Network Long (32 Bit) NTOHS und NTOHL entsprechend für Network to Host, machen aber natürlich das gleiche. Das praktische an den Makros ist, dass man sie auch in Switch-Case-Statements für Konstanten benutzen kann und damit schon zur Compilezeit aufgelöst werden. Zur Verwendung: Intern mit ganz normalen uint16_t und uint32_t rechnen. Direkt vor dem Senden bzw. Empfangen das Makro benutzen, um den Wert umzukopieren. In der Regel muss er ja sowieso von einer lokalen Variable in einen Sendepuffer oder umgekehrt kopiert werden, da kann man ihn mit Hilfe des Makros gleich bei umsortieren.
Obs schrieb: > Gibt es > da jetzt einen einfachen Weg um das zu erreichen? Entweder mit der Union, was Fabian beschrieb, oder eine kleine Umsortierfunktion mit unter Umständen skalierbarer Byteanzahl als Übergabeparameter. Da ist die Frage, was von beiden komfortabler, platzsparender oder schneller ist, und was man davon idealerweise benötigt. Notfalls das Assemblerlisting anschauen, welchen Code eine Union erzeugt, und welchen eine einfache Umsortierung. Gelegentlich bastelte ich für Assemblerprogramme mal irgendwo gefundene Funktionen von Little-Endian auf Big-Endian um, und umgekehrt. Oder ich machte eine Copy-Funktion dazwischen. Denn man findet für den selben µC oft fertige Routinen beider Arten, und möchte sich in seinem Programm auf eine Art fest legen.
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.