Forum: Projekte & Code MMC SD library FAT16 FAT32 read write


von Daniel R. (zerrome)


Lesenswert?

@ Alex (Gast)
Hallo,
und wie läuft es ? Neuigkeiten von der Front?

Grüße Daniel

von Alex (Gast)


Lesenswert?

Sorry das ich nicht eher zurückschreibe. Ein wenig Stressig die letzte 
Zeit :). Also die Usart hat mir die gleichen fehlerhafen Ausgaben 
gemacht. Darum denke ich das es sich nicht wirklich um ein 
Libraryproblem handelt. Es war eher ein Überlauf in einem Array.

Danke für die tatkräftige Hilfe
Alex

von bla (Gast)


Lesenswert?

Schön das du auf den Fehler gekommen bist.
Manchmal ist das echt zum verzweifeln ^^

Schönes Wochenende noch.

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Huch garnicht eingeloggt gewesen...

von Alex (Gast)


Lesenswert?

Ich hätte allerdings nocheinmal eine Frage:). Ist es möglich mit der 
Library auszulesen wieviel Speicherplatz noch auf der Karte frei ist 
(will nur Überprüfen ob die Karte voll ist. Lesen schreiben und löschen 
von Daten auf der Karte Funktioniert mitlerweile einwandfrei :)

Grüße Alex

von Helmut (Gast)


Lesenswert?

Hallo!
Ich nutze auch diese MMC/SD Funktionen und bin damit auch sehr 
zufrieden.
Ich möchte jetzt um Zeit zu sparen die Datei öffnen und erst beim 
Datumswechsel die Datei schliessen und eine neue Datei erstellen.
Wie kann ich nach einem Schreibvorgang die Daten auf der Karte 
aktualisieren ohne die Datei schließen und wieder öffnen zu müssen?

Viele Grüße
Helmut

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.

@ Alex (Gast)
Schön das es jetzt funktioniert :)
Das mit dem Freien Platz ermitteln wollt ich schon immer mal einbauen, 
komme aber nicht dazu. Eigentlich müsste man ja nur die freien Cluster 
in der Fat durchgehen und zählen. Das mit Sektoren pro Cluster 
multiplizieren und fertig...

@  Helmut (Gast)
Ist es denn so zeitkritisch?
Weil eigentlich muss man ja alles, was beim schließen auch gemacht wird, 
bei einem kompletten update der Datei Daten auch machen. Es schadet ja 
übrigens auch nicht eine Datei länger geöffnet zu haben.

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Soo, hier mal auf die schnelle eine Funktion, die die Anzahl der freien 
Bytes bestimmt.
Es sollte aber mindestens ein Cluster frei bleiben am Ende, also nicht 
voll schreiben bis zum Anschlag ! Besser wäre sogar einfach 1 MB frei zu 
lassen...

1
unsigned long long int fat_getCntFreeBytes(void){
2
3
  unsigned long long int cnt=0;
4
  unsigned long int count=0;
5
  unsigned long int secOfFirstPartition;
6
  unsigned long int fatSz;
7
8
  if(TRUE==mmc_read_sector(0,fat.sector)){
9
10
      // bestimmen des 1. sektors der partition
11
      void *vsector=&fat.sector[454];
12
      secOfFirstPartition=*(unsigned long int*)vsector;
13
      if(secOfFirstPartition==0x6964654d){
14
        secOfFirstPartition=0;
15
      }
16
      else{
17
        mmc_read_sector(secOfFirstPartition,fat.sector);
18
      }
19
20
      // anzahl sektoren bestimmen die von einer fat belegt werden
21
      if(fat.fatType==32){
22
        vsector=&fat.sector[36];
23
        fatSz=*(unsigned long int *)vsector-1;
24
        fatSz*=128;
25
      }
26
      else{
27
        vsector=&fat.sector[22];
28
        fatSz=*(unsigned short*)vsector-1;
29
        fatSz*=256;
30
      }
31
32
      fatSz-=1;
33
      // zählen der freien cluster in der fat
34
      do{
35
        if(0==fat_getNextCluster(count)) cnt++;
36
        count++;
37
      }while(count<fatSz);
38
39
      // multiplizieren um auf bytes zu kommen
40
      cnt=cnt*(fat.secPerClust*512);
41
      return cnt;
42
  }
43
}

Grüße Daniel

von Alex (Gast)


Lesenswert?

Vielen dank für die Funktion (Ich brauche zirka 15 Sekunden zum auslesen 
des Speicherplatzes einer 2 Gig Karte. Alles läuft gut!
Gruß
Alex

von holger (Gast)


Lesenswert?

1
      // multiplizieren um auf bytes zu kommen
2
      cnt=cnt*(fat.secPerClust*512);

Und was machste mit ner leeren 8GB Karte? ;) Überlauf anzeigen?

von holger (Gast)


Lesenswert?

>Und was machste mit ner leeren 8GB Karte? ;) Überlauf anzeigen?

Ach was red ich denn da? Du benutzt ja long long int.
Aber mal im Ernst, es sollte eigentlich reichen die
Anzahl der freien kB zu ermitteln. Das spart das long long
Geraffel und benötigt weniger Code.

von Daniel R. (zerrome)


Lesenswert?

Hallo...

@ Alex (Gast)
Wow 15 Sekunden das ist lang. Hatte das garnicht auf realer Hardware 
getestet muss ich gestehen. Aber 15 Sekunden ist zu viel! Da muss ich 
mal überlegen wie das optimaler geht.

@ holger (Gast)
Ja stimmt schon, long long int auf nem AVR 8 Bit :) das muss man nicht 
unbedingt haben. Mal sehn was ich da mache...
Wegen der Code Größe ist mir das eigentlich egal, wer so was braucht 
muss halt platz haben, aber die Geschwindigkeit sollte stimmen.

Grüße Daniel

von Kurt B. (kurt)


Lesenswert?

Hallo Daniel,
was müsste man ändern, damit Dateien mit korrektem Datum/Uhrzeit 
angelegt werden?

Ansonsten gute Arbeit! Deine lib scheint die einzige zu sein, die 
wirklich schnelles schreiben auf SD-Karten ermöglicht.

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo Kurt,
man müsste die Funktion "fat_makeRowDataEntry" in der fat.c dazu 
bewegen, da wo jetzt dummy werte geschrieben werden, richtige werte zu 
schreiben. Also das Datum und die Zeit. In den beiden Zeilen, die mit
1
// unnoetige felder beschreiben
kommentiert sind.
Die dummy Werte sind 0x01010101, also 4 Byte als Hex.
Wo jetzt genau Datum und Zeit steht, müsste ich selber mal genau 
nachschauen. In der Lib werden 12 Byte mit den dummy werten beschrieben, 
da irgendwo muss das hin :)

Grüße Daniel

von Kurt B. (kurt)


Lesenswert?

Hallo,
hier die Lösung:
Zuerst Datum und Uhrzeit besorgen:
1
uint32_t get_datetime()
2
{
3
  uint8_t year,month,day,hour,minute,second;
4
5
  //Die Werte von der RTC holen
6
  year = 2009 - 1980;
7
  month = 12;
8
  day = 2;
9
  hour = 11;
10
  minute = 45;
11
  second = 26 / 2;
12
13
  return (uint32_t) ((year * 33554432) | (month * 2097152) | (day * 65536) | (hour * 2048) | (minute *32) | (second * 1) );
14
}

Dann folgende Funktionen mit zusätzlichem Parameter unsigned long 
datetime ausrüsten: ffopen, ffclose, ffmkdir, flushFileData, 
fat_makeFileEntry, fat_makeRowDataEntry.

Nun fat_makeRowDataEntry abändern:
1
void fat_makeRowDataEntry(unsigned short row, unsigned char name [],unsigned char attrib,unsigned long int cluster,unsigned long int length, unsigned long datetime){
2
3
  fat.bufferDirty=1;                // puffer beschrieben, also neue daten darin(vor lesen muss geschrieben werden)
4
  
5
  row=row<<5;                    // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 ... zeile 15=480)  
6
7
  unsigned char i;                // byte zähler in reihe von sektor (32byte eintrag)
8
  unsigned char  *bytesOfSec=&fat.sector[row];  // zeiger auf sector bytes
9
  void *vsector;
10
11
  for(i=0;i<11;i++) *bytesOfSec++=name[i];        // namen schreiben
12
  *bytesOfSec++=attrib;                  // attrib schreiben
13
14
  *bytesOfSec++=0x01;  //reserviert
15
  *bytesOfSec++=0x01;  //erstellzeitpunkt in 10ms, von 0 bis 199
16
  
17
  //unsigned long datetime: (date_high,date_low,time_high,time_low)
18
  *bytesOfSec++=datetime;    //erstellzeitpunkt lowbyte
19
  *bytesOfSec++=datetime>>8;  //erstellzeitpunkt highbyte
20
21
  *bytesOfSec++=datetime>>16;  //erstelldatum lowbyte
22
  *bytesOfSec++=datetime>>24;  //erstelldatum highbyte
23
  
24
  *bytesOfSec++=datetime>>16;  //datum des letzten zugriffs lowbyte
25
  *bytesOfSec++=datetime>>24;  //datum des letzten zugriffs highbyte
26
  
27
  vsector=&fat.sector[row+20];
28
  *(unsigned short*)vsector=(cluster&0xffff0000)>>16;// low word  von cluster
29
30
  bytesOfSec += 2;        // 2 überspringen (für low word von cluster)
31
  *bytesOfSec++=datetime;    //zeit der letzten änderung lowbyte
32
  *bytesOfSec++=datetime>>8;  //zeit der letzten änderung highbyte
33
  
34
  *bytesOfSec++=datetime>>16;  //datum der letzten änderung lowbyte
35
  *bytesOfSec++=datetime>>24;  //datum der letzten änderung highbyte
36
  
37
  vsector=&fat.sector[row+26];
38
  *(unsigned short*)vsector=(cluster&0x0000ffff);  // high word von cluster
39
  
40
  vsector=&fat.sector[row+28];
41
  *(unsigned long int*)vsector=length;        // laenge
42
}

Natürlich sind die Werte für Erstellung, letzer Änderung und letztem 
Zugriff auf die Datei gleich. Ist das nicht gewünscht, muss man halt 
noch 2 weiter parameter übertragen.

Mfg,
Kurt

von Matze N. (hupe123)


Lesenswert?

Hi,

ich würde gerne die SD-Karte mit dem µC formatieren. Kann mir mal jemand 
weiterhelfen, wie dazu die Funktion aussehen müsste?!

Gruß,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hallo,
das mit dem Formatieren ist nicht so einfach,
mach das lieber mit einem Pc :)
Man müsste die Register der Karte auslesen, um herauszufinden wieviele 
Sekoren die hat. Dann berechnen wieviele Fat Sektoren man braucht, wo 
dann das Root-Dir hin muss usw.
Dann ist immer noch die Frage ob man das so gemacht hat, dass ein 
Betriebssystem das auch lesen kann...

Grüße Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
hier eine neue Version.
Neu ist:

- SDHC Unterstützung
- Eine Funktion die den freien Platz in Bytes ermittelt 
"fat_getFreeBytes()"
- Zeit Stempel Unterstützung beim Anlegen und ändern von 
Dateien/Ordnern,
dazu müssen 2 Funktionen mit leben gefüllt werden. "fat_getDate()" und 
"fat_getTime()" in der fat.c, dort ist auch dokumentiert wie das Format 
der Zeit und des Datums auszusehen haben.
- Kleinere Optimierungen

Viele Grüße

Daniel

Im Anhang: die Lib mit Linux Makefile

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Und noch die AvrStudio Variante

von Jens (Gast)


Lesenswert?

Hallo!
Ich hab das ausprobiert, also die neuste AVRStudio Variante. Eigentlich 
klappts prima, allerdings bekomme ich z.B. die Funktion:
ffrm( unsigned char name[])

nicht aufgerufen ... also nicht so daß der Compiler einverstanden ist. 
Ich habe u.a. versucht:
ffrm(file_name0);
Ging nicht, auch sämtlichen sinnvollen Ansätze die ich probiert habe, 
gingen nicht, woran mag das liegen, verwenden einen ATmega32

von Daniel R. (zerrome)


Lesenswert?

Hallo,
hast du in der config.h auch das gemacht?
1
#define MMC_SMALL_FILE_SYSTEM   FALSE

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Ein normaler Aufruf würde z.B. so aussehen:
1
unsigned char file_name[12]="TEST    TXT";
2
3
ffrm(file_name); // löscht datei mit namen test.txt

Natürlich müsste vorher die Karte und die Fat initialisiert sein...

von Tobi (Gast)


Lesenswert?

Hallo zusammen,

habe nen Mega32L, ne 4GB SDHC, und nen 3,7V Lipo.

meint ihr es gibt Probleme mit der um 0,4V zu hohen Spannung um das 
ganze prinzipiell zu betreiben?

Mfg Tobi

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also ich würde dir empfehlen, einen Stepup-Wandler für die 
Versorgungsspannung zu benutzen. Der Akku wird mit der Zeit mit der 
Spannung runter gehen. Mit nem Stepup könnte man bei um die 1V 
Akkuspannung noch arbeiten. Also das ganze mit nem Stepup auf 3,3V und 
gut is.
Generell kann man mit nem SD-Kommando die Karte fragen was sie für ne 
Spannung mitmacht. 3,3 Volt machen alle, aber es geht eventuell auch 
weniger.

Grüße Daniel

von Tobi (Gast)


Lesenswert?

Hy Daniel,

also der Lipo wäre bei 1V schon lange dahin.

In einer späteren Version werde ich die Spannung sicherlich eh auf 3,3V 
stabilisieren, zumal ich in einem anderen Stromzweig eh nen Wandler auf 
3,7V->5V verbaut habe.

Mir geht es in einem ersten Versuch nur mal darum die Kommunikation 
Mega32L + SD Karte durch einen Versuchsaufbau zu testen. Dabei würde ich 
gerne erst einmal direkt alles brücken können. Wäre prinzipiell ja auch 
möglich da alles mit 3,3V versorgt werden will. Wenn ich wüsste ob die 
3,7V die SD Karte kaputt machen müsste ich nämlich für den 
Versuchsaufbau die Spannung auch schon wandeln was ich gerne für erste 
Versuche erst einmal vermeiden möchte.

mfg tobi

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich hab keine Ahnung von Lipo Akkus :)

Bezugnehmend auf die Simplifyied SD-Spezifkation 2.0, die ich jetzt 
nochmal rausgekramt hab.

Also man übergibt der Karte mit CMD8 die Spannung in der man sie 
betreiben möchte, in dem Fall der Lib wären das 2,7-3,6 Volt. Antwortet 
die Karte korrekt, kann man diese Spannung anlegen. Nur wenn die Karte 
korrekt antwortet initialisiert die Lib die Karte.

Soviel dazu. Ob jetzt 0,1 Volt mehr tödlich für die Karte sind bezweifle 
ich mal stark ;)

Vielleicht hält sich aber auch dein Kartenhersteller nicht genau an die 
Spezifikation...

Hab aber auch schon gehört, dass Leute MMC/SD Karten einfach mit 5V 
betrieben haben, ohne das die kaputt gegangen wären. In der Regel sind 
das ja alles werte, unter denen das dann garantiert läuft...

Grüße Daniel

von Tobi (Gast)


