www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Struct zerlegen für Schleife


Autor: Bernd F. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich benutze den gcc auf AVR, und meine C-Kenntnisse sind -ähm- 
ausbaufähig. Ich habe hier ein struct mit unterschiedlichen Wortbreiten, 
also etwa so:
typedef struct {
    uint8_t wert1;
    uint8_t wert2;
    uint32_t wert3;
    uint16_t wert4;
}my_struct;
my_struct daten;

Ich möchte nun die einzelnen Werte in eine Schleife bekommen, um eine 
Prüfsumme zu berechnen. Zwei Verständnisschwierigkeiten türmen sich vor 
mir. Wie bekomme ich Zugriff auf die einzelnen Werte, also etwa in der 
Art:
for(i=0;i<4;i++)
    {
        machmirdiePruefsumme(daten.wert[i]);
    }

Zum anderen, ich müsste wohl vermutlich zur Berechnung die struct-Werte 
auf 32bit casten. Wie müsste das aussehen?

Ihr seht schon, ich bin da etwas planlos. Hoffentlich habe ich mich 
zumindest verständlich ausgedrückt, und es gibt eine Lösung für die 
Sache.

Danke.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd F. schrieb:

> ausbaufähig. Ich habe hier ein struct mit unterschiedlichen Wortbreiten,
> also etwa so:
>
>
> typedef struct {
>     uint8_t wert1;
>     uint8_t wert2;
>     uint32_t wert3;
>     uint16_t wert4;
> }my_struct;
> my_struct daten;
> 
>
> Ich möchte nun die einzelnen Werte in eine Schleife bekommen, um eine
> Prüfsumme zu berechnen.

Soll die Prüfsumme die Summe der Werte sein oder soll sie die Summe der 
Bytes sein.

> Zwei Verständnisschwierigkeiten türmen sich vor
> mir. Wie bekomme ich Zugriff auf die einzelnen Werte, also etwa in der
> Art:
>
> for(i=0;i<4;i++)
>     {
>         machmirdiePruefsumme(daten.wert[i]);
>     }
> 

so gar nicht. Zumindest macht man das nicht so. Hängt aber auch darvon 
ab, was du unter Prüfsumme verstehst.

> Zum anderen, ich müsste wohl vermutlich zur Berechnung die struct-Werte
> auf 32bit casten.

Komtm drauf an, was du unter Prüfsumme verstehst.

> Wie müsste das aussehen?

> Ihr seht schon, ich bin da etwas planlos. Hoffentlich habe ich mich
> zumindest verständlich ausgedrückt, und es gibt eine Lösung für die
> Sache.

Kommt drauf an, was eigentlich genau das Problem ist. Fangen wir doch 
einfach mal damit an, was denn mit der Prüfsumme geschehen soll.
Wenn es sich um eine byteweise Prüfsumme handelt, die du zb irgendwohin 
übertragen musst, gibt es eine ganz einfache Lösung, indem man den 
Compiler zwingt die struct komplett zu ignorieren und den 
Speicherbereich einfach nur als Abfolge von Bytes anzusehen.

Autor: klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, wenn du die Adresse der Struktur auf uint8_t* casten würdest, sehe 
ich das Problem, dass du die Prüfsumme auch über evtl. eingefügte 
Füll-Bytes berechnest. Du könntest das Alignment mit 
__attribute__((packed)) verhindern, allerdings dann alles GCC 
spezifisch. Ansonsten wirst du dir wohl die einzelnen Bytes mit 
Bitoperationen rausschneiden müssen, falls du für die 
Prüfsummenberechnen Bytes brauchst.

Autor: Oliver J. (helmo2004)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs mal hiermit, obs funktioniert weiß ich nicht. Ist nur sone 
Idee.
    typedef struct {
    uint32_t wert1;
    uint32_t wert2;
    uint32_t wert3;
    uint32_t wert4;
}my_struct;
my_struct daten;

unit32_t *dat=&daten;
    
for(i=0;i<4;i++)
    {
        machmirdiePruefsumme(dat[i]);
    }


