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


von Sam .. (sam1994)


Lesenswert?

Gibt es trotz "Baustelle" ein Möglichkeit die ffls Funktion zu nutzen? 
Ziel ist es, das Dateien über ein Lcd ausgewählt werden können. Ich habe 
die Funktion bereits so abgewandelt, dass ich nur die Dateinamen 
erhalte. Allerdings sind diese im 8.3 Format und ffopen akzeptiert dies 
anscheinend nicht.

von Fabian B. (fabs)


Lesenswert?

ffopen funktioniert super mit 8.3.

Was genau bekommst du denn als Dateinamen zurück? Hast du mal ein 
Beispiel, auch wie du's dann an ffopen weitergibst?

Gruß
Fabian

von Sam .. (sam1994)


Lesenswert?

In meinem Beispiel "MARI    ESM". Das wird an uart und ffopen 
weitergegeben. Als Fehler erhalte ich MMC_FILE_ERROR, also muss das 
file_flag FALSE sein.

von Sam .. (sam1994)


Lesenswert?

Das Öffnen funktioniert übrigens, wenn ich einen Dateinamen, der alle 8 
Zeichen belegt, übergebe (also wenn keine Leerzeichen im Dateinamen 
sind).

Fabian B. schrieb:
> Hast du mal ein
> Beispiel, auch wie du's dann an ffopen weitergibst?
1
ffopen((uint8_t*)buffer, 'r');

von Sam .. (sam1994)


Lesenswert?

Hat keiner eine Idee?

von Fabian B. (fabs)


Lesenswert?

Kannst du mal das ganze Codesegment posten, bitte? Also von einlesen per 
ffls bis öffnen per ffopen. Inkl. Definition relevanter Variablen.

Gruß
Fabian

von Sam .. (sam1994)


Lesenswert?

1
static void lsRowsOfClust_ex (fptr_t uputs_ptr,uint32_t start_sec){
2
3
  uint16_t row;        // reihen
4
  uint8_t sec;        // sektoren
5
  uint8_t tmp[12];      // tmp string zur umwandlung
6
  uint8_t i;        // um dateinamen zu lesen
7
8
  sec=0;
9
  do{
10
    fat_loadSector( start_sec + sec );  // sektoren des clusters laden
11
    for( row=0; row<512; row+=32 ){    // geht durch reihen des sektors
12
13
      if( (fat.sector[row+11]==0x20||fat.sector[row+11]==0x10) && (fat.sector[row]!=0xE5 && fat.sector[row]!=0x00) ){
14
        
15
        // namen extrahieren und anzeigen
16
        for( i=0 ; i<11 ; i++ ){
17
          tmp[i]=fat.sector[row+i];
18
        }
19
        tmp[i]='\0';
20
        uputs_ptr(tmp);
21
22
        // reihe auf file stuct laden um file.length zu bekommen. koverieren und anzeigen...
23
        /*fat_loadRowOfSector(row);    
24
        uputs_ptr((uint8_t*)" ");
25
        ltostr(file.length,(char*)tmp,12,10);
26
        uputs_ptr(tmp);
27
        uputs_ptr((uint8_t*)"\n");*/
28
      }
29
    }
30
  }while( ++sec < fat.secPerClust );
31
}
32
33
// *******************************************************************************************************************************
34
// zeigt inhalt eines direktory an.
35
// unterscheidung ob man sich im rootDir befindet noetig, weil bei fat16 im root dir eine bestimmt anzahl sektoren durchsucht
36
// werden muessen und bei fat32 ab einem start cluster ! ruft lsRowsOfClust auf um cluster/sektoren anzuzeigen.
37
// *******************************************************************************************************************************
38
void ffls_ex(fptr_t uputs_ptr){
39
40
  uint8_t     sectors;  // variable um durch sektoren zu zaehlen
41
  uint32_t   clusters;  // variable um durch cluster des verzeichnisses zu gehen
42
43
  // bestimmen ab welchem cluster eintraege angezeigt werden sollen, bzw in welchem ordner man sich befindet
44
  clusters = (fat.dir==0) ? fat.rootDir:fat.dir;
45
46
  // root-dir fat16 nach eintrag durchsuchen. es bleiben noch 3 moeglichkeiten: nicht root-dir fat16, nicht root-dir fat32 und root-dir fat32
47
  if(fat.dir==0 && fat.fatType==16){
48
    sectors = 0;
49
    do{
50
      // root-dir eintraege anzeigen
51
      lsRowsOfClust_ex( uputs_ptr, clusters + sectors );
52
      sectors += fat.secPerClust;
53
    }while( sectors < (uint8_t)32 );
54
  }
55
56
  // root-dir fat32 oder nicht root-dir fat32/16, nach eintrag durchsuchen
57
  else {
58
    // durch cluster des verzeichnisses gehen und eintraege anzeigen
59
    while(!((clusters>=0x0ffffff8&&fat.fatType==32)||(clusters>=0xfff8&&fat.fatType==16))){    // prueft ob weitere sektoren zum lesen da sind (fat32||fat16)
60
      lsRowsOfClust_ex( uputs_ptr, fat_clustToSec(clusters) );                  // zeigt reihen des clusters an
61
      clusters = fat_getNextCluster(clusters);                        // liest naechsten cluster des dir-eintrags (unterverzeichniss groeßer 16 einträge)
62
    }
63
  }
64
65
}
66
67
uint8_t current_file;
68
uint8_t selected_file = 0;
69
char buffer[12];
70
71
void getFile(char *ptr)
72
{
73
  if(current_file++ == selected_file)
74
    strcpy(buffer, ptr);
75
}
76
77
int main()
78
{
79
  //Initialisierung SD-Karte / Lcd / Uart
80
  current_file = 0; 
81
  ffls_ex(getFile);
82
  lcd_puts(buffer);
83
  uputs(buffer);
84
  if(MMC_FILE_OPENED != ffopen((uint8_t*)buffer, 'r')) 
85
  {
86
    lcd_puts("\nError opening!");
87
    for(;;);
88
  }
89
}

von Sam .. (sam1994)


Lesenswert?

Die Dateien, die volle 8.3 Zeichen haben, können übrigens nur dank 
dieser vorgeschlagenen Änderung gelesen werden: 
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Ich vermute, in der fat_loadFileDataFromCluster ist noch ein weiterer 
Fehler drin, der seit Umstellung auf LFN, diese nicht mehr funktionieren 
lässt?

von Stefan Frings (Gast)


Lesenswert?

Hallo Daniel R.

iste die Aussage noch aktuell, dass die Library nich mehrere Dateien 
gleichzeitig öffnen kann?

SDHC Support ist inzwischen drin, habe ich das richt verstanden?

von Stefan Frings (Gast)


Lesenswert?

Hallo Daniel,

es ist mir gelungen, die Library erfolgreich in mein web basiertes I/O 
Modul einzubinden. Ich habe zwar noch keinen Anwendungsfall für den neu 
gewonnenen Speicherplatz, aber das kommt sicher noch.

Ich musste lediglich die SPI Schnittstelle an den ATxmega128D3 anpassen, 
aber das war überhaupt kein Problem. Schwieriger fiel mir die Einbindung 
in uIP (den Webserver), weil der Multi-Threading fähig ist, die avrfat32 
library aber nicht. Aber ich denke, ich habe das nun mit akzeptablen 
Beschränkungen hinbekommen:

- Der Webserver listet nur die ersten 1300 Bytes des 
Inhaltsverzeichnisses auf. Mehr Dateien will ich sowieso nicht ablegen.

- Beim Datei-Download müssen alle anderen konkurrierenden Web-Anfragen 
warten, bis der Download beendet ist oder abgebrochen wurde.

Vielen Dank für die Veröffentlichung der SD/MMC Karten Library. Sie war 
mir eine sehr große Hilfe.

Mein Projekt ist hier: http://stefanfrings.de/avr_io/

von Wolfgang Sch (Gast)


Lesenswert?

Hallo Thilo,

ich habe ein ähnliches Problem, hast Du inzwischen eine Lösung gefunden?

von Wolfgang S. (wolfgangs)


Lesenswert?

Hallo Thilo,
hast Du inzwischen eine Lösung des Problems gefunden? Bir mir tritt der 
gleiche Fehler auf. Nach Reparatur der Datei bleiben exakt 48k 
verfügbar. Setze ich per PC/Editor noch Zeichen an das Ende der Datei - 
abspeichern - schreibt mein Gerät die nächsten Datensätze einwandfrei. 
Wenn nicht, geht die Datei bei weiterem Beschreiben kaputt. 
Offensichtlich passiert das, wenn die Datenbytes genau bis Sektorende 
reichen. Ist es nur 1 Byte mehr, wird ordentlich weiter geschrieben.


Thilo M. schrieb:
> Mein Problem besteht leider immer noch:
>
> - minutenweises Schreiben, ca. 200 Byte pro Datensatz
> - täglich wird ein neues File angelegt
> - MMC_MAX_CLUSTERS_IN_ROW auf 16383
>
> Nach zwei Tagen wird ein neues File angelegt und ein Stück weit
> beschrieben, danach bleibt das Chipselect auf low und die Karte hängt
> sich auf (bleibt in der Schreib- oder Lesefunktion hängen). Das neu
> angelegte File ist dann defekt.
>
> Hat irgend jemand eine Lösung für dieses Problem?
> Ich bin da irgendwie ratlos.

von Thilo M. (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe noch keine Lösung dafür gefunden, aber falls Daniel das mal 
testen will hänge ich eine Datei an, bei der dieser Fehler auftritt.

Zusätzlich die mmc_config.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Ich habe noch keine Lösung dafür gefunden, aber falls Daniel das mal
> testen will hänge ich eine Datei an, bei der dieser Fehler auftritt.
>
> Zusätzlich die mmc_config.

Fehler beim zyklischen Zufügen von Messdaten zu einer bestehenden Datei.

Heute habe ich einen entscheidenden Hinweis gefunden. Offensichtlich hat 
das etwas mit dem Hersteller und dem Kartentyp zu tun. Eines meiner 
Geräte (hatte ich ganz vergessen) läuft seit 35 Tagen mit zyklischem 
Abspeichern 15s/je ca.60 Byte unter Verwendung einer billigen SD-Card. 
Bei teuren ATP-Industrial-Grade - Karten - 512MB steigt die Geschichte 
bei einer Dateigröße von 48 oder 54KB aus - und zwar immer genau bei 
einem Sektorwechsel zwischen zwei Speichervorgängen.
Dabei werden Daten in den schon benutzten Datenbereich an falscher 
Stelle abgelegt. Es entstehen u.a. neue Dateinamen, die einen Teil der 
ASCII-Zeichen aus den abgespeicherten Daten enthalten.
Ich werde mich mal mit den Unterschieden zwischen industriellen und 
nichtindustriellen SD-Karten beschäftigen und melde mich wieder.

von Thilo M. (Gast)


Lesenswert?

Wolfgang Sch. schrieb:
> Offensichtlich hat
> das etwas mit dem Hersteller und dem Kartentyp zu tun.

Das habe ich nun auch festgestellt.
Eine uralte 256MB Kingston Karte zeigt diesen Fehler nicht. Sie schreibt 
(bis jetzt) fehlerfrei, hat aber deutlich längere Zugriffszeiten.

Die Motorola Micro-SD (2GB) mit Adapter brach nach 38kB ab (siehe oben 
verlinktes File).
Das Zerstören des Files kann man vehindern, indem man bei 10 erfolglosen 
Initialisierungs- Lese- oder Schreibversuchen den Versuch abbricht. Dann 
sind wenigstens die Daten bis dahin nicht verloren.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Wolfgang Sch. schrieb:
>> Offensichtlich hat
>> das etwas mit dem Hersteller und dem Kartentyp zu tun.
>
> Das habe ich nun auch festgestellt.

Hallo Thilo,

ich glaube, ich habe das Problem beseitigen können.
Probiere mal am Ende der Funktion "fat_writeSector"
einige Dummy-Bytes von der SPI zu lesen. Ebenso in "fat_loadSector"
so etwa:
#if (MMC_WRITE==TRUE)
    if( fat.bufferDirty == TRUE )
      {
      fat.bufferDirty = FALSE;    // buffer kann nicht dirty sein weil 
wird geschrieben
      mmc_write_sector( file.currentSectorNr,fat.sector );      // 
schreiben von sektor puffer


      Takte();  //einige Bytes dummy-Lesen



      }
#endif


Offensichtlich brauchen manche Karten an der Stelle noch ein paar Takte.
Das ist erst mal ein vorläufiges Ergebnis, ich teste mal über ein paar 
Tage.
Jetzt bin ich bei 200KB geloggte Daten, soweit bin ich bisher noch nie 
gekommen.

von Thilo M. (Gast)


Lesenswert?

Hi Wolfgang,

habe getan, was du geraten hast, drei Byte zusaätzlich gelesen, und 
siehe da: die Motorola-Karte schreibt auch weiter (alte Datei von oben 
im Anhang verwendet)!

Werde die auch mal ein paar Tage laufen lassen.

;-)

von Wolfgang S. (wolfgangs)


Lesenswert?

Hallo Thilo,

seit 2 Tagen laufen bei mir 3 Geräte mit Karten verschiedener Hersteller 
fehlerfrei.
Problem gelöst!

von Wolfgang S. (wolfgangs)


Lesenswert?

Kleine Änderung:
Um ganz korrekt zu sein habe ich das dummy-read jetzt nur noch an einer 
Position in "mmc_write_sector" eingefügt. Funktioniert.
..............
  if ( retrys == 0)return FALSE;    // If not accepted, return with 
error
  mmc_disable();

  spi_read_byte();
  spi_read_byte();
  spi_read_byte();
  spi_read_byte();
  spi_read_byte();
  spi_read_byte();

  return TRUE;
  }
.............
In den FALSE - Fällen werden sowieso jede Menge Bytes gelesen - ohne 
Schreiben.

von Wolfgang S. (wolfgangs)


Lesenswert?

Wolfgang Sch. schrieb:
> Kleine Änderung:
> Um ganz korrekt zu sein habe ich das dummy-read jetzt nur noch an einer
> Position in "mmc_write_sector" eingefügt. Funktioniert.
> ..............

Kommando zurück! Mit dieser Änderung treten dann doch wieder Fehler auf.
Ich bleibe jetzt bei der Version vom 13.05.

von Thilo M. (Gast)


Lesenswert?

Ich habe seit Jahresanfang eine Sandisk 1GB Micro-SD am Laufen, alle 
paar Wochen taucht ein Fehler auf: Schreiben des Files wird abgebrochen, 
ab 00:00 Uhr wird ein neues File angelegt (so gewollt) und bei jedem 
Schreibvorgang wird ein neues File mit demselben Filenamen angelegt.

Habe auch dort die Änderung eingefügt, weil zufällig heute dieser Fehler 
auftrat. Der Logger hat sofort korrekt weitergeschrieben, mal sehen 
wie's weitergeht.

von Thilo M. (Gast)


Lesenswert?

Hi Wolfgang,

mit 6 zusätzlich gelesenen Byte (wie du oben beschrieben hast) war bei 
einer Motorola 128MB Micro-SD nach 6144 Byte Schluss. Funktioniert also 
auch nicht immer.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Hi Wolfgang,
>
> mit 6 zusätzlich gelesenen Byte (wie du oben beschrieben hast) war bei
> einer Motorola 128MB Micro-SD nach 6144 Byte Schluss. Funktioniert also
> auch nicht immer.

Bin auf der Suche nach der Ursache. Auf jeden Fall tritt aber kein 
Dateisalat mehr auf - oder? Wie äußert sich bei Dir das Problem? Ich 
vermute, dass früher geschriebene Sektoren nicht mehr vorhanden sind?

von Thilo M. (Gast)


Lesenswert?

Wolfgang Sch. schrieb:
> Auf jeden Fall tritt aber kein
> Dateisalat mehr auf - oder?

Nein, das hatte ich vorher schon ausgeschlossen, indem ich 10 Versuche 
beim Lesen und Schreiben gemacht habe, bei Fehler bricht er einfach ab.

Ich habe die zusätzlichen Byte (Lesen und Schreiben) wieder entfernt und 
habe die Taktrate (clk) auf 500kHz heruntergestellt. Seit vier Tagen 
schreibt er jetzt auf der "Problemkarte" fehlerfrei (minütlich ein 
Datensatz).

Manche Karten scheinen an gewissen Stellen ein kleines Päuschen zu 
benötigen, ist der Takt zu schnell, reicht die Zeit nicht. Wenn ich Zeit 
habe, suche ich die Stelle(n), brauche den Logger aber gerade an einer 
Solaranlage.

von Andre (Gast)


Lesenswert?

Hallo,

wie provoziert Ihr den Fehler? ich schreibe Teilweise meherere 100 MB 
Files auf die Karte und habe bis jetzt noch keine Fehler gehabt.

Schreibe entweder in einem Stück oder mit mehrmaligem öffnen der Datei.

Viele Grüße.

von Thilo M. (Gast)


Lesenswert?