Lesenswert?

Genau diese Angaben mit 2,7-3,6V habe ich auch in meiner SD 
Spezifikation.
Das mit dem CMD8 wusste ich noch nicht. Allgemein vermisse ich irgendwie 
eine Zusammenfassung der gazen Commands. Zwar sind auch einzelne 
Commands in der SPezifikation, jedoch irgendwie etwas unübersichtlich.

Ich vermute auch das 0,1V mehr nicht viel ausmacht. Hatte gehofft hier 
Erfahrungsberichte zu finden, da sich grundsätzlich ein Lipo von der 
Spannung her ja anbietet und ich ja sicher ned der erste bin der so 
einen verwendet :)

Das mit den 5V wäre ja schonmal beruhigend zu wissen, da hätte ich nicht 
gedacht das das die Karte lange mitmacht.

Ansonsten ist ja auch kein Vermögen zerstört wenn so eine Karte hops 
geht :)

Ich denke ich werds einfach mal probieren, wenn ich einen Kartenleser 
auftreiben kann der meine Karte liest um herauszufinden ob die Karte 
schon formatiert ist oder dies noch tun muss.

Danke für deine Ausführungen.

MfG Tobi

von Alex (Gast)


Lesenswert?

Hallo zusammen!

Ich habe mal ne Frage bezüglich einer Abfrage ob eine Datei schon 
existiert. Und zwar will ich überprüfen ob eine Datei mit einem Namen 
schon in dem Verzeichniss existiert. Ist so etwas möglich?

Grüße
Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja geht ganz einfach.
1
unsigned char file_flag=fat_loadFileDataFromDir(name);

"file_flag" ist jetzt TRUE wenn die Datei schon existiert oder FALSE 
wenn eben nicht. Nach dem Aufruf von "fat_loadFileDataFromDir(name)" 
sind sogar alle möglichen Daten über die Datei schon bekannt, wenn die 
Datei existiert...

Siehe auch "ffopen()" in der file.c


Grüße Daniel

von Alex (Gast)


Lesenswert?

Danke schon für die tatkräftige Hilfe! ich habe auch noch eine weitere 
Frage. Und zwar kann man auslesen wie groß der gesamte Speicherplatz der 
Fat ist?

Gruß
Alex

von Daniel R. (zerrome)


Lesenswert?

Ich denke du meinst wieviele Sektoren von der Fat belegt werden?
Das ist schon schwieriger.
1
unsigned long int fatSz;
2
3
4
  mmc_read_sector(0,fat.sector);
5
6
  void *vsector=&fat.sector[454];
7
  fatSz=*(unsigned long int*)vsector;
8
  if(fatSz==0x6964654d){
9
    fatSz=0;
10
    }
11
  else{
12
    mmc_read_sector(fatSz,fat.sector);
13
    }
14
15
16
  if(fat.fatType==32){
17
    vsector=&fat.sector[36];
18
    fatSz=(*(unsigned long int *)vsector)-1;
19
    fatSz*=128;
20
    }
21
  else{
22
    vsector=&fat.sector[22];
23
    fatSz=(*(unsigned short*)vsector)-1;
24
    fatSz*=256;
25
  }

Jetzt ist auf der Variable "fatSz" die Anzahl der Sektoren gespeichert, 
die eine bzw. die erste Fat belegt. Der erste Sektor, also ab wo die Fat 
los geht steht auf der Variable "fat.fatSec".

Der hier gepostete Code ist aus der Funktion "fat_getFreeBytes()" aus 
der fat.c...

Grüße Daniel

von Alex (Gast)


Lesenswert?

Danke dir! Aber eigentlich meinte ich die Anzahl der Bytes :). Aber das 
war doch Anz. Der Sektoren * 512 oder? Kann auch sein das ich mich da 
irre.

Gruß Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja Anzahl der Sektoren * 512.

Ich weiß ja nicht was du vor hast, aber zur Sicherheit solltest du evtl. 
noch einen Sektor dazu zählen wenn du irgendwas nach der Fat machen 
möchtest.
Falls es irgendwas mit der Fat ist wird da schon ein Sektor abgezogen, 
um auf garkeinen Fall über das Ende der Fat hinaus zu kommen.

Upps, ich seh grad da bekommst du die Cluster Anzahl raus die in einer 
Fat stehen. Bei dem Code oben muss einmal das "fatSz*=128;" und das 
"fatSz*=256;" weg !

Also so:
1
unsigned long int fatSz;
2
3
4
  mmc_read_sector(0,fat.sector);
5
6
  void *vsector=&fat.sector[454];
7
  fatSz=*(unsigned long int*)vsector;
8
  if(fatSz==0x6964654d){
9
    fatSz=0;
10
    }
11
  else{
12
    mmc_read_sector(fatSz,fat.sector);
13
    }
14
15
16
  if(fat.fatType==32){
17
    vsector=&fat.sector[36];
18
    fatSz=(*(unsigned long int *)vsector)-1;
19
    }
20
  else{
21
    vsector=&fat.sector[22];
22
    fatSz=(*(unsigned short*)vsector)-1;
23
  }




Grüße Daniel

von Matze N. (hupe123)


Lesenswert?

Hi,

ich habe grad ein verzwickes Problem.
Ich würde gerne in eine Datei, die schon einen Text enthält, Text 
einfügen.
BSP:

aus:
    "Hallo, dieser text steht schon drin."

soll:
    "Hallo, dieser text steht schon 1234567890 drin."

werden.

Man könnte jetzt natürliche den restlichen Text überscheiben und neu 
schreiben. Aber das geht nicht, da der Text hinter dem, was eingefügt 
werden soll mehrere MB groß ist und zum Auslagern fehlt mir zum einen 
der Platz und zum anderen die Zeit...

Gibts dafür eine Lösung?!

Gruß,
Matze

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
nein dafür gibt es so noch keine Lösung.

Man müsste Prinzipiell wie in dem an gehangenen Bild vorgehen.
Allerdings müsste das noch weiter verallgemeinert werden.
Also auf Cluster anstelle von 512 Byte Sektoren und auf größere 
einzufügende Sektoren/Cluster.
Mal sehen wie sich das optimal einbauen lässt.
Da komme ich aber auch wohl erst in 2 Wochen dazu, wird auch nicht so 
einfach werden, da das ziemlich tief in die Sektor/Cluster Verwaltung 
eingreift.

Grüße Daniel

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

müsste das nich so sein... ich meine, man will ja evtl mehr als 512 byte 
einfügen. außerdem müsste es zwischen zwei blöcken geschrieben werden.
dein zeichnung würde "ersetzen mit einem anderen sector" bedeuten.
aber sonst meinen wir das selbe! und cool, daß du das machen willst, ich 
steige da nämlich nicht so richtig durch...!

gruß und danke schon mal,
matze :)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
hm wo ich so darüber nachdenke, könnte das übler werden als ich dachte. 
Wenn man nicht genau 512 Bytes dazu macht, oder ein ganzes vielfaches 
davon, läuft das wohl doch auf ein wildes kopieren hinaus. Man hat 
irgendwie immer ein paar Bytes über...
Muss ich mal in Ruhe darüber nachdenken.

Grüße Daniel

von Matze N. (hupe123)


Lesenswert?

naja, ob das so weit gehen muss?! Ja, ok, schön wäre es, jedes Bit auf 
der Karte auszunutzen, aber sein wir doch mal ehrlich, wer Datenmengen 
kleiner als 512 Byte schreiben will, schreibt eh nur Text und der ist eh 
meistens kurz. von daher verschenk man nur wenig, selbst wenn man nur 1 
Byte / Sector schreibt.
Auf der anderen Seite: wenn man, so wie ich das Plane, ca. 175.000 
Einfügevorgänge machen wird, ist schon eine ganze Ecke an verschwendetem 
Speicherplatz (ich habs mal überschalgen: etwas mehr als 80MB - wenn ich 
mich nicht verrechnet habe).
Jedoch, bei der verfügbaren Kapazität heutiger Speicherkarten auch nicht 
mehr so viel... :)

Mach dir also nich so einen Kopf drüber. Die Abfrage, welcher Sektor 
wieviele Bytes noch übrig hat, ist, denke ich, unnötig und 
wahrscheinlich eh viel zu langsam - bzw. wenn man es in eine Variable 
schreibt, viel zu Speicheraufwendig (bei knapp 4,2 mio Sektoren auf 
einer 2GB Speicherkarte)

Grüße,
Matze

von Alex (Gast)


Lesenswert?

Danke für die hilfe :)

aber leider Funktioniert das noch nicht so wirklich. Ich überprüfe z.B. 
die Größe einer Fat auf einer 2 Gig SD Karte. Die Fat hat die volle 
Größe.
Der Quelltext den du oben geschrieben hast also gibt mir für fatSz 3742 
zurück.

unsigned long int fatSz;

  mmc_read_sector(0,fat.sector);

  void *vsector=&fat.sector[454];
  fatSz=*(unsigned long int*)vsector;
  if(fatSz==0x6964654d){
    fatSz=0;
    }
  else{
    mmc_read_sector(fatSz,fat.sector);
    }


  if(fat.fatType==32){
    vsector=&fat.sector[36];
    fatSz=(*(unsigned long int *)vsector)-1;
    }
  else{
    vsector=&fat.sector[22];
    fatSz=(*(unsigned short*)vsector)-1;
  }

Noch einen vorschlag ?  (Fehlt hier vielleicht noch ne multiplikation 
oder soetwas ?

Gruß Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
Auszug aus der fatgen103:
1
[BPB_FATSz32 (byte) 36 (bytes) 4]
2
3
This field is only defined for FAT32 media and does not exist on
4
FAT12 and FAT16 media. This field is the FAT32 32-bit count of
5
sectors occupied by ONE FAT. BPB_FATSz16 must be 0.

,das korrespondiert mit der Prüfung:
1
if(fat.fatType==32){
2
    vsector=&fat.sector[36];
3
    fatSz=(*(unsigned long int *)vsector)-1;
4
    }

jetzt sollte auf der Variablen fatSz laut Spezifikation die Anzahl der 
Sektoren stehen die von einer Fat belegt werden. Wenn du ja genauer 
schreiben würdest wozu du das überhaupt brauchst könnte ich da 
vielleicht auch mehr zu sagen :)
Wenn du jetzt die Anzahl der Bytes haben willst musst du deine 3742 ja 
noch mit 512 Multiplizieren.

Grüße Daniel

von Alex (Gast)


Lesenswert?

Hallo Daniel,

also das passt nicht wirklich. Die Partition ist 2 Gig groß und 3742 * 
512 hat einen Wert von unter 1 MB. Was ich machen will ist, eine 
durchnummerierung von Dateien. Quasi bei 1 Anfangen ...dann 2 dann 3. 
Jede Datei ist hierbei 1 MB groß. Falls ich nun am Ende der Fat 
angekommen bin. Also bei ner 2 Gig Platte zirka bei guten 2000 dann soll 
der wieder von vorne anfangen und die erste überschreiben. Das klappt 
auch eigentlich schon recht gut wenn ich das ganze mit einer statischen 
größe mache, besser wäre das aber wenn ich das mit verschiedenen Karten 
machen könnte die jeweils eine andere Größe haben. Aber danke schonmal 
danke für die Tatkrääftige unterstüzung
Gruß
Alex

von Daniel R. (zerrome)


Lesenswert?

Aha,
da musst du anders ran gehen.

Auf FatSz steht jetzt die Anzahl der Sektoren die eine Fat belegt.
In einem Sektor der von der Fat belegt wird, können 128 Cluster 
"Adressiert" werden.
Wenn man jetzt fat.secPerClust*512 rechnet, bekommt man die Anzahl der 
Bytes die einem Cluster zugeordnet werden.
Die Anzahl der Sektoren die zu einem Cluster zusammengefasst werden ist 
immer eine 2er Potenz. Wahrscheinlich bei einer 2Gb Karte 4 oder 8. 
Damit ist die kleinste Zuordnung 2048 oder 4096 Bytes groß.

Damit solltest du jetzt rechnen können :)

Also:

FatSz*128 = Anzahl Cluster auf der Karte

512 * fat.secPerClust = Bytes in einem Cluster

1MByte / Bytes in einem Cluster = nötige Cluster Anzahl, für die 1 MByte

Anzahl Cluster auf der Karte / nötige Cluster Anzahl für die 1 MByte = 
Maximale Anzahl der der 1 MByte Dateien

Stimmst du dem zu? Könnte mich auch verrechnet haben, war jetzt nur so 
auf die schnelle...Man müsste auch mal schauen wie man rundet um da 
überall save zu sein ;)


Grüße Daniel

von Alex (Gast)


Lesenswert?

Das mit den Bytes auf der Fat werde ich die Tage mal ausprobieren und 
dir ein Feedbag geben :). Ich habe allerdings immoment auch noch ein 
ganz anderes Problem. Ich habe folgenden Quellcode

unsigned long int sd_ausgabe_zaehler;
filenamelan = 1;
char ordner[13];
ordnerName(filenamelan,ordner);
ffcdLower();
if(TRUE == ffcd("1           ")...//--> Gibt true zurück
char zwischenspeicher[5];  // Zwischenspeicher für die Umwandlung
itoa(filenamelan, zwischenspeicher,10);
char dateiname[12]="        CSV";
for(uint8_t i=0;i<strlen(zwischenspeicher);i++)//)i<=3;i++)
{
  dateiname[i]=zwischenspeicher[i];
}
if(MMC_FILE_EXISTS==ffopen((unsigned char *)dateiname))  // --> Datei 
exist
sd_ausgabe_zaehler=file.length;

char zwischenspeicher3[10];
ultoa(sd_ausgabe_zaehler,zwischenspeicher3,10);
ausgabe(zwischenspeicher3);    // Hier gibt er ziemlich große Zahlen aus


Das Problem was ichhabe ist das mit file.length für 10 kB Dateien zum 
Beispiel den Wert 640000000 zurückgibt, was ja nicht kann. Sieht jemand 
warum der das macht und nicht wie erwartet 104800 irgendwas an Bytes 
zurückgibt?

Grüße
Alex

von Alex (Gast)


Lesenswert?

ok die letzte Frage hat sich erledigt :) War ein Fehler meinerseits

Grüße
Alex

von Alex G. (almalex)


Lesenswert?

hi
ich hätte eine frage zu deinem code
ich bekomme über die serielle schnittstelle strings mit der länge von 
2048 zeichen und würde nun gerne wissen wie das geht das ich diese 2048 
zeichen dann schreibe
wenn ich nur 512 zeichen lange  Blöcke bekomme geht es wunderbar
hoffe du kannst mir helfen

danke und mfg alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
du könntest eine Ringpuffer machen. Dessen Größe müsstest du dann noch 
ermitteln, damit da nichts schief geht. So könnten dann schonmal 512 
Bytes geschrieben werden, während noch weitere abgeholt werden (falls du 
einen Interrupt zum abholen der Daten benutzt).
Siehe auch: 
http://de.wikipedia.org/wiki/Warteschlange_(Datenstruktur)#Implementierung_als_Ringpuffer

Das es nicht klappt könnte auch daran liegen, dass du die Schnittstelle 
ohne Flow-Control verwendest, vermute ich mal.
Während die Daten auf die Karte geschrieben werden kommen ja über die 
serielle Schnittstelle neue Daten an die werden aber wohl nicht abgeholt 
während die Lib noch Daten auf die Karte schreibt. Das schreiben der 
Daten auf die Karte benötigt ja eine gewisse Zeit.

