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


von Daniel R. (zerrome)


Lesenswert?

Hallo Friedrich K.,
wie läuft es? Gibt es Fortschritte?

Viele Grüße

Daniel

von Friedrich K. (fiete)


Angehängte Dateien:

Lesenswert?

Hey Daniel,

sehr nett, dass du nachfragst. Aber leider funktionierts noch nicht 
zufriedenstellend. Habe mir mal den Beispielcode geschnappt und 
stückchenweise modifiziert. Die Idee war dann tatsächlich mit ffwrite 
(ohne s) wegzuschreiben und zwar auf knopfdruck == trigger.

Es bleiben dabei zwei Probleme: Ich habe es immernoch nicht geschafft 
ausser beim Beispielcode eine Datei nach dem entnehmen der Karte und 
neuinitialisierung wieder zu öffen und zu beschreiben.
Das zweite Problem ist mehr eine Frage. Ich konnte nicht ganz ausmachen, 
an welcher Stelle des Codes wirklich echt vom RAM auf die Karte 
geschrieben wird. Denn ich würde gern auf Knopfdruck ebenfalls den rest 
der im RAM steht, auf die Karte schreibt, sodass man sie entnehmen kann. 
Wenn ich das recht sehe, dann tut das ffclose nicht allein, sondern 
setzt nur die Flags null.

Am besten poste ich mal wie ich den Beispielcode modifiziert habe. 
Vielleicht ist da was schief gelaufen, was ich nicht seh...

Was du da siehst, ist meine "wunsch-Konfiguration". Sie funktioniert 
nicht. Habe vorher Stückchenweise ausprobiert und sobald ich das ffclose 
auf knopfdruck aufrufe, funktionierts nicht mehr. Die Datei kann nicht 
gelesen werden unter windows (beschädigt) es wird aber eine realistische 
größe angezeigt.
1
    while(1)
2
    {
3
      if(!((PINC&0x01)==0x01))
4
      {
5
        if((PINC&0x01)==0x01)  //<<---- Erst beim Loslassen schreiben.
6
        {
7
             // Datei existiert, also anhaengen !
8
            if(MMC_FILE_EXISTS == ffopen(file_name))
9
            {
10
            
11
             // bewusst kein ffseek, weil ja, nicht geschlossen und Flags noch gesetzt
12
13
             // schreibt "String" Alternativ While Schleife
14
             ffwrite(48);
15
             ffwrite(49);
16
             ffwrite(50);
17
             ffwrite(51);
18
             ffwrite(52);
19
             ffwrite(53);
20
             ffwrite(54);
21
             ffwrite(55);
22
             ffwrite(56);
23
             ffwrite(51);
24
             
25
26
            
27
             // neue Zeile in der Datei
28
             ffwrite(0x0D);
29
             ffwrite(0x0A);
30
31
             /// Bewusst kein ffclose, da erst auf knopfdruck schließen soll
32
             
33
            }
34
          }
35
        
36
      }
37
      if(!((PINC&0x04)==0x04))  // <<--- Kontroll LED
38
      {
39
      ffclose();
40
      PORTD=0xCC;
41
      }
42
    }

Aber Fortschirtte gibts schon. Das ganze soll ein Wasserzähler werden 
der kalt und Warmwsser loggt. Die alte ochsentour mit dem 
selbstdefinirtem RAM hat ja einigermaßen fuktioniert, sodass ich ihn 
schon 24h hab laufen lassen können. Hab mal das Histogramm angehängt ;-)

Gruß, Fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo.

>Ich habe es immernoch nicht geschafft
>ausser beim Beispielcode eine Datei nach
>dem entnehmen der Karte und
>neuinitialisierung wieder zu öffen und zu beschreiben.

Ich vermute mal, dass Du bevor Du die Karte entfernst nicht ffclose 
aufrufst. Mach es doch so, dass Du eine LED einschaltest wenn Du ffopen 
aufrufst und aus, wenn du ffclose aufrufst. So kannst Du genau sehen ob 
die Datei geöffnet oder geschlossen ist.

>Ich konnte nicht ganz ausmachen,
>an welcher Stelle des Codes wirklich
>echt vom RAM auf die Karte...

Bei einem fflushFileData() wird alles was aktuell im Ram ist auf die 
Karte geschrieben. Zudem wird der Dateieintrag geupdatet. Das ist 
prinzipiell ein ffclose(), nur dass die Datei danach nicht neu geöffnet 
werden muss um weiter zu schreiben. Sollte aber so selten wie möglich 
aufgerufen werden, da viele Schreiboperationen auf der Karte gemacht 
werden.

Sind die Taster ordentlich entprellt? Vielleicht geht da einiges 
durcheinander.

So wie ich das sehe, öffnest Du die Datei mehrfach, bevor Du sie 
schließt.
Versuch mal das:
1
   if(MMC_FILE_EXISTS == ffopen(file_name))
2
   {
3
      // Datei existiert, also zum Ende spulen
4
      ffseek(file.length);
5
6
      // hier Status LED an
7
   }
8
9
   while(1)
10
   {
11
      // Pin1 gedrückt?
12
      if(!((PINC&0x01)==0x01))
13
      {
14
         // hier warten bis Taste losgelassen wird!
15
         while( !((PINC&0x01)==0x01) );;
16
17
         // schreibt "String" Alternativ While Schleife
18
         ffwrite(48);
19
         ffwrite(49);
20
         ffwrite(50);
21
         ffwrite(51);
22
         ffwrite(52);
23
         ffwrite(53);
24
         ffwrite(54);
25
         ffwrite(55);
26
         ffwrite(56);
27
         ffwrite(51);
28
29
         // neue Zeile in der Datei
30
         ffwrite(0x0D);
31
         ffwrite(0x0A);        
32
      }             
33
34
      // Pin4 gedrückt?
35
      if(!((PINC&0x04)==0x04))  
36
      {
37
         ffclose();
38
39
         // Status LED hier aus, alles OK. Karte kann entfernt werden!
40
41
         break;   // um aus endlosschleife zu kommen
42
      }
43
44
  }


Ohne den Code so laufen zu lassen, denke ich sollte das gehen.

Hoffe irgendwas hiervon hilft :)

Viele Grüße

Daniel

von Friedrich K. (fiete)


Lesenswert?

Hey Daniel, danke für deine Antwort. Ich werds gleich heute abend mal 
ausprobieren.

Zum Prellen: ich habe mir eigentlich entprellte Taster besorgt. Lese 
gerade, dass man da noch Vorkehrungen treffen muss. Ich bin bisher immer 
davon ausgegangen, das es bei entprellten tastern kein Problem ist... 
Vielleicht hat er bei ffclose deshalb probleme bekommen...

Zu Kontroll LEDs: Ja, hab kontroll LEDs eingefügt, bei denen ich seh, wo 
er grad ist. Ich konnte sogar sehen, dass er auf die Karte geschrieben 
hat, weil er dann läger im ffwrite war und so die LED nen bissel länger 
geleuchtet hatte. In dem code den ich dir schickte, sind die LEDs nur 
noch zum teil drin. Ich schiebe die immer rum im code, um zu gucken, wo 
er grad "hängt".

Zu ffclose: Stört es, wenn ffclose mehrfach aufgerufen wird? Weil die 
Verrenkung dass er erst beim Losassen aus der Schleife steigt, hab ich 
mir bei ffclose gespart.

Zu fflushFileData: Muss man danach noch ffclose aufrufen? Wenn ichs 
recht sehe ja.

Kann es eventuell sein, dass die Karte einen knacks hat?

Ich werde wie gesagt mich heute Abend mal damit auseinander setzen und 
bericht erstatten.

Danke nochmal.

Gruß, Fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo.

>...Verrenkung dass er erst beim
>Losassen aus der Schleife steigt...

Die Verrenkung ist doch nur ein "break;" um aus der Schleife raus zu 
kommen. Ob jetzt bei Taste gedrückt oder losgelassen ist ja nur die 
Abfrage im if...

>Stört es, wenn ffclose mehrfach aufgerufen wird?

Eigentlich nicht, ist aber unnötig. Muss halt so programmiert werden das 
es nicht vor kommt :)

>Zu fflushFileData: Muss man danach
>noch ffclose aufrufen? Wenn ichs
>recht sehe ja.

fflushFileData ist eigentlich dazu gedacht, dass wenn ein Gerät z.B. 
über Tage läuft und Daten loggt, man zwischendurch mal zur Sicherheit 
fflushFileData aufruft. So hat man die Daten bis dahin schonmal 
gesichert, falls der Strom ausfällt oder ähnliches. Dadurch spart man 
sich ein ffclose und ffopen.


Funktioniert die Karte denn unter Windows noch ordentlich? Also 
beschreibbar, lesbar und keine Fehler beim Formatieren? Wenn es da keine 
Probleme gibt, sollte die Karte noch OK sein.



Viele Grüße

Daniel

von Lukas L. (lukas5)


Lesenswert?

Hallo.
Ich bin hier neu im Forum und habe bis jetzt nicht so viel Erfahrung mit 
AVRs. Deswegen bitte sich nicht über meine dummen Fragen ärgern.

Ich werde mein Atmega32L mit 3,3V versorgen und mit 8MHz takten. Meine 
Karte hat 2GB. Ich möchte Fat32 benutzen.

Soll sie zuerst mit dem PC mit FAT32 formatiert werden oder macht das 
dein Programm?
Kanst du mir bitte sagen an welche Pins des Atmega32 ich die SD Karte 
anschliesen muss?
Wo soll ich im Code eine Umstellung von Fat16 auf Fat32 machen?
Mit welcher Funktion wird eine neue Datei erzeugt?
Mit welcher Funktion wird eine Datei beschrieben?

Grüße,
Lukas

von Friedrich K. (fiete)


Lesenswert?

Hey Lukas,

also das mit den SD-Karten ist nicht so ganz ohne. Du solltest schon 
mindestens nen bisschen C mitbringen und das AVR Tutorial wäre auch 
nicht schlecht, einfach, damit du nen bissel weißt, was du tust. Es ist 
jedenfalls im seltensten Fall so, dass man es einschaltet und alles 
funktioniert. Guck dir mal in der Artikelübersicht 
http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten da steht 
schonmal ne Menge drin.

Gruß, fiete

von Lukas L. (lukas5)


Lesenswert?

Hallo.
Man verwendet Belegung wie sie in der "mmc-0.2.H" Datei angegeben ist. 
Habe ich das richtig verstanden? Warum wird denn der SPI-Port für den 
Anschluss verwendet. Das ist doch unpraktisch, jedesmal die Karte 
auszustecken um zu programmieren??
Hast du deine Karte auch an PORTB abgeschlossen?

Grüße,
Lukas

von Friedrich K. (fiete)


Lesenswert?

Der SPI-Port stehllt das Protokoll bereit, das mit der Karte 
kommuniziert. Das ist eine Bus-Kommuikation. Es können also mehrere 
Bauteile angeschlossen werden und nur das, welches aktivirt ist, fühlt 
sich auch angesprochen. Aktivirt wird wenn ichs richtig im kopf hab wenn 
pin 0 auf high gezogen wird...

von Daniel R. (zerrome)


Lesenswert?

Hallo Lukas.

Hier gibt es auch noch mehr Informationen
http://www.mikrocontroller.net/articles/AVR_FAT32

Die neuste Version ist immer unter
http://www.mikrocontroller.net/svnbrowser/avr-fat32
zu bekommen.

Dabei ist auch ein Beispiel Programm wo die Benutzung gezeigt wird.

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Ich versuche gerade die Software mit Keil µVision4 auf einen LPC2148 zu 
portieren. Der Compiler spuckt aber Fehler aus. Da soll wohl noch was 
umgecastet werden?
1
fat.c(120): error:  #852: expression must be a pointer to a complete object type
2
fat.c:                  vsector+=   6;
3
fat.c:                  ^
4
fat.c(123): error:  #852: expression must be a pointer to a complete object type
5
fat.c:                  vsector+=2;
6
fat.c:                  ^
7
fat.c(422): error:  #852: expression must be a pointer to a complete object type
8
fat.c:                          *(unsigned char*)vsector++ = 0x00;
9
fat.c:                                           ^
10
fat.c(431): error:  #852: expression must be a pointer to a complete object type
11
fat.c:                          *(unsigned char*)vsector++ = toupper(name[i]);
12
fat.c:                                           ^
13
fat.c(439): error:  #852: expression must be a pointer to a complete object type
14
fat.c:          vsector++;
15
fat.c:          ^
16
fat.c(478): error:  #852: expression must be a pointer to a complete object type
17
fat.c:                  vsector+=8;
18
fat.c:                  ^
19
fat.c(482): error:  #852: expression must be a pointer to a complete object type
20
fat.c:                  vsector+=6;
21
fat.c:                  ^
22
fat.c(486): error:  #852: expression must be a pointer to a complete object type
23
fat.c:                  vsector+=2;
24
fat.c:                  ^

1
void fat_loadRowOfSector(unsigned short row){
2
3
  #if (MMC_ENDIANNESS_LITTLE==TRUE)
4
    void *vsector;                  // voidpointer, damit man schoen umbiegen kann :)
5
6
    vsector=&fat.sector[row+20];          // row ist byteoffset einer reihe
7
8
    file.firstCluster=*(unsigned short*)vsector;  // high word von first.cluster (20,2)
9
    file.firstCluster=file.firstCluster<<16;
10
    
11
    vsector+=   6;
12
13
    file.firstCluster|=*(unsigned short*)vsector;  // low word von first.cluster (26,2)
14
    vsector+=2;
15
16
    file.length=*(unsigned long int*)vsector;    // 4 byte von file.length (28,4)
17
  #else
18
    unsigned char *psector =& fat.sector[row+31];
19
20
    file.length =  *psector--;    // 31    hoechstes byte
21
    file.length <<= 8;
22
    file.length |=  *psector--;    // 30
23
    file.length <<= 8;
24
    file.length |=  *psector--;    // 29
25
    file.length <<= 8;
26
    file.length |=  *psector;    // 28
27
28
    psector-=7;
29
    file.firstCluster =  *psector--;          // 21  hoechstes byte
30
    file.firstCluster <<= 8;
31
    file.firstCluster = file.firstCluster | *psector;  // 20
32
    file.firstCluster <<= 8;
33
34
    psector+=7;
35
    file.firstCluster = file.firstCluster | *psector--;  // 27
36
    file.firstCluster <<= 8;
37
    file.firstCluster = file.firstCluster | *psector;  // 26
38
  #endif
39
}
1
void fat_makeSfnDataEntry(unsigned char name [],unsigned char attrib,unsigned long int cluster,unsigned long int length){
2
3
  unsigned char i;       // byte zähler in reihe von sektor (32byte eintrag)
4
  void *vsector;         // void zeiger auf sektor, um beliebig casten zu können
5
  unsigned short row;    // reihe in dem sektor
6
7
  fat.bufferDirty = TRUE;   // puffer beschrieben, also neue daten darin(vor lesen muss geschrieben werden)
8
  row = file.row;
9
  row = row<<5;        // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 ... zeile 15=480)
10
  vsector =& fat.sector[row];  // anfangs adresse holen ab der stelle auf sector geschrieben werden soll
11
12
  #if (MMC_TIME_STAMP==TRUE)
13
    unsigned char new=FALSE;
14
    // pruefung ob eintrag neu ist.
15
    if(fat.sector[row]==0xE5||fat.sector[row]==0x00)   new=TRUE;
16
  #endif
17
18
  #if (MMC_TIME_STAMP==FALSE)
19
    // alle felder nullen...
20
    i = 20;
21
    do{
22
      *(unsigned char*)vsector++ = 0x00;
23
    }while( i-- );
24
    vsector =& fat.sector[row];
25
  #endif
26
27
  // namen schreiben (0,10)
28
  i = 0;
29
  do{
30
    #if (MMC_LFN_SUPPORT==TRUE)
31
      *(unsigned char*)vsector++ = toupper(name[i]);
32
    #else
33
      *(unsigned char*)vsector++ = name[i];
34
    #endif
35
  }while( ++i < 11);
36
37
  // attrib schreiben (11,1)
38
  *(unsigned char*)vsector = attrib;
39
  vsector++;
40
41
  #if (MMC_TIME_STAMP==TRUE)
42
    unsigned short time=fat_getTime();
43
    unsigned short date=fat_getDate();
44
45
    // reserviertes byte und milisekunden der erstellung (12,2)
46
    *(unsigned short*)vsector=0x0000;
47
    vsector+=2;
48
49
    if(new==TRUE){
50
      // creation time,date (14,4)
51
      *(unsigned long int*)vsector=date;
52
      *(unsigned long int*)vsector=*(unsigned long int*)vsector<<16;
53
      *(unsigned long int*)vsector|=time;
54
    }
55
    vsector+=4;
56
57
    // last access date (18,2)
58
    *(unsigned short*)vsector=date;
59
    vsector+=2;
60
61
    // low word von cluster (20,2)
62
    *(unsigned short*)vsector=(cluster&0xffff0000)>>16;
63
    vsector+=2;
64
65
    // last write time,date (22,4)
66
    *(unsigned long int*)vsector=date;
67
    *(unsigned long int*)vsector=*(unsigned long int*)vsector<<16;
68
    *(unsigned long int*)vsector|=time;
69
    vsector+=4;
70
71
    // high word von cluster (26,2)
72
    *(unsigned short*)vsector=(cluster&0x0000ffff);
73
    vsector+=2;
74
75
    // laenge (28,4)
76
    *(unsigned long int*)vsector=length;
77
  #else
78
    vsector+=8;
79
80
    // low word  von cluster (20,2)
81
    *(unsigned short*)vsector=(cluster&0xffff0000)>>16;
82
    vsector+=6;
83
84
    // high word von cluster (26,2)
85
    *(unsigned short*)vsector=(cluster&0x0000ffff);
86
    vsector+=2;
87
88
    // laenge (28,4)
89
    *(unsigned long int*)vsector=length;
90
  #endif
91
}