Hi Andre,

die Fehler tauchen bei mir nach mehreren Tagen bis Wochen auf. 
Provoziert habe ich die nicht. Beim einen Logger schreibt er auch 
mehrere Wochen ohne Fehler (tägliche Textfiles mit ca. 220kB), dann 
taucht ein Fehler auf.

von Dietmar W. (Gast)


Lesenswert?

Es ist ein Fehler in der ffcdLower() Funktion,
fat_loadRowOfSector(1); ist falsch!!

richtig ist:
  fat_loadRowOfSector(0x20);

dann funktioniert auch das cd..

uint8_t ffcdLower(void){

  if( fat.dir == 0 )return FALSE;      // im root dir, man kann nicht 
hoeher !

  fat_loadSector(fat_clustToSec(fat.dir));  // laed 1. sektor des 
aktuellen direktory.
  fat_loadRowOfSector(0x20);          // ".." eintrag (parent dir) ist 0 
wenn parent == root
  fat.dir=file.firstCluster;        // dir setzen

  return TRUE;
}
Gruß Dietmar

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
Hallo Thilo,

Du hast recht, der Fehler tritt bei langsamen Takt nicht mehr auf. Ich 
habe jetzt probeweise mal Abspeichern von je 512 Byte programmiert, 
Abtastzeit 10s.
Nach spätestens 3 Minuten tritt der Fehler auf, wenn Takt > 500KHz.
Ursache ist wohl die interne Speicherplatzverwaltung der SD-Karten, die 
sehr viele Speicherzyklen vertragen --> bis zu 10Mio. Praktisch ist der 
Flash auch nur einige 1000mal beschreibbar, die interne Organisation der 
Karte sorgt aber dafür, dass der Speicher möglichst gleichmäßig 
abgenutzt wird.
Diese Umspeicher-Arbeitsschritte macht die Karte allein, ohne äußeres 
Zutun.
Wenn man nun wüsste, wann das passiert, hätten wir das Problem gelöst.
Bin weiter am Testen...

von Thilo M. (Gast)


Angehängte Dateien:

Lesenswert?

Hm...

der Fehler ist immer noch da, trotz 500kHz Takt.
In angehängter Datei wird einfach nicht weitergeschrieben.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Hm...
>
> der Fehler ist immer noch da, trotz 500kHz Takt.
> In angehängter Datei wird einfach nicht weitergeschrieben.

Hallo Thilo,

mir ist nach längerem Test jetzt absolut klar, worin das Problem 
besteht.
Immer, wenn genau bis zum Ende eines Sektors oder Clusters geschrieben 
wird und die Datei dann geschlossen wird, gehen Daten verloren und/oder 
die FAT wird fehlerhaft.
Das kann man simulieren, indem man nicht seine Orginaldaten schreibt, 
sondern  immer 16 oder 32 oder 64.... Byte. Dann tritt der Fehler exakt 
an der gleichen Stelle auf. Kartenart und Hersteller sind egal. Was 
weiter oben angenommen wurde, basierte auf Zufall.
Ich habe jetzt erst mal um den Fehler herumprogrammiert:

ffwrites(Messwerteintrag);
if((file_.cntOfBytes &1) ==0) ffwrite(0x20);

- soll heißen, dass vor dem Schreiben von 0dh 0ah geprüft wird, ob die 
Dateilänge ungerade oder gerade ist. Im letzteren Fall hänge ich noch 
ein Leerzeichen dran.

Seit einigen Tagen läuft es nun ohne Fehler, egal wie schnell, egal 
welcher Kartentyp.

Die Funktion

void fflushFileData(void)

enthält noch einen Fehler, wahrscheinlich ist es irgendwie an dieser 
Stelle falsch:

// wenn fat.cntOfBytes == 0 ist der sektor gerade vorher schon 
geschrieben worden oder es ist noch nichts hinein geschrieben worden. 
dann wert so setzten, dass die schleife uebersprungen wird

count = (file_.cntOfBytes==0) ? 512:file_.cntOfBytes;

Eine Abhilfe habe ich noch nicht gefunden, dazu muss man sich tiefer 
einarbeiten. Vielleicht kann uns Daniel helfen?

von Thilo M. (Gast)


Lesenswert?

Wolfgang Sch. schrieb:
> count = (file_.cntOfBytes==0) ? 512:file_.cntOfBytes;

Man hätte auch schreiben können:

count = (file_.cntOfBytes==0) ? 512:0;

dürfte aber kein Unterschied bei der Funktion sein.
Welcher Fehler taucht denn da auf?

Ist bei dir der Unterstrich nach file (als file_.) überall dran?
Den gibt's bei mir nicht. Evtl. ist das 'ne andere Version?

Ich werde es auch mal testen, gerade Zählerstände zu vermeiden.

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen,
hab leider sehr viel um die Ohren momentan.
Lese aber schon noch mit hier.

Muss mal sehen das ich meine Entwicklungsumgebung für den FAT kram 
wieder zusammenbaue. Sollte sich das mit den geraden und speziell mit 
den 2er Potenzen bestätigen gehe ich dem auf den Grund.

Viele Grüße

Daniel

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Wolfgang Sch. schrieb:
>> count = (file_.cntOfBytes==0) ? 512:file_.cntOfBytes;
>
> Man hätte auch schreiben können:
>
> count = (file_.cntOfBytes==0) ? 512:0;
>
> dürfte aber kein Unterschied bei der Funktion sein.
> Welcher Fehler taucht denn da auf?
>
> Ist bei dir der Unterstrich nach file (als file_.) überall dran?
> Den gibt's bei mir nicht. Evtl. ist das 'ne andere Version?
>
> Ich werde es auch mal testen, gerade Zählerstände zu vermeiden.

Hallo Thilo,
das mit den ungeraden Sektorenlängen habe ich vereinfachend gemacht, um 
gerade komplett gefüllte Sektoren (512 Byte) zu vermeiden. Alle anderen, 
mit einer geraden Anzahl Bytes gefüllter Sektoren werden auch auf 
"ungerade" gebracht, das wäre aber eigentlich nicht nötig.

file_ - Unterstrich:
Die Software wurde auf einem Luminary - Prozessor (ARM-CORTEX) zum 
Laufen gebracht. Compiler:  Keil µVision4.
Bei der Implementierung gab es ein Problem mit der Bezeichnung "file", 
daher der Unterstrich.

Zum Problem:
Ich vermute, dass das Problem darin besteht, dass
fat.bufferDirty = TRUE;
gesetzt wird, wenn
count < 512  (while - Schleife)
aber nicht, wenn
count == 512
Ich werde mal noch ein wenig probieren.

von Fabian B. (fabs)


Lesenswert?

Hat eigentlich mal jemand Lust mit den neuen Erkenntnissen ein Paket zu 
bauen?

Das letzte Paket zu nehmen und dann alle hier gefundenen Fixes 
einzubauen wäre etwas aufwendig.

Vielleicht wäre einer der "Vielverwender" hier dazu bereit?

Gruß
Fabian

von Thilo M. (Gast)


Lesenswert?

Hi Fabian,

ich denke, wenn der Fehler mit den "eben vollen" Sektoren gefunden ist, 
wäre es an der Zeit, da hast du Recht.

Mittlerweile ist es, bis auf diesen Fehler, ziemlich wasserdicht.

Lassen wir Daniel noch Zeit, er kennt seinen Code am besten und dürfte 
wissen, wo er suchen muss. ;-)

von Fabian B. (fabs)


Lesenswert?

Stimmt.
Bisher habe ich die Lib nur für's lesen genutzt, daher habe ich oben 
nach meinem init-Patch nix mehr geupdated. Gerade auch weil's ja 
scheinbar immer wieder Schreibprobleme gab.
Wenn das jetzt wirklich eine Lösung ist, wäre alles zusammen in einem 
"0.7"-release ne tolle Sache.

Gruß
Fabian

von Wolfgang S. (wolfgangs)


Lesenswert?

Daniel R. schrieb:
> Hallo zusammen,
> hab leider sehr viel um die Ohren momentan.
> Lese aber schon noch mit hier.
>
> Muss mal sehen das ich meine Entwicklungsumgebung für den FAT kram
> wieder zusammenbaue. Sollte sich das mit den geraden und speziell mit
> den 2er Potenzen bestätigen gehe ich dem auf den Grund.
>
> Viele Grüße
>
> Daniel

Hallo Daniel,

bin hocherfreut, dass Du noch mal einen Blick darauf wirfst.
Ich konnte aus Platzgründen nicht 512 Byte auf einmal schreiben, deshalb 
16 oder 32 ... Byte. Kann man auch anders machen, z.B. 2x250 Byte, dann 
12 Byte, ev. auch 1x512 Byte -- habe ich aber nicht probiert.
Fehler auslösen:
Wichtig ist nur, dass der Sektor zum Schluss genau bis Ende gefüllt 
wurde.
Bitte für jeden Schreibvorgang

1. Datei öffnen (bzw. neu anlegen)
2. Bytes schreiben
3. Datei schließen

so kann ich bei meinem Gerät den Fehler auslösen.

Viele Grüße,
Wolfgang

von Thilo M. (Gast)


Angehängte Dateien:

Lesenswert?

Scheinbar liegt das Problem nicht nur an den "eben vollen" Sektoren.
Vor zwei Stunden hat er trotz ugerade gehaltener Filegröße einfach 
wieder aufgehört weiterzuschreiben.

Falls es zur Analyse hilft hänge ich da geloggte File mal dran.

von Thilo M. (Gast)


Lesenswert?

Edit:

nachdem ich versucht habe, ein Byte anzuhängen, hat Windows das File als 
schreibgeschützt erkannt und es ließ sich nicht mehr abspeichern.

Scheinbar liegt das Problem in der FAT, nicht an der Datei an sich. 
Irgendwo macht die Software falsche Einträge, warum auch immer.

Ich hatte auch schon den Fall, das der selbe Dateiname 25x vorkam, sich 
aber nur auf eine Datei bezog.

von Thilo M. (Gast)


Lesenswert?

Edit 2:

Karte ist defekt. Lässt sich weder formatieren, noch beschreiben. 
Windows erkennt den Datenträger als schreibgeschützt, egal wie der 
Schiebeschalter steht.

Wäre natürlich ein dummer Zufall, wenn das Stück ausgerechnet jetzt 
gestorben wäre.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Edit 2:
>
> Karte ist defekt. Lässt sich weder formatieren, noch beschreiben.
> Windows erkennt den Datenträger als schreibgeschützt, egal wie der
> Schiebeschalter steht.
>
> Wäre natürlich ein dummer Zufall, wenn das Stück ausgerechnet jetzt
> gestorben wäre.

Hallo Thilo,
bei mir laufen 2 Datenlogger seit 2 Wochen mit 10s Speicherabstand im 
"ungerade" - Modus fehlerfrei. Jedes Mal werden ca. 60 Byte abgelegt.

Gruß, Wolfgang

von Andre (Gast)


Lesenswert?

Hallo,

wie macht sich das bei Euch bemerkbar. Hängt er sich bei Euch auf? Wenn 
ja, in welcher Funktion genau? Ich habe zurzeit das Problem, dass er 
sich kurz nach Start des Logvorgangs aufhängt.

Gruß
André

von Andre (Gast)


Lesenswert?

EDIT1:

ich habe teilweise das Problem, dass er sich in der void 
fat_getFreeClustersInRow(uint32_t offsetCluster) aufhängt
1
 
2
void fat_getFreeClustersInRow(uint32_t offsetCluster){
3
4
  uint16_t cnt=1;    // variable fuer anzahl der zu suchenden cluster
5
6
7
 /// Genau hier hängt er sich auf
8
  while(fat_getNextCluster(offsetCluster)){ // suche des 1. freien clusters
9
    offsetCluster++;
10
  }
11
12
  chain.startSectors = fat_clustToSec(offsetCluster);  // setzen des startsektors der freien sektoren (umrechnen von cluster zu sektoren)
13
  chain.cntSecs = fat.secPerClust;          // da schonmal mindestens einer gefunden wurde kann hier auch schon cntSecs damit gesetzt werden
14
15
  do{                          // suche der naechsten freien
16
    if(0==fat_getNextCluster(offsetCluster+cnt) )  // zaehlen der zusammenhängenden sektoren
17
      chain.cntSecs += fat.secPerClust;
18
    else{
19
      return;                  // cluster daneben ist nicht frei
20
    }
21
    cnt++;
22
  }while( cnt<MMC_MAX_CLUSTERS_IN_ROW );      // wenn man hier raus rasselt, gibt es mehr freie zusammenhaengende als MAX_CLUSTERS_IN_ROW
23
24
25
}

von Thilo M. (Gast)


Lesenswert?

Wolfgang Sch. schrieb:
> bei mir laufen 2 Datenlogger seit 2 Wochen mit 10s Speicherabstand im
> "ungerade" - Modus fehlerfrei.

Bei mir jetzt auch.
Ich hatte den Takt des SPI versehenlich auf 8MBit gelassen, was für das 
DOGm Display kein Problem ist. Nur die alte SD-Karte konnte das nicht 
und hat sich verabschiedet. Die neue PLATINUM 1GB ist für max. 5MBit 
Schreiben spezifiziert und hat mit gelegentlichen Schreibfehlern 
reagiert (Resekt!).

Nun läuft das Ganze mit 1MBit seit Tagen fehlerfrei.
Ich denke, wenn der "Eben-Voll-Fehler" gefunden ist, dann ist das Ganze 
ziemlich wasserdicht.

von Torsten S. (tse)


Lesenswert?

> Nun läuft das Ganze mit 1MBit seit Tagen fehlerfrei.
> Ich denke, wenn der "Eben-Voll-Fehler" gefunden ist, dann ist das Ganze
> ziemlich wasserdicht.

Gratuliere.

Beitrag "MMC/SD-Karte mit FAT16 an AVR"
läuft bei mir  ~5 Jahren 24/7. Steuert nebenbei ne FB und hat nen 
Webserver. Fehlerfrei.

SCNR

von Thilo M. (Gast)


Lesenswert?

Torsten S. schrieb:
> läuft bei mir  ~5 Jahren 24/7. Steuert nebenbei ne FB und hat nen
> Webserver. Fehlerfrei.

Ja, bei mir läuft der Heizungsregler seit 2008 auch prima (8x PT1000, 
DCF77/RTC, 6 Ausgänge, Dreipunkt-Schrittregler, State-Machine, VBus 
(RESOL) einbindung, DOGm-Display), die SD-Karte kam dazu und dürfte 
jetzt serienreif sein.
Webserver habe ich auch zwei am Laufen, machen keine Probleme mit 
SD-Karte seit 1.1.12.

von A.H. (Gast)


Lesenswert?

Hallo Daniel,

mich würde mal interessieren ob es hier schon irgendwelche Fortschritte 
in Bezug auf den Bug mit der Clusterlänge gibt, ich würde die lib gern 
auf einem atmega128 einsetzen welche Version ist denn da angebracht ? Im 
SVN gibt es die 0.6.1 die hatte ich mir jetzt erstmal runtergeladen und 
damit mal ein paar erste Tests gemacht, das funktionierte soweit. Sollte 
ich besser die 0.6.4 verwenden ? Ich habe mal den Thead quergelesen - so 
ganz schlau werde ich daraus eigentlich nicht welche Version nun noch 
bekannte Bugs enthält.

@Wolfgang Sch.: Was genau hast Du denn geändert ?

von Wolfgang S. (wolfgangs)


Lesenswert?

A.H. schrieb:
> Hallo Daniel,
>
> mich würde mal interessieren ob es hier schon irgendwelche Fortschritte
> in Bezug auf den Bug mit der Clusterlänge gibt, ich würde die lib gern
> auf einem atmega128 einsetzen welche Version ist denn da angebracht ? Im
> SVN gibt es die 0.6.1 die hatte ich mir jetzt erstmal runtergeladen und
> damit mal ein paar erste Tests gemacht, das funktionierte soweit. Sollte
> ich besser die 0.6.4 verwenden ? Ich habe mal den Thead quergelesen - so
> ganz schlau werde ich daraus eigentlich nicht welche Version nun noch
> bekannte Bugs enthält.
>
> @Wolfgang Sch.: Was genau hast Du denn geändert ?

Hallo A.H.

das funktioniert, weil zusätzliche Leerzeichen in der Ausgabedatei nicht 
stören:

ffwrites(Messwerteintrag);  //aus Puffer "Messwerteintrag"
Dateilaenge=file_.cntOfBytes;
if((Dateilaenge &1) ==0) ffwrite(0x20);
ffwrite(0xd);
ffwrite(0xa);

von Edi R. (edi_r)


Lesenswert?

In einem Projekt, bei dem eine SD-Karte als Datenspeicher (FAT16 mit 
SFN) werwendet wird, ist mir unangenehm aufgefallen, dass beim Löschen 
einer Datei immer eine weitere Datei mitgelöscht wird. Mit einem 
Diskeditor habe ich festgestellt, dass zwar der erste Buchstabe beider 
Dateinamen durch 0xE5 ersetzt wird, die zur zusätzlich gelöschen Datei 
gehörenden Cluster werden in der FAT aber nicht als "frei" markiert und 
bleiben belegt.

