Forum: Projekte & Code MMC/SD-Karte mit FAT16 an AVR


von Meini (Gast)


Lesenswert?

Soweit ich dein Schaltbild verstehe, sieht alles bis auf eines gut aus.
Du solltest Three-State auf 5Volt legen. Oder schaltbar machen wenn du 
strom sparen willst! Jedenfall muss laut Datenblatt 5Volt anliegen wenn 
der Level Shifter arbeiten soll. ( ich hab die Pin zu Pin Richtigkeit 
deiner Schaltung nicht kontrolliert)

von Meini (Gast)


Lesenswert?

Ach ja noch was:

Wenn du mit dem µC erkennen willst welche Karte eingesteckt wurde 
solltest du die Schalter an den SD Slots getrennt abfragen. Ansonsten 
erkennst du immer nur einen Zustand, also Karte(n) drin.
Aber das ist nur wichtig wenn du auch wirklich beide Kartenslots 
verwenden willst, was ja gar nicht geht weil du nur ein CS durch 
schaltest und keine weiteren Ports am Level Shifter frei hast.

Aber würd ich mir noch vorher überlegen bevor du ein Layout machst.

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

das sind zwei verschiede adapter layouts
die liegen auf der platine übereinander.
Ich kann daher nur eins bestücken, je nachdem welches isch zu erst zu 
kaufen bekommmen und welches günstiger ist

von Ingo S. (ingo-s)


Lesenswert?

Hi,

ich beabsichtige Rolands card library auf der "OpenLog" Hardware Basis 
als Logger (Modellflug) einzusetzen. Das Problem ist nur, das das System 
irgentwann Spannungslos wird.

Es ist nicht kritisch, wenn die letzte Minute nicht geloggt ist. Wie ist 
der Filezustand in diesem Falle wenn die Karte anschliessend in einem PC 
ausgelesen werden soll? Ist das File leer, oder ist es bis zum letzten 
geschriebenen Buffer gefüllt?

Müsste man zwingend zyklisch einen "sync" durchführen oder sogar 
zyklisch das File schliessen und neu im append Mode öffnen? Es fallen 
alle 340ms 512 Byte Daten an.

Gruß Ingo

von holger (Gast)


Lesenswert?

>Das Problem ist nur, das das System
>irgentwann Spannungslos wird.

Dann musst du die Spannung überwachen!

>Es ist nicht kritisch, wenn die letzte Minute nicht geloggt ist. Wie ist
>der Filezustand in diesem Falle wenn die Karte anschliessend in einem PC
>ausgelesen werden soll? Ist das File leer, oder ist es bis zum letzten
>geschriebenen Buffer gefüllt?

Wenn du Pech hast und bei zu wenig Spannung schreibst kann die
ganze Datei Schrott sein. Eventuell sogar das komplette Dateisystem
auf der Karte zerstört werden.

>Müsste man zwingend zyklisch einen "sync" durchführen oder sogar

Kann man machen. Siehe aber auch oben.

>zyklisch das File schliessen und neu im append Mode öffnen? Es fallen
>alle 340ms 512 Byte Daten an.

Das könnte zu lange dauern.

von Torsten S. (tse)


Lesenswert?

> Es ist nicht kritisch, wenn die letzte Minute nicht geloggt ist. Wie ist
> der Filezustand in diesem Falle wenn die Karte anschliessend in einem PC
> ausgelesen werden soll? Ist das File leer, oder ist es bis zum letzten
> geschriebenen Buffer gefüllt?

Es fehlt einfach nur das was in den 512 Bytes 'großen' raw_block' noch 
gepasst hätte. Die Datei selbst ist immer ok und sogar für m$ lesbar.

> Müsste man zwingend zyklisch einen "sync" durchführen oder sogar
> zyklisch das File schliessen und neu im append Mode öffnen? Es fallen

Das muß man nicht denn es ist ja gerade Absicht erst einmal alles zu 
puffern und dann in einem Rutsch diesen Sektor auf die Karte zu 
schreiben.

> alle 340ms 512 Byte Daten an.

Das müßte man ausprobieren.
In meinem Fall, wo nur wenige hundert Bytes über einen langen Zeitraum 
geschrieben werden, mache ich zur Sicherheit immer einen sync. Freilich 
kostet das Performance. Hatte aber noch nie Datenverlust.

> Gruß Ingo
Torsten

von Ingo S. (ingo-s)


Lesenswert?

Hi,

bei Spannungsverlust kann ich nur über die BrownOut detection arbeiten, 
da ich auf der super kleinen Platine nicht herumlöten will.

Wenn die Datei außer dem letzten raw_block ok ist, dann ist das mehr als 
ich gehofft habe. Ich hatte befürchtet, das durch fehlende Einträge in 
der File allocation Table zu viel fehlt bzw. nicht darauf zugegriffen 
werden kann.

Also werde ich das Projekt mal angehen, die Demo Main von Rolands card 
library funktioniert schon auf der "OpenLog" Platine.

Gruß Ingo

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hi zusammen,

Im Anhang findet Ihr die neueste Version von sd-reader. Im Vergleich zur 
letzten Version wurden drei Fehler behoben:
- Ausgabe gleicher Dateinamen bei zwei direkt aufeinander folgenden 
8.3-Dateinamen.
- Berechnung falscher Clusterpositionen oberhalb von 4GB.
- Endlose Auflistung des Verzeichnisinhalts bei gültigem Eintrag direkt 
am Ende des letzten Verzeichnis-Clusters.

Viel Spaß damit!

Gruß,
Roland

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 Morbit (Gast)


Lesenswert?

Hallo,