von Daniel R. (zerrome)


Lesenswert?

Hallo,
versuch mal "#define MMC_ENDIANNESS_LITTLE FALSE" in der config.h
Damit fliegen überall die void Pointer raus. Ist aber evtl. nicht so 
schnell dann.

Es gibt da mit mehreren Kompilern Probleme wegen void Pointern. Verstehe 
ich nicht ganz, weil das eigentlich normaler C Standard sein sollte...

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Hi,

ich hab da auch mal wieder ne Frage.
Ich will mit der neuen Version (0.6.1) einen Ordner anlegen. In der 
Config.h ist #define MMC_LFN_SUPPORT            TRUE. So weit, so gut!
Aber wenn ich nun alle:
1
unsigned char datum_verzeichnis[8];    //Beispiel: "33-33-33
2
datum_verzeichnis[0] = datum[0];
3
datum_verzeichnis[1] = datum[1];
4
datum_verzeichnis[2] = '-';        
5
datum_verzeichnis[3] = datum[3];        
6
datum_verzeichnis[4] = datum[4];        
7
datum_verzeichnis[5] = '-';
8
datum_verzeichnis[6] = datum[6];
9
datum_verzeichnis[7] = datum[7];        
10
11
ffmkdir(datum_verzeichnis);
12
ffcd(datum_verzeichnis);
ein Verzeichnis anlegen will, dann geht das nicht. Windoofs will da wohl 
am ende der Eingabe noch ein abschließedendes Zeichen haben. Kann mir 
bitte jemand verraten, welches das ist?
Und mit einem HEX-Editor kann ich leider kein Verzeichnis öffnen... Bei 
normalen Dateien kann man ja "spicken" wie bestimmte Steuerzeichen 
aussehen. Bei Ordner geht das nich...

Danke für alle guten Tipps!
Matze

von Kurt B. (kurt)


Angehängte Dateien:

Lesenswert?

Danke Daniel. Das lesen von Dateien geht jetzt ohne Probleme. Aber beim 
fclose nach dem schreiben in eine Datei bleibt er hängen. Ein Hardware 
Problem schließe ich aus, da das lesen funktioniert. Timing Probleme 
dürften es auch nicht sein da ich den Prozessor bis auf 12MHz 
runtergetaktet habe.

Im Anhang ist das komplette µVison Projekt, lauffähig mit debug 
Ausgaben, und die debug Meldungen. Er bleibt ganz am Schluss zwischen 
Kontrollpunkt D und E hängen, obwohl er vorher mehrmals korrekt bis E 
durchläuft.

Ich höffe es ist einigermaßen verständlich was ich meine. ;-)


Mfg,
Kurt


PS: Ich habe die Software auch auf einem Mega32 mit 18,x MHz getestet, 
da funktionieren lesen und schreiben wunderbar!

von Kurt B. (kurt)


Angehängte Dateien:

Lesenswert?

Das war natürlich die falsche Datei!
@Moderatoren: bitte löschen.

Hier kommt die richtige.

von Matze N. (hupe123)


Lesenswert?

so gehts:
1
unsigned char datum_verzeichnis[9];    //Beispiel: "33-33-33
2
datum_verzeichnis[0] = datum[0];
3
datum_verzeichnis[1] = datum[1];
4
datum_verzeichnis[2] = '-';        
5
datum_verzeichnis[3] = datum[3];        
6
datum_verzeichnis[4] = datum[4];        
7
datum_verzeichnis[5] = '-';
8
datum_verzeichnis[6] = datum[6];
9
datum_verzeichnis[7] = datum[7];
10
datum_verzeichnis[8] = 0x00;        
11
12
ffmkdir(datum_verzeichnis);
13
ffcd(datum_verzeichnis);

Aber da muss man erstmal drauf kommen... ;)

von Kurt B. (kurt)


Lesenswert?

Leider waren doch meine SPI (SSP) Funktionen falsch! Also bitte meine 
beiden letzten Beiträge ignorieren.

ABER: In der fat_loadSector() ist anscheinend ein return FALSE zuviel?

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.
Wunderbar, dass sich hier alles von selber erledigt :)
Hm, das FALSE da ist wirklich überflüssig... da kommt man ja garnicht 
hin.
Wird geändert.

Viele Grüße

Daniel

von max (Gast)


Lesenswert?

Funktioniert der Code auch auf einen ATmega162?
was muss ich dafür im Makefile ändern?

von Daniel R. (zerrome)


Lesenswert?

Hallo max,
Du musst im Makefile bei

# MCU name
MCU = atmega162

eintragen.

Dann noch in der mmc.h die Pins der Hardware SPI Schnittstelle 
eintragen.
1
  #if defined (__AVR_ATmega162__)
2
  #define SPI_MISO        6  //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
3
  #define SPI_MOSI        5  //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
4
  #define SPI_Clock       7  //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
5
  #define MMC_Chip_Select   0  //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
6
  #define SPI_SS          4  //Nicht Benutz muß aber definiert werden
7
  #endif

Viele Grüße

Daniel

von little man (Gast)


Lesenswert?

Hallo,
erstmal: Super Arbeit!

Leider läuft das Schreiben auf die SD-Karte nur sehr langsam.
Ca. 4kB/s! Auf dem Osi sieht man, dass er manchmal 200ms brauch um auf 
die Karte zu schreiben.

Aber die Datei wird fehlerfrei geschrieben.

Hat jemand eine Ahnung wodran das liegen könnte, ich verzweifle dran?
Habe schon verschiedene SD-Karten ausprobiert, Takt geändert,  immer das 
gleiche Problem!

Daten:
Atmega88 @7.3728Mhz @3,3V

von Matze N. (hupe123)


Lesenswert?

das problem hab ich auch manchmal. versuch mal ne andere SD-Karte.
Wenn ich mal ausversehen die SD-Karte im Slot habe, wenn der ISP dran 
is, dann kriegt sie wohl einen "Schaden". In anderen Geräten geht sie 
dann noch, aber am µC nich mehr. Ich weiß auch nicht, woran das liegt. 
Is halt mein "Word-Around"... Nich schön, weil auf dauer teuer, aber was 
will man machen ;)

von Matze N. (hupe123)


Lesenswert?

Hmm... habe mich wohl geirrt! Sorry!
Ich hatte ja das selbe Problem: mals liefs und mal nicht. Ich habe immer 
mit WinAVR compiliert und bin gestern einfach mal spaßeshalber in das 
AVR Studio gewechselt und habe da den selben Code compiliert - jetzt 
geht alles und zwar immer... also, wenn du mit dem WinAVR arbeitest: 
wechseln ;)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
kann mir eigentlich nur vorstellen, dass es mit Kompiler Optionen zu tun 
hat oder etwas in dieser Richtung. Vielleicht ist es aber auch wenn das 
nur bei einer Karte auftritt eine extrem langsame. Habe hier auch eine 
16MB Karte die extrem langsam ist.

Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Naja, ich habe am Versuchsaufbau nichts geändert! Sogar die selbe Karte 
benutzt. Mit dem ARV Studio geht es nun aber flüssig und vor allem 
immer.
Is komisch, ist aber so.

von little man (Gast)


Lesenswert?

Hallo,

danke für die Anregungen.
Ich arbeite nur mit Avr Studio, also daran lag es nicht.

Habe mal ne ganze Menge an Karten ausprobiert und gemessen. Habe 
festgestellt, dass die Noname Karten am Besten funktionieren.

Habe die Benchmark bißchen umgeschrieben. Schreibe 196k-Datein und davon 
100 Stück und messe die einzelnen Zeiten! Folgende Ergebnisse:

ScanDisk SD 2Gb (neu):
3.2s für die 1.Datei
10s für die 100. Datei

SD-Formel1 256Mb (hab ich irgendwo ausgegraben):
2,6s für die 1.Datei
2,4s für die 100. Datei

NONAME SD-micro 2Gb (aus meinem Handy)
3.6s für die 1.Datei
3.4s für die 100. Datei

CN Memory SD 8Gb mit SD_HC Support (neu)
3.2s für die 1.Datei
25s für die 100. Datei

Hab da noch paar Karten getestet. Manche werden halt sehr lahm! Hab 
keine Ahnung wodran das liegt, benutze einfach die Karten die durchweg 
schnell schreiben. Das sind die Karten die sich mit FAT 16k formatieren 
lassen. Keine Ahnung, ob das damit zusammen hängt??? Bin noch Laie auf 
dem Gebiet!

Welche Karten würdet ihr denn empfehlen? Sind MMC Karten schneller?

von little man (Gast)


Lesenswert?

Ich sollte vielleicht noch folgendes erwähnen:

Atmega88 @3.3V @7,3728MHz

von Daniel R. (zerrome)


Lesenswert?

Hallo,
stimmen diese Daten?

>SD-Formel1 256Mb (hab ich irgendwo ausgegraben):
>2,6s für die 1.Datei
>2,4s für die 100. Datei

>NONAME SD-micro 2Gb (aus meinem Handy)
>3.6s für die 1.Datei
>3.4s für die 100. Datei

Die werden schneller bei 100 Dateien?!?
Zeig mal den Benchmark Code !

Ja MMC Karten sind deutlich schneller, keine Ahnung wieso.

Fat16 zu Fat32 macht bei mir keinen so großen Unterschied. Ist im 
einstelligen KB Bereich.
Ob ich Multiblock ein/aus schalte macht deutliche Unterschiede.

Deine maximale SPI Geschwindigkeit ist f_cpu / 2 also 7,3728 MHz / 2 = 
3,6864 MHz. Das ist jetzt nicht so wahnsinnig schnell. Die Karten sind 
für 25 MHz ausgelegt.

Was willst Du denn eigentlich speichern? Muss das so schnell sein?

Viele Grüße

Daniel

von little man (Gast)


Angehängte Dateien:

Lesenswert?

Hey,

hab jetzt noch paar MMC Karten getestet, lassen sich so mit 77kB/s 
beschreiben. Ich glaub ich werde nun nur MMC benutzen! Funktionieren 
alle durchgehend gut.

Daniel R. schrieb:
> Die werden schneller bei 100 Dateien?!?
> Zeig mal den Benchmark Code !

Hab die benchmark angehängt.
Fand ich auch komisch. Dies tritt nur auf, wenn die Karte formatiert und 
relativ alt ist. Sind da schon Daten drauf, schreibt sie durchgehend 
konstant. Kann sein das die ersten Sektoren schon beschädigt sind!?

Hab mir jetzt mal ein größeren Controller bestellt. Wird mir hier 
einbisschen eng auf dem Atmega88. Dann drehe ich auch die Frequenz auf 
16MHz.

Daniel R. schrieb:
> Was willst Du denn eigentlich speichern? Muss das so schnell sein?

Muss Strom und Spannung mit 2.5kS/s abtasten und ablegen. Desto 
schneller ich speichern kann, desto weniger muss ich Puffern.

Bis dann und vielen Dank für den bereitgestellten Code!

von Matze N. (hupe123)


Lesenswert?

Hi,

ich habe eine Frage zu deinem Benchmark.
Kannst du mir mal bitte die Zeite
1
c = c==254 ? 0 : c;
 erklären. Ich kenne weder ein "?" noch ein ":" in einer Zeile. Nur 
interesse halbe (ich lerne immer wieder was dazu ;)

Liebe Grüße,
Matze

von Bad U. (bad_urban)


Lesenswert?

Hallo,

das ist eine verkürzte Schreibweise für eine Abfrage. Wenn C=254 wird c 
der Wert hinter dem Fragezeichenzugewiesen. Wenn nicht der Wert hinter 
dem : Allerdings bin ich der Meinung, dass es am Ende :c++ heissen 
müsste. Ich kenne das Programm nicht, aber das soll wohl eine 
Zählvariable sein. Kann aber auch sein, dass sie woanders im Programm 
verändert wird. Dann macht diese Art der Abfrage allerdings weniger 
Sinn...

Gruß
Bad Urban

von Matze N. (hupe123)


Lesenswert?

Cool! Wieder was gelernt!!!
Ich habe mal in der Quelltext geschaut, das müsste wirklich ":c++;" 
heißen.

Danke aber fürs übersetzen!!
Gruß,
Matze

von Bad U. (bad_urban)


Lesenswert?

Freut mich wenn ich helfen kann. Bin da das erste mal auch mit großen 
Augen davor gesessen :-)

von holger (Gast)


Lesenswert?

>Ich habe mal in der Quelltext geschaut, das müsste wirklich ":c++;"
>heißen.


Nö.

>      ffwrite(c++);
>      c = c==254 ? 0 : c;

Fällt euch was auf?

Das ist eine kryptische Schreibweise für ein if{}else{}
Sowas gehört in kein C Programm.

von Matze N. (hupe123)


Lesenswert?

Ok, das "ffwrite(c++);" hab ich übersehen. Mein Fehler.

Aber warum sollte ein "c = c==254 ? 0 : c;" nicht in ein c-Programm? 
Vorallem die Begründung, daß es kryptisch sei halte ich für arg 
schwammig. Ich denke, ich werde es zu meinem Standart für solche Fälle 
erklären. Warum sollte ich das nicht dürfen?! Ich finds kurz und 
prägnant.

von hm (Gast)


Lesenswert?

so kann der kompiler auf jeden fall besser optimieren als bei einem 
if/else
und es ist ja schon standard c

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@little man (Gast)

Die interessanten Teile hast Du weggelassen :)
Wie sehen folgende defines bei Dir aus?
1
#define TOP_OCR 0xF9
2
#define START_TCNT 0x06
3
#define PRESCALER 0x03

von little man (Gast)


Lesenswert?

Hey,

hab die defines auf mein CPU Takt angepasst!
Ansonsten, wie gesagt, kaum was an deiner Benchmark verändert.

#define TOP_OCR 0x7A
#define START_TCNT 0x06
#define PRESCALER 0x03

Bis dann!

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also mein Timer Rechner sagt mit einer Frequenz von 7.3728 MHZ müssen 
die Werte bei einem Überlauf von 1 ms:
1
#define TOP_OCR 0x72
2
#define START_TCNT 0x8D
3
#define PRESCALER 0x03

sein. Der Fehler ist dann 0.174%

Ich benutze dazu diesen Rechner:

http://www.b9.com/elect/avr/kavrcalc/index.html

welcher auch unter Linux mit Wine läuft.

Zur Not könnte man auch die Tick Zeit mal mit einem sleep vergleichen...

Viele Grüße

Daniel

von little man (Gast)


Lesenswert?

Hey,

super Rechner. Wusste garnicht, dass es sowas gibt. Hab es mir immer 
selbst alles ausgerechnet.

Bis dann!

von little man (Gast)


Lesenswert?

Hey,

hab den Test noch mal mit den genaueren Werten durchgeführt. Fehlmessung 
von ca. 1%. Also, danke noch mal für den Tipp!

Noch ne Frage!
Welche Karten (SD und MMC) akzeptieren MMC_MULTI_BLOCK? Hab bisher noch 
keine gefunden.

Bis dann!

von Daniel R. (zerrome)


Lesenswert?

Hm, seltsam.
Ich hab nur ein paar total alte Karten bei denen das nicht geht.
Neuere SD sollten das auf jeden Fall haben.

Viele Grüße

Daniel

von Peter (Gast)


Angehängte Dateien:

Lesenswert?

Hi,
ich benutze auch die Lib hier, hab aber ein Problem. Ich schreib alle 5 
Minuten auf die Karte alle 5 Sekunden 2 Werte. Nach ungefaehr 2 Stunden 
bricht das schreiben ab, weil entweder der Schreibvorgang hängenbleibt 
oder die er beim öffnen der Datei hängen bleibt. Vielleicht einer eine 
Idee, woran das liegen könnte? Die Schaltung wird über einen Lf33cf mit 
3,3 v versorgt, also auch stabil. Hab mal die main angehangen, ist im 
Grunde nur eine Erweiterung des beigefügten Beispiels im svn. Ach so µC 
ist ein Atmeg644p.

Grüße Peter

von Matze N. (hupe123)


Lesenswert?

*abo

von Daniel R. (zerrome)


Lesenswert?

Hallo,
sehe ich das richtig, dass der Atmeg644p 4k Ram hat? Weil eigentlich 
würde ich auf Ram Probleme tippen.
Läuft das Programm ohne schreiben auf die SD Karte normal durch?
Versuch mal die Datei einfach geöffnet zu lassen.
Du legst nicht alle 5 Minuten eine neue Datei an oder?

Hab grad nicht die Zeit mir das Programm im Detail anzuschauen, mach ich 
aber am Wochenende.

Viele Grüße

Daniel

von Peter (Gast)


Lesenswert?

Hi,
danke für die Antwort, jo der Atmega644p hat 4kb Ram, nur öffnen geht 
über viele Stunden, hab es dann irgendwann einfach abgebrochen. Nein ich 
öffne nur die existierende Datei immer wieder, schreib rein und 
schliesse sie.
Ich teste jetzt erstmal ohne die Datei immer zu öffnen, ob das schreiben 
dann über einen längeren Zeitraum funktioniert.

