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:
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:
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
intmySignal;
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
intmySignal;
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
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
> ?> 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