Falls dir das nicht weiterhilft, könntest du mal etwas Code Posten, 
damit könnte man sich einen besseren Überblick verschaffen.

Viele Grüße

Daniel

von Alex G. (almalex)


Lesenswert?

ich hätte mir vorgestellt das ich die 2048 zeichen was ich als einen 
string bekomme auf mehrere kleine strings mit 256 zeichen oder so 
aufteile und dann schreibe. wäre das prinzipell möglich?

von Daniel R. (zerrome)


Lesenswert?

Besser immer 512er Blöcke. Es werden nämlich immer 512 Bytes von der Lib 
gepuffert bevor diese geschrieben werden.

von Alex (Gast)


Lesenswert?

Hallo,
so bin zu der Berechnug der Anzahl von Dateien gekommen. Habe das wie 
folgt gemacht :

uint32_t anzahlDateienerrechnen(uint32_t size)
{
  uint32_t anz_Cluster_Karte = size * 128;
  uint32_t byte_pro_Cluster = 512 * fat.secPerClust;
  uint32_t noetige_Cluster_fuer_1_MB = 1048576/byte_pro_Cluster;
  uint32_t anz_Dat = anz_Cluster_Karte/noetige_Cluster_fuer_1_MB;
  return (anz_Dat);
}

Mit
size = fatSz kommt die Richtige Anzahl an 1 MB Dateien raus.

Danke für die Hilfe (fatSz muss man ja vorher berechnen) Aber da ist ja 
schon oben der Quelltext angegeben.
Grüße
Alex

von Alex G. (almalex)


Lesenswert?

hi ich wenn ich einen block mit 512 byts schreiben will. geht das bei 
mir nicht und es kommt auf der seriellen schnittstelle ein neues boot. 
was kann da sein
ich lese die 512 byts über die serielle schnittstelle ein. ich kann 
maximal 256 byts auf einmal schreiben mit deinem code

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.

@ Alex (Gast), schön das es jetzt klappt :)

@ Alex Glaser (almalex) ,welchen Mikrocontroller benutzt du denn? Wenn 
da erneut "Boot..." steht vermute ich mal einen Reset wegen Ramknappheit 
?!? Poste doch mal ein bisschen Code, damit man sehen kann was du da 
genau machst und wie du das machst. Am besten sogar den ganzen Code.

Grüße Daniel

von Alex G. (almalex)


Lesenswert?

hab das problem schon gfunden. habe ein bit zuviel gesendet und dadruch 
hat der buffer nicht gepasst. verwende einen 644 aber trotzdem danke
jetzt wende ich mich dem problem das ich einen string von 2048 zeichen 
empfangen will und denn dann schreiben will und dann einen bit zurück 
senden will wann der nächste gesendet werden soll

von Juergen (Gast)


Lesenswert?

Hallo Daniel,
ich habe noch einen kleinen Fehler in der Funktion
fat_getFreeBytes() gefunden.
Dort wird mit mmc_read_sector(0,fat.sector)
der erste Sektor der Karte in den Buffer gelesen, ohne dass
fat.currentSectorNr dadurch verändert wird.
Später wird mit
fat_getNextCluster(count) der sektor gelesen. Wenn 'count' jetzt 
identisch mit 'fat.currentSectorNr'ist(was durchaus vorkommt) wird der 
Sektor nicht in
den Buffer gelesen.

meiner Meinung nach müsste es ausreichen wenn man Sektor 0 nicht mit
mmc_read_sector(0,fat.sector) liest sondern statt dessen
fat_loadSektor(0) verwendet.

Kannst du dir ja noch mal anschauen.

Grüße
Jürgen

von Alex G. (almalex)


Angehängte Dateien:

Lesenswert?

Hi
ich hab ne frage
ich habe es jetzt geschafft 2048 Zeichen auf die SD karte zu schreiben 
wenn ich die daten über die serielle schnittstelle vom PC schicke. wenn 
ich nun die selben Daten über den 2ten µC erzeuge und zu dem sende der 
es auf die SD karte schreiben soll, funktioniert es nicht. ich poste mal 
den code. die main.c ist die datei die auf den µC gespielt wird, welcher 
die daten zu dem 2ten sendet.
main_simple.c ist deine datei nur wenig verändert

hoffe du kannst mir helfen

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.


@ Juergen (Gast)

Ja stimmt, ich bin davon ausgegangen, dass man nur am Anfang die freien 
Sektoren bestimmt...
Das wird geändert. Dein Vorschlag funktioniert so.


@ Alex Glaser (almalex)

Um mir das genauer anzuschauen fehlt mir momentan einfach die Zeit. 
Vielleicht so in 1,5-2 Wochen, sorry.

Es gibt auch noch einen kleinen Bug, der nur auftritt wenn man die Lib 
im Read-Only Modus betreibt. Dann hat nämlich ffopen evtl. nicht immer 
einen Rückgabewert... Ist aber eigentlich kein Funktionaler Fehler.

Grüße Daniel

von Andre (Gast)


Lesenswert?

Hay Leute

Ich habe nun auch mal versucht unter Codevision zum Laufen zu bekommmen.

Aber leider ohne erfolg.

Ich habe mir die CodeVision_SDLIB_v0.4.4.zip runter geladen und an den 
Mega128 Angepasst. Ich nutze zwar den Mega1281 Aber der ist gleich den 
128 nur mit mehr S-Ram.

Habe das ganze System unter 3,3V laufen den AVR sowie auch 
Verständlicherweisse die SD-Karte.

Kann mir jemand mal einen code in Codevision Posten der Funktioniert.?

Die mmc_init() bzw. die INIT sieht so aus

  if(mmc_init() !=0)
  {
    LED_Rot^=1;
    while(1);
  }
    LED_Gruen^=1;

Aber es bleibt immer auf Rot nie auf Grün und sagt keine SD Karte 
Eingesteckt.

Kann mir jemand weiter helfen.?


Vielen Dank schon mal

von Daniel R. (zerrome)


Lesenswert?

Hallo,
erstmal solltest du besser die neuste Version auf Codevision portierten.

Dann ist das so nicht richtig wie du das machst. So wird nur ein mal 
versucht die mmc/sd karte zu initialisieren...

Das wäre richtig:
1
while (0!=mmc_init()){
2
    LED_Rot^=1;
3
  }
4
LED_Gruen^=1;

jetzt wird rot bei jedem versuch getoggelt und grün nach erfolgreichem 
initialisieren...

Grüße Daniel

von Andre (Gast)


Lesenswert?

jup das war es nun geht die init Funktion. Danke  @Daniel R.

Ich nutze die CodeVision_SDLIB_v0.4.4

nun habe ich auch die filefat.c Eingebunden.

habe auch alle fehler soweit Korrigiert und angepasst.

Nur meckert er  mich bei dieser geschichte voll

Error: filefat.c(635), included from: Neu.c: expression must be a 
pointer to a complete object type

in der Zeile steht das hier

*(unsigned char*)firstCluster++=sector[row+26];

und das macht er durch weg. :-(


MFG: Andre

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich könnte mir da zwei Möglichkeiten vorstellen, warum das nicht klappt.

1. Versuchs mal so:
1
*(unsigned char*)firstCluster=sector[row+26];
2
firstCluster++;

2. Versuchs mal so:
1
*(unsigned char*)firstCluster++=(unsigned char*)sector[row+26];

Klappt da was von?
Das ist wegen dem CodeVision Compiler, da müsste man mal raus finden 
warum der den void Pointer so an meckert..

Mit nimm die neuste Version zum anpassen meinte ich die Version 0.5.7

Grüße Daniel

von Andre (Gast)


Lesenswert?

So gut soweit habe ich nun versucht erstmal die mmc.c, mmc.h und 
config.h eingebunden.

nun habe ich dort das problem das er mir das hier anmeckert

    loop_until_bit_is_set(SPSR,SPIF);

Error: mmc.c(418), included from: Neu.c: undefined symbol 
'loop_until_bit_is_set'



MFG: Andre

von Andre (Gast)


Lesenswert?

ich meinte ich habe die Version 0.5.7 eingebunden.

von Andre (Gast)


Lesenswert?

Ich glaub ich bleib weiter bei der CodeVision_SDLIB_v0.4.4 den da habe 
ich die wenigsten fehler und so.

Den das nimmt ja hier garkein ende mit den ganzen ram. :-)


MFG: Andre

von Daniel R. (zerrome)


Lesenswert?

Hallo,
1
loop_until_bit_is_set(SPSR,SPIF)

ist ein Makro aus der avr-libc, SPSR ist ein Register und SPIF ist ein 
Bit in dem Register. Das Makro ist sehr schnell, daher benutze ich es. 
Dahinter steckt eigentlich:
1
do { } while ((!((*(volatile uint8_t *)(((uint16_t) &(SPSR)))) & (1 << (SPIF)))))

Ändere mal das Makro so wie hier beschrieben. Dann wirst du 
wahrscheinlich noch nen Haufen anderer Fehler bekommen wegen den 
unterschiedlichen Register Namen, die musst du alle ändern.

Poste doch mal die Fehlermeldungen, vielleicht kann man dann mehr sagen. 
Du kannst ja die Teile die in der CodeVision_SDLIB_v0.4.4 stehen 
vergleichen mit den stellen aus der 0.5.7 die nicht auf Anhieb laufen...
Oder du fragst mal nett bei  "Lolipop Er (lolipoper)" ob er nicht 
nochmal die 0.5.7 auf CodeVision portieren mag. Oder du nimmst den 
avr-gcc anstelle von CodeVision :)

Viele Grüße Daniel

Persönliche Nachricht an "Lolipop Er (lolipoper)" : 
http://www.mikrocontroller.net/user/show/lolipoper

von Bernd (Gast)


Lesenswert?

Hallo,

wie schnell kann man mit dieser Bibliothek auf einer SD-Karte 
schreiben?Wie lange brauche ich z.B. um 10 MB zu schreiben?

Danke im Vorraus und Grüße
Bernd

von Matze (Gast)


Lesenswert?

Das hängt von der Taktrate deines µC zusammen. Außerdem ist deine 
Speicherkarte entscheidend. Also einfach mal ausprobieren ;)

Grüße,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hallo,
der Matze hat es schon erwähnt, es hängt von verschiedenen Faktoren 
ab...

Ich sage mal so, mit einer neueren SD Karte und im Multiblock-write 
Modus, bei 10 MHZ SPI Takt etwa 40 Sekunden für 10 MBytes.

von Thorsten (Gast)


Lesenswert?

Hallo,
ich benutze die Fat32 in einer Portierung auf den XMega. Leider ist in 
der Applikation öfter mit dem Wegbrechen der Versorgungsspannung zu 
rechnen und der Controller schreibt ständig in wachsende Dateien.
Gibt es ausser einer Pufferung der Versorgungsspannung eine Möglichkeit 
ein korruptes Dateisystem zu vermeiden?
Ständige ffclose() Aufrufe gefolgt von erneutem öffnen der Datei sind 
denke ich nicht so gut.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
wenn man jetzt so etwas wie "flush" beim schreiben machen würde, also um 
den Dateieintrag zu updaten und die aktuell gepufferten Daten zu 
schreiben, müsste man genau die Dinge machen, die bei einem ffclose 
auftreten. Das einzige was man evtl. übergehen könnte wäre das suchen 
der Datei im Verzeichnis, beim erneuten öffnen. Das wirkt sich aber nur 
bei vielen Dateien in einem Verzeichnis aus.
Generell mach ich mir aber mal Gedanken ob da nicht was zu machen ist.
Umgehen könnte man dass, wenn man nicht nur 512 Bytes puffern würde, 
sondern 1024 Bytes. Dann wären die Möglichkeiten wesentlich größer, aber 
so muss alles durch den 512 Bytes Puffer.
In FAT32 ist ein Journal nicht vorgesehen, wie es bei allen neueren 
Dateisystemen Standard ist. Da muss man dann über dem Standard selber 
was machen...

Viele Grüße

Daniel

von Steffen (Gast)


Lesenswert?

Hallo,

ich habe gelesen, dass du mit linux arbeitest, hast du dir das Image der 
Karte per dd geholt oder wie hast du das gemacht.

MfG

von Daniel R. (zerrome)


Lesenswert?

Hallo,
nein mit dem Tool WinHex, das läuft auch unter Linux gut.
Generell muss man aber nur alle Sektoren einer Karte in eine Datei 
packen, das reicht dann schon...

Grüße Daniel

von Lowtzow .. (lowtzow)


Lesenswert?

hallo

tolles projekt!
ich habe diese library auf einem mega328 im einsatz. wobei daten die 
ausgewertet wurden auf einem lcd angezeigt werden und auf die sd karte 
geschrieben werden. und noch immer mehr als die hälfte an speicher platz 
;-)


möchte noch zusätzlich gps implementieren, wie könnte man das am 
einfachsten realisieren?
kann ich hierbei die uart so verändern, damit sie nur mit dem gps modul 
kommuniziert oder ist diese systembedingt erforderlich?

und wie kann man den syste der einträger in der txt verändern, zb dass 
durchnummerierungen erfolgen

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja die UART kann man einfach benutzen, es wird nur SPI von der Lib 
benutzt.

>und wie kann man den syste der
>einträger in der txt verändern, zb dass
>durchnummerierungen erfolgen

Wie meinst du das?

Willst du eine große Datei erstellen in der alle NMEA Einträge stehen?
Dann musst du die Lib im überschreiben Modus benutzen, dann kannst du 
einfach die Datei öffnen und was anhängen...


Grüße Daniel

von Lowtzow .. (lowtzow)


Lesenswert?

super!

hab gesehn, man kann echt viel mit deinen libs anstellen ;-)
wie wirkt es sich aus, wenn der ffwrites(text) oder andere aktivitäten 
der sd von einem interrupt unterbrochen werden?

habe zb einen interrupt laufen der jede ms ausgelöst wird, brauch diese 
zeit um die flanken eines externen interrupts zu messen.
auf die karte sollte im sek takt geschriben werden. habe bemerkt, dass 
nach einiger zeit anscheinend der schreib prozess wesentlich länger 
braucht. macht sich bemerkbar da das lcd in der selben schleife hängt 
und manchmal 5sek und länger nicht aktualisiert wird. liegt das 
vielleicht an interrupts?
nur wenn ich die interrupts deaktiviere für den sd schreib prozess, kann 
ich einige sekunden keine messwerte empfangen.

von Daniel R. (zerrome)


Lesenswert?

Das ist so schwer zu sagen, da ich nicht genau sehen kann wie du die Lib 
in deinem Code benutzt.
Aber wenn du die Anbindung an die Karte mit Hardware SPI machst, sollte 
eine Unterbrechung keine Probleme machen, da SPI per Definition Clock 
hörig ist. Also könnte man zwischen 2 zu Übertragenden Bytes auch Pausen 
einlegen. Ich gehe mal davon aus, dass wenn man ein Byte auf die 
Hardware SPI gibt, dies auch nicht von Interrupts unterbrochen wird, 
weil Hardware...
Schließt und öffnest du die Datei in die du schreibst bei jedem 
Messwert?

Grüße Daniel

von Lowtzow .. (lowtzow)