Ich konnte es noch nicht richtig zum laufen bringen. Ich bin jetzt mal 
Schrittweise durchgegangen und habe zwei Dinge probiert, zum einen lasse 
ich eine Datei erstellen und einmal lasse ich eine auf der SD-Karte 
befindliche Datei öffnen. Letzteres klappt nicht, es kommt zum Fehler. 
Das Erstellen von Dateien klappt auch nicht richtig. Schieb ich die 
SD-Karte zum Lesen in den PC, so wird zwar die Datei angezeigt, möchte 
ich sie aber öffnen, so sagt mir Windows, dass die Datei nicht existiert 
und ob sie erstellt werden soll.

Nutze einen ATmega16L @ 8MHz und eine SanDisk 2 GB und den Code habe ich 
aus der beiliegenden main.c übernommen bzw. angepasst...

Es geht in dem Code unten nur die grüne LED an, also sollte beim 
Erstellen kein Fehler auftreten?!
Wenn ich die (von mir erstellte) Datei öffne (unten auskommentiert) 
leuchtet die rote LED, sprich ein Fehler tritt auf.

Was ich noch nicht ausprobiert habe, ist, was passiert, wenn ich eine 
Datei erstellen lasse und sie dann öffne.

Die SD-Karte formatier ich über Windows 7 und habe auch schon das Tool 
SDFormatter V2.0, welches auf der Homepage von Roland stand.
1
int main(void) {
2
  sd_raw_init();
3
4
  struct partition_struct* partition = partition_open(sd_raw_read,
5
                            sd_raw_read_interval,
6
                            sd_raw_write,
7
                            sd_raw_write_interval,
8
                            0);
9
10
  if (!partition) {
11
    partition = partition_open(sd_raw_read,
12
                  sd_raw_read_interval,
13
                  sd_raw_write,
14
                  sd_raw_write_interval,
15
                  -1);
16
17
    if (!partition) {
18
    }
19
  }
20
  
21
  struct fat_fs_struct* fs = fat_open(partition);
22
  struct fat_dir_entry_struct directory;
23
  fat_get_dir_entry_of_path(fs, "/", &directory);
24
  struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
25
26
  struct fat_dir_entry_struct file_entry;
27
  if (!fat_create_file(dd, "Test.log", &file_entry)) {
28
    //LED_RED_ON;
29
  } else {
30
    //LED_GREEN_ON;
31
  }
32
33
  /*
34
  struct fat_file_struct* fd = open_file_in_dir(fs, dd, "Track.log");
35
  if (!fd) {
36
    LED_RED_ON;
37
  } else {
38
    LED_GREEN_ON;
39
  }
40
41
  char* data = "abc";
42
  uint8_t data_len = 3;
43
  if (fat_write_file(fd, (uint8_t*) data, data_len) != data_len) {
44
    LED_RED_ON;
45
  }
46
47
  sd_raw_sync();
48
  */
49
  if (!sd_raw_sync()) {
50
    LED_RED_ON;
51
  } else {
52
    LED_GREEN_ON;
53
  }
54
  delay_s(5);
55
  LED_GREEN_OFF;
56
  LED_RED_OFF;
57
//  fat_close_file(fd);
58
  fat_close_dir(dd);
59
  fat_close(fs);
60
  partition_close(partition);
61
62
  return 0;
63
}

von Werner F. (frewer)


Lesenswert?

Hallo,

habe mir die Platine nach Riegel/Radig aufgebaut und versuche nun mal 
mit einer SD Karte 128MB zu testen. Als Prozessor verwende ich den 
ATmega328p. Die Software-Version 20101010 konnte ich ohne weiteres 
compilieren (Studio4) und mit Burn O Mat-USBasp in den Prozessor laden.
Mit einem Terminal Programm kann ich auch kommunizieren.
Ergebnis:
> disk
manuf:  0x02
oem:    TM
prod:   SD128
rev:    07
serial: 0x67783a65
date:   5/4
size:   120MB
copy:   0
wr.pr.: 0/0
format: 0
free:   122290176/125861888
> ls
DCIM/                                0
Test/                                0
> touch Myfile
error creating file: Myfile
> cat Test
error opening Test

DCIM enthält Bilder, Test enthält einen mit Editor geschriebenen kurzen 
Text.
Was mache ich falsch oder was habe ich noch nicht kapiert??

mfG
frewer

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Werner,

Schau bitte mal in die FAQ auf meiner Homepage:
  http://www.roland-riegel.de/sd-reader/faq/#faq_writefails
  http://www.roland-riegel.de/sd-reader/faq/#faq_socketcdcl

Gruß,
Roland

von Werner F. (frewer)


Lesenswert?

Hallo Klaus,

danke für Deinen Tipp. Nun ich habe gelesen und gelesen, konnte es aber 
noch nicht verwerten. Bin also genau dort noch, wo ich war. Werde mich 
doch viel tiefer in die Materie einlassen müssen, obwohl überall 
geschrieben steht, dass es ganz einfach sei.

Hi Roland,
habe die Änderungen in die config.h eingebaut, weil ich meinen Sockel 
ohne die Erkennung eingebaut habe. Die Kapazitäten waren schon immer 
drin und die Dioden aktiviere ich mit einem 2KOhm Widerstand, so dass 
immer die ca 3,5V anliegen (zusätzlich mit 1µ Tantal abgeblockt).
Trotzdem meldet die Eingabe > cat Test wieder "error opening Test".
>touch Myfile hingegen legt jetzt offenbar einen File an, denn ich bekomme mit