Mfg
Peter

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also so nochmal auf die schnelle...
Bist Du Dir sicher, dass nur wirkliche Strings mit ffwrites geschrieben 
werden? Wenn da irgendwo das '\0' fehlt geht das schief.

Grüße

Daniel

von Tobias M. (obi)


Lesenswert?

Hi!

Ich möchte mir einen Datenlogger mit SD bauen.
Gibt es da irgendwelche Beschränkungen?
Also wie groß darf die SD- Karte maximal sein und was für einen µC 
braucht man mindestens?

Danke und Gruß
Tobias

von holger (Gast)


Lesenswert?

>Ich möchte mir einen Datenlogger mit SD bauen.

Wofür?

>Gibt es da irgendwelche Beschränkungen?

Ja. 4GB pro Datei maximal bei FAT32.
Schreibzeiten beschissen wegen sporadischen Aussetzern von
bis zu 500ms. Es sei denn du hast einen Arsch voll RAM.

>Also wie groß darf die SD- Karte maximal sein und was für einen µC
>braucht man mindestens?

FAT32 kann ein paar Terabyte.
ATmega mit mindestens 2kB Ram.

von obi (Gast)


Lesenswert?

>>Ich möchte mir einen Datenlogger mit SD bauen.
>
> Wofür?

Für eine Wetterstation

>>Gibt es da irgendwelche Beschränkungen?
>
> Ja. 4GB pro Datei maximal bei FAT32.
> Schreibzeiten beschissen wegen sporadischen Aussetzern von
> bis zu 500ms. Es sei denn du hast einen Arsch voll RAM.
>
>>Also wie groß darf die SD- Karte maximal sein und was für einen µC
>>braucht man mindestens?
>
> FAT32 kann ein paar Terabyte.
> ATmega mit mindestens 2kB Ram.

Also wenn ich eine 4GB SD- Karte nehme und nen atmega644 mit 4k sram 
müsste das kein problem sein oder?

von Peter (Gast)


Lesenswert?

Hi, ich nochmal,
also die Strings die mittels ffwrite geschrieben werden, sind alle mit 
\0 terminiert. Hab es jetzt ohne ständiges öffnen uns schliessen 
probiert. Brachte auch keinen Erfolg. Brauch nach circa 2h bei einem 
ffwrites ab.
Vielleicht haste noch eine Idee woran es liegen koennte. Danke schon 
mal.

Peter

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@obi (Gast)
Nee das sollte kein Problem sein.

@Peter (Gast)
Hm, Du versuchst das nicht Batterie betrieben oder?
Beim schreiben zieht so eine Karte mal gut strom...

Über welche Datenmenge sprechen wir denn da bei den 2 Stunden?

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@Peter (Gast)
Bist Du da noch dran an dem Problem?

Nur der Vollständigkeit halber, wenn man viel Strom aus einer schwächer 
werdenden Batterie zieht, bricht die Spannung ein -> Kontroller Reset...

von Peter (Gast)


Lesenswert?

Hi,
im Grunde schon, habs erstmal nen bisschen weiter nach hinten geschoben, 
genug andere Arbeit. Ne ich betreib es mit einem Netzteil, und nen 
lf33cv, der sollte eigentlich genug Strom liefern. Ich glaub 
mittlerweile auch nicht mehr das es an der Lib liegt, sondern eher an 
der Karte, SanDisk Extreme III, hab nur leider keine andere zur Hand.

Gruesse
Peter

von Paul P. (pommespaule)


Angehängte Dateien:

Lesenswert?

Guten Abend,
erstmal: Absolut genial was hier für eine Lib entstanden ist. Da muss 
man schon mal den Hut ziehen !

Ich hab allerdings noch ein Problem mit dem Schreiben. Lesen 
funktioniert einwandfrei.
Wenn ich ein einzelnes Byte schreiben will (die Datei ist vorhanden und 
in ihr war vorher auch nur ein Byte):
1
if(TRUE == fat_loadFatData()){
2
  unsigned char file_name_offset[]="OFFS    KOM";
3
  if(MMC_FILE_EXISTS == ffopen(file_name_offset)){
4
    ffwrite(0x99);
5
    ffwrite(0x99);
6
    ffclose();
7
    }
8
  }
muss ich, wie ihr seht, den Befehl dazu zwei Mal geben. Wenn das zweite 
ffwrite auskommentiert ist, tut sich in der Datei gar nichts.

Das Anhängen an die Datei per vorgeschobenem
1
 ffseek(file.length)
funktioniert weder mit einem noch mit zwei Befehlen.

Meine Config habe ich mal angehängt.
Bin über jeden Hinweis dankbar.
Grüße Paul

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

es wäre gut, wenn du mal einige Konstellationen von Defines in config.h 
ausprobierst! Ich wollte gerade deine Lib mit "readonly" übersetzen und 
bekam einige Fehler um die Ohren gehauen. Z.B., wenn man

#define MMC_WRITE FALSE

setzt, kommt:

/home/x/work/x/sd_card/file.c:626: undefined reference to 
`fat_setClusterChain'
/home/x/work/x/sd_card/file.c:627: undefined reference to 
`fat_getFreeClustersInRow'

Grüße & Danke Uwe

von Uwe B. (boerge) Benutzerseite


Lesenswert?

...Zusatz:

wenn man

#define MMC_LFN_SUPPORT  FALSE

setzt, stürzt das Beispielprogramm beim Schreiben der Testdatei 
reproduzierbar ab...

Du solltest wirklich mal dringenst ein Codereview machen!

Grüße Uwe

von Daniel R. (zerrome)


Lesenswert?

Hallo,
bin gerade etwas eng mit der Zeit die ich fürs Hobby zur Verfügung habe.

Das mit dem "readonly" Fehler ist reingekommen, weil ich da die defines 
umgebaut hatte.

#define MMC_LFN_SUPPORT  FALSE
Das schau ich mir morgen oder die Tage mal an. Glaub ich so nicht 
richtig. Läuft bei mir nämlich in anderen Projekten problemlos.

Nur bei schnellen Prozessoren kann es Probleme mit den low level mmc 
Funktionen geben hab ich bemerkt. Aber das sind dann auch keine AVR 
mehr...

Grüße

Daniel

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

meine Testumgebung ist ein Mega168 mit 16MHz getaktet, also eigentlich 
deine Default-Konfiguration...

Daniel R. schrieb:
> #define MMC_LFN_SUPPORT  FALSE
> Das schau ich mir morgen oder die Tage mal an. Glaub ich so nicht
> richtig. Läuft bei mir nämlich in anderen Projekten problemlos.
>
Das Fehlerbild sieht wie folgt aus: es kommen genau zwei Zeilen des 
Dateiinhaltes, auch wenn mehr drin steht.

Grüße Uwe

PS.: für mich wäre es wichtig, wenn die "readonly"-Geschichte 
funktioniert. Ich könnte auch selbst am Code rummachen, aber habe keine 
Berechtigung, das Zeugs wieder ins SVN zurück zu laden... Deshalb würde 
ich es gerne dir überlassen!

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

ein weiterer Fehler:

file.c --> ffls() --> lsRowsOfClust()

Ein Dateiname ist mindestens 11 Zeichen lang. Du deklarierst temp als 
Array mit 11 Byte und schreibst an die 11.Stelle eine \0, als 
Stringende. Damit geht das letzte Zeichen des Dateinamen verloren...

Grüße Uwe

PS.: sorry, dass ich so penetrant bin. Ich wollte eigentlich deine Lib 
zum Einlesen von Basic-Programmen 
(http://www.mikrocontroller.net/articles/AVR_BASIC) von einer SD-Karte 
benutzen, stolpere aber derzeit leider über die Fehler in der Lib.

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

...siehe 
Beitrag "Re: Basic-Interpreter auf einem AVR"

Grüße Uwe

PS.: eine Funktion ffeof() wäre auch ganz nett...

PPS.: aber auch Lob für deine Lib, ich bin trotz einige Ungereimtheiten 
relativ schnell zum Ziel gekommen!

von Sven S. (schwerminator)


Lesenswert?

Tach auch.

Zuerst einmal: Eine super Bibliothek, die auf Anhieb funktioniert hat. 
Top!

Allerdings bin ich nun auf ein Problem gestoßen: Wenn ich eine Datei 
(zum Lesen) öffne und sie von Anfang bis Ende mit ffread() auslese, ist 
es mir danach nicht mehr möglich eine neue Datei zu öffnen. Egal ob ich 
die datei schließe oder nicht. Waron könnte das liegen?

Gruß Sven

von Daniel R. (zerrome)


Lesenswert?

Hallo,
da müsstest Du mal den Code zeigen. Kann ich so nicht viel zu sagen.



Grüße

Daniel

von Sven S. (schwerminator)


Lesenswert?

Hier kommt er:
1
unsigned char file_name[6]=" .mp3";
2
  unsigned char file_handle;
3
  for(uint8_t file_no=0; file_no<10; file_no++){
4
    file_name[0] = file_no + '0';
5
  
6
    printf("loop #%u, trying to open %s\n", file_no, file_name);
7
  
8
    file_handle = ffopen(file_name);
9
    if(MMC_FILE_EXISTS != file_handle)
10
      printf("Error opening file: %s (%u)\n", file_name, file_handle);
11
    else{
12
      printf("%s opened. Size: %lu Bytes\n", file_name, file.length);
13
14
      for(uint32_t b=0; b<file.length/512+1; b++) {
15
        // Regler per UART stellen
16
        input_1 = uart_getc();
17
        input_2 = uart_getc();
18
        if ( !(input_1 & UART_NO_DATA)  && !(input_2 & UART_NO_DATA) ){
19
          switch(input_1){
20
            case 1: sta015_set_atten(input_2); break;
21
            case 2: sta015_set_bass((int8_t)input_2); break;
22
            case 3: sta015_set_treble((int8_t)input_2); break;
23
          }      
24
        }
25
      
26
        // alle 128kB nenn bissel Info lesen
27
        if((b & (0x000000FF)) == 0xFF){
28
          printf("%u Kbit/s ", sta015_read_reg(STA015_REG_AVERAGE_BITRATE)<<1);
29
          printf("Head: 0x%02X%02X%02X ", sta015_read_reg(STA015_REG_HEAD_H), sta015_read_reg(STA015_REG_HEAD_M), sta015_read_reg(STA015_REG_HEAD_L));
30
          printf("Error: 0x%02X ", sta015_read_reg(STA015_REG_ERROR_CODE)&0x3F);
31
          //printf("Ancillary Data bits: 0x%02X%02X ", sta015_read_reg(STA015_REG_ANCCOUNT_H), sta015_read_reg(STA015_REG_ANCCOUNT_L));
32
          //printf("Ancillary Data 1: 0x%02X ", sta015_read_reg(STA015_REG_ANC_DATA_1));
33
          uart_putc('\n');
34
        }
35
    
36
        // Noch zu lesende Bytes ermitteln
37
        int16_t max = 512;
38
        if(b==file.length/512)
39
          max = file.length%512;
40
        
41
        // 512 Bytes von der SD-Karte lesen
42
        SPCR &= ~(1<<CPHA);
43
        for(uint16_t byte=0; byte<max; byte++)
44
          buffer[byte] = ffread();
45
        SPCR |= (1<<CPHA);
46
    
47
    
48
        // BIT_EN auf High
49
        SPI_CS_STA_PORT |= (1<<SPI_CS_STA);
50
    
51
        int16_t i = 0;
52
        // Block an den Decoder senden
53
        while(i < max){
54
          // Auf Data Request warten
55
          while(!(STA015_DATAREQ_PIN & (1<<STA015_DATAREQ)));
56
      
57
          // So lange wie Data Request an ist, Daten senden
58
          while((STA015_DATAREQ_PIN & (1<<STA015_DATAREQ)) && i < max){
59
            // Zeichen an den Decoder senden
60
            SPDR = buffer[i++]; num_bytes++;
61
            // auf SPI Übertragung warten
62
            while(!(SPSR & (1<<SPIF)));
63
          }
64
        }
65
    
66
        // BIT_EN auf LOW
67
        SPI_CS_STA_PORT &= ~(1<<SPI_CS_STA);
68
      }
69
    
70
      ffclose();
71
      printf("Track over\n");
72
    }
73
  }
74
  printf("%lu Bytes gelesen/uebertragen\n", num_bytes);
75
  printf("Fertig!\n");

von Daniel R. (zerrome)


Lesenswert?

Hallo,
wie äußert sich das denn. Bleibt er beim öffnen hängen oder wie?
Versuch mal testweise die Karte vor dem erneuten öffnen neu zu 
initialisieren. Wie sieht die config.h aus und die Initialisierung der 
FAT/Karte?

Viele Grüße

Daniel

von Sven S. (schwerminator)


Lesenswert?

Moin Daniel. Wenn ich die SD-Karte und die FAT neu initialisiere, 
funktionierts. Er hatte zuvor gemeldet, die Datei würde nicht 
existieren.

An der Initialisierung der SD habe ich nichts geschraubt und so von dir 
übernommen. Hier meine config.h:
1
  //#####################################################################################
2
  // BOOL DEFINITIONEN
3
4
  #define TRUE   1
5
  #define FALSE   0
6
7
  //#####################################################################################
8
  // FLAGS
9
10
  // flags fuer ffopen (sind die rueckgabewerte von ffopen, auf diese wird geprueft..)
11
  #define MMC_FILE_NEW       0  // datei existierte nicht, wurde gerade angelegt !
12
  #define MMC_FILE_EXISTS     1  // datei existiert, es kann gelesen werden !
13
  #define MMC_FILE_NOT_EXISTS     2  // datei existiert nicht, wird nur bei read-only zurueckgegeben, wenn die datei nicht gefunden wurde !
14
15
16
  //#####################################################################################
17
  // WICHTIGE SCHALTER
18
19
  // schalter die den funktionsumfang aendern bzw, den funktionsumfang einiger funktionen :)
20
  #define MMC_WRITE           FALSE  // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
21
  #define MMC_OVER_WRITE       FALSE  // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien überschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
22
  #define MMC_MULTI_BLOCK     FALSE  // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber möglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
23
  #define MMC_SDHC_SUPPORT    FALSE  // TRUE, dann mit sdhc unterstuetzung, wenn FALSE, dann nur mmc/sd karten. siehe : http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29
24
  #define MMC_ENDIANNESS_LITTLE    TRUE  // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
25
  #define MMC_LFN_SUPPORT      TRUE  // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
26
  #define MMC_RM_FILES_ONLY    TRUE  // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
27
28
  // schalter die explizit funktionen mit kompilieren oder nicht!
29
  #define MMC_TIME_STAMP       FALSE   // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
30
  #define MMC_RM               FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
31
  #define MMC_SEEK            TRUE  // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
32
  #define MMC_MKDIR            FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
33
  #define MMC_GET_FREE_BYTES  TRUE  // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
34
  #define MMC_LS              TRUE  // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
35
  #define MMC_CD              TRUE  // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
36
  #define MMC_FILE_EXSISTS    TRUE  // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
37
  #define MMC_WRITE_STRING    TRUE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.
38
39
  // vorsicht, da die variable die die sektoren zählt ein short ist (MMC_MAX_CLUSTERS_IN_ROW*fat.secPerClust) !!
40
  #define MMC_MAX_CLUSTERS_IN_ROW 256   // gibt an wie viele cluster am stück ohne fat-lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
41
42
  // wenn "#define INLINE inline" dann werden die statischen funktionen inline kompiliert. macht code groeßer, aber auch schneller!
43
  //#define INLINE inline
44
  #define INLINE
45
46
47
  //#####################################################################################
48
  // SPI EINSTELLUNGEN
49
50
  // wenn MAX_SPEED FALSE dann wird die SPI bus geschwindigkeit nicht hoch gesetzt. ist zum testen von hardware die nicht richtig läuft
51
  #define MMC_MAX_SPEED     TRUE
52
  #define MMC_STATUS_INFO   FALSE
53
54
  // software spi? wenn TRUE muessen in der mmc.h noch die pins eingestellt werden über die die spi kommunikation laufen soll
55
  // es werden nur pins an einem port unterstuetzt !
56
  #define MMC_SOFT_SPI   FALSE

Schönen Gruß!

von docean (Gast)


Angehängte Dateien:

Lesenswert?

Paul P. schrieb:
> Das Anhängen an die Datei per vorgeschobenem ffseek(file.length) funktioniert 
weder mit einem noch mit zwei Befehlen.

dito bei mir!!!

von docean (Gast)


Lesenswert?

Version 0.5.9 tut!

von Sven S. (schwerminator)


Lesenswert?

Hast du eine Idee, woran mein Problem liegen könnte, Daniel?


Gruß Sven

von Daniel R. (zerrome)


Lesenswert?

Hallo.

Leider habe ich momentan keine Zeit wegen dem blöden Weihnachten.
Werde aber kommende Woche dazu kommen mir das alles anzuschauen und die 
Probleme zu beheben.

Viele Grüße

Daniel

von Paul P. (pommespaule)


Lesenswert?

docean schrieb:
> Version 0.5.9 tut!

Interessant, ich habe aber in der zwischenzeit schon einen Workaround 
gefunden. Mit der Funktion ffwrites() läuft es weil fat.bufferDirty = 
TRUE gesetzt wird. Als habe ich mir eine kleine Funktion hingepfuscht 
die das auch nach dem normalen ffwrite() erledigt. Aber mir schwant es 
schon, so elegant ist das nicht ;)
Vielleicht hilft es ja bei der Fehlersuche. Schönen Feiertag noch

von Kurt B. (kurt)


Angehängte Dateien:

Lesenswert?