Auf der Suche nach dem Grund habe ich folgende Codestelle in "file.c" ab 
Zeile 484 entdeckt:
1
  //////// ob ordner oder datei, der sfn und lfn muss geloescht werden!
2
  fat.bufferDirty = TRUE;            // damit beim laden der geaenderte puffer geschrieben wird
3
  do{
4
    fat.sector[row] = 0xE5;
5
    if( row == 0 ){              // eintraege gehen im vorherigen sektor weiter
6
      fat_loadSector(fat.lastSector);    // der davor ist noch bekannt. selbst wenn der aus dem cluster davor stammt.
7
      fat.bufferDirty = TRUE;
8
      row = 512;              // da nochmal row-=32 gemacht wird, kommt man so auf den anfang der letzten zeile
9
    }
10
    row -= 32;
11
  }while(  fat.sector[row+11]==0x0f && (fat.sector[row]&0x40) != 0x40);    // geht durch alle reihen bis neuer eintrag erkannt wird...
12
13
  fat.sector[row] = 0xE5;

Die do..while-Schleife ist doch eigentlich nur für LFN gedacht, oder? 
Wäre es nicht richtiger, die Schleife "andersherum" zu schreiben, also 
so:
1
  //////// ob ordner oder datei, der sfn und lfn muss geloescht werden!
2
  fat.bufferDirty = TRUE;            // damit beim laden der geaenderte puffer geschrieben wird
3
  while(  fat.sector[row+11]==0x0f && (fat.sector[row]&0x40) != 0x40)    // geht durch alle reihen bis neuer eintrag erkannt wird...
4
  {
5
    fat.sector[row] = 0xE5;
6
    if( row == 0 ){              // eintraege gehen im vorherigen sektor weiter
7
      fat_loadSector(fat.lastSector);    // der davor ist noch bekannt. selbst wenn der aus dem cluster davor stammt.
8
      fat.bufferDirty = TRUE;
9
      row = 512;              // da nochmal row-=32 gemacht wird, kommt man so auf den anfang der letzten zeile
10
    }
11
    row -= 32;
12
  }
13
14
  fat.sector[row] = 0xE5;

Dann kommt man überhaupt nicht in die Schleife, falls man keinen LFN 
hat. Ist meine Überlegung richtig?

von A.H. (Gast)


Lesenswert?

@Wolfgang Sch. Danke ich habe das bei mir als bugfix erstmal auch so 
eingebaut.

Mir ist beim testen ein Fehler aufgefallen der in die gleiche Richtung 
zu gehen scheint. Wenn ich am PC eine Datei auf die Speicherkarte 
kopiere z.B. NAME.TXT und der µC soll dann auf die gleiche Speicherkarte 
in die gleiche Datei schreiben gibt es die Daten anschließend zwei mal 
mit identischem Namen und Inhalt aber unterschiedlicher Größe auf der 
Karte.

Wenn ich mit der Datenträgerüberprüfung von XP auf die Karte gehe wird 
putzigerweise kein Fehler gefunden, Windows gibt beim löschen der beiden 
Dateien einen Fehler aus (Datei nicht gefunden) anschließend sind beide 
Dateien weg.

Eine mit Windows auf die Karte kopierte Datei kann ich mir ffrm nicht 
löschen.

Ist das zwischen 0.6.1 und 0.6.4 schon gefixt worden ?

von Andriy (Gast)


Lesenswert?

Hallo alle zusammen.
Ich hab grade die library runtergeladen und an meiner Hard getestet. 
Scheit so weit alles zu funktionieren (riesen dank an Daniel!!!!!) ABER: 
ich hab da noch n Nokia 6100 LCD, dass ueber das selbe SPI geht. Wenn 
man nun zuerst die SD-karte initialisiert usw. und ne Datei liest, bevor 
man etwas mit dem LCD macht, dann klappt's. Wenn man nun nach dem start 
der LCD was macht, dann kommt das Programm einfach nicht weiter. Also 
wie

if( MMC_FILE_OPENED != ffopen("TXT1.TXT",'r') )
  {  mach etwas
  }
  else mach etwas anderes

macht weder etwas noch was anderes. Scheint so, als ob der CS-pin nicht 
richtig tickt....

'Ne Idee was man da macht?

von Edi R. (edi_r)


Lesenswert?

Du hast aber schon zwei CS-Ausgangspins, einen für das LCD und einen 
für die SD-Karte, oder?

von Andriy (Gast)


Lesenswert?

ja sicher doch!
momentan hab ich noch ein Software-SPI hinzugefügt, so dass der LCD da 
drüber läuft. Wenn man solche unabhängige ports benutzt, ist alles OK. 
man kann dateien öffnen, lesen usw. ich hab ne ATMega 64, also viele 
pins, und es wäre nicht weiter kritisch, wenn ich den Software-spi 
lasse, wäre aber trotz dem nicht schlecht rauszufinden, was da los ist.

von Edi R. (edi_r)


Lesenswert?

Kannst Du feststellen, an welcher Stelle er in ffopen() hängen bleibt?

von Milan (Gast)


Lesenswert?

Hallo zusammen,
1
zeile 1
2
zeile 2
3
zeile 3
4
zeile 4
5
zeile 5

das ist eine TXT Datei. Ich will Zeile 3 löschen.

do das es so aussieht:
1
zeile 1
2
zeile 2
3
zeile 4
4
zeile 5

Wie kann ich das machen. Über einen Beispiel würde ich mich freuen.

Danke im Voraus
Milan

von Milan (Gast)


Lesenswert?

im moment benutze ich die funktion.
1
  unsigned long int seek;
2
  unsigned long int countzeichen=0;
3
  unsigned long int countzeilenzeichen=0;
4
  int32_t seekzeile=0;
5
  int zeichen;
6
  char zeile[200];
7
  char strs[200];
8
  bool geloest= false;
9
    if( MMC_FILE_OPENED == ffopen(datei,'r') )
10
    {
11
    seek = file.length;
12
    
13
    
14
    while(seek!=countzeichen)
15
    {
16
      zeichen=ffread();
17
      countzeichen++;
18
      if (zeichen == '\n')
19
      {
20
        seekzeile = file.cntOfBytes;
21
        zeile[countzeilenzeichen]='\0';
22
      
23
        
24
25
        _delay_ms(500);
26
        if (strncmp(zeile,zeilen_bezeichnung,strlen(zeilen_bezeichnung))==0)
27
          {
28
            geloest = true;
29
            
30
            
31
            strcpy(strs, " ");
32
            for (int a=0; a< strlen(zeilen_bezeichnung)-1; a++)
33
            {
34
              strcat(strs, " ");
35
            }
36
                  
37
            file.cntOfBytes= seekzeile-  (strlen(zeilen_bezeichnung)+2);
38
                      
39
            ffwrites(strs);
40
             
41
            ffclose();
42
        
43
            //_delay_ms(20000);
44
            break;
45
          }
46
        countzeilenzeichen=0;
47
        strcpy(zeile, "");
48
      }
49
      else
50
      {
51
        zeile[countzeilenzeichen]=zeichen;
52
      
53
        countzeilenzeichen++;
54
      }
55
    } 
56
  
57
    ffclose();
leider bleiben die daten auf der karte drauf. warum auch immer. In der 
Datei sind die weg, aber ich bekomme fehler wenn ich zeile 2 und 4 
auslese.

Gruss
Milan

von Matze (Gast)


Lesenswert?

Ich tippe mal darauf, wie man es beim PC programmieren auch macht:
Man legt sich eine temporäre datei an. Schreibt da alle Zeilen rein, die 
man behalten will und löscht das die orginal Datei und benennt die 
temporäre Datei um, so dass sie so heißt wie die orginal Datei.

Probier das doch mal.

Grüße

von Milan (Gast)


Lesenswert?

Hallo Matze,
danke für den Tipp, daran habe ich auch gedacht.
Problem ist, dass die Datei bis 50MB oder mehr gross sein kann. Also 1 
zu 1 kopieren geht nicht. Und so viel ich weiss kann ich nur eine Datei 
aufmachen und bearbeiten.

Gruss
Milan

von Matze (Gast)


Lesenswert?

Jo, das stimmt. Du müsstest auslesen, bis dein Speicher voll ist und 
dann dein Speicherinhalt in die temporäre Datei schreiben. Anderes ist 
leider nicht möglich - so weit ich weiß.
Einfach löschen einer Zeile ist aber auch aus Gründen der Datenstruktur 
nicht möglich. Beschäftige dich doch mal damit, wie eine Datei 
eigentlich auf dem Datenträger aussieht. Als Ansatz: leg dir eine Datei 
mit einem kurzen, definierten Inhalt an und öffne die SD- Karte dann mit 
einem HEX- Editor. Suche dann mit dem HEX- Editor nach deiner 
Zeichenfolge als HEX- Werte. Das kannst du auch an deinem PC machen, 
musst nicht extra den µC verwenden.
Wenn du verstanden hast, wie Dateien auf der SD- Karte aussehen, weißt 
du auch, daß ein anderer Weg als mit der temp. Datei echt umständlich zu 
realisieren ist (bis hin zur völligen Unumsetzbarkeit)

von Milan M. (milance)


Lesenswert?

Ist es möglich das ich die zeile ändere:
ALT: zeile 3 --------> NEU: zeile x

damit ich das x ausfiltern kann und nicht anzeigen.

von Matze (Gast)


Lesenswert?

Klar, überschreiben geht. Du musst bloß die Textstelle haben (ffseek ist 
dein Freund)
Aber zu dieser Bibliothek: geplant war das mal als Datenlogger... ;)

Was hast du eigentlich genau vor und wielange brauchst du um 50MB Daten 
zu schreiben?

von Milan M. (milance)


Lesenswert?

Hallo zusammen,
ich habe es geschaft eine zeile zu löschen.
1
file.cntOfBytes= seekzeile-strlen(zeilen_bezeichnung)-2;
2
            for (int a=0; a < strlen(zeilen_bezeichnung)+2; a++)
3
            {
4
              ffwrite(0x0D);
5
            }

und es wird nichts beschädigt.

Gruss
Milan

von Matze (Gast)


Lesenswert?

Fügst du nich nur für jedes Zeichen deiner Zeile einfach ein Return ein 
(0x0D)?

von Milan M. (milance)


Lesenswert?

ja, aber wenn ich die datei aufmache ist die zeile weg.

von A. R. (redegle)


Lesenswert?

Hallo,

wäre sehr nett, wenn mir jemand helfen könnte. Versuche nun seit ein 
paar Wochen schon die Bibliothek zum laufen zu bekommen.

Verwendet einen Atmega644P und dieses Modul von Conrad als Pegelwandler 
http://www.conrad.de/ce/de/product/197220/ um Hardwarefehler zu 
vermeiden.

Für den 10ms Timer (TimingDelay) verwende ich Timer 1.
Dieser zählt bis 16000 bei einem 16MHz Takt und löst somit jede ms ein 
Interrupt aus. Wurde im Interrupt bis 10 gezählt, so werden 10 ms 
abgezogen. Das ganze funktioniert und wurde bereits getestet.
1
volatile uint8_t TimingDelay;  // fuer mmc.c
2
volatile uint8_t Millisekunden_SD = 0;
3
4
ISR(TIMER1_COMPA_vect)//Taktgeber 1ms
5
{
6
  Millisekunden_SD++;
7
  if(Millisekunden_SD==10)
8
  {
9
    TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;  
10
    //TimingDelay wird so lange heruntergezählt, bis TimingDelay == 0 ist.
11
    Millisekunden_SD=0;
12
  }
13
}


In mmc_config.h wurden folgende Änderungen vorgenommen:
1
#define MMC_MAX_SPEED     FALSE

In mmc.h wurde folgende Änderung gemacht:
1
#define __AVR_ATmega644__

Verwendet wird das Hardware SPI


In der Hauptdatei wird folgender code ausgeführt:
1
if(TRUE==mmc_init())
2
{
3
  Display_write_OK();
4
}
5
else
6
{
7
  Display_write_Fehler();
8
}
9
  
10
  
11
if(TRUE ==fat_loadFatData())
12
{
13
  Display_write_OK();
14
}
15
else
16
{
17
  Display_write_Fehler();
18
}

Die Initiallisierung funktioniert. Die Funktion fat_loadFatData() 
liefert hingegeben ein FALSE zurück. Konkret liefert die Funktion 
mmc_read_sector() in der Funktion fat_loadFatData() ein FALSE zurück.
1
TimingDelay = 20;
2
do {  // Wait for data packet in timeout of 200ms 
3
  token = spi_read_byte();
4
} while ( (token == 0xFF) && TimingDelay );
5
  
6
if(token != 0xFE){
7
  return FALSE;  // If not valid data token, retutn with error 
8
}
9
//token ist ungleich 0xFE

Jemand eine Idee, woran das liegen könnte?
Die Karte ist FAT32 Formatiert mit einer Blockgröße von 512 Byte. Es 
handelt sich um eine 1 GB PLATINUM SD Karte.

von jens (Gast)


Lesenswert?

Hallo,

ich versuche auch die Sachen zum Laufen zu bekommen.
Ich verwende folgenden Code:

while (mmc_init() !=0)        // rückgabewert 0 dann ist karte 
initialisiert
  {
    LCD_displayStringLn(Line1,20, "Initializing card faild!");
    while(1)
    {
      nop();
    }
  }

  if(0==fat_loadFatData())        // rückgabewert 0 dann sind die fat 
daten bekannt
  {
    LCD_displayStringLn(Line1,20, "Karte ready...");

    // rückgabewert 2 bedeutet, datei ist nicht vorhanden und wurde 
grade angelegt.
    //bereit zum schreiben !
    if(2==ffopen(file_name))
    {
      LCD_displayStringLn(Line2,20, "Datei wurde angelegt!");
      ffwrites((unsigned char*)"Hallo Welt");
      ffclose();
    }

    // hier ist rückgabewerte eigentlich 1, datei ist vorhanden und 
wurde geöffnet.
    //bereit zum lesen !
    else
    {
      unsigned long int seek = 0;
      unsigned int temp = 0;

      LCD_displayStringLn(Line2,20, "Datei bereits vorhanden!");
      seek=file.length;

      ffseek(2);
      temp = ffread();
      LCD_drawUint16(Line7,100,temp);

      LCD_drawUint16(Line8,100,seek);
      ffclose();
    }
  }
Datei anlegen funktioniert suoer. Ich will aus der Datei genau das "a" 
auslesen. Aber ich komme nicht so richtig klar mit dem ffseek(). Wie 
kann ich in der Datei an diese Stelle springen und genau den Buchstaben 
auslesen?

Grüße, Jens

von Milan M. (milance)


Lesenswert?

Hallo zusammen,
ich benute den Code um eine zeile auszulessen:
1
char* lese_zeile(unsigned long int zeilennr)
2
{
3
  unsigned long int seek;
4
  unsigned long int countzeichen=0;
5
  unsigned long int countzeilen=0;
6
  uint16_t countzeilenzeichen=0;
7
  int zeichen;
8
  char zeile[200];
9
    if( MMC_FILE_OPENED == ffopen(datei,'r') )
10
    {
11
    seek = file.length;
12
    countzeilen++;
13
    
14
    while(seek>=countzeichen)
15
    {
16
      zeichen=ffread();
17
      countzeichen++;
18
      if (zeichen == '\n')
19
      {
20
        countzeilen++;
21
      }
22
      while (zeilennr==countzeilen)
23
      { 
24
        zeichen=ffread();
25
        if (zeichen == '\n')
26
        {
27
          zeile[countzeilenzeichen]='\0';
28
          break;
29
        }
30
        zeile[countzeilenzeichen]=zeichen;
31
      
32
        countzeichen++;
33
        countzeilenzeichen++;
34
      }
35
      if(zeilennr==countzeilen)
36
      {
37
        break;
38
      }
39
    } 
40
  
41
    ffclose();
42
    }    
43
    return zeile;
44
}
leider schreibt er mir immer ein paar leer Zeichen am schluss!
Weiss jemand warum???
Bitte um hilfe.
Gruss
Milan

von Milan M. (milance)


Lesenswert?

Hallo zusammen,
ich habe die lösung gefunden.
1
 if( MMC_FILE_OPENED == ffopen(datei,'r') )