>ls
DCIM/     0
Test/     0
Myfile    0
>
und mit
>write Myfile 'Diesen Text sollte ich in Myfile wiederfinden'
bekomme ich
>ls
DCIM/     0
Test/     0
Myfile    35
>
und mit
>cat Myfile
00000000: 74 20 73 6f 6c 6c 74 65  't sollte'
00000008: 20 69 63 68 20 69 6e 20  ' ich in '
00000014: 4d 79 66 69 6c 65 20 77  'Myfile w'
00000018: 69 65 64 65 72 66 69 6e  'iederfin'
00000020: 64 65 6e 65 72 66 69 6e  'denerfin'

nun ein bisschen komisch aber vielleicht liegt das auch meiner Eingabe. 
Werde mal noch etwas experimentieren.
Jedenfalls vielen Dank, es geht schon was.

mfG
frewer

Sorry, hatte dazwischgeschrieben!!!!
Nun interpretiere ich das Ergebnis, dass die Datei Test keinen Inhalt 
hat (0) obwohl dort drin steht "Das Wetter ist schön" (mit dem PC über 
einen Cardreader beschrieben). Hat das mit der Methode des Schreibens 
mit dem PC zu tun???

von Roland R. (roland) Benutzerseite


Lesenswert?

Hi Werner,

1. Schau Dir mal die Syntax für den write-Aufruf an, Du verwendest den 
Befehl falsch.
2. Das mit den Dioden und dem Widerstand hab ich nicht verstanden.
3. "Test" ist doch ein Ordner, was erwartest Du denn da als Größe??
4. Bei Interpretation der cat-Ausgabe braucht man die Dateigröße, da der 
Einfachkeit halber die letzte Zeile nicht entsprechend der Dateigröße 
abgeschnitten wird. In Deinem Beispiel sind also nur noch die Bytes 0x20 
bis 0x22 gültig.

Gruß,
Roland

von frewer (Gast)


Lesenswert?

Hallo Roland,

vielen Dank für Deinen Kommentar.
Mittlerweile bin ich einen Schritt weiter und verstehe auch nach 
detaillierter Durchsicht des "main" Deine diversen Befehle.
Mit dem Widerstand zwischen der letzten Diode und Masse erzeuge ich eine 
kontinuierliche Vorspannung am SD-Adapter auch, wenn die Karte entnommen 
wird.
Nicht ganz kapiere ich bis jetzt die Anzeige für die Datei Test\ mit der 
Angabe der Größe 0. Denn die Datei enthält, genau wie meine Datei Myfile 
einen kurzen Text und ist kein Directory. Warum kann ich also Myfile 
lesen aber Test nicht?

Bin jetzt dabei, mal ein paar eigene Befehle zu schreiben. Mal gespannt 
wie das klappt.

mfG
Werner

von Roland R. (roland) Benutzerseite


Lesenswert?

Hi Werner,

"Test" wird als Verzeichnis interpretiert, das zeigt der Schrägstrich 
nach dem Namen an. Insofern ist auch klar, warum Du "Test" nicht 
ausgeben kannst.

Kannst Du mit
> cd Test
in das Verzeichnis wechseln? Wenn ja, was zeigt
> ls
an?

Gruß,
Roland

von Werner F. (frewer)


Lesenswert?

Hallo Roland,
ja, das hat funktioniert. Ich komme in das Verzeichnis Test mit cd .. 
und finde dann eine Datei mit meinem Text. Um nicht dauernd die Wandlung 
HEX in Zeichen händisch machen zu müssen, habe ich Deine Routine cat 
geändert und bekomme nun den Text der Datei als Zeichen ausgedruckt. 
Allerdings nur gewandelt, d.h. auch der alte Müll in der Datei wird 
ausgedruckt. Meine Frage ist, warum wird das Endezeichen der Datei nach 
der Eingabe nicht gesetzt und warum der Ausdruck nicht an diesem 
Endezeichen beendet? Sowohl in cat ... als auch in "meinem" read, das ja 
identisch Deinem cat .. ist.

// Eingabe read: - Datei-Inhalt als Text ausgeben
            else if(strncmp_P(command, PSTR("read "), 5) == 0)
            {
                command += 5;
                if(command[0] == '\0')
                    continue;

                /* search file in current directory and open it */
                struct fat_file_struct* fd = open_file_in_dir(fs, dd, 
command);
                if(!fd)
                {
                    uart_puts_p(PSTR("error opening "));
                    uart_puts(command);
                    uart_putc('\n');
                    continue;
                }

                /* print file contents !!meine kleine Änderung!!*/
                uint8_t buffer[8];
                while(fat_read_file(fd, buffer, sizeof(buffer)) > 0)
                {
                 for (i=0;i<8;i++) {uart_putc(buffer[i]);}
                }
                uart_putc('\n');
                fat_close_file(fd);
            }
///
Kann das sein, dass das '\0' im write command nicht bei jeder Eingabe 
als Endekennung geschrieben wird?

mfG
Werner

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Werner,

Es gibt kein "Endezeichen" in einer Datei. Jedes Byte in einer Datei ist 
gültig, somit kann es kein Byte mit einer Sonderbedeutung geben. Auch 
'\0' hat keine besondere Bedeutung. Den FAT-Funktionen werden deshalb 
die Daten immer als Tupel (Puffer, Länge) übergeben, und nicht nur als 
(Puffer).

Mein write-Befehl schreibt die eingegebenen Zeilen nacheinander in die 
Datei, ohne Trennung dazwischen (auch kein Leerzeichen, es sei denn man 
gibt es explizit ein). Wenn Du da Null-Bytes oder was auch immer 
dazwischen haben willst, musst Du die write-Implementierung eben 
entsprechend abändern.