Hallo Daniel,
mir ist etwas merkwürdiges aufgefallen:

Ich schreibe zuerst 10kB in die Datei. Dann schließe ich sie, öffne sie 
erneut und hänge nochmal 10kB hintendran.

Win XP zeigt dann auch den richtigen Inhalt mit 20kB an. Wenn ich chkdsk 
laufen lasse werden aber Fehler korrigiert und die Datei hat danach 
24kB!

Mega32 @ 8MHz, 5V

Guten Rutsch!

Mfg,
Kurt

von Michael R. (Gast)


Lesenswert?

Hallo Daniel,
zunächst vielen Dank für die tolle Arbeit.
Ich habe eine ganzen Tag gebraucht, um meine alten 16MB-SD-Karten zum 
Laufen zu bringen.
Problem war offensichtlich, dass Windows 16MB-Karten nur mit FAT12 
formatiert und diese FAT12 dann beim Schreiben durch den AVR zerstört 
wird.

Wenn man in der Console dagegen "format x: /a:2048" verwendet, wird auch 
die 16MB-Karte in FAT16 formatiert und nun funktioniert alles. Ein 
Hinweis darauf in der Doku wäre nicht schlecht.
Oder vielleicht beim Initialisieren prüfen, ob da auf der Karte 
überhaupt eine nutzbare FAT16 oder FAT32 drauf ist, bevor man da was 
kaputtschreibt.

Eine andere Frage:
Vermutlich gibt es keine Möglichkeit, die 512Bytes RAM für den 
Sektorbuffer irgendwie zu reduzieren?
Mein ATMEGA16 ist da zusammen mit anderen Programmteilen schon extrem 
voll und ich hab da ein bissel Angst vor einem Stack Overflow, bei dem 
ich dann ewig den Bug suche.

Michael

von Barny (Gast)


Lesenswert?

Michael R. schrieb:
> Vermutlich gibt es keine Möglichkeit, die 512Bytes RAM für den
> Sektorbuffer irgendwie zu reduzieren?
Bei Flash-Speichern müssen immer 512Byte auf einmal geschrieben werden.
Wenn man alles auf einen Rutsch schreiben will, braucht man eben diesen 
Speicher.
Du hast jetzt 2 Möglichkeiten.
Entweder du optimierst den Speicherverbrauch, oder du steigst auf einen 
ATmega32 um.

von Michael R. (Gast)


Lesenswert?

Hallo Daniel,
Ich habe hier auch noch ein seltsames Problem bezüglich Anhängen.
Wenn der AVR frisch startet und an eine bestehende Datei anhängen soll, 
dann geht das schief. file.length gibt bei jedem neuen Öffnungsversuch 
immer wieder den gleichen Wert zurück, obwohl ich zwischendurch bei 
geöffneter Datei mit ffwrites was angehängt habe.
Also folgende Reihenfolge:
-Init-CARD/FAT
-ffopen
-ffseek(file.length) (falls MMC_FILE_EXISTS zurückkommt)
-ffwrites
-ffclose
-Init-CARD/FAT (Ich mach das jedes Mal, zur Sicherheit)
-ffopen
-ffseek(file.length)
-ffclose

Beim zweiten ffseek wird genau das gleich zurückgeliefert, wie beim 
ersten ffseek. Die Datei wird einfach nicht größer

Wenn die Datei dagegen frisch angelegt wird, scheint das Verlängern 
beliebig häufig zu klappen, bis ich den AVR neu starte, dann geht es 
wieder nicht.
Also eine bereits vor AVR-Boot bestehende Datei wird nicht mehr 
verlängert, eine gerade selbst angelegte Datei lässt sich immer 
verlängern.

Die 16MB-Karte Karte ist so formatiert(chkdsk-Ausgabe):
  14,1 MB Speicherplatz auf dem Datenträger insgesamt.
  14,1 MB sind verfügbar.

    2.048 Bytes in jeder Zuordnungseinheit
    7.241 Zuordnungseinheiten auf dem Datenträger verfügbar

       16 Bits in jedem FAT-Datensatz.

Irgendwie sieht das so aus, als wird irgendwas nicht richtig 
initialisiert.

  Michael

von Michael R. (Gast)


Lesenswert?

Zu dem Anhängen-Problem:
Ich habe mal ein bisschen weiter gewühlt:
Beim Anhängen werden die Daten richtig auf die Karte geschrieben und 
sind mit einem Hex-Editor auffindbar. Ändert man mit dem Hex-Editor die 
Dateigröße, dann werden die geschriebenen Daten auch für das normale 
Windows Notepad sichtbar.
Beim Schließen der Datei wird scheinbar der FAT-Eintrag nicht richtig 
aktualisiert. Mindestens die Dateigröße wird falsch geschrieben.
Ich habe zwar die Funktionsaufrufe beim flush bis runter zum

mmc_write_sector( fat.currentSectorNr,fat.sector );

nachvollzogen, konnte aber nicht rausfinden, warum die Dateigröße nicht 
oder nicht richtig geschrieben wird. (Habe keinen Debugger, ist sehr 
mühsam).

Michael

von Michael R. (Gast)


Lesenswert?

Soo,
noch ein Stück weiter:

Wenn der AVR die Datei in der aktuellen Sitzung nicht selbst erstellt 
hat,
dann enthält "fat.currentSectorNr" beim Aufruf von "fat_loadSector "in 
der "fflushFileData" immer 0.

fflushFileData:
1
// dafuer sorgen, dass der sektor mit dem geaenderten dateieintrag geschrieben wird, beim neuladen. datensektor der datei neuladen, falls noch weitere bytes geschrieben werden.
2
  fat.bufferDirty = TRUE;
3
  fat_loadSector( save_currentSectorNr );
Das führt dazu, dass "fat_loadSector" versucht, die aktuellen Daten nach 
Sektor 0 zu speichern:
1
  mmc_write_sector( fat.currentSectorNr,fat.sector );  // schreiben von sektor puffer

Glücklicherweise geht das wohl irgendwie schief und dem Bootsektor 
passiert dadurch offenbar nichts.
Warum "fat.currentSectorNr" nicht die Sektornummer des FAT-Eintrags hat, 
kann ich aber nicht mehr nachvollziehen, das wird mir dann zu 
unübersichtlich.

Michael

von Buzzwang (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

bei meiner SanDisk SD 2GB 2 tut es leider nicht.

Genaueres:
Bei meiner alten Karte(SanDisk Extreme III) hat es noch getan. Leider 
ist diese abgeraucht. Ich habe mir dann die oben gesagte gekauft. Init 
läuft durch. Jedoch beim Lesen des 1. Sector gibt es dann einen Zonk.
Unter Windows tut die Karte (FAT32).Im Anhang ist ein Log.
Ich werde mal sehe ob ich noch was rausfinde. Leider habe ich keine 2 
Karte zum gegentesten.

von Gerd G. (elektrikser)


Lesenswert?

Teste gerade die Lib mit verschiedenen Karten.
Bis jetzt funktionieren:
- Sandisk Sd-Card 2 GB
- Kingston SD-Card 256 MB
- Hama SD-Card 256 MB
- Sandisk Mikro-SD 2GB
- Sandisk Mobile Ultra Micro-SDHC 4GB

Mit Verzeichnisse anlegen habe ich noch nichts gemacht. Mir ging es erst 
einmal um das Speichern und Lesen von Daten.

Gruß Gerd

von Buzzwang (Gast)


Lesenswert?

habe gefunden woran es liegt. Ist ein Problem in "mmc_read_sector"

Warte auf 0xFE tut nicht.

Wenn man es ändert auf z.B.
1
   if( 0 != mmc_write_command(cmd))  
2
   {
3
      return FALSE;
4
   }
5
6
   a = 0;
7
   do
8
   {
9
    //Wartet auf Start Byte von der MMC/SD-Karte (0xFE/Start Byte)
10
    a++;
11
    if (a == 255) return FALSE;
12
   }
13
   while (mmc_read_byte() != 0xFE);

dann tut es.

von ka-long (Gast)


Lesenswert?

Moin,

Meine MMC/SD Ansteuerung verhält sich sehr komisch...

Mit einem AtMega16/8MHz hat es mit einer 4GB/SDHC plötzlich funktioniert 
(ein Datenloggen über zwei Stunden ohne Probleme), nachdem ich den LFS 
eingeschaltet hatte...

Wegen zu wenig Speicher hab ich den ATMega16 gegen den pinkompatiblen 
Atmega32 getauscht. Leider habe ich zwischenduch den Code mal etwas (was 
auch immer) modifiziert...

Nach drei Abenden werd ich wohl jetzt frustriert aufgeben:

* mmc_init und load_fat funktionieren

Öffne ich ne Datei in meinem Code mit ffopen ohne was anderes zu tun, 
zeigt mein PC die Datei mit 0 Byte an, gut so.

Öffne ich die Datei und schließe sie direkt wieder mit ffclose, dann 
gibt es keine Datei, aber der PC kann die Karte noch lesen.

Öffne ich die Datei und schreibe ich etwas mit ffwrites wird die FAT 
zerschossen. Egal ob mit oder ohne ffclose.

SPI wird nicht hochgesetzt, ich versorge die Karte mit 3.3V aus einem 
Labornetzteil, der ATMega arbeitet allerdings auf 5V mit 
Spannungsteilern.

Ich hab mit nem Scope die Signale nachgemessen, alle da und für die 
Geschwindigkeit ausreichende Signalintegrität.

Eine andere Karte 2GB/SD läuft gar nicht.

Gruß ka-long

von Michael R. (Gast)


Lesenswert?

Hallo,
ka-long schrieb:
> Ich hab mit nem Scope die Signale nachgemessen, alle da und für die
> Geschwindigkeit ausreichende Signalintegrität.

insbesondere die Clock-Flanken bei SPI sind extrem kritisch. Wenn man 
keinen integrierten Pegelwandler verwenden möchte, kann man auch einen 
kapazitiven Spannungsteiler parallel zum normalen Spannungsteiler 
schalten. Folgende Kombinationen sollten funktionieren:

Oberer Kondensator | unterer Kondensator
22p                | 12p
27p                | 15p
33p                | 18p
39p                | 22p
47p                | 27p
56p                | 33p

Wenn ein Tastkopf dranhängt stimmt das Verhältnis wegen der 
Tastkopfkapazität aber nicht mehr. Man sieht also nicht mehr das 
gleiche, wie die Karte ohne Tastkopf sieht. Man muss sich auf die 
Mathematik verlassen.

Michael

von ka-long (Gast)


Lesenswert?

Hallo Michael,

Sind die Anstiegs- und Fallzeiten denn irgendwo definiert ?

Ich werd mal auf mmc-lib Sektor-Ebene Daten lesen und schreiben und 
schauen, ob es da zu Fehlern kommt oder obs in einer der höheren 
Schichten passiert.
So kann ich vielleicht die HW als Ursache ausschließen...


Gruß ka-long

von Michael R. (Gast)


Lesenswert?

ka-long schrieb:
> Sind die Anstiegs- und Fallzeiten denn irgendwo definiert ?

Wenn Du eine matschige CLK-Flanke hast und da noch Rauschen oder 
sonstige Spikes drauf sind, kann es passieren, dass der Empfänger 2 
Flanken kurz nacheinander sieht und dann auch 2 Bits einliest, obwohl 
nur eine Flanke gesendet wurde. In wie weit Doppelflanken unterdrückt 
werden, steht vielleicht im Datenblatt der Karte. Wenn die Karte aber 
z.B. 50MHz SPI unterstützt, dann muss sie Flanken im Abstand 10ns 
erkennen können. Wenn Deine Anstiegszeit aber z.B.100ns ist, dann hält 
sich der Pegel doch einige Zeit im kritischen Bereich auf und kann eine 
Doppelflanke auslösen, wenn Rauschen/Spikes überlagert ist.
Vernünftig entwickelte Clk-Eingänge haben Schmitt-Trigger-Eingänge und 
intelligente digitale Filter drin, die das Problem entschärfen. Aber 
gerade das ist wohl selten spezifiziert.

Die Flankensteilheit der Datenleitungen ist dagegen weniger kritisch, 
der Pegel muss nur zum Zeitpunkt der jeweiligen CLK-Flanke eindeutig 
high oder low sein.

Michael

von Andi S. (laserandi)


Lesenswert?

Hallo,
erstmal Danke für die gute Arbeit. Ich teste seit ein paar Tagen die 
Version 0.6.1 mit einem mega644. Leider läuft die main_simple.c nur dann 
durch, wenn ich den µC resete.
Schaltet man VCC aus und wieder ein bleibt das Programm in der 
fat_loadFatData(); hängen und zwar beim ersten Aufruf von 
loop_until_bit_is_set(SPSR,SPIF);" in der mmc_write_byte Funktion 
(mmc.c).
Was ich schon getestet habe:
- Verzögerung mit  _delay_ms --> ohne Erfolg
- Verschiedene 1 GB sd-Karten --> ohne Erfolg
- Brummspannung auf VCC < 20 mV (Die ganze Schaltung inkl. µC läuft mit 
3,3 V)
Ich glaube nicht, dass es ein Hardwareproblem ist.
Komisch ist, dass vor "fat_loadFatData();" noch die mmc_init(); 
problemlos aufgerufen wird, ohne das das Programm in mmc_write_byte fest 
hängt?!

Vielleicht könnt Ihr mir einen Tipp geben, was ich noch versuchen kann, 
damit die main_simple.c direkt durchläuft.
Danke.
Gruß
Andi

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen,
ich bin da gerade immer mal wenn ich etwas Zeit habe dran am arbeiten.

Ich habe jetzt einen stm32 mit jtag Debugger, damit arbeitet sich 
wesentlich leichter als mit einem avr und Debug Ausgaben über die 
Konsole :)

Was wohl auf jeden Fall geändert werden wird, sind die Delay schleifen 
in der mmc.c, die werden auf einen Timer umgestellt werden müssen.

Die Initialisierung der Karten wird auch geändert sowie der Ablauf von 
den schreibe und lese Funktionen. Also quasi der ganze Unterbau wird 
geändert. Zudem noch die Datei öffnen Funktion.

Bitte um etwas Geduld...habe bald Semesterferien, die letzten :) da wird 
das wohl spätestens was werden....

Viele Grüße

Daniel

von Michael R. (Gast)


Lesenswert?

Hallo Daniel,
wenn Du das Timing auf einen Timer umstellst, wird das Einbinden in 
verschiedene andere Projekte deutlich schwerer oder unmöglich. Ich habe 
Deine lib in einem Projekt drin, in dem keine Timer mehr verfügbar sind.

Super wäre es, erstmal eine stabile weitgehend bugfreie Version zu 
schaffen, denn derzeit ist das definitiv nicht der Fall.

Ansonsten finde ich Deine Arbeit echt super, eine Lib, die wenig 
Resourcen braucht und einfach einzubinden ist.

Michael

von Daniel R. (zerrome)


Lesenswert?

Hallo.

>wenn Du das Timing auf einen Timer umstellst

Genau da ist beispielsweise einer der Bugs. So eine Karte genehmigt sich 
schon mal bis zu 200 ms um Daten zu speichern oder um einen Block zu 
lesen. Da rasselt man dann einfach aus den warte Schleifen raus, 
zumindest so wie die momentan sind.

Ich hab mir das so vorgestellt, dass man einfach eine bestimmte Funktion 
im 10 ms Takt aufrufen muss.
Im Beispielcode würde ich dann ein Timer Beispiel machen, wie das dann 
letztendlich in einem eigenen Projekt umgesetzt wird muss dann jeder 
selber schauen...

Grüße

Daniel

von Michael R. (Gast)


Lesenswert?

Hallo Daniel,
ich meinte den z.B. den Bug, dass die FAT beim Anhängen nicht richtig 
geschrieben wird.
Ansonsten hat Dein Ansatz mit den Timern definitiv Vorteile, da der 
Controller in den Warteschleifen nicht blockiert wird.
Du baust also keine Timerfunktionen direkt in die Lib ein sondern 
erwartest ein Pollen Deiner Funktionen?

Michael

