www.mikrocontroller.net

Forum: Compiler & IDEs AVR: Bitfelder auf SD-Karte


Autor: Philip H. (lephilip)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Liebe Leute,

ich versuche über die Klabunde-Lib 
(http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT) Messdaten auf 
eine SD-Karte zu schreiben. Prinzipiell funktioniert die Anbindung der 
SD-Karte.

Aber irgendwie komme ich mit der Funktion Fwrite() nicht zurecht.

Hier mein Code:

#übliche Deklarationen ...

typedef struct messDaten{
  unsigned int jahr:7;  //Jahr
  unsigned int monat:4;  //Monat
  unsigned int tag:5;    //Tag
  unsigned int stunde:5;  //Stunde
  unsigned int minute:6;  //Minute
  unsigned int sekunde:6;  //Sekunde
  unsigned int dcf:1;    //valid_dcf_time
  unsigned int E:10;    //Elektr. Feldstärke
  unsigned int T:10;    //Temperatur
  unsigned int H:10;    //Luftfeuchtigkeit
} messDaten;

struct messDaten data;

int main(void){

//data initialisieren
data.jahr=10;  //Jahr
data.monat=7;  //Monat
data.tag=2;    //Tag
data.stunde=12;  //Stunde
data.minute=20;  //Minute
data.sekunde=0;  //Sekunde
data.dcf=0;    //valid_dcf_time
data.E=1023;  //Elektr. Feldstärke
data.T=0;    //Temperatur
data.H=0;    //Luftfeuchtigkeit

#if !defined (__AVR_ATmega161__) && !defined (__AVR_ATmega644__) && !defined (__AVR_ATmega168__)
 SFIOR&=!(1<<PUD);   //Pullups Enable
#else
#endif
// SFIOR=0;   //Pullups Enable

#ifdef MMC_CARD_SPI //SD_CARD_SPI too !
 MMC_IO_Init();
#endif

 ser_init();

 sei();              //enable interrupts



 RED_ON();
 GREEN_OFF();

 if(GetDriveInformation()!=F_OK) // get drive parameters
  {
   puts("\nFehler bei der SD-Karte!\n");
   RED_ON();
   GREEN_ON();
   while(1);
  }

 puts("Messung beginnt\n");

for(int z=0; z<5; z++){

    data.E=readADC(1);
    data.minute=z;
          
          if(Fopen("messung.txt",F_WRITE)==F_OK)
           {
      written=Fwrite((U8*)&data,sizeof(struct messDaten));
            Fclose();
           } 
  _delay_ms(100);
}

 for(;;) // loop forever
  {
  }
}

Was macht das Programm? Es erstellt korrekter Weise die Datei 
MESSUNG.TXT auf der SD-Karte. Die Datei hat auch die korrekte Größe 
(5*64 bit = 40 Byte). Aber der Inhalt stimmt hinten und vorne nicht:

Bedeutung: JAHR    MON  TAG   STD   MIN    SEK    * E          ANDERE................
Soll:      0001010 0111 00010 01100 010100 000000 0 1111111111 00000000000000000000
Ist:       1000101 0000 10011 10001 100000 000101 1 1111000000 11110000000000000000

*) = valid_dcf_time
E = elektrische Feldstärke

Ich habe auch schon versucht, das Bitfeld erst direkt vor dem 
Fwrite()-Befehl mit Daten zu füllen. Bringt alles nichts.
Hat jemand eine Idee, wo der Fehler liegen könnte?

Ich freue mich riesig über Lösungsansätze. Herzlichen Dank und viele 
Grüße,
Philip

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Philip H. schrieb:
> Was macht das Programm? Es erstellt korrekter Weise die Datei
> MESSUNG.TXT auf der SD-Karte.
Ok.

> Die Datei hat auch die korrekte Größe
> (5*64 bit = 40 Byte).
Mutig. Deine Annahme, das Bitfeld sei 64 Bit groß, ist reine 
Spekulation, da der C-Standard über mögliche Füllbytes keine Aussage 
macht.

> Aber der Inhalt stimmt hinten und vorne nicht:
Auch das hängt mit zusammen damit, dass du nichts über Füllbytes oder 
gar Endianness weißt.

Bitfelder sind immer dann und nur dann sehr praktisch, wenn man sie 
als Bitfelder benutzt. Sobald man aber versucht, sie auf irgendwelche 
Weise zu vergewaltigen, etwa durch Casten auf einen Integertyp oder 
durch anderweitige, völlig willkürliche Annahmen über die Darstellung im 
Speicher, gehts in die Hose.

> Ich freue mich riesig über Lösungsansätze.
Du hast ein festes Datensatzformat. Also implementiere es auch fest: 
Nimm einen Vektor mit 8 vorzeichenlosen Bytes (uint8_t[*]). Dahinein 
bastelst du dir deinen Datensatz mit Schiebeoperationen zusammen.
Dadurch umgehst du Probleme mit der Bytereihenfolge und hast keine 
unbekannten Füllbytes mehr.




[*] Gewöhne dir bitte den Blödsinn mit 'U8' wieder ab. Dafür gibt es den 
Standardheader <stdint.h>.

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.