Dass "alter Müll" in der Datei steht, liegt daran, dass die Datei nicht 
gekürzt wird. Wenn Du z.B.
> write test.txt 25
sagst, wird der Dateiinhalt ab Byte-Offset 25 mit den von Dir 
eingegebenen Zeichen überschrieben, bzw. an die Datei angehängt. Wenn Du 
aber weniger Zeichen eingibst als die Datei bereits lang ist, bleiben 
die alten (nicht überschriebenen) Daten eben bestehen. Auch das kannst 
Du natürlich ändern (fat_resize_file()).

Denk bitte auch daran, dass der Puffer für die Kommandozeile nur 24 
Zeichen lang ist und beim Erreichen der Maximallänge implizit ein Enter 
angenommen wird.

Viele Grüße,
Roland

von Werner F. (frewer)


Lesenswert?

merci Roland,
ich glaube, dass ich die Syntax jetzt verstanden habe.
Mit meinem \0 dachte ich an das Ende eines STRING und diesen Wert wollte 
ich zum Begrenzen der Ausgabe benutzen. Wenn ich das write Kommando 
richtig verstehe, dann wird auch \0 abgefragt und in die Datei 
geschrieben. D.h. ich kann in meinem Read Kommando die "Endeabfrage" 
implementieren ohne das write Kommando anzutasten.

Jetzt verstehe ich auch, warum immer wieder bei der Eingabe das < 
Zeichen kam. Hatte mich schon gewundert. Aber dem Grunde nach verändert 
das ja nicht den Inhalt in der datei.

Summa summarum läuft es mit meinem kleinen ATmega328p und der Karte 
richtig prima. Wenn ich noch was vertrauter bin, dann kann ich damit 
"durchstarten". Z.Zt. bin ich dabei, die Routinen zu verstehen - was 
schon ganz schön schwierig ist (bin halt älteres Semester) - aber ich 
komme langsam voran.

Nochmals Dank und bis zur nächsten Frage
mfG
Werner

von Werner F. (frewer)


Lesenswert?

Hi Roland,

habe noch ein Versuchsergebnis mit dem ich noch nicht umgehen kann.
Ich habe folgende Baum auf der SD-Karte:

DCIM/
Test/
Myfile

Ich gehe mit cd Test in ein das Directory Test und beschreibe dort zB 
einen File. Jetzt möchte ich in das Directory DCIM/ mit zB cd DCIM oder 
cd /DCIM. Wäre schön geht aber nicht. Auch komme ich nicht in das Root 
Dir außer natürlich mit "init".

Gibt es da eine Hilfestellung?
Grüße vom Rhein nach ??
Werner

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Werner,

In der Beispiel-Shell der main.c beziehen sich die meisten Operationen 
auf das aktuelle Verzeichnis. FAT stellt für jedes Verzeichnis die 
Spezialnamen "." und ".." bereit. Dabei steht "." für das aktuelle 
Verzeichnis und ".." für das übergeordnete Verzeichnis.

Dein Ziel erreichst Du also so:
> cd Test
> ls
...
> cd ..
> cd DCIM
> ls
...

Denk bitte dran, das ist ein ganz primitiver Prompt, mit relativen 
Pfaden und dergleichen kann der nichts anfangen (wenngleich man das 
natürlich programmieren könnte).

Viele Grüße,
Roland

von Werner F. (frewer)


Lesenswert?

Hallo Roland,

bei aller Liebe, die Variante der Eingabe konnte ich Deiner Beschreibung 
nicht entnehmen. Aber man lernt ja nicht aus. Es klappt prima so. Nun, 
das ganze ist ja mehr zum Lernen als zum Anwenden gedacht. Meine Absicht 
ist eh nur einfache Datenspeicherung. Aber Deine Programmsystem hat mich 
gleich fasziniert, weil es für mich sehr professionell aussieht und mich 
beim Durcharbeiten immer wieder überrascht, weil ich die gegenseitigen 
Links immer suche und außer den eindeutigen Zuordnungen FAT_, 
Partition_,sd_raw usw immer lange suche, bis ich den "Link" finde. Aber 
es macht viel Spaß.

Danke für die rasche Hilfe und Grüße von der Hochwasser-Front
Werner

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo alle miteinander,

Als kleines Update zwischendurch gibts eine neue sd-reader-Ausgabe. Die 
wichtigsten Änderungen:
- Umbenennung bzw. Verschieben von Dateien und Verzeichnissen.
- Korrekturen bei der Behandlung von Little-Endian-Integern auf 16- und
  32-Bit-Architekturen.
- Zusätzlichen Rückgabewert für fat_create_file(), um bereits
  existierende Dateien zu erkennen.
- Doku zum Auslesen der aktuellen Dateiposition mittels fat_seek_file().

Wie immer findet Ihr das Update im Anhang oder unter
  http://www.roland-riegel.de/sd-reader/

Gruß,
Roland

von Martin (Gast)


Lesenswert?

Hallo,

für ein Projekt benötige ich die folgenden Funktionen.
 - get Anzahl der Zeilen in einem file
 - get Zeile, Nummer ... aus dem file zurück

Hat schon jemand solch eine Funktion geschrieben und würde diese mir zur 
verfügung stellen?

Vielen Dank
martin

von Stefan W. (stepw)


Lesenswert?

eine kleine Frage, kann man die SD-Karte an beliebigen Ports anschließen 
oder muß es immer Hardware-MOSI/MISO/SCK sein?

von Martin (Gast)


Lesenswert?

vom Programm wird nur der Hardware SPI unterstützt...
Software SPI wäre aber auch möglich, muss du dann nur selber 
implementieren.

von Stefan W. (stepw)


Lesenswert?

danke für die info - schade, da wüßte ich jetzt nicht wie das gehen 
sollte.

