Hallo
ich will mir eine Art Datenlogger bauen, der Daten auf eine SD-Karte
speichert.
Von der Karte bekomme ich immer 512 Bytes in Form eines Arrays.
Nun will ich am Anfang des Codes sozusagen den Bauplan eines Logs (bspw.
benötigt ein Log 20 Bytes; 0-5: Zeit, 6-15: Ort, 16-19: Information)
festlegen. Diese einzelnen Logs sind nacheinander in den 512 Bytes zu
finden.
Das Programm soll nun nach übergabe der Startposition im 512-Byte-Array
den Log entschlüssen, also dass man dann auf die einzelnen Attribute
zugreifen kann.
Ich hätte an einen Struct gedacht, aber ich weiß nicht, wie man dem dann
die Daten übergibt.
Gruß
Richi
Richard W. schrieb:
> Nun will ich am Anfang des Codes sozusagen den Bauplan eines Logs (bspw.
> benötigt ein Log 20 Bytes; 0-5: Zeit, 6-15: Ort, 16-19: Information)
> festlegen.
Hier muss ich nachhaken.
Ist dieser Aufbau fix oder kann sich der verändern?
> Diese einzelnen Logs sind nacheinander in den 512 Bytes zu
> finden.
> Das Programm soll nun nach übergabe der Startposition im 512-Byte-Array
> den Log entschlüssen, also dass man dann auf die einzelnen Attribute
> zugreifen kann.
>
> Ich hätte an einen Struct gedacht, aber ich weiß nicht, wie man dem dann
> die Daten übergibt.
Indem du die Einzelteile an die Member zuweist. Ein struct ist in diesem
Sinne nichts anderes als mehrere Einzelvariablen, die unter einem
Überbegriff zusammengefasst werden. Mit den Membern arbeitet man ganz
genau so, wie man es auch tun würde, wenn die Varablen einzeln da
stünden.
1 | struct Datum {
| 2 | uint8_t Tag;
| 3 | uint8_t Monat;
| 4 | uint16_t Jahr;
| 5 | char Wochentag[10];
| 6 | };
| 7 |
| 8 | int main()
| 9 | {
| 10 | struct Datum Geburtstag;
| 11 |
| 12 | Geburtstag.Tag = 22;
| 13 | Geburtstag.Monat = 3;
| 14 | Geburtstag.Jahr = 1963;
| 15 |
| 16 | strcpy( Geburtstag.Wochentag, "Sonntag" );
| 17 | }
|
Da verändert sich nichts, ausser dass die einzelnen Teile unter einem
Überbegriff zusammengefasst sind, also in eine Art Container verpackt
sind und dieser Container als ganzes an Funktionen übergeben werden kann
oder in einem Rutsch kopiert werden kann.
Ja, der Aufbau ist Variabel.
Was ich eigentlich wissen will ist wie man das mit dem Übergeben macht,
also ich sag der Funktion die Länge des Logs und die Startposition und
dann Kopiert die Byte1 aus dem 512-Byte_Array nach Struct.Byte1 ...
Also ohne zu wissen was da in dem Struct steht.
Hoffe es ist verständlich?!?
Gruß
Richi
Richard W. schrieb:
> Ja, der Aufbau ist Variabel.
>
> Was ich eigentlich wissen will ist wie man das mit dem Übergeben macht,
> also ich sag der Funktion die Länge des Logs und die Startposition und
> dann Kopiert die Byte1 aus dem 512-Byte_Array nach Struct.Byte1 ...
>
> Also ohne zu wissen was da in dem Struct steht.
Das geht nicht.
Den Aufbau des Ziels musst du schon kennen. Zumindest in groben Zügen.
Aber dein LOG wird ja wahrscheinlich immer denselben Aufbau haben, oder?
Zuerst Zeit, dann Ort, dann Logtext.
Man kann zb den Logtext variabel lang gestalten mittels dynamischer
Allokierung. Aber eigentlich möchte man in einem µC gerade das
vermeiden.
Nein, vielleicht hast du mich falsch verstanden.
Pro Mic eine Logart, da ich verschiedene Sachen loggen möchte und
deshalb auch verschiedene Parameter brauche.
Richard W. schrieb:
> Nein, vielleicht hast du mich falsch verstanden.
Das kann schon sein.
> Pro Mic eine Logart, da ich verschiedene Sachen loggen möchte und
> deshalb auch verschiedene Parameter brauche.
Dann würde ich mir als erstes Gedanken darüber machen, ein gemeinsames
Log-Format zu bekommen, in dem alle möglichen Logs dargestellt werden
können.
Das wird dann der Aufbau der struct.
Beim Einlesen der SD Karte wird festgestellt, welche Daten vorhanden
sind, und die entsprechenden Member der globalen Log-Struktur befüllt.
Oder hab ich dich wieder missverstanden?
(In dem Fall würde ich dich bitten einfach mal konkret ein oder 2 Logs
herzuzeigen und auch wie das Ergebnis aussehen soll)
Der Aufbau der Logs is ja eigentlich egal.
Es geht mir nur darum den Log auf die SD-Karte zu schreiben, wobei auf
einer Seite der Karte mehrere Logs abgespeichert sind.
Ich will also wiisen, wie man einen Struct Byteweise kopiert, also ohne
dass man die interne Aufteilung des Structs kennen muss.
Richard W. schrieb:
> Ich will also wiisen, wie man einen Struct Byteweise kopiert, also ohne
> dass man die interne Aufteilung des Structs kennen muss.
Irgendetwas von der struct musst du kennen und sei es nur die komplette
Größe.
memcpy( ziel, quelle, sizeof(quelle) );
oder mit einer klassischen for Schleife
dazu castest du dir die Startadresse der struct um in einen Bytepointer
und das wars dann schon.
1 | void WriteToSD( uint8_t * Bytes, size_t length )
| 2 | {
| 3 | size_t i;
| 4 |
| 5 | for( i = 0; i < length; ++i )
| 6 | WriteByte( Bytes[i] );
| 7 | }
| 8 |
| 9 | int main()
| 10 | {
| 11 | struct irgendwas Daten;
| 12 |
| 13 | ....
| 14 |
| 15 | WriteToSD( (uint8_t*)&Daten, sizeof( Daten ) );
| 16 | }
|
Oder reden wir jetzt immer noch aneinander vorbei?
Im folgenden Link hab ich aber gefunden, dass die Einzelnen Elemente
nicht unbedingt nebeneinander liegen müssen.
Ich bin mir aber nicht sicher ob das auch beim AVR so ist.
http://pronix.linuxdelta.de/C/standard_C/c_programmierung_18.shtml#5
Vielleicht kannst du mir da helfen ob es wirklich immer so ist, dass er
die Speicherzellen nebeneinander anlegt.
Gruß
Richi
Richard W. schrieb:
> Im folgenden Link hab ich aber gefunden, dass die Einzelnen Elemente
> nicht unbedingt nebeneinander liegen müssen.
> Ich bin mir aber nicht sicher ob das auch beim AVR so ist.
Auf einem AVR hast du kein Padding.
Aber im Allgemeinen hast du recht: Padding müsste man berücksichtigen.
Dazu muss man aber wieder den Strukturaaufbau kennen :-)
OK, dann hast du mir sehr viel weitergeholfen!
Danke!!!
Gruß
Richi
Hallo
melde mich nochmal.
Wie gesagt krieg ich ja ein 512-Byre-Array von der SD-Karte geliefert,
oder muss ihr ein solches liefern.
Nun ist mir aufgefallen, dass, wie ich es bisher gemacht habe, nämlich
den Teil aus dem Array in den Struct zu kopiere, dort zu bearbeiten,
dann wieder zurückkopieren etwas aufwändig ist.
Könnte man es nicht so machen, dass man den Struct irgendwie als Zeiger
deklariert, der dann auf die Startposition der Daten im Array zeigt, und
dass ich dann somit die Daten nicht kopieren müsste?
Ich weiß nicht, was genau ich beim Struct dann alles als Zeiger
deklarieren muss.
Gruß
Richi
Richard W. schrieb:
> Könnte man es nicht so machen, dass man den Struct irgendwie als Zeiger
> deklariert, der dann auf die Startposition der Daten im Array zeigt, und
> dass ich dann somit die Daten nicht kopieren müsste?
Das geht auf PCs sowohl unter Windows als auch Unix-ähnlichen
Systemen (Stichwort "memory mapped file").
Dazu ist eine virtuelle Speicherverwaltung nötig.
Auf Controllern musst du darauf wohl verzichten.
Schade, wäre auch zu schön gewesen...
Gruß
Richi
Richard W. schrieb:
> Könnte man es nicht so machen, dass man den Struct irgendwie als Zeiger
> deklariert, der dann auf die Startposition der Daten im Array zeigt, und
> dass ich dann somit die Daten nicht kopieren müsste?
Wenn du mit "Daten im Array" einen Buffer meinst, in den du den Sektor
von der Karte gelesen hat, kein Problem.
1 | uint8_t buffer[512];
| 2 | struct log_entry *entry = (struct log_entry *)&buffer[42];
|
entry zeigt jetzt auf einen Logeintrag, der beim 43. Byte im Buffer
anfängt.
Virtuelle Speicherverwaltung ist dafür natürlich nicht nötig.
Andreas
Andreas Ferber schrieb:
> Virtuelle Speicherverwaltung ist dafür natürlich nicht nötig.
Meine Aussage bezog sich auf die Frage:
Richard W. schrieb:
> Könnte man es nicht so machen, dass man den Struct irgendwie als Zeiger
> deklariert, der dann auf die Startposition der Daten im Array zeigt, und
> dass ich dann somit die Daten nicht kopieren müsste?
Also ohne in einen Puffer und wieder zurück kopieren zu müssen.
Klaus Wachtler schrieb:
> Also ohne in einen Puffer und wieder zurück kopieren zu müssen.
Ich habe dich schon verstanden, ich glaube nur, der OP meinte eben nicht
das was du meinst ;-)
Da er offensichtlich mit C und Speicherverwaltung noch nicht soviel
Erfahrung hat, wollte ich nochmal explizit darauf hinweisen, dass bei
meiner Lösung kein virtueller Speicher nötig ist.
Andreas
Danke für eure Lösung. Mir ist schon klar dass ich den Buffer brauche,
den hab ich ja in jedem Fall.
Genau so hab ich mir das mit den Zeigern vorgestellt.
Grüße
Richi
Hallo
am Wochenende hab ich jetzt den Code neu umgebaut, also nach dem
Zeigerschema.
Jetzt kommt aber beim Kompilieren immer folgende Meldung:
error: request for member 'Minute' in something not a structure or union
Ich greife auf das Objekt Minute so zu:
Log.Minute = ...
Mit dem * davor gehts auch nicht.
Weiß jemand eine Lösung?
Gruß
Richi
Wenn du endlich einmal irgendwas Verwertbares in Codeform präsentieren
würdest, könnte man dir sicherlich helfen.
(Und ein C-Buch würde auch nicht schaden)
Ich rate jetzt einmal ins Blaue hinein:
Danke, genau das wars.
Gruß
Richi
Richard W. schrieb:
> Danke, genau das wars.
Dann gewinnt eine Aussage von weiter oben noch mehr Gewicht:
Du brauchst Literatur!
Das ist ein Trivialfehler, den du nicht gemacht hättest, wenn du die
Einführungskapitel in deinem nicht vorhandenen Buch über Strukturen und
Pointer durchgearbeitet hättest. Hättest du ein C-Buch (egal welches)
durchgearbeitet, dann wäre dir die Verwendung von * und -> im jeweiligen
Kontext in Fleisch und Blut übergegangen.
Womöglich hast du ja recht, ich hab halt noch nicht mit Zeigern auf
Strukturen gearbeitet, also woher kann ich dann ahnen, dass es bei
Strukturen der Pfeil und nicht das * ist.
Gruß
Richi
Richard W. schrieb:
> ich hab halt noch nicht mit Zeigern auf
> Strukturen gearbeitet, also woher kann ich dann ahnen, dass es bei
> Strukturen der Pfeil und nicht das * ist.
Es ist beides:
Und genau dafür, dass man eben bei was Neuem nichts zu "ahnen" braucht,
ist das Lesen eines C-Buches (vorher!) ja gut.
Richard W. schrieb:
> also woher kann ich dann ahnen,
Genau darum geht es.
Du musst das gar nicht ahnen. Das steht in JEDEM C-Buch drinnen.
Das und noch viel, viel mehr was du zur Zeit noch nicht weißt und
'ahnen' musst. Wenn du lesen würdest, musst du nicht raten oder ahnen.
Du verhältst dich wie jemand, der in einer fremden Stadt Taxifahrer
werden will, aber aus irgendwelchen Gründen den Ankauf eines Stadtplans
verweigert. Statt dessen schlägst du dich durch, indem du an jeder
Kreuzung Passanten nach dem Weg fragst.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|