2
 {
3
  seek = file.length-1;
4
  file.cntOfBytes=0;

durch das file.cntOfBytes=0 fängt es immer vom 0 an. zu lesen.
Es passiert weil ich funktion in funktion gemacht habe. Und dann fängt 
es da wo es bei der erster funktion aufgehört hat!

Gruss
Milan

von Portierer (Gast)


Lesenswert?

Michael P. schrieb:
> Moin,
>
> die meiste Arbeit haben die Routinen für das Lesen und Schreiben der
> SD-Karte gemacht (wegen neu schreiben und so). Bei den FAT- und
> Dateifunktionen habe ich erstmal nur die Void-Pointer (die ICC430
> Version die ich nutze kann damit nicht um), die ganzen Zählvariablen
> angepasst und natürlich die Funktionsaufrufe der Low-Level-Routinen
> geändert. Eben um zu sehen ob es funktioniert. Und es funtkioniert.
>
> Weitere Anpassungen sind sicherlich noch möglich, mach ich irgendwann
> auch noch.
>
> Michael

Ich hänge gerade auch noch daran, die Lib für MSP430 zu portieren. Magst 
du vlt. schreiben, was genau du jetzt angepasst hast? Bisher habe ich 
sämtliche SPI-Routinen angepasst sowie die zugehörigen Makros wie 
MMC_CS_LOW, MMC_READ etc.

Wo ich Probleme mit dem Compiler bekomme, sind die Arithmetiken auf 
void-Pointer wie bei "void *vsector;". Das kommt zum Glück nur zweimal 
vor. Generell ist das dekr/inkr von void Pointern auch nicht 
standardkonform (weder C, noch C++). Siehe dazu mein Thema hier:

http://www.c-plusplus.de/forum/p2249560#2249560

Frage an Michael P.: Wie hast du das angepasst? Frage allgemein: Sollte 
man das in der Bibliothek nicht generell korrigieren?

Falls es die Hilfsbereitschaft vergrößert:
------------------------------------------
Ich bin bereit, den Quelltext meiner Portierung wenn sie läuft zur 
Verfügung zu stellen. Generell wäre ich dann dafür, dass man z.B. 
sämtliche SPI-Funktionen aus der mmc.h auslagert und eine spi.h o.ä. als 
wirkliche Schnittstelle einführt. Entsprechend der Plattform müssten 
dann nur  Makros in der spi.h angepasst und die Methoden in einer 
spi.c(pp) ausgeprägt werden.

von dummkopp (Gast)


Lesenswert?

hallo,

die lib vom daniel funktioniert sehr gut.
schade das ich wohl zu dumm bin einen string ins unit8_t file_name[]; zu 
bekommen um den Datei Namen in der laufzeit zu generieren.
mit char file_name[10] ginge es, aber die ffopen funktion erwartet ein 
uint8_t. wie macht man das wenn man nicht so en dummkopp is?

1
  uint8_t file_name[10];
2
  char zahl_str [3];
3
4
  // Dateinamen z.B. "Jan12.csv" aus aktuellem Datum zusammensetzen
5
    switch(mon)
6
        {
7
        case  1: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'a'; file_name[3] = 'n'; break;
8
        case  2: file_name[0] = '\0'; file_name[1] = 'F'; file_name[2] = 'e'; file_name[3] = 'b'; break;
9
        case  3: file_name[0] = '\0'; file_name[1] = 'M'; file_name[2] = 'a'; file_name[3] = 'r'; break;
10
        case  4: file_name[0] = '\0'; file_name[1] = 'A'; file_name[2] = 'p'; file_name[3] = 'r'; break;
11
        case  5: file_name[0] = '\0'; file_name[1] = 'M'; file_name[2] = 'a'; file_name[3] = 'i'; break;
12
        case  6: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'u'; file_name[3] = 'n'; break;
13
        case  7: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'u'; file_name[3] = 'l'; break;
14
        case  8: file_name[0] = '\0'; file_name[1] = 'A'; file_name[2] = 'u'; file_name[3] = 'g'; break;
15
        case  9: file_name[0] = '\0'; file_name[1] = 'S'; file_name[2] = 'e'; file_name[3] = 'p'; break;
16
        case 10: file_name[0] = '\0'; file_name[1] = 'O'; file_name[2] = 'k'; file_name[3] = 't'; break;
17
        case 11: file_name[0] = '\0'; file_name[1] = 'N'; file_name[2] = 'o'; file_name[3] = 'v'; break;
18
        case 12: file_name[0] = '\0'; file_name[1] = 'D'; file_name[2] = 'e'; file_name[3] = 'z'; break;
19
          };
20
21
    zahl_str[0] = '\0';
22
    itoa(year % 100, zahl_str, 10);
23
    strcat(file_name, zahl_str); //<--- warning: pointer targets in passing argument 1 of 'strcat' differ in signedness
24
25
    strcat(file_name, ".csv"); // <--- warning: pointer targets in passing argument 1 of 'strcat' differ in signedness

von nichmehrganzsodumm (Gast)


Lesenswert?

ich bin selbst draufgekommen: ich schreib die zeichen einzeln rein.
1
    // Dateinamen aus aktuellem Datum zusammensetzen
2
    switch(mon)
3
        {
4
        case  1: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'a'; file_name[3] = 'n'; break;
5
        case  2: file_name[0] = '\0'; file_name[1] = 'F'; file_name[2] = 'e'; file_name[3] = 'b'; break;
6
        case  3: file_name[0] = '\0'; file_name[1] = 'M'; file_name[2] = 'a'; file_name[3] = 'r'; break;
7
        case  4: file_name[0] = '\0'; file_name[1] = 'A'; file_name[2] = 'p'; file_name[3] = 'r'; break;
8
        case  5: file_name[0] = '\0'; file_name[1] = 'M'; file_name[2] = 'a'; file_name[3] = 'i'; break;
9
        case  6: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'u'; file_name[3] = 'n'; break;
10
        case  7: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'u'; file_name[3] = 'l'; break;
11
        case  8: file_name[0] = '\0'; file_name[1] = 'A'; file_name[2] = 'u'; file_name[3] = 'g'; break;
12
        case  9: file_name[0] = '\0'; file_name[1] = 'S'; file_name[2] = 'e'; file_name[3] = 'p'; break;
13
        case 10: file_name[0] = '\0'; file_name[1] = 'O'; file_name[2] = 'k'; file_name[3] = 't'; break;
14
        case 11: file_name[0] = '\0'; file_name[1] = 'N'; file_name[2] = 'o'; file_name[3] = 'v'; break;
15
        case 12: file_name[0] = '\0'; file_name[1] = 'D'; file_name[2] = 'e'; file_name[3] = 'z'; break;
16
          };
17
18
    zahl_str[0] = '\0';
19
    itoa(year % 100, zahl_str, 10);
20
  file_name[4] = zahl_str[1];
21
  file_name[5] = zahl_str[2];
22
  file_name[6] = 'c';
23
  file_name[7] = 's';
24
  file_name[8] = 'v';

von doofi (Gast)


Lesenswert?

beides war falsch.

jetz geht es aber endlich mit itoa und strcat;

das habe ich geändert:
ffopen((uint8_t*)file_name,'r')
ffwrites((uint8_t*)log_daten)

so setze ich den string file_name zusammen;
1
char file_name[10];
2
char zahl_str [3];
3
4
file_name[0] = '\0';
5
switch(mon)
6
      {
7
        case  1: strcat(file_name, "Jan"); break;
8
  case  2: strcat(file_name, "Feb"); break;
9
  case  3: strcat(file_name, "Mar"); break;
10
  case  4: strcat(file_name, "Apr"); break;
11
  case  5: strcat(file_name, "Mai"); break;
12
  case  6: strcat(file_name, "Jun"); break;
13
  case  7: strcat(file_name, "Jul"); break;
14
  case  8: strcat(file_name, "Aug"); break;
15
  case  9: strcat(file_name, "Sep"); break;
16
  case 10: strcat(file_name, "Okt"); break;
17
  case 11: strcat(file_name, "Nov"); break;
18
  case 12: strcat(file_name, "Dez"); break;
19
      };
20
21
zahl_str[0] = '\0';
22
itoa(year % 100, zahl_str, 10);
23
strcat(file_name, zahl_str);
24
strcat(file_name, ".csv");
25
26
if  ( MMC_FILE_OPENED == ffopen((uint8_t*)file_name,'r') )
27
    { 
28
      ffseek(file.length); // ans Datei Ende springen
29
      sht_write_log();
30
      ffclose();
31
    }
32
if  (MMC_FILE_CREATED == ffopen((uint8_t*)file_name,'c') )
33
    {
34
      sht_write_log(); // SHT Logdaten in neue Datei schreiben
35
      ffclose();
36
    }

nunja, die 2 posts vorher warn echt unnötig, sry -.-

von Mr. Dose (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich möchte gerne diese Bibliothek, welche bisher einen sehr guten 
Eindruck macht, für eine Art Datenlogger benutzen. D.h. es müssen 
lediglich Daten an das Ende einer Datei geschrieben werden können. 
Jedoch habe ich dafür nur einen Atmega16 zur Verfügung und das Hex-File 
ist bei mir jedoch 17,8 KB groß. Es passt als nicht auf den Atmega16. 
Dabei habe ich schon die Compiler-Optimierung auf möglichst geringe 
Speichergröße gestellt und in den Config-Files nur das nötigste an 
Funktionalität aktiviert. Den bisherigen Code zum Testen findet ihr im 
Anhang.

Hat jemand von euch vielleicht noch eine Idee wie sich der Code 
verkleinern lässt, denn eigentlich fehlt ja auch noch der Teil der die 
Daten "erzeugt", welche dann auf der SD-Karte gespeichert werden sollen.
Oder ist es überhaupt möglich diese Bibliothek auf einem Atmega16 zu 
verwenden?

Vielen Dank für eure Hilfe.

von huhu (Gast)


Lesenswert?

hm.. ohne mir deinen Quelltext angeschaut zu haben: warum nimmst du nich 
einen größeren ATmega? Der ATmega32 und 64 sind doch pin-gleich, wenn 
ich mich richtig entsinne...
Dann haste auch auf jeden Fall genug Platz für deine Anwendung.

Grüße,
Matze

von Mr. Dose (Gast)


Lesenswert?

hmmmm, passen die den auch in den Sockel eines Atmega16?

von Fabian B. (fabs)


Lesenswert?

Radio Eriwan: im Prinzip ja.

Der mega32 ist im DIP Gehäuse aber Pin-to-Pin kompatibel.

Gruß
Fabian

von Peter S (Gast)


Lesenswert?

Hi,

ich habe ein sehr seltsames Phänomen mit der lib.
Bei meinem Projekt funktioniert das Schreiben auf die Karte oft so wie 
es soll. Also vom Prinzip her geht es (Das Grundgerüst von dem Projekt 
besteht aus einem Vorgänger Projekt, dass seit einem Jahr nun schon 
einwandfrei funktioniert). Wenn ich aber meinen Code verändere schreibt 
die lib offensichtlich nicht mehr auf die Karte. Es entsteht einfach 
eine leere Datei. Wenn man sich die Karte mit einem Hex Editor anschaut, 
sieht man, dass der letzte geschrieben String sich auf der Karte 
befindet, sonst nichts. Er überschreibt also die Daten auf der Karte 
ständig.
Die lib setzt also nach dem schreiben des Strings aus irgend einem Grund 
die Position innerhalb der Datei wieder auf den Ursprungswert. So werden 
vorhandene Dateien nicht vergrößert und neue sind leer.

Wenn ich dann aber wieder die Änderung im Code beseitige, geht es 
wieder.
Das komische ist aber, dass diese Änderungen nicht mit der lib zu tun 
haben, sprich z.b. wenn ich eine bestimmte if-Abfrage entferne oder 
sowas in der Art. Auf alle Fälle sind die Änderungen eindeutig und haben 
definitif nichts mit der lib zu tun. Ich hatte ja auch schon meine 
memcpy in Verdacht, aber selbst wenn ich die rausnehme geht es nicht 
immer. Also ich gehe davon aus, dass ich nicht ausversehen eine Variable 
der lib mit 0 überschreibe. Aber ich finde nun auch schon seit Tagen 
nicht die Lösung von meinem Problem.

Hatte jemand von Euch so was auch schon mal?
Woran könnte es liegen?

von Peter S. (Gast)


Lesenswert?

Ich weiß nicht, ob mein Fehler wirklich weg ist, aber ich habe auf alle 
Fälle doch noch einen Fehler gefunden: Der Timer war nicht auf 10 ms, 
sondern auf 20 ms eingestellt (die Rache des übernommenen Grundgerüsts, 
das lauft nämlich mit 16, statt jetzt mit 8 Mhz). Auf alle Fälle läuft 
die Software im Moment so wie sie soll.
Kann es wirklich am Timer gelegen haben?

von SurtuR (Gast)


Lesenswert?

Hallo wie kann ich mehrere Dateien auf der SD Karte anlegen und 
beschreiben?
In eine kann ich erfolgreich schreiben, diese wird anschließend 
geschlossen. Auch öffnen, anhängen und schließen lässt sich 
reproduzieren. Sowie ich jedoch in eine zweite Datei anlegen/beschreiben 
möchte, wird diese angelegt, aber nichts wird hineingeschrieben? Was 
kann ich da tun? Sie sind in keinem Fall beide gleichzeitig geöffnet.

Gruß,
Ralf

von Chris (Gast)


Lesenswert?

Hallo Leute,
habe volgenden Code:
1
while(PIND &= (1<<PD7)) // fragt CDI ab, liegt an Masse, wenn eine Karte eingesteckt ist
2
  {
3
    rs232_text("\nkeine Karte eingesteckt");
4
    WDH3224_TEXT(155,5,"SD-Karte ?",2,0);
5
  }
6
7
  WDH3224_TEXT(155,5,"          ",2,0);
8
  rs232_text("\nBoot");
9
  WDH3224_TEXT(180,12,"Boot...",2,0);
10
  
11
  // Versuch Karte zu Initialisieren, bis es klappt.
12
  // Unbedingt so, weil die Initialiesierung nicht immer
13
  // auf Anhieb klappt.
14
  while (FALSE == mmc_init())
15
  {
16
    nop();
17
  }
18
  
19
  rs232_text("...");
20
  
21
  
22
  // Fat initialisieren. Nur wenn das klappt sind weitere
23
  // Aktionen sinnvoll, sonst endet das Programm.
24
  if (!fat_loadFatData())
25
  return -1;
26
  
27
  // Wenn auf dem terminal "Boot... OK" zu lesen ist, ist Init OK.
28
  // Jetzt kann man Schreiben/Anhängen/Lesen.
29
  rs232_text("Ok\n");
30
  WDH3224_TEXT(180,27,"OK",2,0);
31
  
32
33
  
34
35
  // Datei existiert, also lesen.
36
  // Gerade angelegt und beschrieben, oder war schon vorhanden
37
  // und es wurde was angehaengt?
38
  if (MMC_FILE_EXISTS == ffopen("TEST    TXT"))
39
  {
40
    
41
42
    rs232_text("\nDatei wird geoeffnet:\n");
43
    WDH3224_TEXT(150,5,"                  ",1,0);
44
    WDH3224_TEXT(150,5,"Datei wird geöffnet",1,0);
45
    
46
    // Setzen einer Variable und dann runterzählen geht
47
    // am schnellsten
48
    unsigned long int seek = file.length;
49
    char *tmp;
50
    
51
    // Lesen eines chars und Ausgabe des chars.
52
    // Solange bis komplette Datei gelesen wurde.
53
    do 
54
    {
55
      sd_card_string[i] = ffread();
56
      i++;
57
    } 
58
    while (--seek);
59
60
    sd_card_string[i+1] = '\0';
61
    rs232_text(sd_card_string);                  //bis hier waren es  4h 50min Arbeit
62
    rs232_text("\n");
63
64
    
65
    rs232_text("\n\nEOF\n");
66
    ffclose();
67
    
68
    //Nun wird der Komplette String anhand von ; in Einzelne zerlegt
69
    sd_card[0] =  strtok_r(sd_card_string,";",&tmp);      //und hier stecken 5h 50min Arbeit drin
70
    for(i=1;i<=300;i++)
71
    {
72
      sd_card[i] =  strtok_r(NULL,";",&tmp);        //bis hier...also 10h 40min
73
    }                      
74
    
75
76
  }
77
78
  else if(MMC_FILE_NOT_EXISTS == ffopen("TEST    TXT"))
79
  { 
80
    rs232_text("\nDatei konnte nicht gefunden werden");
81
    WDH3224_TEXT(150,1,"Datei konnte nicht gefunden werden",1,0);
82
  }

nun, das ganze hatte ich auf meinem Testboard (AT90USB1287)ausprobiert 
und es lief. Jetzt habe ich es auf das Aktuelle Projekt übertragen 
ATMega1284, das SD-Card Modul ist das gleiche geblieben. Nun lauft das 
programm allerdings nur noch bis zu dem Punkt, wo ich "Boot...OK" lesen 
kann. Danach passiert leider nichts mehr. Das einzige was noch anders 
ist, ist die SD-Card und als ich das mal durchgemessen habe, das CS low 
ist.

LG Chris

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

cs = low ist ja richtig... Denkfehler.
Eine Kommunikation findet scheinbar statt, habe die Signale mal 
nachgemessen, siehe Anhang.

LG Chris

von Chris (Gast)


Lesenswert?

Hallo Leute,

es läuft jetzt fast alles.
Habe jetzt das Problem, das ich die zu lesende datei nicht komplett auf 
ein Array im Controller packen kann, da dazu der Speicher fehlt.
Kann ich irgendwie mit ffseek() an eine Bestimmte Stelle in der Datei 
Springen in abhängigkeit der gefundenen Absätze in der Datei am ende ist 
ja immer ein 0x0D für </r>. Habe daas mit ffseek bisher so verstanden, 
das man die Speicherstelle expliziet vorgeben muss...

Bsp. was ich meine.
Ich will aus Zeile 5 ETWAS LESEN, ALSO MÜSSTE 4X 0X0D ERKANNT WERDEN UND 
AB DER NÄCHSTEN STELLE MÜSSTEN ALLE CHARS GELESEN WERDEN BIS WIEDER 0x0D 
kommt!? Geht das ?

LG Chris

von SurtuR (Gast)


Lesenswert?

hi,

hat keiner ne idee oder antwort für mich auf meine frage weiter oben:
( Beitrag "Re: MMC SD library FAT16 FAT32 read write" ) ?

gruß,
ralf

von Gerhard G. (g_g)


Angehängte Dateien:

Lesenswert?

Hallo,

SurtuR schrieb:
> hat keiner ne idee oder antwort für mich auf meine frage weiter oben:

Ich habe es mit zwei verschiedenen Versionen getestet. Beide 
funktionieren nach dem beigelegten Code einwandfrei. Also- zwei 
geöffnete Dateien einmal beschreiben und beim Zweiten öffnen etwas 
anhängen.

Einmal auf Atxmega Ebene und einmal auf LPCXpresso-LPC1769 Ebene.

Code stammt aus LPC1769 Version. Ist aber kompatible mit dem Original 
(AVR).

Gruß G.G.

von SurtuR (Gast)


Lesenswert?

vielen dank g.g. für die antwort.

hmm vielleicht sollte ich es noch einmal mit der neusten version der lib 
probieren. ich benutzte bisher immer eine version vor der 0.6.4 (ich 
glaub es war die mmc-0.6.zip. vielleicht liegt da der fehler. vielleicht 
liegts auch am gering dimensionierten ram des atmega168. mal schauen.

gruß,
ralf

von SurtuR (Gast)


Lesenswert?

leider hat das ummodeln auf version 0.6.4 nichts gebracht.
ich stehe immer noch vor dem problem, das in die zweite datei nichts 
geschrieben wird nachdem sie angelegt wurde.

// entsprechender Bereich mit version < 0.6.4

// Auszug Begin
                else if (puffer[3]='U')
                {
                    if  ((puffer[4]=='S') && (puffer[5]=='1'))
                    {
                        sram_ledred=puffer[7];
                        sram_ledyello=puffer[9];
                        sram_ledgreen=puffer[11];
                        sram_var1=puffer[13];
                        eeprom_write_byte(&cntlogsd,sram_cntlogsd+1);
                        eeprom_write_byte(&ledred,sram_ledred);
                        eeprom_write_byte(&ledyello,sram_ledyello);
                        eeprom_write_byte(&ledgreen,sram_ledgreen);
                        eeprom_write_byte(&var1,sram_var1);

                        sum=0;
                        for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} 
pufflauf=0;
                        updateleds();
                        uputc(0x06);
                    }
                    else if (puffer[4]=='F')
                    {
                        // wenn ESC U F data  -> speichere data auf 
SD-Karte
                         if(MMC_FILE_EXISTS == ffopen(uptdatei))
            {
              ffseek(file.length);
              uint8_t z;
                            for (z=5;z<13;z++)
                            {
                                ffwrite(puffer[z]);
                            }
              ffclose();
              for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} pufflauf=0;
              sum=0;

            }
                     uputc(0x06);
                    }

                }
// Auszug Ende


// Entsprechender Bereich mit Version 0.6.4

// Auszug Begin

                else if (puffer[3]='U')
                {
                    if  ((puffer[4]=='S') && (puffer[5]=='1'))
                    {
                        sram_ledred=puffer[7];
                        sram_ledyello=puffer[9];
                        sram_ledgreen=puffer[11];
                        sram_var1=puffer[13];
                        eeprom_write_byte(&cntlogsd,sram_cntlogsd+1);
                        eeprom_write_byte(&ledred,sram_ledred);
                        eeprom_write_byte(&ledyello,sram_ledyello);
                        eeprom_write_byte(&ledgreen,sram_ledgreen);
                        eeprom_write_byte(&var1,sram_var1);

                        sum=0;
                        for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} 
pufflauf=0;
                        updateleds();
                        uputc(0x06);
                    }
                    else if (puffer[4]=='F')
                    {
                        // wenn ESC U F data  -> speichere data auf 
SD-Karte
                         if(MMC_FILE_ERROR == ffopen(uptdatei,'r'))
            {
              ffopen(uptdatei,'c');
                            ffclose();
            }

            if(MMC_FILE_OPENED== ffopen(uptdatei,'r'))
            {
                ffseek(file.length);
              uint8_t z;
                            for (z=5;z<13;z++)
                            {
                                ffwrite(puffer[z]);
                            }
              ffclose();
              for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} pufflauf=0;
              sum=0;
            }
                     uputc(0x06);
                    }

                }