von Martin (Gast)


Lesenswert?

So ich hab jetzt mal einen ersten entwurf meiner getLine funktion 
geschrieben. Die funktion läuft.

Hat jemand vielleicht noch eine Idee wie man die Funktion schneller und 
effektiver gestalten kann. Vielleicht könnte man auch einen Zeielen 
Abschnitt sich zurückgeben lassen... also von Zeile x bis Zeile y.

Ich hoffe es haben einige Interesse.
1
//##########################################################################################
2
uint8_t file_getLine(uint16_t lineNr,char* zielbuffer)// anzahl Zeilen aktuelles file
3
{ // Rückgabe der Zeilenlänge
4
  // maximale Zeilenlänge von 40 Zeichen
5
  
6
  if(fd)
7
  {
8
    if (lineNr < 1 ) {return 0;}
9
    
10
    uint16_t   counterLines  =0;
11
    int32_t   pos_after_last_enter   = 0;
12
    uint8_t   arbeitsbuffer[40];  
13
    uint8_t    count;
14
15
    //########## Anfang der n-ten Zeile suchen und position in "pos_after_last_enter" zurückgeben
16
    //########## es werden alle '\n' gezählt bis die Anfangsposition der gesuchten Zeile gefunden ist
17
        
18
    while(counterLines < lineNr-1)
19
      {
20
      if(!fat_seek_file(fd, &pos_after_last_enter, FAT_SEEK_SET)) {/* error*/}
21
      
22
      count = fat_read_file(fd, arbeitsbuffer, 40);
23
      for(intptr_t i = 0; i < count; ++i)
24
        {
25
        if(arbeitsbuffer[i] == '\n')  
26
          {
27
          counterLines++;
28
          pos_after_last_enter+=i+1;// Zeiger auf Zeichen nach dem letzten Enter
29
          break;
30
          }
31
        }
32
      }
33
    
34
    //########## Daten ab der gefundenen Position auslesen und in Zielbuffer schreiben    
35
    if(!fat_seek_file(fd, &pos_after_last_enter, FAT_SEEK_SET)) {/* error*/}
36
    count = fat_read_file(fd, arbeitsbuffer, 40);
37
    
38
    for(intptr_t i=0; i<count; ++i)
39
      {
40
      zielbuffer[i] = arbeitsbuffer[i];      
41
      if(arbeitsbuffer[i] == '\n')  
42
        {
43
        zielbuffer[i+1] = 0;
44
        return i; // return Zeilenlänge
45
        }
46
      }
47
  }
48
  return 0;
49
}

von nlsgs (Gast)


Lesenswert?

Zu erst möchte Ich “danke schon” sagen. Ihr Project hilft mir wirklich 
schnell voran. Aber dann habe ich noch eine frage;

Moderne AVR können sich selbst programmieren. Wäre es möglich einen AVR 
aus eine Datei zu laden? Sagen wir mal das wenn es auf eine SD-Karte 
eine Datei namens „imageXXX.avr“ gibt diese geladen wird falls der 
Nummer XXX größer ist als die heutige Versionsnummer. Oder müsste man 
eine .hex Datei laden können?

Verzeihung für mein Deutsch, aber ich nehme an man versteht wo die 
Gedanken gehen.

von Werner B. (werner-b)


Lesenswert?


von Steffen (Gast)


Lesenswert?

Hallo Roland,

erstmal ein großes danke schön für die Bibliohek. Nach einigen 
Startschwierigkeiten bin ich nun doch in der Lage, damit Dateien zu 
lesen, anzulegen und zu schreiben. Allerdings möchte ich mit der 
Bibliothek MP3's auslesen und zu einem Decoder schicken. Hier gibt es 
aber Probleme. Habe zum Testen nun eine .txt angelegt mit 64 Zeichen 
Inhalt.
Die ersten 32 werden auch korrekt in den Buffer gelesen, das wars dann 
aber auch. Das Programm durchläuft einmal die Schleife und springt dann 
raus, obwohl noch 32 neue Bytes darauf warten, gelesen zu werden.
1
void play_sound(const char *file_name, struct fat_fs_struct* fs, struct fat_dir_struct* dd)
2
{
3
  int32_t bytesRead = 0;
4
  int32_t totalBytesRead = 0;
5
  int countVar;
6
        uint8_t songbuffer[32];
7
        struct fat_file_struct* fd;
8
9
  fd = open_file_in_dir(fs, dd, file_name);   
10
        bytesRead = fat_read_file(fd, songbuffer, 32);
11
  
12
        while(bytesRead > 0)  
13
  {
14
    totalBytesRead+=bytesRead;
15
    fat_close_file(fd);
16
    unselect_card();
17
18
// hier steht ein Routine zum senden des Buffer-Inhaltes an den Decoder
19
...
20
//
21
                select_card();
22
                fd = open_file_in_dir(fs, dd, file_name);
23
          fat_seek_file(fd,&totalBytesRead,FAT_SEEK_SET); 
24
    bytesRead = fat_read_file(fd, songbuffer, 32);
25
   }
26
    fat_close_file(fd);
27
}

Hoffe, mir kann geholfen werden.

Gruß
Steffen

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Steffen,

Mal davon abgesehen, dass das so fürchterlich ineffizient ist, sollte es 
schon funktionieren.

Könntest Du bitte zuerst mal sicherstellen, dass alle Funktionsaufrufe 
Erfolg zurückmelden? Was passiert, wenn die Datei 32 Bytes länger ist? 
Wird dann die Schleife einmal mehr durchlaufen? Was macht eigentlich das 
select_card()/unselect_card() in der Schleife?

Gruß,
Roland

von Steffen (Gast)


Lesenswert?