Autor: Sym (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man sollte die Struktur noch mit #pragma pack 1 packen und für die 
Schleifengrenzen unbedingt die sizeof()-Funktion verwenden. Prinzipiell 
sollte die Prüfsummenfunktion auf Basis von Bytes berechnen, da man 
ansonsten das Mischen mit kleineren Datentypen nicht korrekt ist.

Autor: Bernd F. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Kommt drauf an, was eigentlich genau das Problem ist. Fangen wir doch
> einfach mal damit an, was denn mit der Prüfsumme geschehen soll.

Das struct wird am Stück ins Eeprom geschrieben und von dort gelesen. 
Die "Prüfsumme" soll mir eventuelle Schreibfehler aufzeigen.
Wie die Prüfsumme genau aussieht, soweit war ich noch garnicht, ob das 
jetzt eine einfache Summe oder ein CRC wird. Ich lass' mich auch dazu 
gerne beraten.

Danke,
Bernd

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst ne Union machen aus der Struct und einem Bytearray und dann 
die CRC über das Bytearray bis sizeof(struct).
Um Paddingbytes zu vermeiden, zuerst die 32Bit, dann 16bit und dann 8Bit 
Variablen in die Struct packen.


Peter

Autor: Thomas S. (tom72)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde das ganz einfach halten und keine Schleife verwenden.
machmirdiePruefsumme(daten.wert1);
machmirdiePruefsumme(daten.wert2);
machmirdiePruefsumme(daten.wert3);
machmirdiePruefsumme(daten.wert4);

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Du kannst ne Union machen aus der Struct und einem Bytearray

Warum schlägt da eigentlich jeder gleich mit Unions um sich? Ein 
einfacher Zeigercast tut's auch.

> Um Paddingbytes zu vermeiden, zuerst die 32Bit, dann 16bit und dann
> 8Bit Variablen in die Struct packen.

Das spielt beim AVR keine Rolle, weil der eh keinerlei 
Alignment-Anforderungen hat.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas S. schrieb:
> Ich würde das ganz einfach halten und keine Schleife verwenden.
>
>
machmirdiePruefsumme(daten.wert1);
> machmirdiePruefsumme(daten.wert2);
> machmirdiePruefsumme(daten.wert3);
> machmirdiePruefsumme(daten.wert4);
> 

Er will aber nur eine Prüfsumme und nicht 4.

Also Ziel verfehlt, 6, setzen.


Peter

Autor: Udo R. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter: Nicht wenn die Funktion "machmirdiePruefsumme" den 
Prüfsummenwert auf eine globale Variable addiert. So war das wohl auch 
gemeint.

Autor: Thomas S. (tom72)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd hat oben in seinem Beispiel angegeben in welcher Art er die 
struct-Komponenten in der Schleife der Funktion übergeben möchte. Wie 
und wohin die Prüfsumme gerechnet wird??? - sorry steht da nicht. Also 
finde ich den Aufruf für jede Komponente immer gut.
Wenn ich die komplette Prüfsumme über alle Komponenten rechnen will 
brauch ich auch keine Schleife. Dann würde ich nen Zeiger auf die struct 
in der Funktion übergeben und die Prüfsumme zurückgeben.

tom

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Bernd hat oben in seinem Beispiel angegeben in welcher Art er die
> struct-Komponenten in der Schleife der Funktion übergeben möchte. Wie
> und wohin die Prüfsumme gerechnet wird??? - sorry steht da nicht.

"Das struct wird am Stück ins Eeprom geschrieben und von dort gelesen.
Die "Prüfsumme" soll mir eventuelle Schreibfehler aufzeigen."

> Wenn ich die komplette Prüfsumme über alle Komponenten rechnen will
> brauch ich auch keine Schleife. Dann würde ich nen Zeiger auf die
> struct in der Funktion übergeben und die Prüfsumme zurückgeben.

Dann steht die Schleife halt in dieser Funktion.

Autor: Michael H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus schrieb:
> Wenn ich die komplette Prüfsumme über alle Komponenten rechnen will
> brauch ich auch keine Schleife. Dann würde ich nen Zeiger auf die struct
> in der Funktion übergeben und die Prüfsumme zurückgeben.

Mir ist nicht klar wie das auszusehen hätte. Könntest Du das genauer 
beschreiben?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael H. schrieb:
> Rolf Magnus schrieb:
>> Wenn ich die komplette Prüfsumme über alle Komponenten rechnen will
>> brauch ich auch keine Schleife. Dann würde ich nen Zeiger auf die struct
>> in der Funktion übergeben und die Prüfsumme zurückgeben.
>
> Mir ist nicht klar wie das auszusehen hätte. Könntest Du das genauer
> beschreiben?

Die Schleife ist dann in der Funktion drinnen :-)
uint8_t CheckSumm( uint8_t * startByte, size_t size )
{
  uint8_t check = 0;
  size_t  i;

  for( i = 0; i < size; ++i )
    check += *startByte++;

  return startByte;
}

und aufgerufen wird es mit Umcasten der Adresse auf den Beginn der 
struct-Variablen
   ...
   summ = CheckSumm( (uint8_t*)&my_struct daten, sizeof( *my_struct daten ) );

Autor: Thomas S. (tom72)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dito.
So wie Karl Heinz würde ich das auch machen. Vielleicht noch die 
Funktion mit nem const versehen um den Zeiger für Schreibzugriffe zu 
sperren
uint8_t CheckSumm( const uint8_t * startByte, size_t size )

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Udo R. S. schrieb:
> @Peter: Nicht wenn die Funktion "machmirdiePruefsumme" den
> Prüfsummenwert auf eine globale Variable addiert.

Wie unfein.
Dann fehlt aber noch das initialisieren dieser Variablen.

Ich mag mehrfache Aufrufe überhaupt nicht. Ich schreibe schon ne 
Schleife, wenn etwas nur zweimal ausgeführt wird.

Damit bin ich deutlich flexibler.
Laß mal in die Struktur noch weitere Elemente einfügen, dann mußt Du an 
der Schleife nix ändern, die läuft immer bis sizeof(struct).


Peter

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... wohl eher so:
uint8_t CheckSumm( uint8_t * startByte, size_t size )
{
  uint8_t check = 0;
  size_t  i;

  for( i = 0; i < size; ++i )
    check += *startByte++;

  return check;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... schrieb:
> ... wohl eher so:

LOL

Danke für die Korrektur. Du hast natürlich recht

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde zu

uint8_t CheckSumm( const void * start, size_t size )
{
  uint8_t * startByte = (uint8_t*) start;


tendieren und in der Funktion caste, so sehen die Aufrufe sauberer aus

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.