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


von Philip H. (lephilip)


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:

1
#übliche Deklarationen ...
2
3
typedef struct messDaten{
4
  unsigned int jahr:7;  //Jahr
5
  unsigned int monat:4;  //Monat
6
  unsigned int tag:5;    //Tag
7
  unsigned int stunde:5;  //Stunde
8
  unsigned int minute:6;  //Minute
9
  unsigned int sekunde:6;  //Sekunde
10
  unsigned int dcf:1;    //valid_dcf_time
11
  unsigned int E:10;    //Elektr. Feldstärke
12
  unsigned int T:10;    //Temperatur
13
  unsigned int H:10;    //Luftfeuchtigkeit
14
} messDaten;
15
16
struct messDaten data;
17
18
int main(void){
19
20
//data initialisieren
21
data.jahr=10;  //Jahr
22
data.monat=7;  //Monat
23
data.tag=2;    //Tag
24
data.stunde=12;  //Stunde
25
data.minute=20;  //Minute
26
data.sekunde=0;  //Sekunde
27
data.dcf=0;    //valid_dcf_time
28
data.E=1023;  //Elektr. Feldstärke
29
data.T=0;    //Temperatur
30
data.H=0;    //Luftfeuchtigkeit
31
32
#if !defined (__AVR_ATmega161__) && !defined (__AVR_ATmega644__) && !defined (__AVR_ATmega168__)
33
 SFIOR&=!(1<<PUD);   //Pullups Enable
34
#else
35
#endif
36
// SFIOR=0;   //Pullups Enable
37
38
#ifdef MMC_CARD_SPI //SD_CARD_SPI too !
39
 MMC_IO_Init();
40
#endif
41
42
 ser_init();
43
44
 sei();              //enable interrupts
45
46
47
48
 RED_ON();
49
 GREEN_OFF();
50
51
 if(GetDriveInformation()!=F_OK) // get drive parameters
52
  {
53
   puts("\nFehler bei der SD-Karte!\n");
54
   RED_ON();
55
   GREEN_ON();
56
   while(1);
57
  }
58
59
 puts("Messung beginnt\n");
60
61
for(int z=0; z<5; z++){
62
63
    data.E=readADC(1);
64
    data.minute=z;
65
          
66
          if(Fopen("messung.txt",F_WRITE)==F_OK)
67
           {
68
      written=Fwrite((U8*)&data,sizeof(struct messDaten));
69
            Fclose();
70
           } 
71
  _delay_ms(100);
72
}
73
74
 for(;;) // loop forever
75
  {
76
  }
77
}

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:

1
Bedeutung: JAHR    MON  TAG   STD   MIN    SEK    * E          ANDERE................
2
Soll:      0001010 0111 00010 01100 010100 000000 0 1111111111 00000000000000000000
3
Ist:       1000101 0000 10011 10001 100000 000101 1 1111000000 11110000000000000000
4
5
*) = valid_dcf_time
6
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

von Sven P. (Gast)


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>.

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.