Hallo Roland!

Danke für die Antwort. Hatte ich vergessen mit reinzuschreiben, der 
Decoder hängt auch am SPI, daher muss ich die MMC vor jedem neuen 
Leseaufruf neu anwählen bzw. bevor ich die Daten zum Decoder schicke 
abwählen. Und ja, wenn mehr als 32 Bytes zu lesen sind, soll die 
Schleife nochmal durchlaufen werden.
Wie würde denn eine effizientere Variante aussehen? Bin für Hinweise 
etc. offen. :)

Gruß
Steffen

von Steffen (Gast)


Lesenswert?

Mal ein kleines Update: Ohne SPI-Übertragung an den Decoder wird die 
Datei jetzt ordentlich ausgelesen. Wenn ich allerdings die Übertragung 
wieder mit reinnehme, wird mir im zweiten Schleifendurchlauf beim Aufruf 
von fat_read_file eine -1 zurückgegeben. Laut Debugger wird der Fehler 
direkt bei der Parameterüberprüfung in fat_read_file ausgegeben.
Kann mir das nicht erklären, ich verändere weder fd, noch den songbuffer 
noch die Bufferlänge.

Gruß
Steffen

von Steffen (Gast)


Lesenswert?

Scheinbar geht die Information für fd verloren, obwohl der es über 
open_file_in_dir nach dem Übertragen an den Decoder wieder geladen wird. 
Jedenfalls gibt er bei der Parameterüberprüfung von fd in fat_read_file 
-1 zurück.

von Steffen (Gast)


Lesenswert?

Hallo Roland,

hab das Problem gelöst gekriegt. Manchmal hilft es, wenn man sich 
nochmal alle Pin-Deklaration anguckt.
Du meintest, dass meine Variante sehr ineffizient ist. Das macht sich 
auch akustisch bemerkbar. Wie würde Deiner Meinung nach eine 
effizientere Funktion aussehen?

Gruß
Steffen

von holger (Gast)


Lesenswert?

>Du meintest, dass meine Variante sehr ineffizient ist. Das macht sich
>auch akustisch bemerkbar. Wie würde Deiner Meinung nach eine
>effizientere Funktion aussehen?

So vieleicht? Datei offen halten bis der Song fertig ist.
1
void play_sound(const char *file_name, struct fat_fs_struct* fs, struct fat_dir_struct* dd)
2
{
3
  int32_t bytesRead = 0;
4
  int countVar;
5
        uint8_t songbuffer[32];
6
        struct fat_file_struct* fd;
7
8
  fd = open_file_in_dir(fs, dd, file_name);   
9
  if(fd)
10
   {
11
    do
12
    {
13
     bytesRead = fat_read_file(fd, songbuffer, 32);
14
15
// hier steht ein Routine zum senden des Buffer-Inhaltes an den Decoder
16
...
17
//
18
    } while(bytesRead > 0)  
19
    fat_close_file(fd);
20
  }
21
}

von holger (Gast)


Lesenswert?

Nachtrag: kleine Verbesserung;)
1
void play_sound(const char *file_name, struct fat_fs_struct* fs, struct fat_dir_struct* dd)
2
{
3
  int32_t bytesRead = 0;
4
  int countVar;
5
        uint8_t songbuffer[32];
6
        struct fat_file_struct* fd;
7
8
  fd = open_file_in_dir(fs, dd, file_name);   
9
  if(fd)
10
   {
11
    do
12
    {
13
     bytesRead = fat_read_file(fd, songbuffer, 32);
14
     if(bytesRead > 0)
15
     {
16
// hier steht ein Routine zum senden des Buffer-Inhaltes an den Decoder
17
...
18
//
19
     }
20
    } while(bytesRead > 0)  
21
    fat_close_file(fd);
22
  }
23
}

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Steffen,

So wie Holger geschrieben hat, sollte es schon wesentlich besser 
funktionieren. Es ist einfach nicht notwendig, die Datei ständig zu 
schließen, wieder zu öffnen und die Leseposition neu zu setzen. Das sind 
alles Operationen, die relativ aufwendig sind. Je nachdem, wieviel RAM 
Du noch frei hast, sollte der Puffer zum Lesen der Daten auch noch 
wesentlich vergrößert werden. Das ist im Vergleich zu den 
Dateioperationen aber nicht mehr ganz so wichtig.

Gruß,
Roland

von Steffen (Gast)


Lesenswert?

Hallo zusammen!

An der Stelle wollte ich mich einfach nochmal für die schnelle Hilfe 
bedanken, die mir zuteil wurde. :)

Gruß
Steffen

von Daniel (Gast)


Lesenswert?

Hallo Roland,

ich möchte Daten (Texte) mit einem ATmega2560 auf eine SD-Card 
schreiben, die dann später am PC ausgelesen werden sollen.
Deine Daten (Version 20110243) habe ich übernommen. Da an meiner MCU ein 
LCD und einige Taster sind, benötige ich "alles" mit "uart" nicht. 
Meldungen gehen ans LCD.
Nun das Problem: "sd_raw_init" und "Partition_open" wird ausgeführt, 
aber dann kommt die Meldung "opening filesystem failed".
Ich vermute, dass die Hardware OK ist, da "...init" und "...open" 
durchlaufen werden. Wieso es aber bei "fs_open" nicht geht weis ich 
(noch) nicht.
Über Infos würde ich mich freuen.

Vielen Dank!
MfG Daniel

von Frank H. (gowi)


Lesenswert?

