Forum: Compiler & IDEs Bauplan 512-Byte-Array


von Richard W. (richi)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Richard W. (richi)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Richard W. (richi)


Lesenswert?

Nein, vielleicht hast du mich falsch verstanden.
Pro Mic eine Logart, da ich verschiedene Sachen loggen möchte und 
deshalb auch verschiedene Parameter brauche.

von Karl H. (kbuchegg)


Lesenswert?

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)

von Richard W. (richi)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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?

von Richard W. (richi)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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 :-)

von Richard W. (richi)


Lesenswert?

OK, dann hast du mir sehr viel weitergeholfen!
Danke!!!


Gruß
Richi

von Richard W. (richi)


Lesenswert?

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

von Richard W. (richi)


Lesenswert?

???

von Klaus W. (mfgkw)


Lesenswert?

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.

von Richard W. (richi)


Lesenswert?

Schade, wäre auch zu schön gewesen...

Gruß
Richi

von Andreas F. (aferber)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

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.

von Andreas F. (aferber)


Lesenswert?

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

von Richard W. (richi)


Lesenswert?

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

von Richard W. (richi)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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:
1
  Log->Minute = ...

von Richard W. (richi)


Lesenswert?

Danke, genau das wars.

Gruß
Richi

von Karl H. (kbuchegg)


Lesenswert?

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.

von Richard W. (richi)


Lesenswert?

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

von Stefan E. (sternst)


Lesenswert?

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:
1
(*Log).Minute = ...
1
Log->Minute = ...

Und genau dafür, dass man eben bei was Neuem nichts zu "ahnen" braucht, 
ist das Lesen eines C-Buches (vorher!) ja gut.

von Karl H. (kbuchegg)


Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.