// Auszug Ende

von Ralf R. (surtur)


Lesenswert?

Oh ich hätte obigen Code vielleicht doch lieber in einen Dateianhang 
packen sollen.

sorry.

gruß,
Ralf (SurtuR)

von blödkopp (Gast)


Lesenswert?

also irgendwie is da doch noch n bug drin vermute ich.
ich zeichne werte auf, schon ne ganze weile -alle paar minuten. für 
jeden monat wird ne extra datei angelgegt.

sobald die aktuelle zu beschreibende datei aber 76kB gross ist, lässt 
sich die karte nicht mehr beschreiben. sie lässt sich zwar 
initialisieren, aber sobald ein schreibvorgang gestartet wurde, wechselt 
die meldung von "init-ok" auf "init-felher".

es läuft lange gut, aber warum ist nach 76kB schluß?
kann das jemand bestätigen?

am code sollte es nicht liegen, so ein seltsamer fehler...
1
/**************************************************************************************
2
 Funktion zum erzeugen eines DateiNamens für die MMC Karte
3
 Parameter: year  0000 bis 9999
4
            month 00 bis 31
5
 **************************************************************************************/
6
void mmc_file_name(uint16_t year, uint8_t month)
7
  {
8
    char zahl_str[3];
9
10
  file_name[0] = '\0';
11
  zahl_str[0] ='\0';
12
13
    // Dateinamen aus Datum (year, month) zusammensetzen
14
    switch(month)
15
        {
16
        case  1: strcat(file_name, "Jan"); break;
17
        case  2: strcat(file_name, "Feb"); break;
18
        case  3: strcat(file_name, "Mar"); break;
19
        case  4: strcat(file_name, "Apr"); break;
20
        case  5: strcat(file_name, "Mai"); break;
21
        case  6: strcat(file_name, "Jun"); break;
22
        case  7: strcat(file_name, "Jul"); break;
23
        case  8: strcat(file_name, "Aug"); break;
24
        case  9: strcat(file_name, "Sep"); break;
25
      case 10: strcat(file_name, "Okt"); break;
26
        case 11: strcat(file_name, "Nov"); break;
27
        case 12: strcat(file_name, "Dez"); break;
28
          };
29
30
    itoa(year % 100, zahl_str, 10);
31
  strcat(file_name, zahl_str);
32
  strcat(file_name, ".csv");
33
  }
34
35
36
/**************************************************************************************
37
 Funktion die alle 7,5 minuten ausgeführt wird um SHT messdaten zu speichern
38
 **************************************************************************************/
39
void sht_save_log()
40
  {
41
    mmc_file_name(year, mon); // Dateinamen aus aktuellem Datum erzeugen
42
  
43
44
45
  if (MMC_WRITE ==TRUE)    // create and append only if write is TRUE
46
     { // ****************************************************
47
     // if file exists, it will be opened and then append to it.
48
     if  ( MMC_FILE_OPENED == ffopen((uint8_t*)file_name,'r') )
49
         { 
50
         ffseek(file.length); // ans Datei Ende springen
51
         sht_write_log();
52
         ffclose();
53
             }
54
55
     // ***************************************************
56
     // if the file does not exist, it will be created and written to it.
57
     if  (MMC_FILE_CREATED == ffopen((uint8_t*)file_name,'c') )
58
         {
59
           sht_write_log(); // SHT Logdaten in neue Datei schreiben
60
         ffclose();
61
             }
62
     }
63
  }
64
65
/**************************************************************************************
66
 SHT Logdaten auf MMC Karte schreiben
67
68
 Dateiname; z.B: "Jan12.csv"
69
70
 Sht1 01. 20:15:30Uhr 31,13°C 56,08%
71
 Sht2 01. 20:15:30Uhr 30,14°C 55,45%
72
 Sht3 01. 20:15:30Uhr 00,00°C 00,00%
73
 Sht4 01. 20:15:30Uhr 00,00°C 00,00%
74
 **************************************************************************************/
75
void sht_write_log()
76
  {
77
    char zahl_str[4];
78
  uint8_t zahl_speicher; // Wert aus der laufenden Zeit entnehmen damit sich der Rechenwert nicht während der Verarbeitung ändert
79
  char datenreihe[40];
80
81
82
    for (uint8_t i =0; i<4; i++)
83
      {
84
      datenreihe[0] = '\0';
85
          zahl_str[0] = '\0';
86
87
          // Sensor (Sht1 bis Sht4)
88
      strcat(datenreihe, "Sht");
89
      itoa(i+1, zahl_str, 10);
90
      strcat(datenreihe, zahl_str);
91
          strcat(datenreihe, " ");
92
93
      // Tag (01 bis 31)
94
      zahl_speicher = day;
95
      itoa(zahl_speicher, zahl_str, 10);
96
      if  (zahl_speicher <10) {strcat(datenreihe, "0");}
97
          strcat(datenreihe, zahl_str);
98
          strcat(datenreihe, ". ");
99
100
        // Uhrzeit (00:00:00 bis 23:59:59)
101
      zahl_speicher = hh;
102
      itoa(zahl_speicher, zahl_str, 10);
103
      if  (zahl_speicher <10) {strcat(datenreihe, "0");}
104
          strcat(datenreihe, zahl_str);
105
          strcat(datenreihe, ":");
106
      
107
      zahl_speicher = mm;
108
      itoa(zahl_speicher, zahl_str, 10);
109
      if  (zahl_speicher <10) {strcat(datenreihe, "0");}
110
      strcat(datenreihe, zahl_str);
111
          strcat(datenreihe, ":");
112
113
          zahl_speicher = ss;
114
          itoa(zahl_speicher, zahl_str, 10);
115
      if  (zahl_speicher <10) {strcat(datenreihe, "0");}
116
      strcat(datenreihe, zahl_str);
117
      strcat(datenreihe, "Uhr ");
118
      
119
        // Temperaturwert
120
      itoa(sht_temp_mittelwert[i] / 100, zahl_str, 10);
121
        if  (sht_temp_mittelwert[i] / 100 <100) {strcat(datenreihe, "0");}
122
      if  (sht_temp_mittelwert[i] / 100 < 10) {strcat(datenreihe, "0");}
123
          strcat(datenreihe, zahl_str);
124
          strcat(datenreihe, ",");
125
126
      itoa(sht_temp_mittelwert[i] % 100, zahl_str, 10);
127
      if  (sht_temp_mittelwert[i] % 100 < 10) {strcat(datenreihe, "0");}
128
      strcat(datenreihe, zahl_str);
129
           strcat(datenreihe, "°C ");
130
131
      // Luft-Feuchtewert
132
      itoa(sht_feucht_mittelwert[i] / 100, zahl_str, 10);
133
      if  (sht_feucht_mittelwert[i] / 100 <10) {strcat(datenreihe, "0");}
134
      strcat(datenreihe, zahl_str);
135
          strcat(datenreihe, ",");
136
137
          itoa(sht_feucht_mittelwert[i] % 100, zahl_str, 10);
138
      if  (sht_feucht_mittelwert[i] % 100 <10) {strcat(datenreihe, "0");}
139
      strcat(datenreihe, zahl_str);
140
          strcat(datenreihe, "%");
141
142
          // Mittelwerte zurücksetzen
143
      sht_temp_mittelwert[i] =0;
144
      sht_feucht_mittelwert[i] =0;
145
          
146
      // Datenreihe auf SD-Karte schreiben
147
          ffwrites((uint8_t*)datenreihe);
148
149
          // new line in file
150
        ffwrite(0x0D);
151
      ffwrite(0x0A);
152
        };
153
  };

von Thilo M. (Gast)


Lesenswert?

blödkopp schrieb:
> sobald die aktuelle zu beschreibende datei aber 76kB gross ist, lässt
> sich die karte nicht mehr beschreiben.

Was für ein Nickname! :-)

Du hast vermutlich das Problem mit den "eben vollen" Sektoren.
Lies mal die Dateigröße aus und teile sie durch 512. Wenn's ohne 
Nachkommaanteil aufgeht, dann siehe
Beitrag "MMC SD library FAT16 FAT32 read write"
dort wurde gezeigt, wie das Thema umgangen werden kann.

Und achte auf die max. Schreibgeschwindigkeit die deine Karte kann!
Ich bin da auch schon 'reingefallen.

von Thilo M. (Gast)


Lesenswert?

Ups, Link stimmt nicht, hier der richtige:
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

von Chris (Gast)


Lesenswert?

Hallo Leute,
habe gerade das Problem, dass meine Datei nicht mehr gefunden wird.
1
if (MMC_FILE_EXISTS == ffopen("TEST000.TXT"))
2
  {
3
    WDH3224_CLEAR();
4
    WDH3224_TEXT(3,0,"Datei wird geoeffnet",2,0);
5
    
6
    rs232_text("\nDatei wird geoeffnet:\n");
7
8
       
9
    // Phase 1
10
    for( i = 0; i < ZeilenNr - 1; i++ )
11
    {
12
       while( ffread() != '\n' );
13
    }
14
15
    // Phase 2
16
    n = 0;
17
    while( ( get_c = ffread() ) != '\n' )
18
    sd_card_string[n++] = get_c;
19
    sd_card_string[n] = '\0';
20
    
21
    WDH3224_TEXT(20,0,sd_card_string,1,0);
22
    rs232_text(sd_card_string);                
23
    rs232_text("\n");
24
    rs232_text("\nEOF\n");
25
    ffclose();
26
  
27
28
  }
29
30
  else 
31
  { 
32
    rs232_text("\nDatei konnte nicht gefunden werden");
33
    WDH3224_TEXT(150,2," Datei konnte nicht gefunden werden ",1,1);
34
  }

das init der Karte wird mit OK bestätigt und beim öffnen, springt er 
gleich in die ELSE Anweisung. Habe jetzt schon zich mal den Dateinamen 
gewechselt immer auf das Format 8.3 geachtet, die Karte Formatiert und 
acuh mal mehrere Dateien gleichzeitig drauf gepackt zum testen, aber er 
will nie eine  davon öffnen. Hatte das schon jemand? oder kann mir vlt. 
sagen was da falsch laufen könnte?

von blähkopp (Gast)


Lesenswert?

Thilo M. schrieb:
> blödkopp schrieb:
>> sobald die aktuelle zu beschreibende datei aber 76kB gross ist, lässt
>> sich die karte nicht mehr beschreiben.
>
> Du hast vermutlich das Problem mit den "eben vollen" Sektoren.
> Lies mal die Dateigröße aus und teile sie durch 512. Wenn's ohne
> Nachkommaanteil aufgeht, dann siehe
> Beitrag "Re: MMC SD library FAT16 FAT32 read write"
> dort wurde gezeigt, wie das Thema umgangen werden kann.
>
> Und achte auf die max. Schreibgeschwindigkeit die deine Karte kann!
> Ich bin da auch schon 'reingefallen.


also rechne ich
hm, vielen dank für deinen hinweis

von Thilo M. (Gast)


Lesenswert?

Ich meinte, wenn du das Eigenschaften-Fenster der Datei aufmachst, der 
Wert hinter "Größe" (nicht Größe auf Datenträger, die lässt sich immer 
durch 512 teilen).

von Thilo M. (Gast)


Lesenswert?

Thilo M. schrieb:
> der
> Wert hinter "Größe"

Wert in Byte (Win XP), nicht kB hochrechnen.

von Achim (Gast)


Lesenswert?

Hallo,

vielen Dank zunächst mal für diesen tollen Thread.
Ich versuche gerade, die Bibliothek für ein Projekt mit einem ATMEGA128 
zu verwenden. Klappt eigentlich beinahe alles auf Anhieb, ABER....

Beim Erzeugen eines Directories wird dieses auch angelegt, was jedoch 
verdächtig lange dauert. Ca. 1-2 Sekunden @8MHz. Das muss eigentlich in 
einigen ms erledigt sein. Wenn dann in dieses Verzeichnis gewechselt 
werden soll, klappt dies nicht. Das Erzeugen einer neuen Datei findet 
trotzdem im Hauptverzeichnis statt.
Wird die SD-Karte dann unter Windows gelesen, kann nicht in das 
Verzeichnis gewechselt werden, obwohl es angezeigt wird. Es sei 
angeblich nicht verfügbar.
Das Berechnen mit fat_getfree dauert ebenfalls sehr, sehr lang. Da 
kommen schon einige Sekunden zusammen. Der errechnete freie 
Speicherplatz scheint aber zu stimmen.