von recently (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich hätte mal eine Frage zur "Superfloppy"-Erkennung. Mit meiner frisch 
gekauften 2GB-SD-Karte lief das AVR-FAT-Paket auf meinem Pollin net-io 
mit SD-Addon zunächst tadellos. Diese SD-Karte hatte in Sektor 0 einen 
MBR mit Partitionstabelle. Nun habe ich die SD-Karte in meinem 
Windowsrechner neu mit FAT32 formattiert. Dadurch verschwand der MBR und 
die neue Partition beginnt nun ohne Umwege direkt in Sektor 0, die Karte 
hat also "Superfloppy"-Format. Wenn ich es richtig verstanden habe, 
untersucht die AVR-FAT-Software den Boot-Code der Partition auf die 
Zeichenkette "medi", die an der Stelle erwartet wird, wo sonst die 
Anfangsadresse der 1.Partition steht. Dies funktioniert bei mir nicht. 
Die Zeichenkette "medi" ist um 2 Bytes versetzt, wodurch die 
Superfloppy-Erkennung scheitert und alles weitere natürlich auch. Habe 
das Debugger-Listing angehängt, in dem der Versatz zu erkennen ist. Habe 
ich irgendetwas nicht richtig beachtet ?

Vielen Dank für Tipps
recently

von daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich bin dazu gekommen mal ein wenig an der Lib zu arbeiten.
Als Anhang mal die frischen Dateien.

Es gibt einige Änderungen.

In der mmc.c ist aufgrund der Portierbarkeit ein eigener SPI Teil dazu 
gekommen. Zum anpassen an andere Plattformen müssen jetzt nur noch die 
Funktionen,

spi_init
spi_maxSpeed
spi_write_byte
spi_read_byte

und die defines,

#define MMC_CS_LOW     GPIO_ResetBits(GPIOA, GPIO_Pin_4)
#define MMC_CS_HIGH    GPIO_SetBits(GPIOA, GPIO_Pin_4)

angepasst werden.

Auch in der mmc.c geändert:
Die Initialisierung der SD/MMC Karten.
Die Bestimmung ob Superfloppy oder nicht.
Zeit gesteuerte delay Schleifen beim lesen/schreiben, wegen der Totzeit 
der Karten bei diesen Operationen.

Ganz wichtig! Es muss irgendwo eine globale Variable
1
 volatile unsigned char TimingDelay;
 geben, die in 10 ms Intervallen bis 0 runtergezählt wird!

In der file.c hat sich ffopen geändert.
Es wird jetzt nicht mehr einfach die Datei angelegt wenn sie noch nicht 
vorhanden war. Hat oft zu Verwirrung geführt.

ffopen(name,'r') öffnet die Datei falls vorhanden und gibt 
MMC_FILE_OPENED zurück. Oder aber MMC_NOTHING_DONE.

ffopen(name,'c') legt eine Datei an falls es die Datei noch nicht gibt 
und gibt MMC_FILE_CREATED zurück. Oder aber MMC_NOTHING_DONE wenn es die 
Datei schon gab...

In der fat.c hat sich das suchen nach Dateinamen geändert. Bei kurzen 
Dateinamen wird von PC Betriebssystemen manchmal nur ein SFN angelegt. 
Das ist jetzt in der Lib angepasst.


Es wird demnächst noch weiter gehen...

Grüße

Daniel

von Manfred (Gast)


Lesenswert?

Mit den neuen Modulen ist bei mir nichts mehr compilierbar ... schade, 
ob das jetzt wirklich ein Gewinn war ?

Gibt es denn dazu auch eine passendes "main_simple", das nach diesem 
Totalaustausch der Quellen noch läuft ? Das man es wenigstens mal 
ausprobieren kann ?

von recently (Gast)


Lesenswert?

Hallo Daniel,

vielen Dank für die neue Version. Die Superfloppy-Erkennung sieht gut 
aus. Gibt es denn auch eine AVR-Version ? Die Version im fix-zip-file 
scheint für STM32-Hardware ausgelegt ?

Viele Grüße
recently

von Daniel R. (zerrome)


Lesenswert?

Hallo,
es wird die Tage die AVR Version geben.
Jo, das ist für einen STM32 momentan.
Sollte jetzt keine finale Version sein.

Viele Grüße

Daniel

von daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
jetzt sollten alle Fehler behoben sein.

Hier schonmal die STM32 Version. Bisher nur mit lfn Option getestet...
Die AVR Variante braucht noch etwas Zeit,
sollte aber auch relativ einfach aus der SMT32 Version zu portieren 
sein.

Viele Grüße

Daniel

von Michael R. (Gast)


Lesenswert?

Hallo,
ist der Datei Anhängen Bug gefixt?

Michael

von recently (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Daniel,

ich beschäftige mich gerade intensiv mit dem AVR-FAT-Code und habe eine 
Frage zum Element file.dir : Das Element wird in der Funktion 
fat_loadFatData einmal auf 0 gesetzt und dann an verschiedenen Stellen 
der Software auf 0 geprüft ... was ist die Bedeutung dieses Elements ?

von recently (Gast)


Lesenswert?

... meinte natürlich das Element "fat.dir"

von Daniel R. (zerrome)


Lesenswert?

Hallo,
da wird der 1. Cluster des aktuellen Verzeichnisses gespeichert. Damit 
man weiß in welchem Ordner man sich befindet.
Wird nur durch ffcd() und ffcdLower() geändert. Mit ffcd() wechselt man 
in ein Verzeichnis und mit ffcdLower() geht man ein Verzeichnis höher 
(auch als "cd.." bekannt).

Viele Grüße

Daniel


PS: Die AVR Version ist soweit. Bin nur noch ausgiebig am testen.

von recently (Gast)


Lesenswert?

danke für die schnelle Antwort ...

Viele Grüße
recently

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
hier jetzt mal die fertigen Sachen.

Es wäre super, wenn ein paar Leute mittesten könnten.

Es gab eigentlich nur einen Bug, den ich selber eingebaut hatte von 
0.5.9 auf 0.6.1, dummerweise...

Der ist jetzt weg und es gibt neue Features...

Viele Grüße

Daniel

von recently (Gast)


Lesenswert?

Hallo Daniel,

mit meinem ATMega32 (der NetIO von Pollin) mit 18.432 MHz bekomme ich 
Schwierigkeiten beim compilieren ... Die Taktfrequenz wird im Header 
nicht angeboten und weiterhin hat der Mega32 auch kein "TCCR0A" ...

Viele Grüße
recently

von Daniel R. (zerrome)


Lesenswert?

Hm, dann musst Du den Timer per Hand einstellen.
Die Timer ISR muss alle 10ms aufgerufen werden.
Für den mega32 werde ich das aber wohl auch noch einbauen...

Grüße

Daniel

von nicht Gast (Gast)


Lesenswert?

Hallo,
ich werde deine Version auch testen.
Ich wollte mal fragen warum du überall "unsigned char var[]" als 
Parameter nutzt.
Könnte man da nicht "char *var" nehmen dann muss man nicht immer rum 
casten wenn man Standard lib Funktionen nutzt.
Also statt:
extern unsigned char ffopen( unsigned char name[], unsigned char 
rw_flag);
ein:
int8_t ffopen(char *name, uint8_t rw_flag);

Vielen dank das du das hier veröffentlicht hast, wie gesagt soll nur ein 
Vorschlag sein.

von XMEGA (Gast)


Lesenswert?

Servus,


 Daniel R. schrieb:
> Es wäre super, wenn ein paar Leute mittesten könnten.

hab mich mal mit der neuen  Version beschäftigt.

Bis jetzt war ich begeistert- aber nun macht es doch erhebliche 
Probleme. Insbesondere mit einem neuen Prozessor.

Die Timer-Geschichte mag zwar funktionieren ist aber gegen der 
vorherigen Version komplizierter geworden.

Mit den #If, #else, #endif  verliert man total die Übersicht.

Trotz alledem bin ich über Deine Vorgängerversion froh, die funktioniert 
ohne Probleme auf allen Atmegas/Atxmegas.

Gruß XMEGA

von Daniel R. (zerrome)


Lesenswert?

Hallo,
bei der Timer Version ist das einzige komplizierte, dass es eine ISR 
geben muss die alle 10ms aufgerufen wird und in der
1
TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;
seht.
Sonst hat sich alles nur zum Vorteil geändert.
Besonders bei sfn (short file names) ist es doch wesentlich bequemer
1
 unsigned char file [] = "test.txt";
zu schreiben als
1
 unsigned char file [] = "TEST    TXT";

Aber gut, zu dem Timer Punkt werde ich mir etwas überlegen. Vielleicht 
hat ja jemand eine Idee, wie man aus F_CPU und ein paar Assembler 
Befehlen auch so etwas hinbekommen kann wie gezieltes warten von maximal 
200 ms.

Wenn man eclipse als IDE benutze, kann man die #if die nicht benutzt 
werden ausblenden lassen, oder sie grau hinterlegen lassen, das ist sehr 
übersichtlich.

char * mag ich nicht als Standard Typ verwenden, weil das signed ist und 
somit im 2er Komplement. Das ist nicht so Ressourcen schonend...

Viele Grüße

Daniel

von nicht Gast (Gast)


Lesenswert?

Daniel R. schrieb:
> char * mag ich nicht als Standard Typ verwenden, weil das signed ist und
> somit im 2er Komplement. Das ist nicht so Ressourcen schonend...

Aha, ok wenn du meinst, für String Bearbeitung macht das zwar keinen 
unterschied aber nun ja...

Für den Timer währe es sinnvoll wenn man per define einstellen könnte 
alle wie viel ms die Zähler runtergezählt wird, so könnte man eine 
Bestehende Timer Funktion verwenden.
1
// in Header
2
#define COUNT_VALUE  15  // Value in ms
3
4
// irgendwo im Code
5
TimingDelay = 1000 /  COUNT_VALUE;
6
if(!TimingDelay)
7
  TimingDelay =1;
8
while(wait);

von Daniel R. (zerrome)


Lesenswert?

Den Code versteh ich nicht...

Wie ist das gemeint?

Man kann doch bestehende Timer einfach mitbenutzen... es muss halt nur 
TimingDelay im 10ms Takt um 1 runter gezählt werden, bis auf 0.
Um mehr muss man sich nicht kümmern.

von nicht Gast (Gast)


Lesenswert?

Daniel R. schrieb:
> es muss halt nur
> TimingDelay im 10ms Takt um 1 runter gezählt werden

Und das ist der Punkt. wenn deine Timer mit z.B. 15ms oder 5ms laufen 
kannst du sie nicht so einfach benutzen.
Bzw. musst du selber im Timer schauen das du z.B (5ms) nur jedes zweite 
mal dekrementierst oder (15ms) jedes zweite mal doppelt dekrementieren 
musst.

von nicht Gast (Gast)


Lesenswert?

Sorry hatte da noch einen kleinen Fehler im Code
1
// in Header
2
#define COUNT_VALUE  15  // Value in ms
3
4
// irgendwo in mmc.c
5
TimingDelay = 1000 /  COUNT_VALUE;
6
7
if(!TimingDelay)
8
  TimingDelay =1;
9
10
while(TimingDelay && funktionaufdiegewartetwird());

von Daniel R. (zerrome)


Lesenswert?

Ok, ich dachte ja nur, dass ich ein Beispiel der Benutzung gebe.

>..wenn deine Timer mit z.B. 15ms oder 5ms laufen
>kannst du sie nicht so einfach benutzen...

Wenn man das dann in ein Projekt einbaut, muss man sich genau um solche 
Dinge ja Gedanken machen und ändern.

Mit der Anweisung:
Decrementiere TimingDelay im 10ms Takt um 1, bis auf 0, sollte man ja 
klar kommen können.
Man kann aber auch einfach TimingDelay nach 200ms auf 0 setzten und gut 
ist. Die Idee ist halt, mindestens 200ms auf die Karten zu warten.

Ich Persönlich würde ja eine Lösung ganz ohne Timer auch besser finden, 
hab aber noch nicht die zündende Idee wie man das schön machen könnte.

von little_man (Gast)


Lesenswert?

Hallo,

Allgemeine Frage:
Funktioniert der Code mit MMCplus Karten?

Bekomme nämlich Transcend MMCplus Karten (1GB & 2 GB) nicht ans laufen!
Die Karte kann nicht initialisiert werden. Andere Karten funktionieren!

mfg

von Kurt B. (kurt)


Lesenswert?

Ich bekomme leider auch eine 2GB Verbatim SD-Card und eine 1GB von 
Platinum nicht zum laufen. Nur eine alte 1GB Noname funktioniert.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ist MMCplus der Standard 3.0 ? Das sollte nämlich gehen.

Wobei ich mehrmals Probleme hatte ist, wenn der MISO Pin keinen Pullup 
hat. Das geht mit alten Karten meistens noch, aber mit neuen nicht mehr.

Den Initialisierungs Kram hab ich bei anderen abgeschaut, und nur noch 
mal mit den Specs verglichen...

>Man kann aber auch einfach TimingDelay
>nach 200ms auf 0 setzten..

Muss ich mir selber etwas widersprechen, ist nämlich einmal nach 200ms 
und beim Initialisieren der Karten 1000ms...

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Leider funktioniert trotz MISO PullUP nur eine der 3 Karten. Mit der 
0.5.9C hatten die alle funktioniert.
Schade dass ich keine Zeit zur Fehlersuche habe.

Aber jetzt was positives: Die Performance scheint besser geworden zu 
sein. Statt 60kB/s sind es nun 80kB/s auf einem Mega32 mit 18,432Mhz.

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo,

>..0.5.9 hatten die alle funktioniert..

das blöde ist das ich keine Karte habe mit der es nicht klappt, daher 
ist das Fehlersuchen nicht möglich.

80kB/s ist aber trotzdem sehr langsam. Benutzt Du software SPI?
Mit 18,432Mhz Quarz und hardware SPI müsste das eine sehr langsame Karte 
sein.

Ich hab hier SD Karten die mit 16Mhz 170kB/s machen. Auch welche mit 
über 200kB/s...

Alles schreibend, lesend noch schneller...

Außerdem ist an den schreib Routinen eigentlich nichts geändert.

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Nein, ich nutze Hardware SPI.
Wahrscheinlich liegt die geringe Geschwindigkeit daran dass ich immer 
nur ein einzelnes Byte schreibe?

Falls sonst niemand Probleme mit den SD Cards hat, habe ich wohl einen 
Fehler eingebaut der so offensichtlich ist dass ich ihn immer übersehe. 
;-)

Mfg,
Kurt

von little_man (Gast)


Lesenswert?

Hallo!

>ist MMCplus der Standard 3.0 ?

Ich meine das ist der neue Standard 4.0. Kann mich aber auch täuschen!

mfg

von Daniel R. (zerrome)


Lesenswert?

@ Kurt Bohnen (kurt)

Also wenn Du normal mit ffwrite() schreibst, puffert die Lib eh 512 
Bytes zwischen. Da sollte das Problem nicht liegen.
Ach ja, wenn überschreiben an ist, ist das schreiben etwas langsamer...

@ little_man (Gast)

Ja stimmt, ist 4.x, wenn Du da eine Spezifikation findest, schau ich mir 
das mal an und setzt das dann um...


Viele Grüße

Daniel

von Sven S. (schwerminator)


Angehängte Dateien:

Lesenswert?

Das könnte helfen.

Gruß Sven

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja das sieht auf den ersten blick schon mal sehr gut aus.


Danke :)

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Daniel R. schrieb:
> Ich hab hier SD Karten die mit 16Mhz 170kB/s machen. Auch welche mit
> über 200kB/s...

Hallo Daniel,
kannst du ein paar Namen nennen?

Mfg,
Kurt

von Markus K. (Gast)


Lesenswert?

Hallo zusammen

Erstmal vielen Dank fuer die tolle Library. Bin ziemlich neu in der Welt 
von uC. Trotzdem habe ich es geschaft dank der Library auf die SD-Karte 
zu speichern. Das spricht wohl fuer sich. (super super Sache das)

Ein Problem habe ich aber noch.
1
 ffseek(file.length);
Dauert am Anfang ca. 5ms  30min. spaeter 28ms (Datei ist dann 2.85MB 
gross)

Habe weiter oben beim Eintrag vom 17.9.2010 gesehen das ffseek nicht 
durchgefuehrt werden muesste wenn File nicht geschlossen wird. 
Funktioniert bei mir aber leider nicht. (Auf dem SPI-Bus sind noch 
andere Teilnehmer. Sollte aber doch nichts ausmachen)

Um meine Frage kurz zu fassen: Wie kann ich die Zeit zum spulen 
verkuerzen?
(Sollte doch moeglich sein file.length zu merken aber wie?)

Vielen Dank

von Daniel R. (zerrome)


Lesenswert?

@ Kurt Bohnen (kurt)
Muss ich mal nachschauen, bin grad nicht zuhause.

@ Markus K. (Gast)
Schließt Du die Datei beim schreiben immer oder wieso das ffseek?
Du könntest alternativ ein fflush machen anstelle von schließen...

Zeig doch mal ein bisschen code


Viele Grüße

Daniel

von Markus K. (Gast)


Lesenswert?

Ja ich schliesse sie nach jedem anhaengen wieder. Hab auch mal versucht 
sie offen zu lassen doch dann stimmten die Eintraege nicht mehr. Ich 
haenge alle 200ms ein paar Daten an.(sollte so eine xml Datei entstehen)

Verstehe ich das richtig:
fflushFileData(); anstelle von ffclose();
und dann kein ffopen(filename); mehr oder?

Vielen Dank.

von Daniel R. (zerrome)


Lesenswert?

Ja genau.

>Hab auch mal versucht sie offen zu lassen
>doch dann stimmten die Eintraege nicht mehr.

Das müsstest Du mal genauer erklären, bzw zeigen, wie Du die lib 
benutzt.

Viele Grüße

von Markus K. (Gast)


Lesenswert?

Sorry war mein Fehler hab wohl irgendwo im Code vergessen ffclose oder 
ffopen auszukommentieren.

Nun funktioniert es mit dem geoeffnet halten der Datei.
Sorry

Nochmals Vielen Dank fuer deine tolle Library

von Daniel R. (zerrome)


Lesenswert?

Hi, kein Problem.
Viel Spaß noch :)

von Fabian B. (fabs)


Lesenswert?

Hallo Daniel.
 Danke erstmal für die Lib, grad die Fat Funktionen sind super und Fat32 
geht auch einwandfrei.

Ich habe aber immer wieder mit der Karteninitialisierung Probleme.
Kleine Karten < 1GB gingen vom Start weg aber die grossen, bei denen man 
im Init in den SDv2-Block läuft machten Probleme.
Ausserdem habe ich einige Karten gehabt, die nicht sofort auf CMD0 
reagiert haben. Und auch auf CMD16 reagieren manche nicht sofort. 
Hierfür habe ich jeweils eine Schleife eingefügt.

