Hallo, in einer (beliebigen) Struktur möchte ich alle Bytes nacheinander aufrufen, um sie in einem EEPROM zu speichern. Mir ist es dabei vollkommen egal, wie die einzelnen Elemente angeordnet sind, ich möchte einfach nur das komplette Gebilde Byte für Byte im EEPROM speichern. Wie kann ich in der Struktur die einzelnen Bytes (0...n, n ist bekannt) aufrufen? Danke für alle Antworten, mit vielen Grüßen Dennik
Z.B. indem Du die Struktur (genauer deren Addresse) auf uint8_t* castest. Oder eine Union mit einem passenden Array drumrumbastelst. Oder gleich die richtige Funktion zum schreiben in den EEPROM benutzt.
Dennik schrieb: > Mir ist es dabei > vollkommen egal, wie die einzelnen Elemente angeordnet sind, ich möchte > einfach nur das komplette Gebilde Byte für Byte im EEPROM speichern. Byte-weiser Zugriff wäre in etwa so möglich:
1 | struct EGAL |
2 | {
|
3 | int x; |
4 | int y; |
5 | }; |
6 | // ... |
7 | |
8 | struct EGAL s; |
9 | |
10 | char* ptr = (char*)&s; |
11 | |
12 | int i; |
13 | for (i = 0; i < sizeof(struct EGAL); ++i) |
14 | {
|
15 | // print each byte |
16 | printf("%d,", ptr[i]);
|
17 | } |
Wenn du die Struktur in einer union mit einer Variable passender Größe zusammenfasst, dann kannst du über die Einzelvariable die komplette Struktur auslesen. Nur das Rückschreiben ist etwas komplizierter, weil du dann wieder die Einzelgrößen schreiben musst. Beispiel:
1 | union DEINE_UNION{ |
2 | struct DEIN_STRUCT{ |
3 | u8 deine_variable1; |
4 | u8 deine_variable2; |
5 | };
|
6 | u16 deine_zusammenfassung; |
7 | };
|
Wenn ich dein Problem richtig verstanden habe, dann heisst die Lösung deines Problems "union". Da sieht dann so ungefähr aus:
1 | union{ |
2 | byte[LEN_STRUCT] rawData; |
3 | struct { |
4 | // hier kommen deine Structfelder rein >
|
5 | int mySignal; |
6 | } Data; |
7 | } myUnion; |
Kannst dann über myUnion.rawData[x] auf die Rohdaten zugreifen, und über myUnion.Data.mySignal auf einzelne Nutzdaten. Hoffe das in obigem Code kein Fehler drinnen ist, habe die Syntax nicht überprüft. Oder halt auf einen byte pointer casten, aber das finde ich persöhnlich nicht so sauber.
Die Union-Variante setzt voraus, daß der byte-Array-Teil größer sein muss als der struct-Teil. Das aber ist nicht garantiert, und so ist das eine schöne potentielle Fehlerquelle. Sofern das Ergebnis des byteweisen Zugriffs nicht auf einer komplett anderen Hardwarearchitektur wiederum in einer Struktur genutzt werden soll, ist am typecast nichts "unsauber".
peterguy schrieb: > Oder halt auf einen byte pointer casten, aber das finde ich persöhnlich > nicht so sauber. Egal wie du es machst, diese Operation wird niemals 'sauber' sein. Denn streng genommen ist auch die Union Variante nicht vom C-Standard gedeckt. Genausogut könnte ich argumentieren, dass das umcasten des Pointers auf einen anderen Typ die etwas ehrlichere Variante ist, weil die Absicht dahinter klarer ist, als das verschleierte einschreiben in eine Union und auslesen über einen anderen Union-Member (und genau das ist dann auch der Punkt, an dem der Standard keine Zusicherung mehr macht: offiziell darf man eine Union nur über den Member auslesen über den die Daten auch in die Union gekommen sind) Diese Lösung mit union
1 | union{ |
2 | byte[LEN_STRUCT] rawData; |
3 | struct { |
4 | // hier kommen deine Structfelder rein >
|
5 | int mySignal; |
6 | } Data; |
7 | } myUnion; |
ist allerdings ganz schlecht, weil sie den Programmierer dazu zwingt die Strukturgröße zu kennen. Bei solchen Sachen IMMER eine Lösung suchen, die das Abzählen von irgendwelchen Größen dem Compiler aufbürdet. Sprich: sizeof benutzen!
Rufus Τ. Firefly schrieb: > Die Union-Variante setzt voraus, daß der byte-Array-Teil größer sein > muss als der struct-Teil. Das aber ist nicht garantiert, und so ist das > eine schöne potentielle Fehlerquelle. Mit __attribute__((_packed_)) stellt das kein Problem dar.
Vielen Dank für die schnellen Antworten. Den Vorschlag vom klaus habe ich implementiert. Zumindest ist der Compiler schon mal damit zufrieden. Wenn ich morgen auch noch die EEPROM-Leseroutine fertig habe, werde ich testen können, ob es funktioniert. Mit vielen Grüßen und nochmals Danke, Dennik
Das hier
>1 | > union{ |
2 | > byte[LEN_STRUCT] rawData; |
3 | > struct { |
4 | > // hier kommen deine Structfelder rein > |
5 | > int mySignal; |
6 | > } Data; |
7 | > } myUnion; |
8 | >
|
ist übrigens noch aus einem ganz anderen Grund schlecht. Die union kann so nur über rawData initialisiert werden, direkt in mySignal zu schreiben, funktioniert nicht.
Rufus Τ. Firefly schrieb: > Die Union-Variante setzt voraus, daß der byte-Array-Teil größer sein > muss als der struct-Teil. Das aber ist nicht garantiert, und so ist das > eine schöne potentielle Fehlerquelle.
1 | struct DATA |
2 | {
|
3 | u8 x; |
4 | u8 y; |
5 | }; |
6 | |
7 | #define LEN sizeof(struct DATA) |
8 | |
9 | union DATA_ACCESS |
10 | {
|
11 | struct DATA data; |
12 | u8 access[LEN]; |
13 | }; |
Die union kann je nach Alignment Platz verschwenden, aber das "access" Array ist nie zu klein.
Dennik schrieb: > Vielen Dank für die schnellen Antworten. > Den Vorschlag vom klaus habe ich implementiert. Zumindest ist der > Compiler schon mal damit zufrieden. Wenn ich morgen auch noch die > EEPROM-Leseroutine fertig habe, werde ich testen können, ob es > funktioniert. ? Du brauchst 24 stunden um die Aufrufe so zu schreiben
1 | eeprom_read_block( (uint8_t*)&myStructVariable, |
2 | (uint8_t*)&eemyStructVariable, |
3 | sizeof( *myStructVariable ) ); |
bzw.
1 | eeprom_write_block( (uint8_t*)&myStructVariable, |
2 | (uint8_t*)&eemyStructVariable, |
3 | sizeof( *myStructVariable ) ); |
für die Variablen
1 | struct irgendwas { |
2 | ...
|
3 | };
|
4 | |
5 | struct irgendwas eemyStructVariable EEMEM; |
6 | struct irgendwas myStructVariable; |
> ? > Du brauchst 24 stunden um die Aufrufe so zu schreiben Nein - es wird in 24 Stunden fertig sein. Die Daten werden übrigens dreifach im EEPROM abgelegt und sowohl nach dem schreiben, als auch beim Lesen miteinander verglichen. Weiterhin wird das interne Prozessabbild des verwendeten µCs zyklisch mit den gespeicherten EEPROM-Daten aktualisiert. - Incl. Test dauert das einfach etwas. Mit freundlichen Grüßen, Dennik
Die ersten Test's des Programms sind positiv verlaufen. Die von klaus vorgeschlagene Lösung scheint gut zu funktionieren. Nochmals herzlichen Dank (an alle), Dennik
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.