Lesenswert?

da ich derzeit noch am erproben bin, verwende ich deine lib im großen 
und ganzen original nur leichte anpassung für mega328. aufrufe werden 
nach der mainsimple vorlage gemacht, wobei die datei auch jedesmal 
geschlossen wird

mir ist in der nacht noch etwas eingefallen. da ich noch freien speicher 
habe, könnte ich ca 60sek am mega328 speichern und dann gesammelt 
übetragen mit intterupt disable (2-3fehlende werte in einer min ist 
nicht so schlimm)

kann sein, dass das spulen zum dateiende nach einiger zeit länger 
dauert?!
1
 
2
      sprintf(text,"%u",(int)heartbeat_output);
3
4
// Dateinamen müssen in diesem Format sein !
5
    unsigned char file_name[20]="TEST    TXT";
6
7
    // string zum in die datei schreiben schreiben
8
    //unsigned char str[13]="Hallo Datei!";
9
//    unsigned char str[13]="heartbeat_output";
10
11
12
    // Datei existiert nicht, also anlegen !
13
    if(MMC_FILE_NEW == ffopen(file_name)){
14
15
       // schreibt String
16
       //ffwrites(str);
17
     ffwrites(text);
18
19
       // neue Zeile in der Datei
20
       ffwrite(0x0D);
21
       ffwrite(0x0A);
22
23
       // schließt Datei
24
       ffclose();
25
     }
26
27
28
29
     // Datei existiert, also anhaengen !
30
     else{
31
32
       ffseek(file.length);   // spult bis zum Dateiende vor um anzuhaengen !
33
34
       // schreibt String
35
       //ffwrites(str);
36
     ffwrites(text);
37
38
39
       // neue Zeile in der Datei
40
       ffwrite(0x0D);
41
       ffwrite(0x0A);
42
43
       // schließt Datei
44
       ffclose();
45
     }
46
47
48
     // Datei existiert, also kann man lesen.
49
     if(MMC_FILE_EXISTS == ffopen(file_name)){
50
51
        // setzen einer Variable und dann runterzaehlen geht am schnellsten !
52
        unsigned long int seek=file.length;
53
54
        // lesen eines chars und Ausgabe des chars.
55
        // solange bis komplette Datei gelesen wurde.
56
        do{
57
           uputc(ffread());
58
        }while(--seek);
59
60
        ffclose();

von Daniel R. (zerrome)


Lesenswert?

Hallo,

>kann sein, dass das spulen zum dateiende
>nach einiger zeit länger dauert?!

Das kommt auf die Datenmenge an, da man sich durch die schon verketteten 
Cluster suchen muss. Ist die Datei um die mehreren MB oder sogar GB kann 
das dauern.

>..und manchmal 5sek und länger..

5 Sekunden ist ne verdammt lange Zeit. Stimmt da vielleicht irgend etwas 
anderes nicht? In 5 Sekunden würde man wenn es gut läuft 1,3 Millionen 
Bytes auf eine Karte schreiben können.
Blockiert der Interrupt sich selber oder so?

Poste doch mal den ganzen Code, als Datei Anhang. So kann ich da nicht 
viel dazu sagen. In dem von dir gezeigten Code sehe ich keinen Fehler...

Grüße Daniel

von Lowtzow .. (lowtzow)


Lesenswert?

Daniel R. schrieb:
> 5 Sekunden ist ne verdammt lange Zeit. Stimmt da vielleicht irgend etwas
> anderes nicht? In 5 Sekunden würde man wenn es gut läuft 1,3 Millionen
> Bytes auf eine Karte schreiben können.
> Blockiert der Interrupt sich selber oder so?
>
> Poste doch mal den ganzen Code, als Datei Anhang. So kann ich da nicht
> viel dazu sagen. In dem von dir gezeigten Code sehe ich keinen Fehler...

hab mich ein bisschen herumgespielt.
habe testweise werte nacheinander auf die karte geschrieben, mit 
systemzeit in ms. dabei ist mir aufgefallen, dass der datenstring sehr 
schnell ca.20ms auf die karte geschrieben wird.
also am schreiben kanns nicht liegen.
testweise, habe ich die datei nicht geschlossen, selbes problem, je 
länger die datei wird desto länger hält sich der mega328 mit der sd 
karte auf.

und dann ist mir eingefallen, dass in deinem beispiel die datei über den 
uart wieder ausgelesen wird. diese funktion ist zwar in meinem code auch 
vorhanden, nur wird sie nicht gebraucht!
und na klar nach 30x25 Zeichen braucht das auslesen über den uart schon 
ne zeit...

also auslesen raus und alles super toll jetzt! danke für den support 
hier und tolle libs für die sd-card hast du geschrieben, die tadelos 
funktioniern!! danke!

der fehler war mein programm...
der fehler war wie immer menschlich ;-)

von Daniel R. (zerrome)


Lesenswert?

Schön das es jetzt klappt :)

Oft muss man Geduld haben wenn etwas nicht klappt und man nicht richtig 
Debuggen kann wegen fehlender Geräte wie z.b. Spektrum-Analyzer oder 
Logik-Analyzer... Da ist Kreativität gefragt ;)

Viele Grüße

Daniel

von Uhu U. (uhu)


Lesenswert?

Weißt du, daß es hier auf dem Forum svn gibt, in das man solche Projekte 
einchecken kann?

Beitrag "Hinweis: Artikelsammlung"

Das macht es deutlich einfacher, die aktuelle Version zu finden ;-)

von Daniel R. (zerrome)


Lesenswert?

Hm, ja hatte mir das mit dem SVN auch schon mal überlegt.
Werde das mal in Angriff nehmen.

Auf http://www.mikrocontroller.net/articles/AVR_FAT32 unter "4. Der 
Code"
ist aber auch immer die neuste Version verlinkt.

Aber stimmt schon SVN wäre schöner.

Viele Grüße

Daniel

von Mark (Gast)


Lesenswert?

Hi,

vielen Dank für die Library. Ich habe dazu eine Frage:
Warum wird ein anderer Pin als der Hardware SPI SS für MMC_Chip_Select 
verwendet? Funktioniert das nicht mit dem SPI SS?
Bei meinen Board ist das CS der SD Karte an dem SPI SS angeschlossen. 
Ich habe das Problem, dass meine 2 GB Sandisk MicroSD Karte nicht 
erkannt wird. Ich habe Karten von zwei verschiedenen Herstellern 
getestet. Bei MMC_Chip_Select habe ich den Pin von SPI SS angegeben. 
SDHC ist auf false. Sonst ist es der gleiche Code wie im Wiki Eintrag.


Vielen Dank & Gruß
Mark

von Daniel R. (zerrome)


Lesenswert?

Hallo,
das mit dem MMC_Chip_Select Pin hatte ich einfach so von Ulrich Radig 
übernommen, ohne viel darüber nachzudenken. Warum genau es nicht klappt, 
wenn man den richtigen SPI SS Pin nimmt weiß ich nicht genau. Müsste man 
mal im Datenblatt nachschauen, vielleicht muss man da nur noch was 
einstellen, damit es klappt.
Kannst du nicht einfach einen anderen Pin nehmen?

Grüße Daniel

von Werner B. (werner-b)


Lesenswert?

Das ist mir schön öfter aufgefallen. Manche Leute haben regelrecht Angst 
vor dem SS Pin. Könnte das evtl. mit dem (berechtigterweise) miserablen 
Image des Namens zu tun haben?
 :-\

von Mark (Gast)


Lesenswert?

Zur Info: Es funktioniert auch mit dem SPI SS, ein Kontakt des MicroSD 
Slots war nicht richtig angelötet.

von Amega (Gast)


Lesenswert?

Hallo,

Neue Dateien werden nich angelegt, append funktioniert wenn die Datei 
nicht leer ist. Habt ihr ne Idee?

SanDisk MicroSD 2GB(+Adapter), 3.3V LM317, Pagelwandler - 3.3K,1.8K
ATMega32, 16MHz
stable-mmc-0.5.7



Mfg,
Amega

von Daniel R. (zerrome)


Lesenswert?

Hallo,
zeig mal den Code, hast du in der config.h etwas geändert?

Besorg dir für 20 Cent nen HC4050 als Pegelwandler oder lass den Atmega 
mit 3,3 Volt laufen.

Du könntest auch mal probieren ob die Einstellung in der config.h,
1
#define MMC_MAX_SPEED FALSE

etwas bringt.

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

So, es gibt jetzt ein SVN-Repository für die Bibliothek.
Dort wird immer die Neuste Version zu haben sein.
Immer als AvrStudio Projekt und mit Linux Makefile.

Das jetzige Update enthält eigentlich nur 2 Fixes.
1. Ein return wert ist dazu gekommen in der Funktion ffopen
2. In der fat_getFreeBytes wird der Sektor anders geladen.

Zusätzlich sind noch ein paar Funktionen static geworden.

Viele Grüße

Daniel

Link zu allen SVN:
http://www.mikrocontroller.net/svn/list

Link zur Bib.:
http://www.mikrocontroller.net/svnbrowser/avr-fat32

von Amega (Gast)


Lesenswert?

Hi,
ffopen->fat_loadFileDataFromDir kommt nicht zurück - endloss Schleife?
Hab die SD-Karte under Linux formatiert (fat16,fat32):
fdisk (type 6,b,c), dann mkfs.vfat .
Wie ich schon gerschrieben habe, funktioniert nur wenn die Datei da ist
und nicht leer.

Ich kann versuchen auch unter Windows die Karte zu formatieren.

Mfg

von Amega (Gast)


Lesenswert?

Nachdem ich unter Windows die Karte formatiert habe, wird nun neue Datei 
angelegt, die bleibt aber leer.
Wenn ich noch mal versuche, dann gibts die Datei doppelt.

Wie funktioniert bei auch? Habt ihr mit 2GB Karte getestet?

Bin aber trotzdem froh, dass sich was bewegt :)

von Amega (Gast)


Lesenswert?

Hab bemerkt, dass ich eventuel mkfs.vfat falsch aufgerufen habe.
-F habe ich vergessen
mkfs.vfat -F 32 dev....

von Daniel R. (zerrome)


Lesenswert?

Hallo,
klappt es denn jetzt?

Mit Linux hab ich es nie hin bekommen, dass bei einer frisch 
formatierten Karte das Root Directory mit 0x0fffffff abgeschlossen wird. 
Linux hat da, immer 0x08ffffff oder so draus gemacht. Wenn das Dir dann 
nicht mehr leer ist, ist korrekter Weise 0xffffffff draus geworden.

Kannst du dir die Sektoren der Karte anschauen? Wenn ja sieh mal nach 
wie der Root-Dir Cluster in der Fat aussieht. Hilfreiches Tool dafür 
WinHex. Läuft auch unter Linux.

Viele Grüße

Daniel

von GG (Gast)


Lesenswert?

Servus,

Amega schrieb:

>Wie funktioniert bei auch? Habt ihr mit 2GB Karte getestet?

Ich verwende 3 unterschiedliche Karten, zb. Verbatin Micro 2 Giga

Die Karten funktionieren einwandfrei.

Betreibe meine Karte mit einem Atxmega128a3 mit 16Mhz. SPI-Takt 8Mhz.

fat_getFreeBytes() benötigt bei einer 2 Giga Karte gerademal 200 mS.

Bin voll zufrieden.


Gruß GG

von Amega (Gast)


Lesenswert?

@Daniel:
Addresse 0x200 hat fff8 ffff:

dd if=/dev/mmcblk0p1 of=sdcard.bin bs=512 count=2
hexdump sdcard.bin

0000000 3ceb 6d90 646b 736f 7366 0000 4002 0001
0000010 0002 0002 f800 00ec 0010 0004 0000 0000
0000020 eff0 003a 0000 8929 cb0e 204b 2020 2020
0000030 2020 2020 2020 4146 3154 2036 2020 1f0e
0000040 5bbe ac7c c022 0b74 b456 bb0e 0007 10cd
0000050 eb5e 32f0 cde4 cd16 eb19 54fe 6968 2073
0000060 7369 6e20 746f 6120 6220 6f6f 6174 6c62
0000070 2065 6964 6b73 202e 5020 656c 7361 2065
0000080 6e69 6573 7472 6120 6220 6f6f 6174 6c62
0000090 2065 6c66 706f 7970 6120 646e 0a0d 7270
00000a0 7365 2073 6e61 2079 656b 2079 6f74 7420
00000b0 7972 6120 6167 6e69 2e20 2e2e 0d20 000a
00000c0 0000 0000 0000 0000 0000 0000 0000 0000
*
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200 fff8 ffff 0000 0000 0000 0000 0000 0000
0000210 0000 0000 0000 0000 0000 0000 0000 0000
*
0000400


Formatiert ahbe ich so:
mkfs.vfat -F 16 /dev/mmcblk0p1

fdisk -l:
        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1               1       60352     1931256    6  FAT16

von Amega (Gast)


Lesenswert?

Es funktioniert nun!!
1. mkfs.vfat  mit -F 16
2. alles gelöscht und neu kompiliert (make depends funkionieren!?!?)

Ich probiere mal mit Fat32.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
mkfs.vfat formatiert das komisch... hast du keinen Windows Rechner zum 
Formatieren zur Hand?
Es liegt an dem blöden Eintrag für das Root-Dir.

Grüße Daniel

von Amega (Gast)


Lesenswert?

Mit Fat32 ist die endloss Schleife zu beobachten:

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1               1       60352     1931256    b  W95 FAT32

hexdump /dev/mmcblk0p1 (sehe ich nirgendwo ffff ffff)
0000000 58eb 6d90 646b 736f 7366 0000 0802 0020
0000010 0002 0000 f800 0000 0010 0004 0000 0000
0000020 eff0 003a 0eb5 0000 0000 0000 0002 0000
0000030 0001 0006 0000 0000 0000 0000 0000 0000
0000040 0000 b429 cb13 204b 2020 2020 2020 2020
0000050 2020 4146 3354 2032 2020 1f0e 77be ac7c
0000060 c022 0b74 b456 bb0e 0007 10cd eb5e 32f0
0000070 cde4 cd16 eb19 54fe 6968 2073 7369 6e20
0000080 746f 6120 6220 6f6f 6174 6c62 2065 6964
0000090 6b73 202e 5020 656c 7361 2065 6e69 6573
00000a0 7472 6120 6220 6f6f 6174 6c62 2065 6c66
00000b0 706f 7970 6120 646e 0a0d 7270 7365 2073
00000c0 6e61 2079 656b 2079 6f74 7420 7972 6120
00000d0 6167 6e69 2e20 2e2e 0d20 000a 0000 0000
00000e0 0000 0000 0000 0000 0000 0000 0000 0000
*
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200 5252 4161 0000 0000 0000 0000 0000 0000
0000210 0000 0000 0000 0000 0000 0000 0000 0000
*
00003e0 0000 0000 7272 6141 5a4b 0007 0002 0000
00003f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000400 0000 0000 0000 0000 0000 0000 0000 0000
*
0000c00 58eb 6d90 646b 736f 7366 0000 0802 0020
0000c10 0002 0000 f800 0000 0010 0004 0000 0000
0000c20 eff0 003a 0eb5 0000 0000 0000 0002 0000
0000c30 0001 0006 0000 0000 0000 0000 0000 0000
0000c40 0000 b429 cb13 204b 2020 2020 2020 2020
0000c50 2020 4146 3354 2032 2020 1f0e 77be ac7c
0000c60 c022 0b74 b456 bb0e 0007 10cd eb5e 32f0
0000c70 cde4 cd16 eb19 54fe 6968 2073 7369 6e20
0000c80 746f 6120 6220 6f6f 6174 6c62 2065 6964
0000c90 6b73 202e 5020 656c 7361 2065 6e69 6573
0000ca0 7472 6120 6220 6f6f 6174 6c62 2065 6c66
0000cb0 706f 7970 6120 646e 0a0d 7270 7365 2073
0000cc0 6e61 2079 656b 2079 6f74 7420 7972 6120
0000cd0 6167 6e69 2e20 2e2e 0d20 000a 0000 0000
0000ce0 0000 0000 0000 0000 0000 0000 0000 0000
*
0000df0 0000 0000 0000 0000 0000 0000 0000 aa55
0000e00 0000 0000 0000 0000 0000 0000 0000 0000
*
0001400