Ich habe die Init-Fuktion etwas angepasst:
1
unsigned char mmc_init (void){
2
3
  unsigned char cmd, ty, ocr[4];
4
  unsigned short n, j;
5
6
  spi_init();
7
  mmc_disable();
8
9
  for (n = 100; n; n--) spi_read_byte();    // 80 dummy clocks
10
11
  ty = 0;
12
  j=100;
13
do {
14
  if (mmc_send_cmd(CMD0, 0) == 1) {      // Enter Idle state 
15
    j=0;
16
    TimingDelay = 100;            // Initialization timeout of 1000 msec
17
18
    if (mmc_send_cmd(CMD8, 0x1AA) == 1) {  // SDv2? 
19
      for (n = 0; n < 4; n++){
20
        ocr[n] = spi_read_byte();    // Get trailing return value of R7 resp 
21
        }
22
      if (ocr[2] == 0x01 && ocr[3] == 0xAA) {            // The card can work at vdd range of 2.7-3.6V 
23
      
24
//        while (TimingDelay && mmc_send_cmd(ACMD41, 1UL << 30));  // Wait for leaving idle state (ACMD41 with HCS bit)
25
        while (TimingDelay) {  // Wait for leaving idle state (ACMD41 with HCS bit)
26
          mmc_send_cmd(CMD55, 0);
27
          if(mmc_send_cmd(ACMD41, 1UL << 30))
28
            break;
29
        }
30
                                ty = CT_SD2 | CT_BLOCK;
31
      }
32
    } else {        // SDv1 or MMCv3 
33
      if (mmc_send_cmd(ACMD41, 0) <= 1)   {
34
        ty = CT_SD1; 
35
        cmd = ACMD41;  // SDv1 
36
      } else {
37
        ty = CT_MMC; 
38
        cmd = CMD1;    // MMCv3 
39
      }
40
      while (TimingDelay && mmc_send_cmd(cmd, 0));      // Wait for leaving idle state 
41
    }
42
    while(TimingDelay && (mmc_send_cmd(CMD16, 512) != 0));
43
    if(!TimingDelay) ty = 0;
44
  } else { j--; }
45
  }while(j>0);
46
  fat.card_type = ty;
47
  mmc_disable(); 
48
49
  if( fat.card_type == 0 ){
50
    return FALSE;
51
  }
52
  #if (MMC_MAX_SPEED==TRUE)
53
    spi_maxSpeed();
54
  #endif
55
56
  return TRUE;
57
}

Um SDHC-Karte überhaupt zum laufen zu bewegen (besonders eine 
8GB-MicroSD) musste ich die ACMD41-Schleife noch um das vorherige Senden 
von CMD55 erweitern, so wie es in der Spec auch gefordert wird.

Die Abfrage auf CMD58 habe ich raus genommen, da diese von keiner meiner 
Karten anders als mit 05 (Illigal Command) beantwortet wird.
Bei meinen SDHC Karten mit 4 und 8GB hat das mit
1
ty = CT_SD2 | CT_BLOCK;
ganz gut funktioniert, aber jetzt habe ich eine extrememory 2GB bei der 
er auch in den SDv2-Block läuft die nur mit
1
ty = CT_SD2;
läuft. Also die Zugriffe der FAT-Funktionen klappen sonst halt nicht 
mehr.
Gibt es noch eine andere Möglichkeit als CMD58 hier eine Unterscheidung 
zu machen?

Eine 1GB Platinum hingegen läuft auch in diesen Block bleibt jedoch am 
ACMD41 hängen: es kommt immer 0x00 zurück, sie kommt also nie in den 
Idle-State.

Any Ideas? Gerade bezüglich des CT_SD2 bzw. CT_BLOCK, weil wenn dann nur 
noch die Platinum Karte nicht ginge wäre das zu verschmerzen...die 
scheinen ja eh etwas tricky zu sein.

Gruß
Fabian

von Fabian B. (fabs)


Lesenswert?

Noch eine Ergänzung:

wenn ich die CMD58 Abfrage vor der CMD55->ACMD41 Kombination sende 
bekomme ich eine "Antwort". Die Karten senden dann nicht mehr 05 
(Illegal Command) sondern immer 01 (Idle State). Wenn ich danach noch 4 
Byte lese bekomme ich für das CCS Bit aber immer 0, egal ob SDHC oder 
nicht HC.
Es muss doch noch eine Möglichkeit geben SDv2 von SDHCv2 Karten zu 
unterscheiden?!

Gruß
Fabian

von Michael R. (Gast)


Lesenswert?

Hallo,
hatte gerade mit meinem 8MHz-System Probleme, die SD-Karte zuverlässig 
zu initialisieren. Nachdem ich den SPi-Prescaler von 128 auf 64 geändert 
habe, gehts jetzt offenbar zuverlässig. Die Initialisierungs-SPI-Clock 
wird in der MMC.C fest mit fCPU/128 gesetzt.
Vielleicht wäre es sinnvoller dass diese in Abhängigkeit vom CPU-Takt 
gesetzt wird, der in irgendeinem h-file definiert wird.

Laut einigen Quellen müssen die Init-Takte mit 100-400kHz erzeugt 
werden, was beim 128er Teiler erst ab 12,8Mhz zutrifft. Vielleicht wäre 
es auch sinnvoller, beim AVR standardmäßig den 64er-Teiler zu nutzen. 
Das deckt besser die typischen Taktfrequenzen ab.

Michael

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.

@ Fabian B. (fabs)
Hast Du einen PullUp an MISO?
Wie schnell ist dein Kontroller?
Die Init Routine hab ich selber nur abgeschaut,
die die ich selber geschrieben hatte ist raus geflogen,
obwohl die gut war...vielleicht mach ich das wieder rückgängig.


@ Michael R. (Gast)
Ja werde ich ändern.

Viele Grüße

Daniel

von Fabian B. (fabs)


Lesenswert?

@Daniel: Ich hab noch einen gravierenden Fehler in der Soft gefunden. 
Jetzt geht auch CMD58. Alle Karten initialisieren nun korrekt, soweit so 
gut.
Nur auf meiner MicroSDHC (8GB) kann ich zwar die Fat initialisieren und 
auch ffopen gibt ein Ok, aber ich bekomm keine Dateiinfos (filesize oder 
Daten). Dabei ging die Karte vorher ... ich find das aber noch raus 
(morgen) und werde die Routine dann posten.

Gruß
Fabian

von Daniel R. (zerrome)


Lesenswert?

>Alle Karten initialisieren nun korrekt...

Na das klingt doch schon mal gut.

von Fabian B. (fabs)


Lesenswert?

So.
 Ich habe habe jetzt die Init soweit dass alle meine Karte initialisiert 
werden. Getestet wurden:
 - Canon SD 16MB
 - Nokia MMC 32MB (2x)
 - extrememory MMC 256MB (mit FAT16 und FAT32)
 - Platinum SD 1GB (meldet sich als SDv2)
 - extrememory SD 2GB (meldet sich als SDv2)
 - SanDisk SDHC 4GB (Ultra II)
 - SanDisk MicroSDHC 8GB (2x)
 - Noname MicroSDHC 8GB

Hierfür musste ich zwei Änderungen an der mmc.c vornehmen.
Bei den Definitions ganz oben im File war das define für ACMD41 falsch.
Korrekt ist:
1
#define  ACMD41  (41)  // SEND_OP_COND (SDC)
vorher war dort (0x80+41) definiert.
Ich denke auch bei ACMD13 und ACMD23 müsste dieses (0x80) weg, aber da 
ich diese Kommandos nicht selbst brauchte und bisher keine Fehler 
diesbezüglich feststellte hab ich das erstmal so gelassen.

Die zweite Modifikation betrifft die Funktion mmc_init. Wie oben schon 
geschrieben hatte ich ein paar Karten die nicht sofort auf CMD0 
antworten, also habe ich hier eine Schleife drum gelegt. Auch bei 
anderen Kommandos war dies notwenig (CMD55->ACMD41, CMD58, CMD16).
Ich poste hier einfach mal die ganze Funktion:
1
unsigned char mmc_init (void){
2
3
  unsigned char cmd, ty, ocr[4];
4
  unsigned short n, j;
5
6
  spi_init();
7
  mmc_disable();
8
9
  for (n = 100; n; n--) spi_read_byte();    // 80+ dummy clocks
10
11
  ty = 0;
12
  j=100;
13
do {
14
  if (mmc_send_cmd(CMD0, 0) == 1) {      // Enter Idle state 
15
    j=0;
16
    TimingDelay = 100;            // Initialization timeout of 1000 msec
17
18
    if (mmc_send_cmd(CMD8, 0x1AA) == 1) {  // SDv2? 
19
      for (n = 0; n < 4; n++){
20
        ocr[n] = spi_read_byte();    // Get trailing return value of R7 resp 
21
        }
22
      if (ocr[2] == 0x01 && ocr[3] == 0xAA) {            // The card can work at vdd range of 2.7-3.6V 
23
        while (TimingDelay) {  // Wait for leaving idle state (ACMD41 with HCS bit)
24
          mmc_send_cmd(CMD55, 0);
25
          if(!mmc_send_cmd(ACMD41, 1UL << 30))
26
            break;
27
        }
28
29
        while(TimingDelay) {
30
        if (mmc_send_cmd(CMD58, 0) == 0x00) {    // Check CCS bit in the OCR 
31
          for (n = 0; n < 4; n++){
32
            ocr[n] = spi_read_byte();
33
            }
34
          ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;  // SDv2 
35
          break;
36
        }
37
        }
38
      }
39
    } else {        // SDv1 or MMCv3 
40
      if (mmc_send_cmd(ACMD41, 0) <= 1)   {
41
        ty = CT_SD1; 
42
        cmd = ACMD41;  // SDv1 
43
      } else {
44
        ty = CT_MMC; 
45
        cmd = CMD1;    // MMCv3 
46
      }
47
      while (TimingDelay && mmc_send_cmd(cmd, 0));      // Wait for leaving idle state 
48
    }
49
    if(ty != (CT_SD2 | CT_BLOCK)) {
50
      while(TimingDelay && (mmc_send_cmd(CMD16, 512) != 0));
51
    }
52
    if(!TimingDelay) ty = 0;
53
  } else { j--; }
54
  }while(j>0);
55
  fat.card_type = ty;
56
  mmc_disable(); 
57
58
  if( fat.card_type == 0 ){
59
    return FALSE;
60
  }
61
  #if (MMC_MAX_SPEED==TRUE)
62
    spi_maxSpeed();
63
  #endif
64
65
  return TRUE;
66
}

Was mir noch auffiel:
Laut Spec muss ein ACMD immer auf ein CMD55 folgen. Im SDv1 or MMCv3 
block wird nur so direkt ein ACMD41 versucht. Ich vermute, dass hier 
eigentlich auch ein CMD55 vorher noch sein müsste, da ich aber mit keine 
Karte, die diesen Block durchläuft Probleme hatte lass ich es so.

Vielleicht kannst du, Daniel, diese Funktion so bei dir einpflegen und 
mal testen.

Nicht direkt als Bug zu bezeichnen: ich hatte noch eine 
Unregelmässigkeit.
Bei den SanDisk MicroSDHC 8GB konnte ich die Karte korrekt 
initialisieren, Fat initialisieren und auch Fileopen lieferte ein Ok, 
die Datei hatte laut file.length jedoch eine grösse von 0 und auch ein 
"blindes" ffread() lieferte nur Schrott. Da auf der Karte auch vorher 
schon Daten waren habe ich sie dann mal formatiert und die Datei wieder 
drauf kopiert und dann ging's einwandfrei.
Gibt es da vielleicht Zugriffprobleme auf Dateien ab einer bestimmten 
"Position auf der Karte", also weit hinten? Und wäre es vielleicht 
sinnvoll ffopen failen zu lassen wenn die Dateigrösse 0 ist?

Ich verwende:
At90Can128, 10MHz, HC4050 als Pegelwandler, 3V3 Regler für SD Karte, 
HW-Spi

Gruß
Fabian

von recently (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit dem neuen Code:

Wenn ich das richtig verstehe, wartet die Funktion mmc_wait_ready 
lediglich solange, bis auf der Miso-Leitung H-Pegel anliegt:
1
static unsigned char mmc_wait_ready (void){
2
3
  TimingDelay = 50;
4
5
  do{
6
    if(   spi_read_byte() == 0xFF ) return TRUE;
7
  }while ( TimingDelay );
8
9
  return FALSE;
10
}

Zur Aktivierung der Karte wird also zunächst CS auf 0 gesetzt und dann 
getestet, ob Miso auf H-Pegel geht (oder bereits ist):
1
static unsigned char mmc_enable(){
2
      
3
   MMC_CS_LOW;
4
   if( !mmc_wait_ready() ){
5
       mmc_disable();
6
    return FALSE;
7
   }
8
9
   return TRUE;
10
}

Das funktioniert bei mir leider nicht. Meine Karte(n) liefert vor 
Absendung des CMD0 Kommandos immer L-Pegel. Aus diesem Grund kommt es 
bei mir nicht zur CMD0 Absendung. Habe die mmc_wait_ready erstmal 
auskommentiert, wäre für eine Erläuterung dankbar ...

Viele Grüße
recently

von Daniel R. (zerrome)


Lesenswert?

Hallo.

>getestet, ob Miso auf H-Pegel geht (oder bereits ist)

Miso sollte H sein, weil da ein PullUp dran sein sollte.
Ich muss das im Wiki unbedingt mal ändern.

Damit sollte das dann klappen.

Viele Grüße

Daniel

von recently (Gast)


Lesenswert?

Hallo Daniel,

vielen Dank für die schnelle Antwort. Habe den Schaltplan von meinem 
Pollin Net-IO mit SD-Karten-ADD-On untersucht und finde dort keinen 
Pullup.

Bin ein wenig irritiert, die Hardware funktionierte ja mit der alten 
Software, auf dem Oszilloskop sieht das Miso-Signal auch normal aus, 
schön rechteckig und ungefähr zwischen 0 und 3V. Aber es ist 0V, wenn 
die Karte herausgezogen oder gerade hereingesteckt wurde.

Was für ein Widerstand sollte da eingelötet werden ?

- recently -

von Daniel R. (zerrome)


Lesenswert?

Bei der alten Version war das mit dem wait anders gelöst.
Es sollte ein 10K Widerstand gegen +3,3 Volt sein.
Damit die Karte am DO Pin auf jeden Fall vor cmd0 auf high ist.
Siehe auch:
Dritter Unterpunkt.
http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten#DOs_und_DON.27Ts_bei_der_Ansteuerung


Viele Grüße

Daniel

von Fabian B. (fabs)


Lesenswert?

Das kann auch ein Effekt der der Karte sein, dass die die Leitung 
schwach auf low zieht wenn sie eingesteckt wird und direkt Saft bekommt 
(evtl. noch mit Prelleffekten auf der Versorgung). Da ich die Versorgung 
der Karte bei mir immer erst einschalte, wenn die Karte im Slot 
detektiert wurde, konnte ich dieses Verhalten bei inzwischen ca. 15 
getesteten Karten nicht feststellen.

@Daniel R: hast du den mmc_init mal testen können?

Gruß
Fabian

von Daniel R. (zerrome)


Lesenswert?

Leider nein, hab diese Woche noch 2 Klausuren und es war Karneval :)
Komme ich aber bald dazu, danke das Du da soviel Mühe mit rein 
Investiert hast.

Viele Grüße

Daniel

von recently (Gast)


Lesenswert?

Hallo Daniel,

habe den 10k Widerstand eingebaut ... Unterschied wie Tag und Nacht. Die 
Initialisierung funktioniert jetzt sauber und reproduzierbar (ohne 
Pullup hatte ich mehrere CMD0-Wiederholungen, jetzt immer genau 1x). 
Sollte man Pollin mal mitteilen ... :-)

Vielen Dank für den Tipp !

Viele Grüße
recently

von johnn (Gast)


Lesenswert?

Haloo,
Ich bin nur Anfänger und ich möchte nur einfacher Programm machen. 
Programm macht neue Datei – zum Beispiel „1.txt“ und schreibt jede 10 
Sekunden Temperatur (es ist in string format). Jede Temperatur an neue 
Zeile. Zuerst möchte ich nur library 0.6.2 testen.

Ich habe SD-Karte, ATMega 168 – es ist durch MISO, MOSI, SCK und CS 
verbinden.
Jetzt teste ich Version 0.6.2. Ich habe AVR Studio 4.18, ich öffne 
main_simple.c, dann gebe ich Project -> Configuration Options – ich 
schreibe Frequency 16MHz (ich habe 16 MHz Krystal). Und dann 
programmierte ich den Prozessor. Ich lasse den Programm etwa 10 sekunden 
laufen. Aber es macht nichts. Die Karte ist leer. Mache ich etwas 
schlecht ? Muss ich noch etwas machen ? Die Karte ist normal formatiert 
in Windows – FAT.
Können Sei mir bitte helfen ? Vielen Dank.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
läuft der ATMega 168 mit 3,3 Volt?
Läuft das Beispielprogramm ohne irgendwelche Änderungen?
Wie sieht die Schaltung aus?

Versuch immer in kleinen Schritten etwas auszuprobieren, bis es läuft 
und erweitere es dann erst.

Viele Grüße

Daniel

von johnn (Gast)


Lesenswert?