Ich verwende die die Version 0.6.4, AVR Studio 4.18, WinAVR-20100110.

Getestet habe ich mit einer 32MB, einer 2 GB und einer 16 GB Karte. 
Verhalten ist bei allen identisch. MAX_SPEED wurde auch schon getestet.

Hat jemand noch eine Idee, woran es liegen könnte?

Das Schreiben klappt mit voller Geschwindigkeit ohne jedes Problem. 
Einen Hardwarefehler kann ich eigentlich ausschliessen.



Vielen
Dank

von Lukas (Gast)


Angehängte Dateien:

Lesenswert?

Da ich die Bibliothek fix brauchte und ich keine Lust auf lange 
Diskussionen hier hatte, hab ich die mal debuggt. (allerdings nur für 
sfn und FAT 16) - ich hoffe, dass ich den Rest nicht allzu sehr kaputt 
gemacht habe.

"wichtigste Bugs":
- bei cdLower wurden die zeilen nicht richtig übergeben
- beim Löschen gabs auch ernsthafte Probleme
- bei mkdir muss der Verzeichnisname exakt 11 Zeichen lang sein (auch 
Leerzeichen)

Ich hänge den code mal an, vielleicht interressiert sich jemand dafür
(ich übernehme aber keinen Support und keine Haftung)

von Milan M. (milance)


Lesenswert?

Chris schrieb:
> Hallo Leute,
> habe gerade das Problem, dass meine Datei nicht mehr gefunden wird.
> das init der Karte wird mit OK bestätigt und beim öffnen, springt er
> gleich in die ELSE Anweisung. Habe jetzt schon zich mal den Dateinamen
> gewechselt immer auf das Format 8.3 geachtet, die Karte Formatiert und
> acuh mal mehrere Dateien gleichzeitig drauf gepackt zum testen, aber er
> will nie eine  davon öffnen. Hatte das schon jemand? oder kann mir vlt.
> sagen was da falsch laufen könnte?
Hallo zusammen ich habe das gleiche Problem.
kann jemand bitte helfen. ich komme nicht weiter.
Gruss
Milan

von Milan M. (milance)


Lesenswert?

Hallo zusammen
also es funktioniert wieder. leider nur ohne lange dateiname.

Gruss
Milan

von fauli (Gast)


Lesenswert?

Daniel R. schrieb:
> Hallo zusammen,
> hab leider sehr viel um die Ohren momentan.
> Lese aber schon noch mit hier.
>
> Muss mal sehen das ich meine Entwicklungsumgebung für den FAT kram
> wieder zusammenbaue. Sollte sich das mit den geraden und speziell mit
> den 2er Potenzen bestätigen gehe ich dem auf den Grund.
>
> Viele Grüße
>
> Daniel

hallo,
nach tagen oder wochen geht aufeinmal nix mehr obwohl bis dahin sauber 
messdaten auf MMC gespeichert wurden. das ist echt ärgerlich, hatte ich 
das thema mmc doch schon abgehackt.
hab jetzt mittlerweile mehrere mmc teiber durchprobiert und finde es 
echt schade das gerade dieser anfängerfreundliche leicht zu 
integrierende treiber hier noch bugs drin hat denn der is eigentlich der 
beste.

gruß

von Thilo M. (Gast)


Lesenswert?

fauli schrieb:
> nach tagen oder wochen geht aufeinmal nix mehr obwohl bis dahin sauber
> messdaten auf MMC gespeichert wurden

Hi fauli,
das Problem habe ich auch, nach vielen Monaten einwandfreiem Betrieb 
schreibt der Logger auf einmal nix mehr.

Ich habe den Eindruck, dass es an meinem Kartenadapter liegt 
(Kontaktproblem zur Micro-SD-Karte).
Hatte auch am PC schon Probleme mit den ausgeleierten Adaptern. Evtl. 
hat da jemand Erfahrungen?

von tomZack (Gast)


Lesenswert?

...tuts eigentlich ffrm mittlerweile ?

Habe einige Tests gemacht und es scheint keine Verzeichnisse zu löschen.

ffrm("ABCDE      ");
oder
ffrm("ABCDE");

steigen beide in


file.c
// datei/ordner nicht vorhanden, dann nicht loschen...
  if(FALSE==fat_loadFileDataFromDir(name)){
    return FALSE;
  }


aus.
Das Verzeichnis ist aber vorhanden. Es macht auch keinen Unterschied, ob 
man das Verzeichnis mit dem Controller oder mit Windows anlegt...


GRuß

Tom

von Radek S. (rsikon)


Lesenswert?

Hallo,
Ich benutze bibliotekido Unterstützung MMC / SD:

AVR-mmc-0.6.4.zip
Autor: Daniel R. (zerrome)
Datum: 24.07.2011 08:49

Es funktioniert gut mit MMC, hat SD-Karte nicht unterstützt. Warum?


Radek

von Gregor B. (gregor54321)


Lesenswert?

Gibt es noch ein Repository?
mir ist aufgefallen, dass in mmc.c spi_init() (Version 0.6.4) eine 
direktive fehlt:
1
static void spi_init(void){
2
  MMC_Direction_REG &=~(1<<SPI_MISO);                  // miso auf input
3
  MMC_Write         |= (1<<SPI_MISO);                  // PullUp für Eingang setzen
4
  MMC_Direction_REG |= (1<<SPI_Clock) | (1<<SPI_MOSI) | (1<<SPI_SS);  // clock, mosi + chip select auf output
5
6
// compiler anweisung by gregor: SPE wird sonst immer gesetzt
7
#if (MMC_SOFT_SPI==FALSE)  
8
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);  // hardware spi: bus clock = idle low, spi clock / 128 , spi master mode
9
#endif
10
  mmc_disable();  // chip select auf high, karte abwaehlen
11
}

von Gregor B. (gregor54321)


Lesenswert?

Wie kann ich bei geöffneter Datei die FAT updaten / zur SD schreiben? Da 
ich noch unkalkulierbare Zustände habe, sind alle gesammelten Daten nach 
einem Reset verloren...

von Edi R. (edi_r)


Lesenswert?