von Amega (Gast)


Lesenswert?

ich probiere noch einmal unter Winx ... shutdown

von Amega (Gast)


Lesenswert?

Hi Daniel,

Mit Winx Enchantix formatierte (FAT32) Karte funktioniert!

Mfg
Amega

von Amega (Gast)


Lesenswert?

@Daniel: hab diff gemacht und so was gefunden:

21c36
< 00003e0 0000 0000 7272 6141 5a4b 0007 0002 0000  <- Linux
---
> 00003e0 0000 0000 7272 6141 ffff ffff 0002 0000  <-Windows

Weiss ich nicht ob es relevant ist, aber pasten ist kostenlos ;)

Und ab Adresse 0:
< 0000000 58eb 6d90 646b 736f 7366 0000 0802 0020
< 0000010 0002 0000 f800 0000 0010 0004 0000 0000
---
> 0000000 58eb 4d90 4453 534f 2e35 0030 0802 0026
> 0000010 0002 0000 f800 0000 003f 00ff 0010 0000

Mfg

von Amega (Gast)


Lesenswert?

Wäre dann nicht richtig Wert zwischen 0x#FFFFFF8 – 0x#FFFFFFF zu 
erwarten als EOC?

http://www.embedded-code.com/download/mmc_sd_memory_card_driver_technical_manual.pdf
....
0x#FFFFFF8 – 0x#FFFFFFF EOC (End Of Clusterchain) (typically you should 
use 0x#FFFFFFF

von Amega (Gast)


Lesenswert?

Hab die Funktion fat_loadFileDataFromDir geändert und nun filegt das 
Ding :)