Alex K. schrieb:
> Martin Wende schrieb:
>> Im 8.3 Format muss der Dateiname komplett aus Großbuchstaben bestehen.
>> Sonst zickt win wenns auf der SD Karte liegt.
> Juhu, das wars.... !!!
> DANKE!!!!!!!!
>
> Meine Einstellungen sind nun:
>
> #define FAT_LFN_SUPPORT 0
> #define FAT_DELAY_DIRENTRY_UPDATE 0
> #define SD_RAW_SDHC 0
> #define SD_RAW_WRITE_BUFFERING 1
>
> und ein sd_raw_sync(); nach jedem schreiben.
>
> Danke euch, ihr habt meinen Tag gerettet...

Also ich habe das gleiche Problem. Es werden zwar Dateien auf der 
SD-Karte erzeugt (microSD mit 2 GB, FAT16, kein SDHC), aber die sind 
leer. Ich habe die gleichen Optionen eingestellt und nur Großbuchstaben 
benutzt. Leider keine Änderungen. Wenn ich chkdsk /F durchlaufen lassen, 
bekomme ich die Meldung, dass "verlorene Ketten" gefunden wurden. Wenn 
chkdsk diese Dateien wiederherstellt, kann ich mir den Inhalt der 
Dateien im Ordner "FOUND.000" anzeigen lassen. Mein Code sieht so aus:
1
int main()
2
{
3
        /* setup sd card slot */
4
        if(!sd_raw_init())
5
        {
6
#if DEBUG
7
            uart_puts_p(PSTR("MMC/SD initialization failed\n"));
8
#endif
9
            continue;
10
        }
11
12
        /* open first partition */
13
        struct partition_struct* partition = partition_open(sd_raw_read,                                              sd_raw_read_interval,
14
                                                            0,
15
                                                            0,
16
                                                            0
17
                                                           );
18
19
        if(!partition)
20
        {
21
            /* If the partition did not open, assume the storage device
22
             * is a "superfloppy", i.e. has no MBR.
23
             */
24
            partition = partition_open(sd_raw_read,
25
                                       sd_raw_read_interval,
26
                                       0,
27
                                       0,
28
                                       -1
29
                                      );
30
            if(!partition)
31
            {
32
#if DEBUG
33
                uart_puts_p(PSTR("opening partition failed\n"));
34
#endif
35
                continue;
36
            }
37
        }
38
39
        /* open file system */
40
        struct fat_fs_struct* fs = fat_open(partition);
41
        if(!fs)
42
        {
43
#if DEBUG
44
            uart_puts_p(PSTR("opening filesystem failed\n"));
45
#endif
46
            continue;
47
        }
48
49
        /* open root directory */
50
        struct fat_dir_entry_struct directory;
51
        fat_get_dir_entry_of_path(fs, "/", &directory);
52
53
        struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
54
        if(!dd)
55
        {
56
#if DEBUG
57
            uart_puts_p(PSTR("opening root directory failed\n"));
58
#endif
59
            continue;
60
        }
61
        
62
  struct fat_dir_entry_struct fdes;
63
  uint8_t ret_value;
64
  struct fat_file_struct* ffs;
65
  ret_value = fat_create_file(dd, "ABDEEFGH.TXT", &fdes);
66
  if (ret_value == 1) {
67
    ffs = fat_open_file(fs, &fdes);
68
    if (!ffs) {
69
      uart_puts_p("a");
70
    }
71
    fat_write_file(ffs, "Hello World", 12);
72
    fat_close_file(ffs);
73
    /* close directory */
74
    fat_close_dir(dd);
75
    /* close file system */
76
    fat_close(fs);
77
    /* close partition */
78
    partition_close(partition);
79
    while (1) {}
80
}

von Torsten S. (tse)


Lesenswert?

Probier mal sd_raw_sync() nach write/close damit die buffer vom ram auch 
auf die Karte geschrieben werden bevor Du diese entfernst oder den Saft 
abdrehst.

von Martin (Gast)


Lesenswert?

Hallo,
ich versuche mich gerade am Erzeugen einer Datei und komme dabei nicht 
weiter, mein Code sieht so aus:
1
int connect_sd(void)
2
{
3
  struct partition_struct* partition;
4
  struct fat_dir_struct* dd;
5
  struct fat_fs_struct* fs;
6
  
7
  if(!sd_initiated)
8
  {
9
    if(!sd_raw_init())
10
    {
11
      uart_puts("MMC/SD initialization failed\n");
12
    }
13
    else
14
    {
15
      sd_initiated=1;
16
      uart_puts("MMC/SD initialization successful\n");
17
    }
18
  }
19
  if(sd_initiated)
20
  {
21
    struct partition_struct* partition = partition_open(  sd_raw_read,
22
    sd_raw_read_interval,
23
    sd_raw_write,
24
    sd_raw_write_interval,
25
    0
26
    );
27
    if(!partition)
28
    {
29
      partition = partition_open(sd_raw_read,
30
      sd_raw_read_interval,
31
      sd_raw_write,
32
      sd_raw_write_interval,
33
      -1
34
      );
35
      if(!partition)
36
      {
37
        uart_puts("opening partition failed\n");
38
      }
39
    }
40
    if(partition!=0)
41
    {
42
      sd_partitioned = 1;
43
      uart_puts("partition found\n");
44
      fs = fat_open(partition);
45
      if(!fs)
46
      {
47
        uart_puts("opening filesystem failed\n");
48
      }
49
      struct fat_dir_entry_struct directory;
50
      fat_get_dir_entry_of_path(fs, "/", &directory);
51
      dd = fat_open_dir(fs, &directory);
52
      if(!dd)
53
      {
54
        uart_puts("opening root directory failed\n");
55
      }
56
      else
57
      {
58
        uart_puts("opening root directory successful\n");
59
        sd_root=1;
60
      }
61
    }
62
    if(sd_root!=0)
63
    {
64
      struct fat_dir_entry_struct* fd;
65
      struct fat_file_struct* ffs;
66
      if(fat_create_file(dd,"BLABLA.TXT",&fd)!=0)
67
      {
68
        ffs = fat_open_file(fs,&fd);
69
        fat_write_file(ffs,"teststring",11);
70
      }
71
      else
72
      {
73
        uart_puts("failed to create file\n");
74
      }
75
      fat_close(fs);
76
      partition_close(partition);
77
    }
78
  }
79
  return sd_root;
80
}
Bis zum öffnen des root Verzeichnisses klappt es, dann bekomme ich die 
Fehlermeldung "failed to create file". Wäre super wenn hier jemand einen 
Tipp hätte!
Viele Grüße,
Martin

von Martin (Gast)


Lesenswert?

Am Schluss muss es natürlich
1
if(sd_root!=0)
2
    {
3
      struct fat_dir_entry_struct* fd;
4
      struct fat_file_struct* ffs;
5
      ffs = fat_create_file(dd,"BLABLA.TXT",&fd);
6
      if(ffs!=0)
7
      {
8
        ffs = fat_open_file(fs,&fd);
9
        fat_write_file(ffs,"teststring",11);
10
      }
11
      else
12
      {
13
        uart_puts("failed to create file\n");
14
      }
15
      fat_close(fs);
16
      partition_close(partition);
17
    }
 heissen!

von Martin (Gast)


Lesenswert?

Bekomme jetzt war "writing successfull", die Datei "TEST.TXT" bleibt 
aber leer. Woran könnte das liegen?
1
if(sd_root!=0)
2
    {
3
      struct fat_file_struct* fd = open_file_in_dir(fs, dd, "TEST.TXT");
4
      if(!fd)
5
      {
6
        uart_puts("could not open test.txt\n");
7
      }
8
      else
9
      {
10
        fat_write_file(fd,"testzeile",15);
11
        sd_raw_sync();
12
        uart_puts("writing sucessfull\n");
13
      }
14
      
15
      fat_close(fs);
16
      partition_close(partition);
17
    }

von Martin (Gast)


Lesenswert?

Habe es nun gelöst, der Fehler lag im Schreibschutz, hatte das im 
config-file nicht richtig angepasst. Ansonsten danke für die super Bib!

von Dirk B. (garag)


Lesenswert?

Martin schrieb:
>
1
if(sd_root!=0)
2
>     {
3
>       struct fat_dir_entry_struct* fd;
4
>       struct fat_file_struct* ffs;
5
>       ffs = fat_create_file(dd,"BLABLA.TXT",&fd);
6
>       if(ffs!=0)
7
>       {
8
>         ffs = fat_open_file(fs,&fd);
9
>         fat_write_file(ffs,"teststring",11);
10
>       }
11
>       else
12
>       {
13
>         uart_puts("failed to create file\n");
14
>       }
15
>       fat_close(fs);
16
>       partition_close(partition);
17
>     }

Die Funktion fat_create_file() erwartet doch einen Zeiger auf die 
fat_dir_entry_struct Struktur und keinen Zeiger auf einen Zeiger.

Müsste es nicht wie folgt anfangen (vor fd kein Stern)?
1
if(sd_root!=0)
2
{
3
    struct fat_dir_entry_struct fd;
4
    struct fat_file_struct* ffs;
5
    ffs = fat_create_file(dd,"BLABLA.TXT",&fd);

von Sven W. (sven_w18)


Lesenswert?

Hi !

Ich habe ein Problem mit dem Timing beim Öffnen einer Datei.

Und zwar liest mein Programm WAV-Dateien von der SD und gibt diese über 
den PWM des Atmega168 wieder. Die Daten werden gepuffert.

Die Dateien werden per Dateiname ausgewählt.

Nur habe ich, wenn ich die Datei wechseln will, eine unschöne Pause 
zwischen den Tracks.


sound_file=open_file_in_dir(fs, dd, dateiname);

Dauert verhältnismäßig lange.


Ziel des Programms soll sein, eine Schaltung mit Lagesensor und Tastern, 
die jeh nach Lage oder Tastendruck einen Sound wiedergibt.
z.B. Modellbau-Schiff: Motor an, Motor läuft schnell, Motor läuft 
langsam, Hupe, Motor aus usw.


Hat jemand eine Idee, wie ich ohne nennenswerte Zeitverzögerung die 
Dateien hintereinander abspielen kann?

1
uint8_t find_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name, struct fat16_dir_entry_struct* dir_entry)
2
{
3
    while(fat16_read_dir(dd, dir_entry))
4
    {
5
        if(strcasecmp(dir_entry->long_name, name) == 0)
6
        {
7
            fat16_reset_dir(dd);
8
            return 1;
9
        }
10
    }
11
12
    return 0;
13
}
14
15
//***************************************************************
16
17
struct fat16_file_struct* open_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name)
18
{
19
    struct fat16_dir_entry_struct file_entry;
20
    if(!find_file_in_dir(fs, dd, name, &file_entry))
21
        return 0;
22
23
    return fat16_open_file(fs, &file_entry);
24
}

von ruepel (Gast)


Lesenswert?

Servus,

an dieser Stelle möchte ich mich bei Roland Riegel bedanken.
Die Sourcen arbeiten einwandfrei.

Egal, ob MMC, SD, 32GB oder 2GB.

Gut gemacht. Ich hatte mir eine zeitlang überlegt, auf FatFs von ELM 
umzusteigen, aber das braucht es nicht.

Gruß Klaus

Beitrag #5847275 wurde von einem Moderator gelöscht.
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.