Atmega hatte 5Volt, jetzt läufte mit 3,3V aber es geht auch nicht.
Ich mache keine Änderungen - nur frequency.
Die Schaltung ist wie hier 
(http://www.mikrocontroller.net/articles/AVR_FAT32), aber keine HC4050 
(ich habe 3,3 Volt).

von Daniel R. (zerrome)


Lesenswert?

Hallo,
dann mach doch mal noch einen PullUp an MISO vom Kontroller. 
Beziehungsweise an DO der Karte.
Dann könntest Du noch mal versuchen in der mmc_config.h
1
#define MMC_MAX_SPEED     FALSE

zu setzen.

Und eventuell die mmc_init() zu benutzen die in folgendem Link 
angesprochen wird.

Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Falls das alles nichts hilft, müsstest Du mal ein Foto vom Aufbau machen 
und hochladen, damit man sich eventuell ein bild von möglichen 
Fehlerquellen machen kann.

Du solltest auch mehrere Karten ausprobieren ob vielleicht nur eine 
bestimmte nicht funktioniert.

Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Hallo zusammen

Ich habe ein Problem mit der AVR Fat32 Library

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

Zur Hardware:

Ich verwende einen Atmega16 mit 12MHz Quarz
Am Hardware SPI Hängt die SD Karte (micro SD)
Der Atmega wird mit 3,3V Betrieben.

Nun das Problem

Die Library funktioniert grundsätzlich sehr gut... Ich habe die Dateien 
1:1 übernommen uns es klappte auf anhieb.

Doch ich habe das problem, das wenn ich z.B. die Datei bild.bmp öffnen 
lassen will mit der Lib, dann verwende ich folgenden Code
1
while (FALSE==mmc_init()){  //Karte Initialisieren
2
      nop();
3
    }
4
  Out1_1;
5
  if(TRUE == fat_loadFatData()){
6
    unsigned char file_name[9]="bild.bmp";
7
8
    if(MMC_FILE_EXISTS == ffopen(file_name)){
9
      Out1_0;
10
      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !
11
      seek=file.length;
12
      // Lesen eines chars und Ausgabe des chars.
13
              // Solange bis komplette Datei gelesen wurde.
14
              while(ucBufferCounter != 56) //Daten auslesen
15
              {
16
                 ucBuffer[ucBufferCounter] = ffread();
17
                 --seek;  //Byte Zähler
18
                 ucBufferCounter++;
19
              } //56Bytes Buffer auslesen
20
    }
21
22
  }

nicht von den 56Bytes irritieren lassen... das spielt derzeit keine 
rolle!


Doch wenn ich diesen Code ausführen lasse, dann meldet der Code das Die 
Datei existiert jedoch erstellt er selbige auf der Karte.

Wenn ich Die karte also in den PC einschiebe, befindet sich zweimal die 
Datei bild.bmp im Root verzeichniss... Windows motzt nun also und ich 
muss die Karte formatieren...

Wass jedoch prblemlos geht, ist eine von der Lib erstellte Datei lesen 
oder zu erweitern... Auch mit dem Computer... Aber es kann ja nicht 
sein, das ich immer mit dem AVR eine Datei erstellen muss und diese Dann 
am Computer bearbeiten muss. Dies geht sowiso nur bei txt dateien.

Getestet habe ich den Code mit mehreren Karten. An dennen liegt es also 
nicht! An der Lib config habe ich nichts verändert!

Was auch merkwürdig ist, das bei dem Beispielcode von hier
http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Code
steht beim Filename "man beachte die Grossbuchstaben" aber es hat im 
beispiel nur kleinbuchstaben.

Hat jemand eine idee wo hier der wurm drinn sein könnte?

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich komme grad nicht dazu ne neue Version zusammen zu packen in der auch 
die neue Initialisierungsfunktion ist und auch die neue 
fat_loadFiledataFromCluster.
1
//***************************************************************************************************************
2
// prueft auf lange dateinamen (lfn), ermittelt anhand des langen dateinamens den kurzen. nur der kurze
3
// enthaelt die noetigen informationen um die datei lesen zu koennen. ist der gesuchte dateiname gefunden
4
// aber im naechsten sektor/cluster ermittelt die funktion selbstaendig diese und holt die informationen !
5
//***************************************************************************************************************
6
static unsigned char fat_loadFileDataFromCluster(unsigned long int sec , unsigned char name []){
7
8
    unsigned short row;    // um durch zeilen zu gehen, eigentlich erstes byte einer reihe...
9
    unsigned char sectors;  // um durch sektoren zu zaehlen, sectors+sec = tatsaechliche sektornummer (absoluter sektor)
10
    unsigned char i;      // um durch eine zeile/reihe zu laufen
11
    unsigned char j;      // laufvariable fuer sfn
12
13
    // diese variablen muessen statisch sein, weil ein lfn eintrag auf 2 cluter aufgeteilt sein kann !
14
    static unsigned char checksum = 0;  // die kurze dateinamen checksumme, die ausgelesene.
15
    static enum flags { wait=0,start,readout } lfn_state;
16
    static unsigned char match = 0;    // treffer bei datei namen vergleich zaehlen
17
18
    const unsigned char map[13]={1,3,5,7,9,14,16,18,20,22,24,28,30};    // index von map ist index des zu pruefenden bytes und inhalt ist index des zu pruefenden bytes in der reihe
19
    const unsigned char name_length = strlen((char *)name)-1;      // es wird die laenge des dateinamen zum vergleichen benoetigt!
20
21
    sectors = 0;
22
23
    // 5 moegliche zustaende im inneren der beiden schleifen...
24
    do{                      // sektoren des clusters pruefen
25
    row=0;                    // neuer sektor, dann reihen von 0 an.
26
    mmc_read_sector(sec+sectors,fat.sector);  // laed den sektor sec auf den puffer fat.sector
27
    fat.lastSector = file.currentSectorNr;    // sichern der alten sektor nummer
28
    file.currentSectorNr = sec + sectors;    // setzen des aktuellen sektors
29
    do{                      // reihen des sektors pruefen
30
      // 1.) nach einem eintrag mit 0x00 kommt nix mehr => restlicher cluster leer!
31
      if( fat.sector[row]==0x00 ){
32
        return FALSE;
33
      }
34
      // 2.1) ist eintrag ein lfn eintrag?   siehe: http://en.wikipedia.org/wiki/File_Allocation_Table#Long_file_names
35
      if( (fat.sector[row]&0x40) == 0x40 && fat.sector[row+11] == 0x0F && fat.sector[row] != 0xE5 ){                                      // ist lfn eintrag, jetzt pruefen...
36
        lfn_state = start;
37
      }
38
      // 2.2) ist eintrag ein sfn eintrag? 
39
      if( (fat.sector[row+11] == 0x10 || fat.sector[row+11] == 0x20) && fat.sector[row] != 0xE5 && lfn_state != readout){
40
        // vergleich von sfn dateinamen
41
        i = 0; j = 0;
42
        do{          
43
          if( fat.sector[row+i] == 0x20 ){     // ueberspringen von leerzeichen auf der karte
44
            i++; continue;
45
          }
46
          if( name[j] == '.' ){           // ueberspringen von punkt im dateinamen
47
            if( i <= 7) break;
48
            j++; continue;
49
          }
50
          if( fat.sector[row+i] != toupper(name[j]) )  break;
51
          i++; j++;
52
        }while(i<11);
53
        // datei gefunden
54
        if( i == 11 && j != 11){
55
          lfn_state = readout;                                      // ist lfn eintrag, jetzt pruefen...
56
          checksum = fat_lfn_checksum( &fat.sector[row] );
57
        }
58
      } 
59
      // 3.) lfn gefunden, jetzt verarbeiten. raussuchen der richtigen bytes und direkter vergleich mit dem original.
60
      if( lfn_state == start || match !=0 ){
61
        i=12;
62
        do{
63
          if( fat.sector[row+map[i]]!=0x00 && fat.sector[row+map[i]]!=0xFF ){  // gueltiger buchstabe. ist gueltig wenn, es nicht 0 oder ff ist.
64
            if( fat.sector[row+map[i]] == name[name_length-match] ){    // vergleich mit original, ist treffer?
65
              match += 1;                          // bei treffer index zaehler fuer vergleich hochzaehlen
66
            }
67
            else {            // wenn ein gueltiger buchstabe keinen treffer verursacht, ist es die falsche datei !
68
              lfn_state = wait;     // zurueck zu ausgangszustand
69
              match = 0;        // treffer zurueck setzen
70
              break;          // weitere pruefung nicht noetig da eintraege ungleich!
71
            }
72
          }
73
        }while(i--);            // zeichen index einer zeile/reihe abarbeiten
74
        // komplette uebereinstimmung und sequenz id 1 ==> datei gefunden !!
75
        if( (name_length-match) == -1 && (fat.sector[row]&0x01) == 0x01){
76
          lfn_state = readout;      // langer dateiname stimmt ueberein, jetzt zustand wechseln.
77
          match = 0;            // vergleich index zurueck setzen, damit nicht wieder in diesen zustand gewechselt wird.
78
          checksum = fat.sector[row+13];  // checksumme sichern zum vergleich mit der errechneten anhand des kurzen dateinamens. in naechstem zustand vergleich.
79
        }
80
      }
81
      // 4.) gesuchte reihe auf stuct file laden zum weiter verarbeiten. das ist der sfn eintrag, mit dem firstCluster, der laenge usw...
82
      if( lfn_state == readout && fat.sector[row+11] != 0x0F ){
83
        lfn_state = wait;
84
        fat_loadRowOfSector(row);
85
        file.row = row>>5;                  // reihe sichern, ist fuer ffrm wichtig
86
        if(checksum==fat_lfn_checksum(&fat.sector[row])){  // pruefen ob checksumme stimmt...wenn ja alles klar :)
87
          file.entrySector = file.currentSectorNr;    // sichern des sektors in dem der sfn dateieintrag steht.
88
          return TRUE;
89
        }
90
      }
91
92
      }while( (row+=32) < 512 );      // mit row+32 springt man immer an die 1. stelle einer reihe (zeile) und das durch einen ganzen sektor
93
    }while( ++sectors < fat.secPerClust );  // geht durch sektoren des clusters
94
95
    return FALSE;              // datei nicht gefunden, zumindest in diesem cluster...
96
}

Diese Funktion solltes Du mal test weise in der fat.c austauschen.

>man beachte die Grossbuchstaben

Die Kommentare in den Sourcen sind nicht immer aktuell ^^

Sag mir mal ob in der mmc_config.h
1
MMC_LFN_SUPPORT TRUE
ist.


Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Daniel R. schrieb:
> Die Kommentare in den Sourcen sind nicht immer aktuell ^^

Kein Problem :)

Vielen Dank für die Antwort

Ich habe LFN Support auf True
und auch MMC File Exists auf True

Ich verwende übrigens die neuste Version aus dem SVN

habe besagten Code ersetzt jedoch kommen nun folgende Meldungen

../fat.c:195: error: 'struct Fat' has no member named 'lastSector'
../fat.c:195: error: 'struct File' has no member named 'currentSectorNr'
../fat.c:196: error: 'struct File' has no member named 'currentSectorNr'
../fat.c:255: error: 'struct File' has no member named 'currentSectorNr'

Anscheinend ist das Struct geändert worden von dir :)

von Daniel R. (zerrome)


Lesenswert?

Hm, ja stimmt.
Die Version aus dem SVN ist nicht die neuste.

Nimm diese:

http://www.mikrocontroller.net/attachment/101158/0.6.2.zip

Muss das mal ins SVN hochladen...

von Daniel R. (zerrome)


Lesenswert?

Ach ja und in der 0.6.2 musst Du noch die besagte Funktion tauschen...

Muss das die Tage mal alles sortieren^^

von C. H. (hedie)


Lesenswert?

Vielen dank für den Hinweis und die neue Lib

Was meint der Compiler mit undefined reference timing delay?

Muss ich diese Funktion bereitstellen?

von Daniel R. (zerrome)


Lesenswert?

Es muss eine
1
volatile unsigned char   TimingDelay;  // fuer mmc.c

Variable im Programm geben die in 10 ms Intervallen runtergezählt wird 
bis 0. Wenn Du Dich an der main_simple.c orientierst sollte das kein 
Problem werden.

von C. H. (hedie)


Lesenswert?

Hat geklappt Danke!

Deine Lib ist echt Genial!!!

Hoffentlich lädstd du bald die neue Version hoch :)

von Daniel R. (zerrome)


Lesenswert?

Schön das es geklappt hat :)

Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Ich habe mit deiner Neusten Version ein sehr merkwürdiges aber 
reproduzierbares verhalten entdeckt.

Ich möchte auf der Speicherkarte überprüfen ob die Datei logfile.txt 
existiert...

Das mache ich wie folgt:
1
unsigned char file_name_2[]="logfile.txt";
2
3
  if(ffileExsists(file_name_2))
4
  {
5
    text_neu("OK",90,90,1,0,0,255);
6
  }
7
  else
8
  {
9
    text_neu("ERROR",90,90,1,255,0,0);
10
  }

Problem -> Die funktion liefert immer Error zurück obwohl die Datei auf 
der Speicherkarte liegt (habe auch grossklein schreibung geachtet!) LFN 
ist aktiviert.

Prüfe ich hingegen ob die Datei test.bmp existiert, klappt der test 
einwandfrei. Beide Dateien beinhalten etwas. sind also nicht 0Byte 
gross!

Nun das ganz spezielle...

Möchte ich nun also die Datei Lesen (logfile.txt) wass ja eigentlich 
nicht gehen sollte, so wird diese angelegt und es befinden sich wieder 
zweimal die selben dateien auf der Karte. Wichtig hier zu beachten ist, 
das die Lib die neue Datei mit Grossbuchstaben erstellt egal ob ich der 
Funktion kleibuchstaben übergeben habe.

Könnte dies ein hinweis darauf sein, das in dieser funktion nicht auf 
LFN geachtet wird?

Vielleicht sagt dir meine Fehlerbeschreibung ja etwas...

Ansonsten keine Probleme :)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja klingt irgendwie danach:

Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Ersetze die Funktion in der fat.c durch die Funktion aus dem Post.
Benutzt Du die Version 0.6.2 ? Da sollte wenn Du die Datei zum lesen 
öffnest auf jeden Fall keine zweite Datei mit dem selben Namen angelegt 
werden.

Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Hallo Daniel

Ja ich habe die Funktion ersetzt... Ja ich verwende die Version 0.6.2

Ich habe das Problem gefunden...

Es scheint so, als ob die Funktion File Exists nur mit kurzen Dateinamen 
klar kommt...

Dies stört mich nicht weiter, da ich ja darauf achten kann...

Aber wollte dir halt dennoch den hinweis geben :)

von Daniel R. (zerrome)


Lesenswert?

Wenn Du mal in ffileExsists reinschaust, dann siehst du da, dass genau 
das gleiche gemacht wird, zum prüfen ob es die Datei gibt, wie beim 
öffnen.

von C. H. (hedie)


Lesenswert?

Dann ist es allerdings etwas merkwürdig das LFN nicht unterstützt wird 
obwohl ich den Schalter auf True habe. Das selbe ist es mit SDHC karten

Ich habe den schalter auf True

Aber 8GB Karten werden nicht initialisiert.... (FAT)

von Daniel R. (zerrome)


Lesenswert?

Hast Du die hier gepostete mmc_init Version benutzt?
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Hast Du die hier gepostete fat_loadFileDataFromCluster Version benutzt?
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Damit geht das auf jeden Fall.

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach was mir noch einfällt zu

>Ja ich verwende die Version 0.6.2

Das kann nicht sein. In der 0.6.2 ist der Schalter für SDHC raus 
geflogen.

von C. H. (hedie)


Lesenswert?

Daniel R. schrieb:
> Das kann nicht sein. In der 0.6.2 ist der Schalter für SDHC raus
> geflogen.

Ohhh.... schande... Tut mir leid... ja du hast recht... ich habe auch 
keinen.

Daniel R. schrieb:
> Hast Du die hier gepostete mmc_init Version benutzt?
> Beitrag "Re: MMC SD library FAT16 FAT32 read write"
>
> Hast Du die hier gepostete fat_loadFileDataFromCluster Version benutzt?
> Beitrag "Re: MMC SD library FAT16 FAT32 read write"
>
> Damit geht das auf jeden Fall.
>
> Viele Grüße

Ich habe diese Version von der du mir den link gesendet hast.

von Daniel R. (zerrome)


Lesenswert?

Ok, Du brauchst die Version 0.6.2 hier aus dem Thread und dann musst Du 
die beiden Funktionen austauschen. Die Beiden Funktionen aus den Links 
die ich gepostet hab. Dann wird es klappen. Bin wie gesagt noch nicht 
dazu gekommen die einzubauen und das ins SVN hochzuladen.

Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Ok

Vielen Dank

Ich werde die Anpassungen vornehmen und eventuelle probleme wieder 
fragen wenn ich darf :)

Ich denke das ich dann auch mit den Verzeichnissen arbeiten kann... Das 
klappt mommentan auch noch nicht

von johnn (Gast)


Lesenswert?

Und hast du in library behandelt Ergennung der Karte und Schutz von 
Überschreibung ?

von johnn (Gast)


Lesenswert?

und wo muss ich die Karte anschliessen ? Ich habe ATMega 168.
in mmc.h schreibt mann
1
    #if defined (__AVR_ATmega168__)
2
                #define SPI_MISO                        4  //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
3
                #define SPI_MOSI                3  //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
4
                #define SPI_Clock                       5  //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
5
                #define SPI_SS                          2  //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist (CS)
6
        #endif
 - CS (Karte) - PB2 (ATMEga168)


und hier in der Tabelle 
http://www.mikrocontroller.net/articles/AVR_FAT32
schreibt man CS (Karte) - PB1 (ATMEga168)


Was ist richtig ?

von Daniel R. (zerrome)


Lesenswert?