Schade, dass es niemanden mehr gibt, der sich wirklich aktiv um dieses 
brauchbare Projekt kümmert. Daniel R. (zerrome) ist wohl ausgestiegen 
:-(

Aber zur Frage: Du kannst die Änderungen mit fflushFileData() auf die 
SD-Karte schreiben. Damit steigt allerdings die Schreiblast, d. h. es 
gibt mehr Schreibzugriffe.

von Andre (Gast)


Lesenswert?

Guten Abend,

ich habe mal ne Frage. Habt ihr auch hin und wieder das Problem, dass 
die SD sich nicht initialisieren lässt? Ich habe auch das Gefühl, wenn 
ich voher die freien Bytes auslese hängt sie sich noch öfters auf.

Jemand Erfahrung damit, bzw. kann das jemand bestätigen?

Wie schließt ihr die SD an? Irgendwo noch extra Pullups/downs?

Viele Grüße
André

von Edi R. (edi_r)


Lesenswert?

Schade, dass es niemanden mehr gibt, der sich wirklich aktiv um dieses
brauchbare Projekt kümmert. :-(

Ich schaue auch nur sporadisch hier rein, deshalb kommt die Antwort erst 
mit großer Verspätung.

Ich habe Pull-Ups (75 kOhm) an CS (Chip Select) sowie an den unbenutzten 
Datenleitungen DAT1 und DAT2. Beim Initialisieren, also vor dem 
Umschalten auf SPI, müssen diese Leitungen die richtigen Pegel haben. 
Außerdem lege ich über die Versorgungsleitungen einen keramischen 
Stützkondensator mit 100 nF, und zwar möglichst nahe an der SD-Karte.

Bei mir hängt sich die SD-Karte nie auf, aber das Abfragen der freien 
Bytes dauert ziemlich lange. Vielleicht interpretierst Du das nur als 
"Aufhängen". Warte einfach mal länger ab, das kann durchaus Minuten 
dauern.

von Andi M. (rootsquash)


Lesenswert?

Hallo!
Huch, hier ist ja nicht mehr so viel los. Naja, vielleicht hat ja 
trotzdem jemand Lust zu Helfen:

Okay, ich hatte mal wieder ein wenig Zeit an meiner Terrariensteuerung 
weiter zu basteln. Ziel war es den Temperaturverlauf auf einer SD-Karte 
zu speichern.

Grundprinzip des bisherigen Programms:
4 MHz ATMega162, Interrupt über Timer1 jede Millisekunde, die ISR zählt 
dann gegebenenfalls die Uhr weiter und soll sich um die 
Wellenpaketsteuerung der Heizung kümmern.
Die Lichtsteuerung passiert dann im Hauptprogramm. Code-Schnipsel dazu 
finden sich bei Bedarf am Ende des Posts.
Jetzt habe ich aus einem USB-Dongle mit SD-Karten-Leser die Halterung 
ausgelötet und mit einem 74HC4050 an den Hardware-SPI des ATMegas 
gehangen.
Ich habe versucht den Interrupt auf 10 ms zu setzen:
1
        // Configure Timer 1
2
//         TCCR1A = 0x00;
3
        TCCR1B |= (1<<CS10);
4
        OCR1AL = 0x9C40;
5
        TIMSK |= (1<<OCIE1A);   //Allow Compare Interrupt

Als Hauptprogramm habe ich erstmal einfach das Beispielprogramm genommen 
und die UART-Ausgabe durch eine Ausgabe auf das angeschlossene 
LCD-Display ersetzt.
Nach etwas Rumwackeln an der Karte fing er dann auch an auf die Karte zu 
schreiben. Das Ergebnis:
1
ls -l
2
total 0
3
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
4
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
5
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
6
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
7
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
8
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
9
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT

Die Datei sollte nicht nochmal neu erstellt werden wenn es sie schon 
gibt und eigentlich sollten die Dateien auch einen Inhalt haben. So ganz 
scheint es also noch nicht funktioniert zu haben.
Ausserdem:
Was kann/muss ich tun um dieses Programm auf meinen 1 ms-Timer 
anzupassen?
Wenn es ein Problem mit der Karte gibt bleibt das Programm in 
irgendwelchen Schleifen hängen, was bei der Steuerung der Temperatur 
oder des Lichts störend sein dürfte.
Gibt es dafür bekannte Lösungen die einfach zu implementieren sind und 
zuverlässig funktionieren?
Ich möchte dieses Projekt eigentlich gerne mit einem µC weitermachen, 
auch wenn es  mit einem Raspberry wohl einfacher wäre ;)


Hier die versprochenen Code-Schnipsel (ich hoffe sie sind nicht zu lang 
fürs Forum):
1
  // Configure Timer 1
2
  TCCR1A = 0x00;
3
  TCCR1B |= (1<<CS11) | (1<<WGM12); //Prescaler 8, CTC1 (renamed WGM12) = 1
4
  OCR1A = 500-1; //((4000000/8)/1000) = 500
5
  TIMSK |= (1<<OCIE1A);  //Allow Compare Interrupt
6
7
while(1)
8
  {
9
    wdt_reset();
10
    switch (dcf_status)
11
    {
12
      case 1:  //1: call dcf_sync() to find bit 59/bit 0
13
//und so weiter
14
15
      case 0:  //0: "normal" operation
16
        if(oldsecond!=second)//once per second is enough
17
        {
18
          oldsecond=second;
19
          show_matched_time(1,2);
20
          check_temp();  //check the temperature a few times per minute
21
        }
22
        break;
23
//und so weiter
24
      default: restart_via_watchdog_timeout();
25
    }
26
    sleep_mode();
27
  }
1
ISR(TIMER1_COMPA_vect)
2
{
3
  millisecond++; 
4
  dcf_read_level();
5
  counter_high++;counter_low++;
6
  if((millisecond%200)<dimmer_value*20)
7
  {
8
    OUT_PORT |= (1<<OUT_DIMM);
9
  }
10
  else
11
  {
12
    OUT_PORT &= ~(1<<OUT_DIMM);
13
  }
14
  if(millisecond == 1000)  //RTC +1 second
15
  //{langweilig}
16
}

: Bearbeitet durch User
von Florian (Gast)


Lesenswert?

ffls gibt bei mir nicht alle Dateien im root-Verzeichnis aus...
Weiß jemand woran das liegen kann?

von Wolfgang S. (wolfgangs)


Lesenswert?

Bitte immer daran denken, dass das Problem mit dem "Sektor gerade voll" 
immer noch besteht (siehe viel weiter oben). Also: Immer schön nur eine 
ungerade Datenanzahl auf die Karte schreiben. Dann treten diese 
komischen FAT-Geschichten (Daten weg, plötzlich mehrere Dateien mit 
gleichem Namen usw.) nicht auf.

von Micha (Gast)


Lesenswert?

Bin grade mal durch den Thread "durchgeflogen" - wenn ich das richtig 
verstehe hat der Autor die Weiterentwicklung aufgegeben? Sehr schade 
falls wahr, weil das wirklich ein gutes und nützliches Projekt ist.

Selber experimentier ich grade mit 'ner etwas schrägen Anwendung: 
Dateien auf einem FAT Datenträger, die Container für CP/M Disk-Images 
sind. Wobei ich dann typischerweise Datenblöcke von 512 Byte Größe in 
der Gegend rumschiebe.

Bei der Gelegenheit hab ich (neben allen positiven Aspekten) eine Sache 
an dem Projekt-Code entdeckt der mir nicht optimal erscheint: die 
Funktion ffseek lädt gleich einen 512 Byte Sektor, wenn sie die passende 
absolute Adresse gefunden hat. Fühlt sich aus meiner Sicht irgendwie 
nicht "richtig" an - ffseek sollte diese Adresse nur zurückliefern und 
es dann anderen Funktionen überlassen, ob der Sektor gelesen oder 
geschrieben werden soll.

Just my 2 cents.

Ansonsten: Klasse Projekt!

von Micha (Gast)


Lesenswert?

Hab gestern und heute ein wenig mit der Bibliothek experimentiert, und 
dabei folgenden Fehler gefunden:

In der *main_simple.c* Beispieldatei werden für eine Reihe von 
Systemtakten die Konstanten für den Timer definiert, die Definition für 
20MHz Systemtakt ist fehlerhaft. Dort steht (Version 0.6.4):
1
#if(F_CPU == 20000000)      // error 0.16%
2
  #define TOP_OCR 0x4D
3
  #define START_TCNT 0xB2
4
  #define PRESCALER 0x04
5
#endif

Hier die passenden Werte für diesen Systemtakt:
1
#if(F_CPU == 20000000)      // error 0.16%
2
  #define TOP_OCR 0xC2
3
  #define START_TCNT 0x3D
4
  #define PRESCALER 0x05
5
#endif

von Martin M. (mcmaier)


Lesenswert?

Habe diese Lib auch im Einsatz und bisher mit dem Ungerade-Modus das 
Problem mit den vollen Sektoren umgangen.
Wollte der Sache aber auf den Grund gehen, damit das lästige 
Prüfen-und-Leerzeichen-anhängen entfällt.
Deshalb habe ich die Bibliothek mal genauer untersucht.
Zu Testzwecken habe ich immer 512 Byte auf einmal geschrieben. Wie 
erwartet blieb die Datei jedes Mal bei 32kB "hängen" (Zuordnungseinheit 
32768 Bytes). Beim Schreiben von ungeraden Datenblöcken waren auch 
größere Dateien möglich.

Vor dem Schreiben wird ja immer zuerst ffseek() ausgeführt, um an die 
akutelle Position in der Datei zu gelangen. Dabei bin ich in ffseek() 
auf folgendes gestoßen:
1
// suchen des sektors in dem offset ist
2
  while( offset >= 512 ){
3
    sectors += 1;
4
    offset -= 512;
5
    file.seek += 512;                    
6
    chain.cntSecs -= 1;
7
    
8
    if ( chain.cntSecs == 0 ){
9
      fat_getFatChainClustersInRow(fat_getNextCluster( chain.lastCluster ));
10
      sectors = chain.startSectors;
11
    }
12
  }

Wenn aber der Sektor genau vollgeschrieben ist (Bytes % 512 == 0) und 
keine weiteren Sektoren mehr anstehen, gab das einen Überlauf bei 
chain.cntSecs -= 1;

Habe also folgendes ausprobiert:
1
 while( offset >= 512 ){
2
    sectors += 1;
3
    offset -= 512;
4
    file.seek += 512;   
5
            
6
    if(offset > 0)
7
    {
8
      chain.cntSecs -= 1;
9
    }
10
    
11
    if ( chain.cntSecs == 0 ){
12
      fat_getFatChainClustersInRow(fat_getNextCluster( chain.lastCluster ));
13
      sectors = chain.startSectors;
14
    }
15
  }

Und siehe da, keine Probleme mehr, auch wenn ich immer 512-Byte Blöcke 
geschrieben habe.

Kann das jemand verifizieren?

von Wolfgang S (Gast)


Lesenswert?

Hallo Martin,

ich habe ja vor langer Zeit den Fehler entdeckt, aber nie Zeit gehabt, 
nach der Ursache zu suchen. Mit der Beseitigung dieses Fehlers dürfte 
das Projekt perfekt sein. Einige Geräte laufen bei mir seit Jahren im 
ungerade-Modus fehlerfrei (LUMINARY-CPU's). Ich teste morgen und teile 
das Ergebnis mit.

Danke für Deine Bemühungen!

von Martin M. (mcmaier)


Lesenswert?

Hallo Wolfgang,

leider scheint das auch noch nicht ganz des Rätsels Lösung zu sein.
Habe zwei Datenlogger mit der Modifikation laufen.
Einer läuft tadellos, beim anderen habe ich Sprünge in der Aufzeichnung, 
wenn ein Sektor vollgeschrieben wurde. Da sind dann plötzlich ein paar 
Zeilen vertauscht...
Die Sprünge laufen nach diesem Prinzip (Jede Zeile steht für einen 
Eintrag)
111111
22 555555
666666
777777
        22222
333333
444444

Muss auch mit dem ffseek() zusammenhängen, womit er mit dem Schreiben 
wieder einsteigt...

Hast du schon was herausgefunden?

von Wolfgang S (Gast)


Lesenswert?

Hallo Martin,

tatsächlich ist da immer noch der Wurm drin. Ab 15.Mai habe ich etwas 
mehr Zeit, da werde ich das Problem lösen. Das Hauptproblem ist, dass 
man die komplette Funktionsweise der Software erst mal verstehen muss. 
Ich schätze, dass ich etwa 3-4 Tage Einarbeitung benötige.

Ich melde mich wieder!

von Philipp (Gast)


Lesenswert?

Hi,
echt cooles Projekt, hat soweit erst mal auch gut geklappt. Leider bin 
ich mit der Dauer für solch einen Schreibvorgang noch nicht wirklich 
zufrieden. Dauert schon ne weile, bis man seine Daten auf die SD kriegt. 
Hat da jemand Tipps, wie das vielleicht schneller gehen könnte?

von Johannes (Gast)


Lesenswert?

Hallo,

ich versuche einen Datenlogger mit einem ATmega 8A aufzubauen. Ich habe
mir den Beitrag durchgelesen und den Source-Code angeschaut. Sehr
hilfreich, danke!

Das Beispiel ist mit einem ATmega 8

http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status

Schaltung aufgebaut wie im Beispiel. Ich habe allerdings einige Probleme
mit dem Code:

Zunächst hatte ich Probleme mit den Timer-Registern, die haben im Code
andere Bezeichnungen als im Datenblatt des ATmega 8 und des 8A. Die habe
ich entsprechend des AVR-Datenblattes angepasst.

Original:

static void timer0_init(){

  TimingDelay = 0;  // initialisierung der zaehl variable

  TCCR0A = 1<<WGM01;     // timer0 im ctc mode
  TIMSK0 = 1<<OCIE0A;    // compare interrupt an

  TCNT0 = START_TCNT;    // ab wo hochgezaehlt wird,
  OCR0A = TOP_OCR;  // maximum bis wo gezaehlt wird bevor compare match

  TCCR0B = PRESCALER;// wenn prescaler gesetzt wird, lauft timer los
  sei();    // interrupts anschalten, wegen compare match
}

Angepasst:

static void timer0_init(){

  TimingDelay = 0;  // initialisierung der zaehl variable

  TCCR1A = (1<<WGM12);     // timer0 im ctc mode
  TIMSK = (1<<OCIE1A);    // compare interrupt an

  TCNT0 = START_TCNT;    // ab wo hochgezaehlt wird,
  OCR1A = TOP_OCR;// maximum bis wo gezaehlt wird bevor compare match

  TCCR1B = PRESCALER;// wenn prescaler gesetzt wird, lauft timer los
  sei();    // interrupts anschalten, wegen compare match
}

Dann bin ich noch total erstaunt, dass der uC mir nur über eine Baudrate
von 600 antwortet, im Quelltext steht doch 9600 ?!? hatte jmd das selbe
Problem?

"// Wenn auf dem terminal "Boot... OK" zu lesen ist, ist Init OK."

Und ich bekomme immer nur "\nBoot" als Antwort, das aber in regelmäßigen
Abständen. Woran kann das liegen, bei euch funktionierts doch überall,
ich habe ja am Quelltext quasi nichts verändert. Hatte es mit drei
verschiedenen SD-Karten probiert, alle standartformatiert, immer mit dem
gleichen Ergebnis.

Hat jmd von euch Erfahrungen mit dem Source-Code "AVR Version 0.6.4" vom
oben Beschriebenen Link?

Ich danke euch im Voraus für eure Antworten.

Grüße

Johannes

von Claudio (Gast)


Lesenswert?

Hallo Johannes

Hast du die clk-div fuse des atmega entfernt bzw. gesetzt?

Denn je nach einstellung, wird der interne/externe clock durch 8 
geteilt.

von Johannes (Gast)


Lesenswert?

Hallo Claudio,

nein ist eigentlich nicht an.

Macht aber auch keinen Sinn. Dann müssten es ja 1200 Baud sein und nicht 
600 Baud (9600 / 8).

von Johannes B. (johannes_jjb)


Lesenswert?

Hallo ich nochmal mit einem Update,

heute habe ich das Ganze nochmal mit einem ATmega 169A probiert.

Habe 1:1 den Quelltext von

http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code-Beispiel

Aktuellste Version 0.6.4 genommen.  Gleiche Problematik mit der Bautrate 
600 statt 9600 und dass ich nur "\nBoot" empfange.

Ich habe nichts am Quelltext verändert und benutze die 
Beispeilschaltung.

Komisch ...

Bei wem geht die Software denn und was verwendet ihr für eine Hardware?

Grüße

Johannes

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallöchen..

Benutze die Version 6.4. Auf meinem Xmega128A1 funktioniert Lesen und 
Schreiben über SPI mit 8MHz problemlos. Mit 16Mhz SPI Clock laufen 
leider nicht alle SD Karten (Class4). Gibt Fehler bei der 
Initialisierung, könnte vlt. aber am Timer im Xmega liegen. Werde das 
mal überprüfen. Ferner funktioniert der MultiBlock Modus nicht. Habe 
einige Unverständlichkeiten in der Datei "mmc.c" für den MultiBlock 
Zugriff gefunden wzB:
1
// **********************************************************************************************************************************
2
// stop multiblock schreiben
3
// **********************************************************************************************************************************
4
uint8_t mmc_multi_block_stop_write (void){
5
6
  uint8_t cmd[] = {0x40+13,0x00,0x00,0x00,0x00,0xFF};  // CMD13 (send_status), response R2
7
  uint8_t response;
8
9
  mmc_write_byte(0xFD);          // stop token
10
11
  mmc_wait_ready();
12
13
  response=mmc_write_command (cmd);    // cmd13, alles ok?
14
15
  mmc_wait_ready();
16
17
  mmc_disable();
18
  return response;
19
}

Compiler Error: "response=mmc_write_command (cmd);"

Hab diese Zeile ersetzt durch:
spi_write_byte(cmd);
response = spi_read_byte;

Es scheint aber noch mehr Fehler in den Routinen für den MultiBlock 
Zugriff zu geben. Bin auf der Suche..

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallöchen..

Da bin ich nochmal schnell. Der Initialisierungsfehler mit 16MHz SPI 
Clock lag an dem verwendeten Breakout Board für die SD Karte. Da sitzen 
5 Volt Pegelwandler zwischen den Steuerleitungen zur SD Karte um den 
Pegel von 5 Volt auf 3.3 Volt abzusenken. Auf dem Board sitzt ein 
Umschalter für 5 Volt oder 3 Volt Betrieb. Dieser steht bei mir auf 3 
Volt, da ich einen Xmega mit 3.3 Volt Betriebspannung verwende.  Diese 
Pegelwandler scheinen bei 16MHz die Signalflanken der Steuerleitungen zu 
sehr abzuflachen, so dass eine sichere und gute Datenübertragung zur 
oder von der SD Karte nicht mehr gewährleistet ist.

Habe jetzt die Pegelwandler überbrückt, so das die Steuerleitungen 
direkt mit dem Xmega verbunden sind.

Bild: SD Karte Breakout Board

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Lesenswert?

Hallöli..

Hab leider immer noch das Problem das bei MultiBlock Read kein Byte von 
der SD Karte gelesen wird. Das Programm verweilt leider dauerhaft in der 
while Schleife und wartet auf ein zu empfangenes FE Byte. Hab 
verschiedene SDHC Karten (Class4) ausprobiert. Woran könnte es liegen ?
1
// **********************************************************************************************************************************
2
// starten von multi block read. ab sektor addr wird der reihe nach gelesen. also addr++ usw...
3
// **********************************************************************************************************************************
4
uint8_t mmc_multi_block_start_read (uint32_t addr){
5
  
6
  uint8_t cmd[] = {0x40+18,0x00,0x00,0x00,0x00,0xFF};  // CMD18 (read_multiple_block), response R1
7
  uint8_t response;
8
9
  mmc_enable();
10
11
  // addressiertung bei mmc und sd (standart < 2.0) in bytes, also muss sektor auf byte adresse umgerechnet werden.
12
  // sd standart > 2.0, adressierung in sektoren, also 512 byte bloecke
13
  
14
  //if(fat.card_type==0) addr = addr << 9; //addr = addr * 512, nur wenn mmc/sd karte vorliegt
15
  addr = addr << 9;
16
17
  cmd[1] = ((addr & 0xFF000000) >>24 );
18
  cmd[2] = ((addr & 0x00FF0000) >>16 );
19
  cmd[3] = ((addr & 0x0000FF00) >>8 );
20
  cmd[4] = (addr &  0x000000FF);
21
22
  mmc_wait_ready ();
23
24
  spi_write_byte(cmd);    // commando senden und response speichern
25
  response=spi_read_byte();
26
27
  while (spi_read_byte() != 0xFE){    // warten auf start byte
28
    nop();
29
  };
30
31
  return response;
32
}

von Torsten S. (tse)


Lesenswert?

Wenn man die Berichte nur mal überfliegt ist es besser sich nach einer 
Alternative umzusehen die auch das tut was sie soll.

FatFs von ElmChan ist z.B. so eine.

Dem Autor war nicht mal klar was der Unterschied zwischen einer .h und 
.c Datei ist wenn man sich die ersten Posts in diesem Thread anguckt. 
Das spricht Bände.

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo Torsten

Danke für den Tip. Die Software von ElmChan habe ich mir bereits 
angesehen. Macht einen sehr guten Eindruck. Allerdings müsste ich dafür 
die ganzen Routine in meinem Synth Projekt ändern 
(http://www.cczwei-forum.de/cc2/thread.php?postid=86316#post86316). 
Dafür habe ich aber im Moment keine Zeit. Ferner weis ich nicht, wieviel 
Ram für die Zwischenspeicherung der Daten im Prozessor notwenig ist. 
Muss mit dem Ram sehr sparsam umgehen, da andere  Funktionen in meinem 
Synthesizer auch Speicherplatz beanspruchen.

Mir ist aufgefallen, dass in den Funktionsroutinen 
"mmc_multi_block_start_read" und "mmc_multi_block_read_sector"  beim 
Warten auf das Startbyte nur 0x00 empfangen wird. Wenn ich diese 
Routinen umgehe findet eine Datenübertragung statt. Allerdings sind die 
ersten Bytes nur Müll. Mir scheint es so, das die SD Karte die 
MultiBlock Befehle nicht versteht. Bin aber kein Experte in Bezug auf 
das FAT32 System. Verschiedene aktuelle SD Karten (Class4) habe ich auch 
getestet.

Mir ist auch nicht ganz klar, ob sich der MultiBlock Zugriff in meinem 
Projekt lohnt. Fürs Laden eines Sound Presets von der SD Karte wird 
immer auf eine 32KByte große Binär Datei zugeriffen. Diese Datei 
beinhaltet die Parameter und WAV-Dateinamen für insgesammt 128 Presets 
in einer Sound-Bank. Beim Laden von Sound Samples siehts ein wenig 
anders aus. Ein Wav-File kann die Größe von 1KByte bis 1MByte haben.

Bild 1: Datei und Ordner-System im Synthesizer
Bild 2. Preset Menü


Gruß Rolf

: Bearbeitet durch User
von Moritz Hännes (Gast)


Lesenswert?

Guten Tag,

ich scheitere am versuch die Version 3.1 zu kompelieren, leider bekomme 
ich fünf fehler (alle Fehler sind in der Datei fat-0.3.c):

-conflicting types for 'fat_writeSector'
-conflicting types for 'fat_getNextCluster'
-conflicting types for 'fat_getFreeCluster'
-conflicting types for 'fat_setCluster'
-'superfloppy' undeclared (first use in this function)

ich verwende Atmel Studio 6.2.
Wie könnte ich diese Fehler beheben ?





Grüße

Moritz

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo Moritz

Ich habe mit der Version 0.6.4 auch Probleme beim kompilieren und bin 
aus diesem Grund wieder zurück auf eine 5er Version glaube ich. Kanns 
leider nicht genau sagen. Im Anhang die kompilierten Dateien. Einfach 
die Dateien in  AVR Studio 6.2 im Solution Explorer als Existen Item 
"adden" bzw laden und kompilieren. Wichtig ist die initialisierung eines 
Timers mit 10ms Interrupt, da sonst zeitkritische Sachen in der SD 
Routine nicht funktionieren. In dem Timer wird die Variable TimingDelay" 
decrementiert.

1
//*************************************************************************
2
// SDCARD Delay Timer 10msec
3
//*************************************************************************
4
ISR (TCD1_OVF_vect)
5
{
6
  TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;
7
8
}

Hab dir mal den Source Code drangehangen. die zwei Dateien sd_card.c und 
sd_card.h sind meine Funktionsroutinen im Programm und als Beispiel 
gedacht. Ist aber alles noch etwas konfus. Ich hoffe das hilft dir 
weiter :)

LG Rolf

: Bearbeitet durch User
von holger (Gast)


Lesenswert?

>ich scheitere am versuch die Version 3.1 zu kompelieren,

Was willst du mit diesem uralten Kram? Alle bereits
gefundenen Fehler noch mal suchen? Nimm ne neuere Version
und klopp den Dreck in die Tonne.

von Torsten S. (tse)


Lesenswert?

Etwas drastisch formuliert, aber so ist es.

von Uwe Z. (uwezi)


Lesenswert?

In einem Datenlogger-Projekt habe ich bisher FatFs von ElmChan 
verwendet, der hat aber in der aktuellen Version einige radikale 
Veränderungen bei einigen Funktionsaufrufen vorgenommen und die 
Konfiguration ist dank der vielen Module auch schon immer sehr chaotisch 
gewesen - es ist wohl schwer, eine eierlegende Wollmilchsau auf Dauer am 
Leben zu erhalten.

Hier dagegen läuft die Konfiguration dank einer zentralen .h-Datei sehr 
einfach und problemfrei und ich konnte den Kode direkt und ohne Probleme 
zum Laufen bringen - Version 0.6.1 vom SVN-Server ist zwar 4 Jahre alt, 
ließ sich aber problemlos mit AVR-Studio 6.1 und aktueller Toolchain 
kompilieren.

Testsystem: 3,3V ATmega328P und microSD SDHC von 4GByte und 8GByte.

Der Quellkode selbst ist etwas gewöhnungsbedürftig - bin dabei, den Kode 
etwas aufzuräumen und zu anglifizieren.

 Aber : Bei der Verwendung langer Dateinamen scheint es ein Problem zu 
geben, wenn der lange Dateiname kürzer ist, als ein kurzer Dateiname - 
eine auf diese Weise erstellte Datei hat plötzlich zwei Punkte im 
Dateinamen und läßt sich unter Windows nicht öffnen - da sich das 
vermeiden läßt, habe ich noch nicht nach dem Fehler gesucht...

 Und erst jetzt sehe ich ein, daß die "aktuelle" Version auf dem SVN 
eine uralte Version ist, und man sich wie immer hier im Forum durch 
Gigazeilen von Kommentaren und inkrementellen Änderungen Lesen muß. 
Schade eigentlich. Ich will ja nicht wirklich etwas umsonst und ohne 
Arbeit haben, hatte mich ja schon daran gemacht, die Version 0.6.1 
aufzuräumen, aber das macht dann ja wohl keinen Sinn mehr... Mal sehen, 
och ich Version 0.6.4 ebenfalls direkt und unproblematisch zum Laufen 
bekomme, auch wenn mir der eingeführte 10ms-Timer doch einiges 
Kopfzerbrechen bereitet - abgesehen von Aktivitäten soll mein Logger nur 
einmal pro Sekunde aufwachen, aber das läßt sich sicher irgendwie 
anpassen...

Ich hoffe, ich habe jetzt schließlich die aktuelle Version gefunden...

von Willi Burkhardt (Gast)


Lesenswert?

Hat jemand von Euch erfahrungen mit dieser implementierung gemacht:
https://github.com/BizzaBoy/RFAT

Besonderes Interesse wäre wie "robust" diese Implementierung wirklich 
ist. Der Autor behauptet ja es sei: "100% power fail safe."

von Rolf D. (rolfdegen)


Lesenswert?

Hallöchen..

Ich benutze die aktuelle Version der FAT32 Library.

Ich hab nun folgendes Problem. In einem Ordner befinden sich insgesamt 9 
Dateien. Mit der 'ffrm()' Funktion möchte ich eine Datei aus dieser 
Liste löschen. Leider werden aus der Liste immer 2 Dateien gelöscht.

Z.B. Datei-Liste mit Bezeichnung 1-9. Wenn ich die Datei '3' lösche, 
dann wird die Datei '2' mit gelöscht. Wenn ich Datei '9' lösche, wird 
Datei '8' auch gelöscht. Wenn ich die 1.Datei '1' lösche, wird Datei '2' 
auch gelöscht. Ist nur eine Datei vorhanden und wird diese gelöschr, 
bekomme ich wieder andere Dateien mit 0Byte angezeigt ????


Mein Code:
1
// set folder
2
  ffcd(""); ffcd("SAMPLE");
3
    
4
  // file available ?
5
  if (fat_loadFileDataFromDir(sample_name) == TRUE)
6
  {
7
    // delete file
8
    ffrm(sample_name);
9
    ffclose();
10
  }

Hardware: SDHC Card 4GB SanDisk Fat32 Format
Software: Aktuelle Version FAT32

Schreib- und Lesefunktionen funktionieren problemlos. Nur das löschen 
der Dateien nicht. Kann mir vielleicht jemand helfen. Danke im Voraus.

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo..

Hier im Forum gabs einen Beitrag von Lukas 
Beitrag "Re: MMC SD library FAT16 FAT32 read write" indem 
er auf einige Fehler in der FAT32 Library hingewiesen hat.

Das Löschen von Dateien funktioniert mit der neuen 'ffrm()' Routine von 
Lukas problemlos.

Im Anhang nochmal die FAT32 Library von Lukas.

Gruß Rolf

: Bearbeitet durch User
von andy (Gast)


Lesenswert?

Hey,

ich hab eine Frage zur "TimeDelay" variable...die wird doch nur 
benötigt, damit man in einem Fehlerfall nicht in einer Endlosschleife 
steckt, oder? D.h. man braucht diese nicht unbedingt im ISR 
dekrementieren. Oder liege ich da falsch?

Frage2: mmc_init()und fat_loadFatData() wird ohne Probleme(return == 
TRUE) ausgeführt. Wenn ich dann eine Datei anlege
1
if (ffopen(fname, 'c') == MMC_FILE_CREATED)
2
{
3
 ffwrites((uint8_t*) "test");
4
 ffwrite(0x0D);
5
}
6
ffclose;
und diese schließe, findet die Funktion ffopen(fname, 'r') die Datei 
nicht.(Fehlercode: MMC_FILE_ERROR)
Hatte jemand evtl. noch dieses Problem?

von Rolf D. (rolfdegen)


Lesenswert?

Hallo Andy,

in der 'mmc_init' wird TimingDelay auch benutzt. Könnte sein, dass deine 
Karten dann nicht mehr richtig initialisiert bzw erkannt werden, wenn du 
es weglässt. Da ich mehrere Timer-Interrupts in meinem Synthesizer 
benutze, habe ich TimingDelay mit integriert.

Ich benutze die letze Version 6.4 Datei Anlegen und Öffnen geht bei mir 
ohne Probleme.


Beispiel:
(die Delays sind nur für die Textmeldungn auf meinem Display notwendig)
1
// save Preset Data ---------------------------------------------------
2
  set_preset_folder();
3
  
4
  // Data.bin file available ?
5
  if (fat_loadFileDataFromDir("Data.bin") == FALSE)
6
  {
7
    fillrectangle(30,38,280,145,color_blue1);
8
    rectangle(33,42,99,243,color_white);
9
    fillrectangle(139,42,180,65,color_blue1);
10
    draw_string("File 'Data.bin' not found!",42,75,6,color_white);
11
    _delay_ms(1000);
12
    if(MMC_FILE_CREATED == ffopen("Data.bin",'c') )
13
    {
14
      draw_string("create new File...",42,90,6,color_white);
15
      _delay_ms(500);
16
      ffwriten(0,0x8000);
17
    }
18
    ffclose();
19
  }
20
21
22
void set_preset_folder(void)
23
{
24
  // set Preset Folder --------------------------------------------------
25
  ffcd("");
26
  ffcd("PRESET");
27
  
28
  // set PRBANK Folder --------------------------------------------------
29
  char folder_temp[9];
30
  strcpy(folder_temp,"PRBANK");
31
  
32
  char xx[3];
33
  sound_bank = sel_sound_bank;
34
35
  itoa(sound_bank,xx,10);
36
  if (sound_bank > 9)
37
  {
38
    strcat(folder_temp,xx);
39
  }
40
  else
41
  {
42
    strcat(folder_temp,"0");
43
    strcat(folder_temp,xx);
44
  }
45
  ffcd(folder_temp);
46
  
47
  // Set SOUND Folder --------------------------------------------------
48
  char folder_temp1[10];
49
  strcpy(folder_temp1,"SOUND");
50
  
51
  char xx1[4];
52
  sound_bank = sel_sound;
53
54
  itoa(sound_bank,xx1,10);
55
  if (sound_bank < 10)
56
  {
57
    strcat(folder_temp1,"00");
58
    strcat(folder_temp1,xx1);
59
  }
60
  else if(sound_bank < 100)
61
  {
62
    strcat(folder_temp1,"0");
63
    strcat(folder_temp1,xx1);
64
  }
65
  else
66
  {
67
    strcat(folder_temp1,xx1);
68
  }
69
  ffcd(folder_temp1);
70
  ffclose();
71
  _delay_ms(100);
72
  
73
}

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Bezogen auf meinen Beitrag #3769720 vom 19.08.2014 10:27 (etwas weiter 
oben):

Ich habe das Datei System auf der 4GB SD Karte meines Synthesizers 
geändert. Dazu gehört das abspeichern oder löschen von Samples und 
Presets.
Das hört sich jetzt nicht gerade kompliziert an, aber die Arbeit steckt 
mal wieder in den Details. Die Abbildung zeigt die Ordner Stuktur auf 
der SD Karte.

Auf der SD Karte gibt es drei Ordner mit der Bezeichnung PRESET, SAMPLE 
und SYSTEM. Im Ordner 'Preset' sind die gesamten Sound Parameter, 
UserWave-Table und ggf das Sample-File für den Sound abgespeichert. Der 
Ordner 'SAMPLE' beinhaltet die gesamte Sample Library. Hier kann man 
Samples laden, speichern oder löschen, ohne eine Beeinflussung auf die 
Preset Sounds. Dadurch kann man z.B. die komplette Sample Library auf 
der SD Karte ändern oder austauschen, ohne Gefahr zu gehen, dass sich 
die Preset Sounds verändern. Falls ein Preset ein Sample-File besitzt, 
wird dieses immer im Preset Ordner mit abgespeichert.
Im Ordner 'SYSTEM' befinden sich System relevante Daten wzB Bilder, 
Sequenzer-Daten, USERWAVE-Table und die aktuelle Midi CC Tabelle. Die 
USERWAVE-Table besteht aus 128 festen Wellenformen mit 256 Byte Größe 
und kann beliebig ausgetauscht werden. Damit stehen dem Benutzer 
unendlich viele Möglichkeiten der Soundgestaltung zur Verfügung.

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Lesenswert?

andy schrieb:
> Hey,
>
> ich hab eine Frage zur "TimeDelay" variable...die wird doch nur
> benötigt, damit man in einem Fehlerfall nicht in einer Endlosschleife
> steckt, oder? D.h. man braucht diese nicht unbedingt im ISR
> dekrementieren. Oder liege ich da falsch?
>
> Frage2: mmc_init()und fat_loadFatData() wird ohne Probleme(return ==
> TRUE) ausgeführt. Wenn ich dann eine Datei anlege
>
1
if (ffopen(fname, 'c') == MMC_FILE_CREATED)
2
> {
3
>  ffwrites((uint8_t*) "test");
4
>  ffwrite(0x0D);
5
> }
6
> ffclose;
7
>
> und diese schließe, findet die Funktion ffopen(fname, 'r') die Datei
> nicht.(Fehlercode: MMC_FILE_ERROR)
> Hatte jemand evtl. noch dieses Problem?

Hi Andy

Ich glaube ich hatte mal ein ähnliches Problem.
Es könnte noch daran liegen, dass du zuerst einen Ordner anlegen musst 
und dann eine neue Datei in dem Ordner erstellen kannst.

Gruß Rolf

von andy (Gast)


Lesenswert?

Hey Rolf,

danke für deine Antwort. Leider hat es daran nicht gelegen. Habe jetzt 
auch Timingdelay mit eingebaut, hilft auch nichts. Bin immer noch am 
suchen der Lösung. Wenn ich den Fehler finde, melde ich mich ;)

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo Andy :)