fat.c@172
  while(!((  (i>=0x8ffffff && i<=0xfffffff ) 
&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){// prueft ob weitere 
sektoren zum lesen da sind (fat32||fat16)



Bin neugierig, ob linux-formatierte Karte unter Winx lesbar ist.

von Amega (Gast)


Lesenswert?

Und noch was habe ich festgestellt: append funktioniert bei mir nicht 
wenn die Datei leer ist.

von Amega (Gast)


Lesenswert?

ups 0x#FFFFFF8 != 0x8ffffff !?!?
..war sonnig heute ;)

von Amega (Gast)


Lesenswert?

Und noch was:
http://www.pjrc.com/tech/8051/ide/fat32.html
Also, the end-of-file number is actually anything equal to or greater 
than 0xFFFFFFF8, but in practive 0xFFFFFFFF is always written.

von Daniel R. (zerrome)


Lesenswert?

>ups 0x#FFFFFF8 != 0x8ffffff !?!?
Kommt auf die Endianness an ;)


>fat.c@172
>  while(!((  (i>=0x8ffffff && i<=0xfffffff )
>&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){// prueft ob weitere
>sektoren zum lesen da sind (fat32||fat16)

Ja sollte so laufen, bläht das den Code auf? Keine Ahnung wie viel mehr 
Aufwand ein größer gleich im Gegensatz zu gleich ist...

>append funktioniert bei mir nicht
>wenn die Datei leer ist.

Das schau ich mir mal an. Aber eigentlich sollte das kein Problem sein, 
weil ans Ende spulen bei Dateigröße 0 kein Problem ist.

file.c@168
while( offset>=512 ){ ...

offset ist hier die Byte Stelle zu der man spulen möchte. Bei Dateigröße 
0 ist das 0 und 0 ist nicht >= 512, also wird in ffseek nichts 
sinnvolles gemacht...

Nur um sicher zu gehen, du appendest ;) ja so oder?
1
if(MMC_FILE_EXISTS == ffopen(file_name)){
2
   ffseek(file.length);
3
   uputc('a');
4
   ffclose();
5
}

Grüße Daniel

von Amega (Gast)


Lesenswert?

End-of-Cluster - FAT32 - >= 0x0FFFFFF8
Der Beweis ist here zu finden:
http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/fatgen103.doc
......
IsEOF = FALSE;
If(FATType == FAT12) {
    If(FATContent >= 0x0FF8)
        IsEOF = TRUE;
} else if(FATType == FAT16) {
    If(FATContent >= 0xFFF8)
        IsEOF = TRUE;
} else if (FATType == FAT32) {
    If(FATContent >= 0x0FFFFFF8)
        IsEOF = TRUE;
}

von Daniel R. (zerrome)


Lesenswert?

Ja krass, das hatte ich doch tatsächlich immer überlesen.
Wird geändert werden, danke.
Gewundert hatte es mich doch schon warum Linux das so seltsam formatiert 
:)

Grüße Daniel

von Alex G. (almalex)


Lesenswert?

kann es sein das man bestimmte ascii zeichen nicht schreiben kann? weil 
ich schicke den richtigen string, und wenn ich die zeichen einzeln 
ausgebe stimmen sie auch, nur auf der sd karte stehen sie nicht
danke mfg alex

von Daniel R. (zerrome)


Lesenswert?

Wenn du Strings mit der Funktion ffwrites schreibst, darf in dem String 
logischerweise kein '\0' alias 0x00 vorkommen, da dies ja ein String 
Ende markiert. Bei anderen Steuerzeichen bin ich mir nicht sicher ob die 
gehen.

Mit ffwrite kannst du jedes Byte Zeichen auf die Karte schreiben.

Falls das immer noch nicht geht, müsstest du mal ein bisschen Code 
zeigen und die Zeichen die du schreiben möchtest.

Viele Grüße

Daniel

von Tom (Gast)


Lesenswert?

Hi,

ich hab ne allgemeine Frage: Warum verwendest du für Strings unsigned 
char* anstatt char*? Die Ascii Tabelle geht doch nur bis 127 und dadurch 
gibt es bei mir viele Warnings.

von Uhu U. (uhu)


Lesenswert?

Da kann ich nur aus dem eigenen Nähkästchen plaudern: signed char ist 
einfach nur krank, wenn es Zeichen und keine int-Werte enthält.

Aber vielleicht ist es auch Gewohnheitssache, mit den Abstrusitäten von 
signed char - Vergleichen zurecht zu kommen.

von Lowtzow .. (lowtzow)


Lesenswert?

habe heute versucht daten über den uart einzulesen, lib ist ja 
vorhanden.

verwende ich jedoch
1
 ugetc();
zum auslesen, dann bekomme ich beim kompilieren folgenden fehler

:369: undefined reference to `ugetc'
1
#include "uart.h"
 ist im maincode geaddet und initalisieren und
1
 uputc(ffread());
 funktioniert im main programm auch, beim kompilieren dabei gibts auch 
keine fehler. nur wenn ich ugetc aufrufen möcte schreit er eine 
fehlermeldung.
kann das bitte mal wer testetn obs ähnliche fehler gibt?!

mfg
low

von Lowtzow .. (lowtzow)


Lesenswert?

hab die einstellung gefunden die geändert werden muss config.h ;-)

von Uhu U. (uhu)


Lesenswert?


von Daniel R. (zerrome)


Lesenswert?

Hm,
hab ich da was überlesen oder geht es im Prinzip nur um vfat, also mit 
langen Dateinamen?

Das die da so auf dem fat noch herumreiten, wird wohl eher irgendwie 
exFat mit Zusammenhängen ?!?

Fat16/32 ist ja schon ziemlich in die Jahre gekommen. Wenn man mal so 
moderne Dateisysteme sieht...

von Lowtzow .. (lowtzow)


Lesenswert?

hallo

wenn ich einen string mit vielen zeichen schreiben will hängt sich das 
programm auf. hab schon vieles probiert. \0 macht auch keinen 
unterschied. anscheinend gibt es ein limit für die stringlänge?! denn 
mit strings die kürzer sind funktioniert alles problemlos. anbei ein 
beispiel für eine länge die bei mir nicht mehr klappt.
1
char map_start[] = "awedawereeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeawedawereeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeawedawereeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\0 ";
2
ffwrites(map_start);

hat wer einen tipp?!

ps. fat32 formatierte karten klappen derzeit auch nicht, kann man das wo 
umstellen?!

speicher ist eigentlich noch da
Program:   14360 bytes (43.8% Full)
(.text + .data + .bootloader)

Data:       1528 bytes (74.6% Full)
(.data + .bss + .noinit)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich vermute mal Ram Überlauf. Wo in deinem Programm kommst du auf die 
1528 bytes Ramverbrauch??

Pack den String mal ins Flash und probier das nochmal.
Oder mach ein kleines Array und schreib das wiederholt auf die Karte...

Mit was Fat32 Formatiert? Mit Windows?
Welche Version der Lib nutzt du?
Was genau meinst du mit klappt nicht ?!?

Wenn du ein CharArray so erstellst brauchst du das '\0' am Ende nicht! 
Das wird dann automatisch mit dran gemacht.
1
char map_start[] = "awedaweree";


Welchen Controller benutzt du?

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Hallo,
und wie sieht es aus? Läufts?

von Lowtzow .. (lowtzow)


Lesenswert?

Daniel R. schrieb:
> Hallo,
> ich vermute mal Ram Überlauf. Wo in deinem Programm kommst du auf die
> 1528 bytes Ramverbrauch??
>
> Pack den String mal ins Flash und probier das nochmal.
> Oder mach ein kleines Array und schreib das wiederholt auf die Karte...
>
> Mit was Fat32 Formatiert? Mit Windows?
> Welche Version der Lib nutzt du?
> Was genau meinst du mit klappt nicht ?!?
>
> Wenn du ein CharArray so erstellst brauchst du das '\0' am Ende nicht!
> Das wird dann automatisch mit dran gemacht.
>
>
1
> char map_start[] = "awedaweree";
2
>
>
>
> Welchen Controller benutzt du?
>
> Grüße Daniel

ok, mal wieder ein programmfehler meinerseits ;-)
anscheinend is das ram übergelaufen. habe mal die ganzen strings ins 
eeprom des avr (atmega328p) abegelegt und jetzt klappts das beschreiben 
mit langen strings auf die sd problemlos.
mein ram ist so voll weil ich große array habe ca. 100 uint16_t array 
und dann noch lcd/sd/gps. und alles sehr unaufgeäumt.
das mit fat32 muss ich noch testen, aber ich tipp mal drauf es 
funkt.formatiert ist jedenfalls alles it windows.
bin derzeit ganz zufieden mit fat16 läuft alles super und prima!!  danke 
daniel!!
hab das programm jetzt soweit geschireben, dass ich auf der sd-karte ein 
kml file für google earth  erstelle und die gps koordinaten reinschreib.

mfg low

von Daniel R. (zerrome)


Lesenswert?

Hallo,
es gibt auf http://www.mikrocontroller.net/svnbrowser/avr-fat32/ eine 
neue Version, in der ist nur die Bestimmung des Cluster Endes geändert.
Das behebt das Problem mit Linux formatierten Karten :)

Wurde hier thematisiert 
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Danke  Amega (Gast)


Grüße Daniel

von aga (Gast)


Lesenswert?

Hallo

ich würde gerne meine gps Datensammlung gerne speichern
und bin auf diesen Foren Beitrag gestoßen

Das was hier angeboten wird ist ein bischen viel
kann mir jemand sagen welche DAteien und Methoden ich brauche, um nur 
die Datensammlung zu speichern.

benutze einen atmega16

mfg aga

von Daniel R. (zerrome)


Lesenswert?

Hallo,
orientier dich einfach an dem Beispiel in der main.c

Oder hier dran: 
http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel

Da ist ein einfaches Beispiel wie man die schreib/lese Funktionen 
benutzt.
Wenn du speziellere Hilfe möchtest, musst du schon ein bisschen mehr 
verraten :)

Oder noch besser ein wenig Code Posten, zu dem man Hilfestellung geben 
kann.

Grüße Daniel

von Nig G. (nig)


Lesenswert?

Hallo Daniel,
erstmal meinen herzlichsten Dank für deine Arbeit an diesem Projekt, das 
über die Zeit wirklich hervorragend geworden ist!

@alle: Mein Dank gilt natürlich auch für alle anderen, die sich an 
diesem Projekt beteiligt haben oder wertvolle Vorarbeit geleistet haben!

Ich verwende die SD-Library (leicht angepasst) auf einem ATmega64 unter 
IAR und soweit läuft auch alles perfekt mit unterschiedlichsten 
SD-Karten.
Nun sind mir aber 3 Dinge/fehler aufgefallen, die ich hier mal 
ansprechen wollte, weil ich die in den bisherigen Diskussionen noch 
nicht finden konnte.

1.) Fehler in der Funktion "fat_loadFileDataFromCluster"?
Beim Vergleich des Dateinamens werden in der folgenden Zeile nur 10 
Zeichen verglichen, obwohl der Dateiname aus 11 Zeichen besteht. 
Folglich wird also das letzte Zeichen ignoriert, wodurch "MEINFILE1.TXT" 
und "MEINFILE1.TX2" im Vergleich identisch sind!
Bisher:
1
if(0==strncmp((char*)file.name,(char*)name,10)){
Korrigiert:
1
if(0==strncmp((char*)file.name,(char*)name,11)){

2.) Fehler in der Funktion "fat_loadSector"?
Am Ende der Funktion steht "return FALSE;" wobei diese Stelle niemals 
erreicht werden kann. Diese Funktion kann in der bestehenden Form nur 
"TRUE" zurückgeben, weshalb sich eine Prüfung auf Fehler bisher auch 
völlig erübrigt. Bei welcher Bedingung, hätte denn FALSE zurückgegeben 
werden sollen?

3.) Hier (http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten) 
steht:
"Nachdem die Karte deselektiert wurde (/CS auf high), die Taktleitung 
noch einige Male pulsen, damit die Karte DO hochohmig/tri-state schaltet 
(vgl. Chans Erläuterungen)."
Das wird in der SD-Library bisher noch nicht gemacht, weshalb ich das 
bei mir noch eingefügt habe. Das könnte z.B. folgendermaßen gelöst 
werden. An jeder Stelle, wo im Source "MMC_Disable()" steht, müsste nur 
ein Schreibbefehl folgen, oder?. So z.B.:
1
MMC_Disable();  // CS High
2
mmc_write_byte(0xFF); // dummy write, 8 CLK-Pulse nachdem CS High, damit die Karte DO tri-state schaltet

Viele Grüße
Nig

von test (Gast)


Lesenswert?

Hallo,

kann mir jemand sagen welche MMC SD Katen man am besten benutzen

die auch günstig zu bekommen sind?!?!


MfG

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ Nig G. (nig)

Bei Punkt 1 und 2 hast du recht, ist mir irgendwie durchgegangen :)
Wird geändert.

Zu Punkt 3, diese Karten sind SPI hörig, also brauchen eigentlich für 
alles einen CLK um was zu machen, zumindest die meisten. Das mit dem "DO 
hochohmig/tri-state" wirkt sich aber auch nur aus, wenn man mehrere 
"Geräte" am selben SPI Bus hat, sonst wäre das egal.
Wird aber geändert.

Danke für die Unterstützung.

@ test (Gast)

Man kann jede Karte nehmen, auch so ganz billige für 2-3 Euro. Wichtig 
nur, es müssen MMC, SD oder SDHC Karten sein.

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach ja, ich überlege grade die Prüfung in fat_loadSector ganz raus zu 
nehmen, ist zwar nicht so schön ohne Fehler Prüfung, aber so wie es bis 
jetzt immer war bringt es ja auch nix...

Mal als Zwischenlösung:
1
unsigned char fat_loadSector(unsigned long int sec){
2
  
3
  if(sec!=fat.currentSectorNr){
4
  #if (MMC_WRITE==TRUE)
5
    if(fat.bufferDirty==1){      
6
             fat.bufferDirty=0;
7
             if(FALSE==mmc_write_sector(fat.currentSectorNr,fat.sector)) return FALSE; 
8
    }
9
  #endif
10
  if(FALSE==mmc_read_sector(sec,fat.sector)) return FALSE; 
11
  fat.currentSectorNr=sec;      
12
  }  
13
    
14
  return TRUE;             
15
}

von mega8 (Gast)


Lesenswert?

ich bekomme immer die Fehlermeldung aus der funktion ffclose:

../file-0.3.c:119: error: 'kb_buffer' undeclared (first use in this 
function)

Damit liegt der Compiler auch völlig richtig, kb_buffer wurde da 
nirgendwo deklariert, aber hab natürlich nichts verändert, einfach nur 
eure Codebeispiele kopiert.
Muss ich was im Projekt bei AVR Studio einstellen?
Makefile benutze ich nämlich keine...

von Daniel R. (zerrome)


Lesenswert?

Hallo,
oha du versuchst da die Version 0.3 zu kompilieren...
Nimm die aus dem SVN und dann sollte das ohne Probleme gehen.

Viele Grüße

Daniel

PS: In der SVN Version ist auch eine AVR-Studio Projektdatei dabei...

Aktuelle Version: 0.5.9
http://www.mikrocontroller.net/svnbrowser/avr-fat32

von Marek N. (Gast)


Lesenswert?

Moin,

ich experimentiere derzeit auch mit SD-Karten an einem ATmega32. Derzeit 
noch mit dem Code von Ulrich Radig.
Würde gerne mal am WE diesen Code ausprobieren.
Gibt es schon Unterstützung für LFN?

Beste Grüße, Marek

von Daniel R. (zerrome)


Lesenswert?

Hi,
nein gibt es noch nicht.
Hab da aber eine Idee, wie man da tatsächlich reguläre Unterstützung für 
lange Dateinamen hin bekommt ohne nochmal 256 Byte Ram zu brauchen :)
Aber vor Mitte Juli wird da nix draus werden...

Aber es ist jeder herzlich eingeladen mit zu entwickeln. Ich pflege das 
dann in die Lib ein.

Viele Grüße

Daniel

von Thorsten J. (Gast)


Lesenswert?

Hallo,

ich hab nun auch endlich die Software erfolgreich zum Laufen bekommen. 
Der Kasus Knaxus war bei mir, dass ich die Software-SPI verwendet habe, 
welche eben so schnell läuft, wie es der Prozessortakt hergibt. Bei 
18,432MHz ist das für die SD-Karte einfach zu schnell. Ich habe ein paar 
zusätzliche Delays eingebaut und dann ging es.

Von meiner Seite dann auch nochmals vielen Dank, für die ganze Mühe, die 
du bisher hier rein gesteckt hast.

Gruß Thorsten

von Daniel R. (zerrome)


Lesenswert?

Hallo,
kannst du mal zeigen an welchen Stellen du da delays reingebaut hast, 
weil eigentlich ist selbst 20 MHz SPI nicht zu schnell für SD/MMC 
Karten...

Viele Grüße

Daniel

von GG (Gast)


Lesenswert?

Servus,



Thorsten J. schrieb:



> ich hab nun auch endlich die Software erfolgreich zum Laufen bekommen.
>
> Der Kasus Knaxus war bei mir, dass ich die Software-SPI verwendet habe,
>
> welche eben so schnell läuft, wie es der Prozessortakt hergibt. Bei
>
> 18,432MHz ist das für die SD-Karte einfach zu schnell. Ich habe ein paar
>
> zusätzliche Delays eingebaut und dann ging es.

ich betreibe meine SD-Card (Verbatim Micro 2 GB) hardwaremäßig mit 20 
MHZ!
Proz. Atxmega
Prozessortakt 2*10 MHz,keine SPI-Teilung, also 20 MHZ am SPI. Das ist 
eine nachweisbare Geschwindigkeit.


Deine Aussage: „Ein paar zusätzliche Delays“  kann heißen: 1,2 oder xx 
Mhz.

Wei schnell ist der SPI-Takt nun wirklich?

Gruß GG

von Thorsten J. (Gast)


Lesenswert?

Ich hab in der mmc_read_byte() und mmc_write_byte()
1
MMC_Write &=~(1<<SPI_Clock);  //erzeugt ein Clock Impuls (Low)

ergänzt zu
1
_delay_us(SOFT_SPI_DELAY_US);
2
MMC_Write &=~(1<<SPI_Clock);  //erzeugt ein Clock Impuls (Low)
3
_delay_us(SOFT_SPI_DELAY_US);

und hab dann getestet. Die Funktion _delay_us() stammt dabei aus der 
<util/delay.h>.

Für SOFT_SPI_DELAY_US waren Werte größer 0.3 notwendig, damit die Karte 
arbeitet. Das ergibt einen Takt von etwa 300kHz, der jedoch einen hohen 
Jitter aufweist.

Wenn ich das noch recht im Hinterkopf habe war es auch so, dass die 
Karten zur Initialisierung mit maximal 400kHz betrieben werden dürfen. 
Bei Verwendung der Hardware-SPI wird dem auch Rechnung getragen und erst 
nach erfolgter Initialisierung auf volle SPI-Geschwindigkeit geschaltet.

Gruß

Thorsten

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja guter Einwand. Die Initialisierung im Software SPI Modus schau ich 
mir nochmal an. Bin eh grade eine ordentliche Platine für eine SD Karte 
am machen. Wenn das fertig ist, gibt es eine neue Version...

Danke und viele Grüße

Daniel

von Harry L. (mysth)


Lesenswert?

Hallo,

ich versuch gerade die Funktionen auf einem "myAVR Stamp256 PLUS" zum 
Laufen zu bringen.
http://shop.myavr.de/index.php?sp=article.sp.php&artID=100062

Zunächst mal hab ich in mmc.h folgende Ergänzungen gemacht:
1
  // der SS pin des SPI ports wird nicht benutzt! also da nich die karte anschließen, sondern an MMC_Chip_Select !
2
3
  #if defined (__AVR_ATmega2560__)
4
    #define SPI_MISO            3  //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist (DO)
5
    #define SPI_MOSI            2  //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist (DI)
6
    #define SPI_Clock           1  //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
7
    #define MMC_Chip_Select     0  //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist (CS)
8
    #define SPI_SS              0  //Nicht Benutz muß aber definiert werden
9
  #endif
10
11
  #if defined (__AVR_ATmega128__)


Bei diesem Board ist die CS-Leitung der SD-Karte direkt mit dem SS-Pin 
des Controller verbunden.
Daher hab ich einfach mal ganz "blauäugig" den entsprechenden Portpin in 
die obigen Definitionen eingetragen.

Das mitgelieferte Beispielprogramm liefert "Boot..OK"
Ich hab zur Fehlersuche noch weitere "uputs" eingebaut, und schon der 
nächste Aufruf meldet sich nicht mehr zurück: (keine augabe von uputs)
1
    // Datei existiert nicht, also anlegen !
2
    if(MMC_FILE_NEW == ffopen(file_name)){
3
4
        uputs((uint8_t*)"wrote new File\r\n");

ich würde mich über einen Tip freuen!

Harry

von Harry L. (mysth)


Lesenswert?

Hallo,
das Problem ist gelöst, seitdem ich die aktuelle Version aus dem SVN 
verwende.
Danke nochmal an Daniel für dieses Library!!!

Harry

von Harry L. (mysth)


Angehängte Dateien:

Lesenswert?

Anpassungen für ATMega2560:

Ich hab das Library um Support für ATMega2560 CPUs erweitert.

Im Anhang sind die geänderten Files.

Harry

<edit>

Mein Fehler!
nicht mmc.c, sondern mmc.h wurde angepasst.

von Harry L. (mysth)


Angehängte Dateien:

Lesenswert?

die fehlende mmc.h

Harry

von Daniel R. (zerrome)


Lesenswert?

Hallo,
wird im neuen Release aufgenommen werden.

Danke und viele Grüße

Daniel

von Tim (Gast)


Lesenswert?

Hi,

ich habe mal eine Frage wie ich es schaffe, dass es nur eine FAT auf der 
SD-Karte gibt, ist fürs Verständnis leichter nachzuvollziehen.

von Daniel R. (zerrome)


Lesenswert?

Hi,
unter Linux gibt es die Möglichkeit zu sagen das nur mit 1 er Fat 
formatiert werden soll... Unter Windows geht das so glaube ich nicht.

Viele Grüße

Daniel

von Tim (Gast)


Lesenswert?

Ich habe das bis jetzt immer mit GParted unter ubuntu gemacht, da habe 
ich die Option nur 1 Fat anzulegen noch nicht gefunden. Könntest du mir 
bitte ein Stichwort geben wonach ich besser googlen kann.

von Daniel R. (zerrome)


Lesenswert?

Also so formatiere ich unter Linux Fat32 mit einer Fat und 4 Sektoren 
pro Cluster:
1
/sbin/mkdosfs -v -F32 -f1 -s4 -I /dev/sde

Formatiert wird so das Gerät /dev/sde, das ist bei mir ein Kartenslot 
mit einer SD Karte drin.


Daniel

von Matze N. (hupe123)


Lesenswert?

Hi, ich habe auch mal wieder ein Problem:

Ich will grade die neuste Version einbinden (von 0.5.7 auf 0.5.9).
Ich rufe in meinem Programm an manchen Stellen die ffwrites-Funktion wie 
folgt auf
1
ffwrites("huhu");
jedoch bekomme ich nun zu jedem Schreibbefehl die Nachricht, daß da was 
mit den Definitionen nicht passt. Hier einer der vielen gleichen Fehler:
1
main.c:62: warning: passing argument 1 of 'ffwrites' makes pointer from integer without a cast

Ich habe etwas geforscht und an jeder Ecke steht in der neuen Version 
"unsigned". Und daran wird es wohl auch liegen. Warum wurde das denn 
umgestellt?!

Aber was mir viel wichtiger ist, was kann ich gegen diesen Fehler 
machen?

Vielen Dank für alle guten Ratschläge!! :)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
das hatte mehrere gute Gründe, einer davon ist z.B. das so evtl. das 2er 
Komplement entfällt...
Versuch es so und das Warning verschwindet:
1
ffwrites((unsigned char*)"huhu");

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Cool! Danke! Hätt ich aber auch selber drauf kommen können... :( Naja, 
manchmal is man eben betriebsblind ;)

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

So nun habe ichdas zweite Problem: ich kann weder mit der alten (0.5.7) 
noch mit der neuen (0.5.9) Version auf meine SD-Karten schreiben. Obwohl 
SDHC aktiv ist.
Als Speicherkarten benutze ich die zwei im Foto.
Ich formatiere mit WindowsXP Pro.

Ich habe jeweils mit den Beispiel programmen ausprobiert.
Komisch ist, daß in der neuen Version machmal (jedes 15-20ste Mal) durch 
die
1
mmc_init
 gegangen wird (die drei Punkte erscheinen), jedoch erscheint nie das 
"OK".
Bei der alten Routine klappt noch nicht mal der erste Schritt.

Die Hardware die ich benutze ist ein ATmega128 mit 7,3728Mhz.

Angeschlossen ist alles richtig, sonst würden ja die drei Punkte auch 
nich erscheinen - wurde aber dennoch schon x-Mal kontrolliert.

Kann mir jemand helfen?!

Grüße aus Hannover

von Daniel R. (zerrome)


Lesenswert?

Hallo,
so Fehler wie irgendwas klappt manchmal und manchmal nicht, sind 
meistens Hardware Fehler... Benutzt du Software SPI oder Hardware, wie 
lang sind die Kabel, Welche Spannungs Pegel...
Mach mal ein Bild vom Aufbau, dann kann ich evtl. mehr sagen

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

hmm... ich habe eben noch mal alle Lötstellen kontrolliert und 
vorsichtshalber alle nachgelötet - geht aber immer noch nichts.

ich betreibe die karte:
- ohne treiber baustein
- direkt an einem ATmega128
- bei 3,3V.

Meinen Eagleplan habe ich angehängt. Ich hoffe, ich hab keinen Fehler in 
der Verschaltung gemacht :)

Viele Grüße und schon mal besten Dank für deine Hilfe!

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

Hab den Anhang vergessen: hier nun der Schaltplan

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

ich habe eben einfach mal zwei 10k Ohm Pull-Up-Widerstände an die CS- 
und die MISO eingebaut (siehe Anhang), weil ich das hier gelesen hatte: 
http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten. aber das 
hilf auch nichts! Ich verzweifel noch!!! Hilfe!

von Daniel R. (zerrome)


Lesenswert?

Hallo,
du steckst doch den SPI Programmer aus wenn du die Karte testest oder?

Mehr fällt mir grad nicht ein, schaue aber später nochmal genauer...

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Ja, aber klar. Geht aber trotzdem nich...

Viel Spaß beim Fußball nachher!

von Daniel R. (zerrome)


Lesenswert?

Hm, Schaltplan sieht Ok aus.
Jetzt könnte der Fehler immer noch in der Software liegen oder im 
Tatsächlichen Aufbau der Schaltung.
Ich hab selber so eine 2GB Scandisk Karte und mit der funktioniert es...
Hast du was in der config.h geändert oder in der mmc.h ?
Wie sieht die Initialisierung genau aus?
Mach doch mal ein Foto der fertigen Schaltung.

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Hi danke für deine Mühe!!!

Ich denke nich, daß es an der Software liegt. Ich hab nichts in deinem 
Beispielprogramm geändert. Ich will morgen noch mal die Schaltung in 
schön aufbauen - sieht echt nach Kraut und Rüben aus.
Wenns fertig is, lade ich ein paar Fotos hoch.

Grüße und genieß das schöne Wetter - in Hannover sind noch 30°C und ich 
muss raus: hier drinnen sind die nämlich auch ;)

Grüße,
Matze

von Matze N. (hupe123)


Lesenswert?

Hi es lag wirklich nich an der Software. Ich habe zwei Sachen geändert:

1) beim ATmega128 geht der ISP nicht über den SPI sondern tw. über den 
USART0. Ich habe meinen UART-RS232 von dieser doppelbelegten 
Schnittstelle abgelötet.
2) Ich habe gleichzeitig den µC gewechselt. Hatte noch nen zweiten 
mega128.

Ich habe eben nochmal den neuen µC mit eingesteckter RS232 Schnittstelle 
programmiert. Geht trotzdem. Lag also wohl an einem def. µC... Jetzt 
gehts aber!!!
Aber warum mich das jetzt vier Tage meines Lebens kosten musste, weiß 
ich auch nich.. ich hasse diese Kleinigkeiten an denen es immer hängt!

Dennoch vielen Dank für deine Hilfe!

von Daniel R. (zerrome)


Lesenswert?

Hallo,
schön das es jetzt klappt...

Es ist nur Zeitverschwendung wenn man nichts dabei gelernt hat :)

Viele Grüße

Daniel

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

Hi,

ich habe da etwas ganz komisches grad festgestellt. Ich kann in eine 
Datei mit einer Funktion nichts schreiben.

Ich will in eine Datei für eine Log-Datei bevor die Daten aufgezeichnet 
werden eine Startsequenz schreiben (Funktion: sd_geschw_start(void)).
Ich habe in die Datei eine UART-Ausgabe ("start") eingebaut; diese 
erscheint auch auf meinem Terminal, aber es steht kein "huhu" in der 
Datei. Nur ein "ende"... WARUM zu Teufel?!
Hat jemand ne Idee?

Grüße,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hallo,
bei dem Stück Code das du gepostet hast, zähle ich ~95 Bytes nur an 
Ascii Zeichen... Das ist ziemliche Ram Verschwendung...

Bin mir jetzt da grad nicht sicher, aber benutzt du fat_str richtig?
Versuche mal an ffopen einen festen Dateinamen zu übergeben, um das 
Problem einzugrenzen.

Ach ja und schließt du die Datei auch irgendwann vor verlassen des 
Programms auch?!?

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Hi Daniel,

ich habe den Tag über in meinem Wust an Funktion gewütet und vieles 
zusammen gestrichen, dabei fiel mir auf, daß in einer anderen Datei an 
zwei stellen wirklich das "ffclose()" gefehlte... dennoch danke für 
deine Mühe. Jetzt geht alles :D

Morgen gibts dann erste Probeläufe mit meinem neuen Datenlogger :D :D

Gute Nacht,
Matze ;)

von Matze N. (hupe123)


Lesenswert?

So geht alles. Allerdings habe ich grade versucht eine 
Verzeichnisstruktur anzulegen. Beim Aufruf von
1
ffmkdir
 habe ich aber noch Probleme:

Mein Quelltext dazu sieht wie folgt aus:
1
 unsigned char verzeichnis[13]=  "TEST";  
2
ffmkdir(verzeichnis);
(Natürlich nachdem die Karte initiallisiert wurde :)
Auf meiner SD-Karte taucht auch ein Ordner auf. Allerdings kann ich 
diesen nicht Öffnen. Windows XP Pro sagt mir:
1
TEST bezeiht sich auf einen Pfad, der nicht verfügbar ist. Dieser kann auf einer Festplatte dieses Computers [...] sein.Stellen Sie sicher, daß der Datenträger korrekt eingelegt ist, [...]. Und wiederholen sie den Vorgang. ...
Muss ich bei dem Funktionsaufruf irgendwie mehr beachten?!

Achja: wieso funktionieren eigentlich nur Grossbuchstaben sowohl bei 
Dateinamen als auch bei Verzeichnissen?!

Danke für deine Hilfe,
Matze ;)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
versuch mal "TEST       " als Verzeichnisname ( 4 Buchstaben und 7 
Leerzeichen). Das mit den Großbuchstaben ist noch aus der DOS Zeit, also 
aus der Fat16 Zeit quasi.
Wenn ich lange Dateinamen Unterstützung mit eingebaut habe wird sich das 
alles etwas vereinfachen, zumindest in der Anwendung :)

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Viel besser! Jetzt gehts!!!

Danke!

von Andre V. (Firma: -----) (fichte)


Lesenswert?

Sagt mal hat es schon jemand geschaft es unter Codevision zum Laufen zu 
bekommen.?


Habe jetzt schon soviel Probiert aber leider ohne erfolg. :-(

von Daniel R. (zerrome)


Lesenswert?

Hallo,
wenn mir ja jemand sagen könnte wie CodeVision mit void Pointern umgeht 
könnte ich da vielleicht was machen... Aber die Dokumentation da finde 
ich etwas dürftig. Glaube es hakt da am meisten, der Rest sind ein paar 
Register und Kleinigkeiten...

Grüße Daniel

von Andre V. (Firma: -----) (fichte)


Lesenswert?

Habe mir mal vor einigen tagen die Neue Light Version von Codevision 
gezogen und getestet.
Die haben ja eine Sd Lib drin und die Funktioniert ja auch super.

Nur komme ich nicht ganz zurecht damit.
Kam zwar auf Display den Inhalt der Datei schreiben und auch Ordner etc. 
aber ich möchte die Werte für andere Sachen Übernehmen und das geht 
irgentwie nicht.

MFG: Andre

von Rene (Gast)


Lesenswert?

Hallo zusammen,

ich wollte gerne wissen, welche Lesegeschwindigkeiten ich bei der 
Verwendung dieser FS32-Bibliothek von SD-Karten zu erwarten habe.

Im Einsatz soll ein ATmega168 mit 8 Mhz eingesetzt werden.
SPI in Hardware mit halber Taktgeschwindigkeit.

Und gibt es Möglichkeiten die Leserate zu maximieren, z.B. FAT16 anstatt 
FAT32?

MfG
Rene

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also wesentlich schneller wird es durch Fat16 nicht werden, da das nur 
mit den Fat einträgen selbst in Zusammenhang steht. Also nur bei Fat 
lookups ins Gewicht fällt...
Also mit Fat32, multiblock-write und 4 Mhz SPI werden wohl so um die 
100-150 k Bytes/Sec gehen. Mit MMC Karten evtl. sogar mehr.

Viele Grüße

Daniel

von Rene (Gast)


Lesenswert?

Hi Daniel,

danke für die prompte Antwort.

Das mit dem Multiblock ist ja so eine Sache, da es wohl nicht von jeder 
Karte unterstützt wird.
Wie ist denn die maximal zu erwartende Leserate ohne 
Multiblock-Unterstützung?
Ich würde gerne universell bleiben, was die SD-Karten angeht.

MfG
Rene

von Daniel R. (zerrome)


Lesenswert?

Hm,
ich hab nur eine uralte Karte die Multiblock nicht unterstützt.
Bei den neueren sollte das wohl immer gehen.
Die Geschwindigkeit hängt auch stark von der Karte ab.
Schätzungsweise wird lesen auch im Bereich 100-150 kBytes/sec liegen...

Viele Grüße

Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
hier mal eine kleine Beta der Version 0.6
Falls da mal jemand reinschauen mag :)

Neu:
Lange Dateinamen, kleinere Vereinfachungen.

Was geht noch NICHT:
Root dir bei Fat16 beschreiben wenn dort schon mehrere Einträge sind.
Einen vollen Ordner erweitern.

Was geht:
Dateien mit langem Dateinamen lesen.
Ordner mit langem Dateinamen lesen/wechseln zu.

Beim Anlegen wird wie gesagt noch der Ordner nicht erweitert!
Bei einem leeren Ordner und 4 Sektoren/Cluster könnte man aber 
mindestens 4 Dateien mit Dateinamen von 255 Zeichen Länge anlegen ;)

Datei mit langem Dateinamen anlegen löschen.
Ordner mit langem Dateinamen anlegen rekursiv löschen.

Beispiel für den Aufruf:
1
ffopen((unsigned char*)"langer name test.txt")

So wird wie gehabt, die Datei angelegt wenn nicht vorhanden, oder 
geöffnet wenn vorhanden.

Viele Grüße

Daniel

von martin (Gast)


Lesenswert?

hallo
funktioniert auch eine microsd mit einem adapter?

von Daniel R. (zerrome)


Lesenswert?

Hallo,
was meinst du mit einem Adapter?
Ein Card-slot?!?
MicroSd geht.

Viele Grüße

Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
hier mal die zweite Beta.

Lange Dateinamen werden jetzt komplett unterstütz. Bei Ordnern und 
Dateien. Das ist allerdings nicht ganz Standard konform. Sollte aber 
keine Probleme Machen solange man die Karte mit Geräten liest/schreibt, 
die auch lange Dateinamen unterstützen !

Es gibt eine Option in der config.h die heißt "MMC_ENDIANNESS_BIG", wie 
der Name vermuten lässt, kann damit die Byteorder umgestellt werden. Wer 
mit den void Pointer Probleme hatte sollte das mal ausprobieren :)

Die Funktion "fflushFileData()" kann jetzt während geschrieben wird 
aufgerufen werden, sie sorgt dafür, dass die Dateiinformationen 
gesichert werden. Allerdings sollte das möglichst selten gemacht werden, 
da immer mindestens 2 Sektoren geschrieben werden müssen !

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Soo, ist fertig :)

Wäre schön, wenn ich evtl. ein bisschen Feedback bekommen könnte, falls 
irgendwo was schief läuft oder es Verbesserungen gibt.

Das einzige Problem, dass immer noch besteht ist, dass bei Software-SPI 
bei der Initialisierung nicht langsamer getaktet wird, da is mir noch 
nicht wirklich was schönes zu eingefallen :)

Die neue Version gibts hier: 
http://www.mikrocontroller.net/svnbrowser/avr-fat32

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach ja, Wiki:http://www.mikrocontroller.net/articles/AVR_FAT32
wird noch angepasst werden...

von Buzzwang (Gast)


Lesenswert?

Hallo,
ich bin neu hier und habe es mal ausprobiert.

Die 0.6.0 hat nicht getan !
Ich habe es 1:1 genommen und laufen lassen.
Der Controller konnte wohl schreiben + lesen + zufügen.
Aber in Windows wurde die Datei nicht erkannt. Windows zeigte die Datei 
mit "Test.txt." (mit '.' am Ende) mit 0kb an.
Öffnen und Löschen ging nicht. Nur neu formatieren.

Danach bin ich auf die 0.5.9 umgestiegen. Hat geklappt.

Info:
2GB Flash Karte
ATMEGA16 @ 16 MHz

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja ich war irriger weise davon ausgegangen, dass wenn Linux das 
ordentlich anzeigt, Windows das auch macht. Macht es aber nicht...
Werde später ein update machen, da gibts dann auch noch mehr neue Sachen 
:)

Viele Grüße

Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

So neue Version 0.6.1 hochgeladen.

http://www.mikrocontroller.net/svnbrowser/avr-fat32/

Man kann jetzt wesentlich mehr konfigurieren in der config.h


Viele Grüße

Daniel

PS: Als Anhang noch ein Benchmark Programm für atmega168 @ 16 MHZ

von Jens (Gast)


Lesenswert?

Hallo!
Also ich habe getestet 0.6.0 - das Problem mit dem nich lesen können 
etc. unter Windows hatte ich auch. Jetzt habe ich 0.6.1 getestet, im 
Prinzip funktionierts, wenn die Karte leer ist legt es die Datei an, 
allerdings steht dann 2 x "Hallo Datei!" in der Datei, je einmal in 
einer Zeile.
Ist das normal / gewollt?
Darüber hinaus, befindet sich eine leere test.txt auf der Karte passiert 
nichts bzw. das Programm kommt nicht zum Ende - habe 3 LED zum debuggen, 
irgendwo nach dem init bleibts stehen und die Datei bleibt leer, ich 
werde berichten wenn ich den Wunden Punkt gefunden habe ...

Ich verwende einen ATmega2561 @ 16MHz, sandisk 1GB bzw. Platinum 2GB

Aber ne tolle Sache ischs in jedem Fall

Gruß Jens

von Jens (Gast)


Lesenswert?

okay manchmal beantworten sich fragen von selber, das mit dem doppelten 
vorkommen des "Hallo Datei!" ist gewollt, also streichen wir die Frage!

von Daniel R. (zerrome)


Lesenswert?

Hallo,

>Darüber hinaus, befindet sich eine leere
>test.txt auf der Kart

das ist nicht normal soweit ich verstehe was Du machst. Zu welcher Datei 
befindet sich die leere test.txt auf der Karte?

Grüße Daniel


PS: Bin für jede Anregung dankbar !

von Jens (Gast)


Lesenswert?

nein nein, weil 0.6.0 nicht funktioniert hatte hab ich etwas rumprobiert 
- u.a. hatte ich eine leere test.txt angelegt, nach dem Durchlauf des 
Programms war die dann immernoch leer, das war dann aber auch bei 0.6.1 
so.
Werde mich noch n bissi mehr damit beschäftigen, vielleicht kann ich ja 
noch was konstruktives beitragen ;)
Grüßle

von Uwe S. (lan-opfer)


Lesenswert?

...kann mir jmd. ein wenig behilflich sein?? Ich habe Version 0.6.1 
heruntergeladen, im AVR-Studio meinen Controller (XMeaga 64A3) 
eingestellt und compiliert. Es hagelt gleich einige Fehlermeldungen:
../mmc.c:128: error: 'DDRB' undeclared (first use in this function)
../mmc.c:128: error: (Each undeclared identifier is reported only once
../mmc.c:128: error: for each function it appears in.)
../mmc.c:128: error: 'SPI_MISO' undeclared (first use in this function)
../mmc.c:129: error: 'SPI_Clock' undeclared (first use in this function)
.
.
.
Ich denke, es fehlen ein paar einstellungen für den Controller. Aber ich 
weiss nicht wo und was...

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich kenne die Atxmegas nicht.
Wie setzt man denn da einen Pin auf 1 bzw. 0 ?
In der mmc.h müssen die Pins an der die Karte hängt eingestellt werden.
Wenn aber bei einem xmega die Pins anders angesteuert werden müsste man 
da noch mehr anpassen...


Viele Grüße

Daniel

von XMEGA (Gast)


Lesenswert?

Hallo,

Uwe S. schrieb:
> fehlen ein paar Einstellungen für den Controller

in der mmc.h sind einige Atmega vordefiniert! Aber kein Atxmega.

Wenn du mit solchen Kaliebern arbeitest, solltest  du schon etwas 
Hintergrundwissen über die Hard- und Software besitzen.

Dir jetzt einen fertigen Code zuliefern ist nicht die richtige 
Vorgehensweise. Wenn dir der Befehl DDRB z.B. nichts sagt, ist das 
Betreiben einer SD-Card am XMEGA schon aussichtslos.

Sollte dennoch Intresse bestehen, melde dich nochmals.


Gruß GG

von Uwe S. (lan-opfer)


Lesenswert?

...nein - DDRB sagt mir jetzt so aus dem Kopf nix. Mit Atmels arbeite 
ich zum ersten mal. Ich habe vorher mit ARM9 (davor SAB509, PIC, ...) 
gearbeitet. Ich muss jetzt wohl hoffen,  dass mir der XMega dann nicht 
zu gross wird ;-)

@Daniel R.: bei den XMega ist die IO-Struktur neu gemacht - es gibt ein 
paar Register mehr. Ist hier ganz gut beschrieben:
http://www.stromflo.de/dokuwiki/doku.php?id=xmega-c-tutorial

von Daniel R. (zerrome)


Lesenswert?

Ok, sollte sich ganz einfach portieren lassen.
Schau ich mir später mal an.
Mit Deiner Hilfe Uwe S. wird das schon werden. Ich selber habe keine 
atxmega da.
Du könntest schon mal rausfinden an welchen Pins die SPI Schnittstelle 
liegt und in welchen Registern man die einstellt...

Viele Grüße

Daniel

von Uwe S. (lan-opfer)


Lesenswert?

...so - da bin ich wieder. Ich widme mich dem Thema nur sehr 
unregelmässig - je nachdem, wie ich Zeit habe.
In der mmc.h und der uart.h werden wohl durch die Compilerdirectiven die 
prozessorspezifischen Einstellungen vorgenommen - richtig? Ich denke, da 
müsste mann den XMega "reinzaubern".
"#if defined (_AVR_ATXmega64a3_)" oder so ähnlich - weisst du, wie das 
festgelegt werden muss?

An meinem Board ist ja der 64A3 drauf und für die SD-Karte wurde 
folgende Konfig. verwendet:
CS - PB1
MOSI - PC5
MISO - PC6
SCK - PC7
-> also SPIC

Als nächstes müsste ich deine Einstellungen mal vergleichen mit dem 
Manual:
http://www.atmel.com/dyn/resources/prod_documents/doc8077.pdf ab S. 229 
sind die Register beschrieben. Leider weiss ich nicht, in wie fern die 
sich mit dem ATMega decken.

LG

Uwe

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also ich bin ab morgen erstmal ein paar Tage weg :)

Wegen
>#if defined (AVR_ATXmega64a3)
weiß ich selber nicht genau wie das mit den Xmegas geht, weiß aber hier 
sicher jemand anderes im Forum.

Also so wie ich das sehe, müsste in der mmc.h das in etwa so geändert 
werden:
1
  #define MMC_Write   PORTB  
2
  #define MMC_Read   PINB
3
  #define MMC_Direction_REG DDRB

zu
1
  #define MMC_Write   PORTC.OUT  
2
  #define MMC_Read   PORTC.IN
3
  #define MMC_Direction_REG PORTC.DIR

Jetzt ist das Problem, dass der CS Pin auch an Port C sein sollte, geht 
das irgendwie bei Deinem Board?
1
  #if defined (_AVR_ATXmega64a3_)
2
  #define SPI_MISO        6 
3
  #define SPI_MOSI        5 
4
  #define SPI_Clock     7  
5
  #define MMC_Chip_Select   (zusätzlicher Pin von PORTC) 
6
  #define SPI_SS        0
7
  #endif

Dann gibt es noch 2 Stellen in der mmc.c die geändert werden müssten
1
// hardware spi: bus clock = idle low, spi clock / 128 , spi master mode
2
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);

und
1
//SPI Bus auf max Geschwindigkeit
2
SPCR &= ~((1<<SPR0) | (1<<SPR1));
3
SPSR |= (1<<SPI2X);

So wie ich das sehe, brauchst Du nur das Register CTRL vom Xmega. Dann 
sollte das laufen...

Viel Spass beim Basteln.

Bis die Tage dann

Viele Grüße

Daniel

von xmega (Gast)


Angehängte Dateien:

Lesenswert?

Servus,


Daniel R. schrieb:
> So wie ich das sehe, brauchst Du nur das Register CTRL vom Xmega. Dann
>
> sollte das laufen...

ich habe dir ein lauffähiges Projekt eingestellt.

Atxmega128a3, SPIC(SD-CARD), USART 115200 USARTF0

SPIC(SD-CARD) sollte auf allen XMEGA laufen!

Gruß xmega

von Buzzwang (Gast)


Lesenswert?

bei mir läuft es nun auch super. Vielen Dank für alles.
Die neue Version braucht viel weniger Platz (ca. 4kb) als die 0.5.9.
Es tuts auch der ATMEGA8
ATMEGA8 @ 8Mhz + 2GB SD-Card

von Friedrich K. (fiete)


Lesenswert?

Hallo.

Danke erstmal an Daniel für den Code!

In den Bemühungen den Code v.0.6.1 für eienn Mega8 auszudünnen, bin ich 
inzwischen bei 84% Speicherbelegung. Nur leider funktioniert es nicht, 
wenn ich LFN an und abschalte. Jednefalls ändert sich nach 
Neukompilierung nicht die Speichergröße.
Das zweite Problem hat wohl mit dem ersten zu tun. Ich habe den Plan 
eine START.TXT in Windows zu erzeugen, auslesen zu lassen und das in 
eine TEST.TXT (mehrmals) hineinzuschreiben. Nur für Testzwecke. Wenn ich 
mir das Ergebnis danach unter Windows anschaue, finde ich zwei 
START.TXT. Ich habe das Gefühl, dass er die Datei nochmal neu anlegt, 
wohl weil er die existierende nicht erkennt. Den Inhalt kann er aber 
lesen und schreibt ihn auch brav in die TEST.TXT

Was habe ich hier falsch gemacht?

Gruß, fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo, bin wieder da :)

@ xmega (Gast)
Danke dafür, muss ich mir mal in ner ruhigen Minute zu Gemüt führen.

@ Friedrich K. (fiete)
Klingt nach Benutzerfehler. Man kann beispielsweise nicht 2 Dateien 
gleichzeitig öffnen. Poste mal den Code der bei Dir Probleme macht. Dann 
kann ich bestimmt mehr dazu sagen.

Viele Grüße

Daniel

von Friedrich K. (fiete)


Lesenswert?

Hey Daniel,

danke dass dus dir mal anschaust.
1
int main(void)
2
{
3
4
    DDRD=0xCC;
5
    PORTD=0xCC;        //0=beide an
6
                //4=linke an
7
                //8=rechte an
8
                //C=beide aus
9
  
10
  
11
12
  
13
14
  // Versuch Karte zu Initialisieren, bis es klappt. Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.
15
  while (FALSE==mmc_init())
16
    {
17
    nop();
18
    }
19
20
    PORTD=0xC8;
21
22
23
  // Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !
24
  if(TRUE == fat_loadFatData())
25
    {
26
    
27
    unsigned char start_dat[] = "START   TXT";
28
      
29
    //  if(MMC_FILE_EXISTS == ffileExsists(start_dat))
30
        {
31
        if(MMC_FILE_EXISTS == ffopen(start_dat))
32
        
33
          {
34
          
35
             // lesen eines chars und Ausgabe des chars.
36
              // solange bis komplette Datei gelesen wurde.
37
        
38
          for(i=0; i<19; ++i)
39
            {
40
            dat[i]=ffread();
41
            }
42
        
43
              ffclose();
44
          PORTD=0xC0;
45
        
46
             }
47
        }
48
      
49
  unsigned char file_name[]="LOG     TXT";
50
    
51
52
53
54
       // Datei existiert nicht, also anlegen !
55
      if(MMC_FILE_NEW == ffopen(file_name))
56
        {
57
58
       // Schreibt String auf Karte ! Nur richtige Strings koennen mit ffwrites geschrieben werden !
59
       ffwrites(dat);
60
61
       // Neue Zeile in der Datei
62
       ffwrite(0x0D);
63
       ffwrite(0x0A);
64
65
       // Schließt Datei
66
       ffclose();
67
       }
68
69
      // Datei existiert, also anhaengen !
70
      if(MMC_FILE_EXISTS == ffopen(file_name))
71
        {
72
73
       ffseek(file.length);   // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !
74
75
       // schreibt String
76
       ffwrites((unsigned char*)dat);
77
78
       // neue Zeile in der Datei
79
       ffwrite(0x0D);
80
       ffwrite(0x0A);
81
82
       // schließt Datei
83
       ffclose();
84
         }
85
       PORTD=0x00;
86
87
    }
88
89
}

Und ein Auszug aus der config.h, damit du weißt, was ich ein und 
ausgestellt hab.
1
  #define MMC_WRITE         TRUE  // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
2
  #define MMC_OVER_WRITE       FALSE  // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien überschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
3
  #define MMC_MULTI_BLOCK     FALSE  // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber möglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
4
  #define MMC_SDHC_SUPPORT    FALSE  // TRUE, dann mit sdhc unterstuetzung, wenn FALSE, dann nur mmc/sd karten. siehe : http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29
5
  #define MMC_ENDIANNESS_LITTLE  TRUE  // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
6
  #define MMC_LFN_SUPPORT      FALSE  // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
7
  #define MMC_RM_FILES_ONLY    TRUE  // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
8
9
  // schalter die explizit funktionen mit kompilieren oder nicht!
10
  #define MMC_TIME_STAMP       FALSE   // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
11
  #define MMC_RM           FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
12
  #define MMC_SEEK        TRUE  // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
13
  #define MMC_MKDIR        FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
14
  #define MMC_GET_FREE_BYTES    FALSE  // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
15
  #define MMC_LS          FALSE  // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
16
  #define MMC_CD          FALSE  // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
17
  #define MMC_FILE_EXSISTS    TRUE  // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
18
  #define MMC_WRITE_STRING    TRUE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.


Ich habe mir ein paar LED's als Kontrolle eingebaut und der Code, so wie 
er ist, läuft zumindest danach zu urteilen durch. Ich muss dazu sagen, 
dass meine C-Kenntnisse auch eher dürftig sind...

Gruß, Fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ohne den Code jetzt laufen zu lassen würde ich da schon ein paar Dinge 
als potentielle Probleme sehen.

Also das ist so ein Kandidat:
1
for(i=0; i<19; ++i)
2
{
3
   dat[i]=ffread();
4
}

das sollte besser "for(i=0; i<19; i++)" heißen. Dann sollte dat 
mindestens "unsigned char dat[20]" sein, weil du 19 Elemente und das 
'\0' speichern willst.

Dann noch:
1
ffwrites(dat);

Das funktioniert nur problemlos, wenn auf dat jetzt wirklich ein String 
steht. In C ist ein String immer mit '\0' terminiert, dafür musst Du 
sorgen. Ist das nicht so, schreibt die Funktion ffwrites Ram Inhalt auf 
die Karte bis sie auf eine 0 alias '\0' im Ram trifft.

Sonst sieht das eigentlich Ok aus.

Viele Grüße

Daniel

von Friedrich K. (fiete)


Lesenswert?

Danke Daniel,
das Array ist eigentlich richtig definiert, aber der letzte genannte 
Punkt könnte Probleme bereitet haben, das habe ich noch nicht bedacht. 
Ich probiere es mal aus...

Gruß, Fiete

von Friedrich K. (fiete)


Lesenswert?

Japp, fehlenden Terminal-zeichen lag es wohl. Ich bin nun ein ganzes 
Stück weiter, allerdings habe ich nun wieder Schwierigkeiten:

Es soll ein Datenlogger werden, der zwei Kanäle loggt und das auch in 
zwei files schreiben soll. Damit er nicht bei jedem furz schreibt, soll 
er erstmal pro Kanal 95Byte in den RAM schreiben, und dann den String 
aus dem RAM auf die Karte wegschreiben.

Also habe ich zwei Arrays definiert (und somit, wenn ichs recht verstehe 
auch den RAM reserviert):

unsigned char kanal_0 [95];
unsigned char kanal_1 [95];

in einer for-Schleife schreibe ich diese nun voll und wenn sie voll 
sind, dann wird ffwrites aufgerufen:
1
for(unsigned int j=0;j<20;j++)
2
        {
3
        kanal_0[j+w*20]=dat[j];
4
        }        
5
        
6
        w++;
7
        if(w==5)
8
        {
9
          // Datei existiert, also anhaengen !
10
            if(MMC_FILE_EXISTS == ffopen(filename_knal_0))
11
            {
12
          PORTD=0x80;           // <----- Fehlerkontrolleuchte
13
           ffseek(file.length);   // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !
14
15
           // schreibt String
16
           ffwrites((unsigned char*)kanal_0);
17
18
          
19
           // schließt Datei
20
           ffclose();
21
22
          PORTD=0x00;           // <------ Fehlerkontrolleuchte
23
          w=0;           
24
          }

Analog für Kanal 1.

Wenn NUR Kanal 0 angesprochen wird, dann funktioniert das wunderbar,
wenn NUR Kanal 1 angesprochen wird auch, aber wenn beide angesprochen 
werden, dann ist eine der beiden Files meist nicht mehr lesbar und die 
Strings in der Datei haben kaputte Stellen drin (irgendwelche Zeichen, 
die da nicht hingehören). Das pikante ist, dass das Problem wohl nicht 
im RAM auftritt, denn wenn ich z.B. 5x von kanal 1 auf die SD-Karte 
schreibe, und dann einmal von kanal 2, dann treten Fehler an Stellen 
auf, die vorher schon geschrieben wurden. Daher vermute ich, dass die 
FAT irgendwie Probleme macht oder ich irgendetwas anderes nicht bedacht 
habe...

Interrupts kommen eigentlich auch nicht in Frage für das Problem, weil 
ich erst wieder die Kanäle auslese, wenn alles andere abgeschlossen ist.

Jetzt hab ich überlegt, dass der Stack eventuell Probleme machen könnte, 
aber ich bin ja noch knapp 300Byte übrig für den Stack. Ich kann mir 
nicht vorstellen, dass das Probleme bereitet.

Ein weiters Problem ist, dass der Controller nur Dateinen beschreiben 
kann, die er selber angelegt hat, und auch leider nicht mehr nach einer 
Neuinitialisierung. D.h. ich muss die kanal.txt immer löschen, bevor ich 
das Programm nochmal duchlaufen lassen kann. Könnte es vielleicht auch 
damit zusammenhängen?

Bin für Tipps dankbar.

Besten Gruß aus Heidelberg,
fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also eigentlich puffert die Lib schon. Um genau zu sein 512 Bytes, da 
das genau ein Sektor ist. Da könntest Du Dir den ganzen Quatsch mit dem 
Puffern der Kanäle sparen.

Das ist so gefährlich
1
for(unsigned int j=0;j<20;j++)
2
    {
3
    kanal_0[j+w*20]=dat[j];
4
    }
Wenn w 5 ist und j 20, dann ist 20+5*20 = 120, also deutlich über der 
Array Grenze hinaus. Damit überschreibst Du was weiß ich im Ram...

Was für Daten kommen den so vor bei den Kanälen? Falls da Steuerzeichen 
vorkommen, also z.B. integer 0, dann geht das mit ffwrites NICHT.
Also noch mal ganz deutlich: NUR Strings sollten mit ffwrites 
geschrieben werden! Ein String wird mit '\0' terminiert. Also Ascii Code 
Buchstaben und Zahlen im Ascii Code quasi.

Mein Vorschlag wäre im http://de.wikipedia.org/wiki/CSV_(Dateiformat) 
Format die beiden Kanäle in eine Datei zu schreiben, aber in zwei 
Spalten in der Datei. Dann brauchst Du Dir um puffern keine Gedanken 
mehr zu machen, da das ja schon die Lib macht.

>Ein weiters Problem ist, dass der
>Controller nur Dateinen beschreiben
>kann, die er selber angelegt hat...

Ich vermute das Programm kommt vorher schon durcheinander, oder der 
Dateiname entspricht nicht den Konventionen.

Viele Grüße

Daniel

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.