Hallo,
die Tabelle ist so zu lesen:

Pin 1 der SD/MMC Karte soll an Pin 15 des ATmega168
Pin 2 der SD/MMC Karte soll an Pin 17 des ATmega168
...
...


Bei der DIP Version des ATmega168 sieht man im Datenblatt, dass Pin 15 
des IC der Port B1 des Kontrollers ist.

>Und hast du in library behandelt Ergennung
>der Karte und Schutz von Überschreibung ?

Du meinst ob eine Karte im Slot steckt und der Hardware Schreibschutz an 
ist?
Ja da ist was in der Lib, weiß aber nicht genau ob das auf Anhieb 
funktioniert.



Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach, sorry...
Das was in den defines steht ist richtig. Hab gerade erst verstanden was 
Du meinst.

CS der Karte soll an PB2 vom ATmega168

von Kurt B. (kurt)


Lesenswert?

Kurt Bohnen schrieb:
> Leider funktioniert trotz MISO PullUP nur eine der 3 Karten. Mit der
> 0.5.9C hatten die alle funktioniert.
> Schade dass ich keine Zeit zur Fehlersuche habe.

Heute hatte ich Zeit. Das Problem war wohl, das ich "alten" Code aus dem 
SVN genommen hatte. Mit dem aktuellen Code und den Patches aus dem 
Thread hier funktionieren jetzt alle Karten!

Ein Problem bleibt immer noch:
Ich schreibe 921600 Byte auf die Karte. Kontrolle mit Win XP: Dateigröße 
und Inhalt OK. Dann nach checkdisk: Datei ist 4kB größer weil Datenmüll 
am Ende angehängt wurde.
Das passiert aber nur bei FAT32 formatierten Karten. Bei FAT16 gibt es 
keine Probleme. LFN hat keinen Einfluss.

Mfg,
Kurt

von Sven S. (schwerminator)


Lesenswert?

Moin! Ich verzweifel hier mal wieder an der Ansteuerung einer 
MicroSD-Karte (habe schon zwei verschiedene probiert). MCU ist ein 
AT90CAN128, Pegelwandler ein MAX3002. Die Verdrahtung habe ich schon 
hundertmal geprüft. MISO-Pullup (10k) habe ich auch.

Ich schaffe nicht einmal die mmc_init(). spi_read_byte() gibt immer nur 
0 zurück. Nach dem Timeout wird dann abgebrochen. Was kann ich noch 
machen, bin völlich ratlos?

Ich habe die neueste Version im Einsatz inkl. den Modifikationen aus den 
Posts hier.

von Daniel R. (zerrome)


Lesenswert?

Hm, mach doch mal ein Foto vom Aufbau.

>habe schon zwei verschiedene probiert

Wenn das nicht total außergewöhnliche Karten sind sollten die schon 
gehen.

>Nach dem Timeout wird dann abgebrochen.

Also die Timer Einstellungen sind richtig? Ist vielleicht der Timer zu 
schnell eingestellt? Überprüf mal ob die Zeiten des Timers stimmen.
Ich mache die Einstellungen um nicht nachdenken zu müssen mit 
http://clsql.med-info.com/download.html

>Ich schaffe nicht einmal die mmc_init()

Klingt für mich irgendwie nach Hardware Problem

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Daniel,
hast du eine Idee wo mein Problem liegt oder sonst jemand? Ich bin doch 
wohl nicht der einzige, der seine Karten mal mit chkdsk geprüft hat?

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo Kurt,
also ich würde mal vermuten, dass da die 2. Fat dran schuld ist.

Hast Du die Möglichkeit die Karte mal so zu formatieren, dass nur eine 
Fat angelegt wird?

Sonst kann ich mir das eigentlich nicht erklären. Besonders, weil es nur 
bei Fat32 auftritt. Bis auf die Fat Einträge selbst ist Fat16 und Fat32 
nämlich identisch.

Unter Linux würde formatieren mit nur einer Fat so aussehen:
1
mkdosfs -v -F32 -f1 -s4 -I /dev/sdb

Der Befehl erstellt ein Fat32 Dateisystem mit nur einer Fat und 4 
Sektoren pro Cluster auf dem Device sdb.

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Linux habe ich nicht. Aber ich könnte den SD Formatter 3.0 probieren.

von Sven S. (schwerminator)


Angehängte Dateien:

Lesenswert?

So ich habe jetzt mal alle Signale vor (5V, high) und hinter (3V, low) 
dem Pegelwandler aufgenommen. Herausgekommen ist der Anhang. Die kurzen 
Puls bei MISO low sind etwa 10ns lang. Kann jemand bei der Deutung des 
Bildes helfen?

von Sven S. (schwerminator)


Angehängte Dateien:

Lesenswert?

So ich habe jetzt mal je einen SPI Interpreter auf die low und high side 
gepackt. Auf der low side können auch Bytes entziffert werden - 
natürlich nicht auf der high side. Machen die Bytes Sinn? Ist der 
Pegelwandler defekt?

von Sven S. (schwerminator)


Lesenswert?

Jetzt fall ich gleich vom Glauben ab: Wenn der LogicAnalyser 
angeschlossen ist, funktioniert scheinbar alles, d.h die Test-Datei wird 
geschrieben (obwohl die aufgezeichneten Kurven anderes schließen 
lassen), ziehe ich ihn ab, geht nix mehr. Wodurch lässt sich so ein 
Verhalten erklären?
Ich habe spontan an das hier gedacht: 
http://www.eevblog.com/2011/03/11/eevblog-155-itead-studio-pcb-prototype-goof/ 
Aber ein Massefehler kann ich eigentlich ausschließen. Irgendwelche 
Ideen?

Vielen Dank im Vorraus und entschuldigung für die vielen Posts in Folge.

Gruß Sven

von Kurt B. (kurt)


Lesenswert?

Wenn ich die Karte mit dem SD Formatter 3.0 formatiere tritt das Problem 
nicht mehr auf. Aber gibt es nicht einen Workaround für die Firmware?


Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ Sven S. (schwerminator)

Hast du abblock Kondensatoren an allen IC's?
Was benutzt Du als Pegelwandler?


@ Kurt Bohnen (kurt)

Es wird dafür keinen Workaround geben. Das würde nämlich bedeuten, dass 
alle Fat Operationen zwei mal gemacht werden müssten. Die zweite Fat ist 
eigentlich gedacht um zu schauen ob es einen Unterschied gibt. Gibt es 
den muss wohl ein Fehler vorliegen. Korrigieren kann man den dann aber 
noch nicht.

Eventuell eine Alternative zu dem normalen check disk suchen.


Viele Grüße

Daniel

von Sven S. (schwerminator)


Lesenswert?

Abblockkondensatoren sind reichhaltig verbaut. Als Pegelwandler benutze 
ich einen MAX3002. Einen solchen habe ich schonmal erfolgreich mit einer 
SD-Karte betrieben, allerdings ohne MISO-Pullup, ich werde das Gefühl 
nicht los, dass sich MAX3002 und der Pullup aus welchen Gründen auch 
immer nicht vertragen. In meiner jetzigen Schaltung ist der Pullup mit 
10k dimensioniert auf der 3V-Seite des Wandlers, was jedoch 
grundsätzlich richtig sein müsste...

Gruß Sven

von Daniel R. (zerrome)


Lesenswert?

Hm, ja eigentlich schon...
Da fällt mir grad auch nix mehr zu ein.

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Daniel R. schrieb:
> @ Kurt Bohnen (kurt)
>
> Es wird dafür keinen Workaround geben. Das würde nämlich bedeuten, dass
> alle Fat Operationen zwei mal gemacht werden müssten. Die zweite Fat ist
> eigentlich gedacht um zu schauen ob es einen Unterschied gibt. Gibt es
> den muss wohl ein Fehler vorliegen. Korrigieren kann man den dann aber
> noch nicht.
>
> Eventuell eine Alternative zu dem normalen check disk suchen.

OK. Dann muss ich diesmal zu Elm Chans lib wechseln. Die ist zwar 
deutlich größer aber in dieser Hinsicht toleranter.

Trotzdem vielen Dank!

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

In Chans Lib wird die zweite Fat auch nicht beschrieben, da hast Du das 
gleiche Problem.

Das hat ja auch nix mit Tolerant zu tun. Sondern mit dem Unsinn zwei Fat 
Tabellen führen zu müssen anstelle von ordentlichen Codes um Fehler zu 
beheben. Die Idee einfach alles doppelt da hin zu schreiben ist ein 
Repetition Code und ne ganz große Glanzleistung von MS...

Du hast ja geschrieben, dass die Daten korrekt sind und nach einem check 
disk erst falsch. Vielleicht sind die ja schon vorher falsch? Poste doch 
mal die Änderungen die du gemacht hast, vielleicht kann ich dann mehr 
dazu sagen.


Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Ich bin mir jetzt fast sicher dass das FAT32 Problem bei Chan nicht 
auftritt, werde das aber nochmal prüfen.

Daniel R. schrieb:
> ganz große Glanzleistung von MS...
Da gebe ich dir Recht!

Ich kann nicht ausschließen dass jemand mein Projekt benutzt der seine 
SD-Card mit FAT32 und Windows formatiert. Wenn er dann aus welchem Grund 
auch immer checkdisk laufen lässt und die neu angelegten Dateien mit 
Müll volgestopft werden ist das weniger schön...

Daniel R. schrieb:
> Poste doch
> mal die Änderungen die du gemacht hast

Keine, nur die Portdefinitionen. Dann einfach eine neue Datei erstellen, 
900kB reinschreiben und schließen.

Ich melde mich später nochmal mit mehr Details.
Mfg,
Kurt

von JVogel (Gast)


Lesenswert?

Muss ich hier SPI verwenden oder kann ich das auch an andere Pins 
hängen?

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ JVogel (Gast)

Kannst auch an andere Pins hängen, musst dann aber software SPI benutzen 
und einschalten in der config. Zudem musst Du dann natürlich auch die 
richtigen Pins einstellen in der mmc.h

von JVogel (Gast)


Lesenswert?

OK danke, ich probier das mal die Tage aus

von Sven S. (schwerminator)


Lesenswert?

Hallo nochmals. Ich habe noch ein paar Tests gemacht:
- Auch ohne Pullup klappts nicht ohne LogicAnalyser
- Zusätzlicher 100n bringt ebenfalls nicht den gewünschten Erfolg
- Folgende Leitungen auf der High-Side des Pegelwandlers müssen an den 
LA geklemmt sein, damit es funktioniert: CS, SCK und MOSI (+ GND) - 
sprich alle Leitungen in Richtung der SD. Die Eingangsimpedanz des LA 
ist wie folgt: 200K Ohms, paralleled by <5pF.

Welche Schlüsse kann ich aus der Information ziehen?

von JVOGEL (Gast)


Lesenswert?

Bei mir hängt das programm bei  mmc_enable(); nach dem SPI_INIT

mmc_send_cmd(CMD0, 0)
->if ( FALSE == mmc_enable() )

dort bleibt es hängen woran kann das liegen?

Hab einen Atmega32@16mhz

Timer :
1
  TCCR0 = (1<<CS02) | (1<<CS00) | (1<<WGM01);
2
  TCNT0 = START_TCNT;
3
  OCR0 = TOP_OCR;
4
5
ISR (TIMER0_COMP_vect)
6
{
7
  TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;
8
    
9
}

mmc.h
1
  #define MMC_Write     PORTC  //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
2
  #define MMC_Read     PINC
3
  #define MMC_Direction_REG DDRC
4
5
  #if defined (__AVR_ATmega32__)
6
    #define SPI_MISO       3  //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
7
    #define SPI_MOSI        2  //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
8
    #define SPI_Clock       1  //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
9
    #define SPI_SS          0  //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist (CS)
10
  #endif

mmc_config.h
1
    //#####################################################################################
2
  // WICHTIGE SCHALTER
3
4
  // schalter die den funktionsumfang aendern bzw, den funktionsumfang einiger funktionen :)
5
  #define MMC_WRITE       TRUE  // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
6
  #define MMC_OVER_WRITE     FALSE  // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien ueberschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
7
  #define MMC_MULTI_BLOCK   FALSE  // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber moeglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
8
  #define MMC_ENDIANNESS_LITTLE   TRUE  // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
9
  #define MMC_LFN_SUPPORT    FALSE  // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
10
  #define MMC_RM_FILES_ONLY  TRUE  // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
11
12
  // schalter die explizit funktionen mit kompilieren oder nicht!
13
  #define MMC_TIME_STAMP     FALSE   // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
14
  #define MMC_RM         FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
15
  #define MMC_SEEK      TRUE  // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
16
  #define MMC_MKDIR      FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
17
  #define MMC_GET_FREE_BYTES  FALSE  // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
18
  #define MMC_LS        FALSE  // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
19
  #define MMC_CD        FALSE  // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
20
  #define MMC_FILE_EXSISTS  FALSE  // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
21
  #define MMC_WRITE_STRING  TRUE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.
22
  #define MMC_WRITEN      FALSE  // TRUE  und MMC_WRITE TRUE, dann wird die funktion ffwriten mit kompiliert.  mit dieser funktion koennen mehrere zeichen auf die karte geschrieben werden!
23
24
  // vorsicht, da die variable die die sektoren zaehlt ein short ist (MMC_MAX_CLUSTERS_IN_ROW*fat.secPerClust) !!
25
  #define MMC_MAX_CLUSTERS_IN_ROW 256   // gibt an wie viele cluster am stueck ohne fat-lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
26
27
//#####################################################################################
28
  // SPI EINSTELLUNGEN
29
30
  // wenn MAX_SPEED FALSE dann wird die SPI bus geschwindigkeit nicht hoch gesetzt. ist zum testen von hardware die nicht richtig läuft
31
  #define MMC_MAX_SPEED     TRUE
32
  #define MMC_STATUS_INFO   FALSE
33
34
  // software spi? wenn TRUE muessen in der mmc.h noch die pins eingestellt werden ueber die die spi kommunikation laufen soll
35
  // es werden nur pins an einem port unterstuetzt !
36
  #define MMC_SOFT_SPI   TRUE

von JVOGEL (Gast)


Lesenswert?

VCC ist 2,73V, Atmega läuft mit
5V leitungen werden aber mit einem Spannugnteiler runter gebracht.

                ______
sd |-----------[ 470 ohm]--------- Atmega(5V)
            |   --------
            |
            |
            _
           | | 620ohm
           | |
           | |
           | |
           |_|
            |
            |
          ___ GND
           _
            _

von jvogel (Gast)


Lesenswert?

Also Spannung hab ich mit dem Multimeter nachgemesse, kann es sein, dass 
die 2,7V doch noch etwas zu wenig für die SD(Microsd) karte sind?

von Daniel R. (zerrome)


Lesenswert?

Moin, bei irgend einem cmd an die Karte kann man als Parameter die 
Spannung mit angeben. Die Karte antwortet dann positiv oder nicht. Weiß 
aber grad nicht aus dem Kopf welches cmd das ist.
3,3 Volt wäre schon besser und erwarte nicht zu viel von den 
Spannungsteilern.

@ Sven S. (schwerminator)
Probier mal 1k Widerstände längst den Leitungen, quasi als Terminator...
Was sagt denn das Datenblatt vom MAX3002 zu korrekten Beschaltung?


Viele Grüße

Daniel

von jvogel (Gast)


Lesenswert?

Ok dan kram ich mal lieber in meiner kiste irgendwo hab ich noch ein 
Spannungsregler au 3V, oder ich bau mir einen Spannungseiler der mit ca 
3.3V gibt. Was denkt ihr ist die bessere Wahl?

von JVOGEL (Gast)


Lesenswert?

aber der timer ist richtig eingestellt oder?

von JVOGEL (Gast)


Lesenswert?

Hat das jemand von euch mit soft SPI am laufen?

von Kurt B. (kurt)


Angehängte Dateien:

Lesenswert?

Daniel R. schrieb:
> In Chans Lib wird die zweite Fat auch nicht beschrieben, da hast Du das
> gleiche Problem.

HELLO1.TXT wurde mit Chans Lib erstellt. TEST1.TXT mit deiner, Daniel.
Danach habe ich die Karte auf Fehler prüfen lassen. Wie man sieht ist 
HELLO1.TXT unverändert, TEST1.TXT ist genau um 4kB gewachsen.

Daher würde ich vermuten das irgendeine Variable falsch initialisiert 
wird oder falsch abgefragt, <,>,<=,>=...

Das Problem ist mir schon in früheren Versionen vor der 0.6.2 
aufgefallen.

Mfg,
Kurt

von marvin (Gast)


Lesenswert?

Hallo ich habe das gleiche problem wie jvogel. Auch an einem atmega32 
ich habe ihn auf 3.3v laufen und den timer von ihm kopiert ist der timer 
falsch?  Und oder geht nur. Soft spi nicht? Sry schreibe vom handy aus 
dh vielleicht buchstaben drwher etc

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ Kurt Bohnen (kurt)
Tatsächlich, glaube es gibt da ein Problem in der Fat.
Es wird ein Cluster zu viel verkettet. Was erstmal an den Daten nichts 
ändert, da die Dateilänge ja stimmt. Es wird aber Platz verschenkt.
Bin das gerade am ändern.

@ marvin (Gast)
Welche Werte nimmst Du denn?

Viele Grüße

Daniel

von JVOGEL (Gast)


Lesenswert?

bei mir hat er probleme mit
1
loop_until_bit_is_set(SPSR,SPIF);

hab jetzt auch mal hardware SPI getestet, bitte hilft mir wer

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.