Hier meine kleine Funktionsbibliothek für die SDCARD im Anhang. 
Vieleicht hilft es dir.

Lieben Gruß und guten Rutsch. Rolf

: Bearbeitet durch User
von Torsten S. (tse)


Lesenswert?

Hallo Rolf,

Obwohl diese lib nicht als eine der zuverlässigsten gilt hast Du Dich 
dran gemacht diese benutzbar zu machen - mutig. Und scheinbar tuts die 
auch.

Beim überfliegen des obigen Quelltextes bin ich beeindruckt. Ohne von 
dieser Materie allzuviel zu verstehen kann ich nur ahnen wieviel Arbeit 
da drin steckt. Respekt!

Das einzige was mir nicht gefällt sind die vielen einzelnen 
read_par_value() und write_par_value() Aufrufe. Vielleicht könnte man 
das in ein struct packen und mit einem einfachen memcpy initialisieren 
oder von der Karte lesen.

Einen guten Rutsch,
Torsten

von Nicolai (Gast)


Lesenswert?

Hallo Leute,

erstmal vielen Dank für die Library. Ich wollte einen Datenlogger bauen,
und wenn die mmc_init durchläuft funktioniert alles hervorragend. Nur 
manchmal kommt er nicht durch die prozedur
1
   while (FALSE == mmc_init()){
2
    _delay_ms(100);
3
4
  }

Egal wie lange ich warte, die init läuft nicht durch. Hingegen andere 
male funktioniert es... es scheint ziemlich zufällig zu sein. Außerdem 
habe ich herrausgefunden, dass wenn ich mit meinem Finger den Miso pin 
berühre, dann funktieniert das meistens, kann aber ebenfalls zufall 
sein. Ein Hardreset des controllers hilft auch nicht immer. Wenn Die 
Spannungsversorgung an bleibt und die sd karte einmal initialisiert 
worden ist und man dann den controller resettet, dann geht es fast 
immer. Aber wenn diese wieder ausgeschaltet wurde, dann funktionier das 
weniger oft.

Hatte jemand von euch schonmal solche probleme? Ich bin mittlerweile 
wirklich ratlos.

Grüße

Nicolai


PS: ATMEGA32 16MHZ Quartz SDHC 8GB

von dummy (Gast)


Lesenswert?

>Hatte jemand von euch schonmal solche probleme? Ich bin mittlerweile
>wirklich ratlos.

Mach mal einen Pullup an MISO.

von nicolai (Gast)


Lesenswert?

Hallo,
Der letzte Beitrag ist ja schon etwas her...
ich habe die hardware so aufgebaut wie beschrieben und benutze auch den 
Beispielcode. Leider kommt der Controller fast nie druch die MMC_Init 
funktion.
Ich habe jetzt alle Einträge hier gelesen und auch weitere die man so im 
Internet findet. Leider konnte mir keiner so wirklich helfen. Wenn die 
karte erstmal initialisiert ist funktionier das Schreiben auch 
zuverlässig mehrere Tage lang. Interessanter Weise hängt sich die 
Funtkion wirklich auf...
hat jemand damit schon Erfahrung?

Viele Grüße

Nicolai

von Peter (Gast)


Lesenswert?

Hallo,
ich hoffe hier liest manchmal noch jemand mit. Habe die lib erfolgreich 
zum laufen gebracht. Nur mit neuen SD-karten gibt es auf einmal 
Probleme. Lesen und schreiben klappt nur einmal. Dann kann man zwar die 
geschrieben machen auf dem PC anschauen jedoch nicht auf der MCU. 
Unterscheid zu alten karten ist der "First Physical Sector". Bei den 
altern Karten ist diese immer 1 bei den neuen 8192. Was hat das zu 
bedeuten und kann das mein Problem sein? Wie kann man das lösen?
Grüße Peter

von Peter (Gast)


Lesenswert?

Hallo,
würde eigentlich eine Lösung für das Schreibprobkem bei vollen Clustern 
gefunden?

von Wolfgang (Gast)


Lesenswert?

Das Problem hatte ich vor Jahren gefunden, aber noch keine Lösung. Ich 
verwende die Software bisher in vielen Projekten völlig ohne Probleme. 
Das war nur möglich, weil ich immer nur Klartext an PC zu übertragen 
hatte, da störte es nicht, ein zusätzliches Leerzeichen vor dem 0d0a 
einzufügen, wenn die übertragene Zeichenzahl für diese Zeile ungerade 
war.

Seit der Findung des Problems liegt ein Link zu meiner E-Mail auf diesem 
Beitrag. In den neuen Einträgen war bisher noch kein Lösung des Problems 
dabei.

von Marius (Gast)



Lesenswert?

Hallo,

Seit einiger Zeit versuche ich es diese Bibliotheken einzubinden und zu 
nutzen.

Im konkreten Fall geht es hier um einen Atmega48 der auf eine SD-Karte 
schreiben soll.

Nun bin ich relativ ungeübt, was Bibliotheken einbinden usw angeht, 
sodass ich wahrscheinlich eine deutlich detailliertere Anleitung 
benötige.

Nun zum Eigentlichen Problem:
Ich arbeite derzeit mit Atmel Studio 7. Beim Erstellen eines neuen 
Projektes, füge ich:

fat.c, fat.h
file.c, file.h
mmc.c, mmc.h
mmc_config.h
uart.c, uart.h
hinzu.
Danach bekomme ich diese Fehlermeldungen angezeigt(Im Anhang 
fehlermeldung_anfang_sd)

Dabei ist mir aufgefallen, dass in der mmc.h kein AT_Mega48 enthalten 
ist, weshalb ich den Mega8(der Pingleich ist) kopiert habe und umbenannt 
habe. (Zu sehen in Aenderung1_mmc.h_)
Danach sind mehr Fehlermeldungen aufgetaucht, die so wie es ausschaut, 
viel mit dem UART zu tun haben. (Zu sehen in 
fehlermeldung_nachAenderung1_sd)

Da stellt sich mir die Frage, warum benötige ich diese uart.h überhaupt?

Nun bin ich mir unsicher, ob ich total auf dem Holzweg bin oder mich 
langsam der Lösung des Problems nähere.

Ich würde mich über Antworten sehr freuen.

Mit freundlichem Gruß
Marius

von Stefan F. (Gast)


Lesenswert?

Im Tutorial gibt es das Setting

> #define MMC_SDHC_SUPPORT  TRUE

Aber in den Quelltexten von Version 0.6.4 
(http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip) 
konnte ich dieses Setting nicht finden.

Ist das Setting überflüssig geworden oder ist der Link zum Download 
nicht mehr aktuell?

von Hau Wech (Gast)


Lesenswert?

Wer Fehlermeldungen des Kompilers bekommt , wie

DECLARATION_AC_POWER_ON_IRGENDWAS undeclared ,

dem fehlen additionelle Header-Files , oder aber hat diese Deklarationen 
in weiteren System-Headern der Compillier-Umgebung schon vorhanden .

Insbesondere wenn die Kompillierumgebung Linux ist , dann werden mit den 
GCC-Bibliotheken und besonders mit dem Linux-Kernel in 
/usr/include/*/linux ständig Deklarationen verändert , ausgelagert in 
andere Header , oder gar vollständig entfernt , oder umbenannt .

Dieser Strang ist schon ca. 10 Jahre alt , und viele Systemheader des 
GNU-Compilers , der C-Bibliotheken und des Linux-Kernels werden sehr 
andersartig aussehen .


Die Kompillierumgebung hat sich sehr verändert , und man müsste sich 
Linux - Betriebssystem e aus alten Zeiten besorgen , um an die Header 
und Fertigkompillierten Bibliotheken zu kommen , die zum Kompillieren 
und Finalem Verlinken bzw. Statischem Einbau nötig sind .

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.