Sorry das ich nicht eher zurückschreibe. Ein wenig Stressig die letzte
Zeit :). Also die Usart hat mir die gleichen fehlerhafen Ausgaben
gemacht. Darum denke ich das es sich nicht wirklich um ein
Libraryproblem handelt. Es war eher ein Überlauf in einem Array.
Danke für die tatkräftige Hilfe
Alex
Ich hätte allerdings nocheinmal eine Frage:). Ist es möglich mit der
Library auszulesen wieviel Speicherplatz noch auf der Karte frei ist
(will nur Überprüfen ob die Karte voll ist. Lesen schreiben und löschen
von Daten auf der Karte Funktioniert mitlerweile einwandfrei :)
Grüße Alex
Hallo!
Ich nutze auch diese MMC/SD Funktionen und bin damit auch sehr
zufrieden.
Ich möchte jetzt um Zeit zu sparen die Datei öffnen und erst beim
Datumswechsel die Datei schliessen und eine neue Datei erstellen.
Wie kann ich nach einem Schreibvorgang die Daten auf der Karte
aktualisieren ohne die Datei schließen und wieder öffnen zu müssen?
Viele Grüße
Helmut
Hallo zusammen.
@ Alex (Gast)
Schön das es jetzt funktioniert :)
Das mit dem Freien Platz ermitteln wollt ich schon immer mal einbauen,
komme aber nicht dazu. Eigentlich müsste man ja nur die freien Cluster
in der Fat durchgehen und zählen. Das mit Sektoren pro Cluster
multiplizieren und fertig...
@ Helmut (Gast)
Ist es denn so zeitkritisch?
Weil eigentlich muss man ja alles, was beim schließen auch gemacht wird,
bei einem kompletten update der Datei Daten auch machen. Es schadet ja
übrigens auch nicht eine Datei länger geöffnet zu haben.
Grüße Daniel
Soo, hier mal auf die schnelle eine Funktion, die die Anzahl der freien
Bytes bestimmt.
Es sollte aber mindestens ein Cluster frei bleiben am Ende, also nicht
voll schreiben bis zum Anschlag ! Besser wäre sogar einfach 1 MB frei zu
lassen...
1
unsignedlonglongintfat_getCntFreeBytes(void){
2
3
unsignedlonglongintcnt=0;
4
unsignedlongintcount=0;
5
unsignedlongintsecOfFirstPartition;
6
unsignedlongintfatSz;
7
8
if(TRUE==mmc_read_sector(0,fat.sector)){
9
10
// bestimmen des 1. sektors der partition
11
void*vsector=&fat.sector[454];
12
secOfFirstPartition=*(unsignedlongint*)vsector;
13
if(secOfFirstPartition==0x6964654d){
14
secOfFirstPartition=0;
15
}
16
else{
17
mmc_read_sector(secOfFirstPartition,fat.sector);
18
}
19
20
// anzahl sektoren bestimmen die von einer fat belegt werden
>Und was machste mit ner leeren 8GB Karte? ;) Überlauf anzeigen?
Ach was red ich denn da? Du benutzt ja long long int.
Aber mal im Ernst, es sollte eigentlich reichen die
Anzahl der freien kB zu ermitteln. Das spart das long long
Geraffel und benötigt weniger Code.
Hallo...
@ Alex (Gast)
Wow 15 Sekunden das ist lang. Hatte das garnicht auf realer Hardware
getestet muss ich gestehen. Aber 15 Sekunden ist zu viel! Da muss ich
mal überlegen wie das optimaler geht.
@ holger (Gast)
Ja stimmt schon, long long int auf nem AVR 8 Bit :) das muss man nicht
unbedingt haben. Mal sehn was ich da mache...
Wegen der Code Größe ist mir das eigentlich egal, wer so was braucht
muss halt platz haben, aber die Geschwindigkeit sollte stimmen.
Grüße Daniel
Hallo Daniel,
was müsste man ändern, damit Dateien mit korrektem Datum/Uhrzeit
angelegt werden?
Ansonsten gute Arbeit! Deine lib scheint die einzige zu sein, die
wirklich schnelles schreiben auf SD-Karten ermöglicht.
Mfg,
Kurt
Hallo Kurt,
man müsste die Funktion "fat_makeRowDataEntry" in der fat.c dazu
bewegen, da wo jetzt dummy werte geschrieben werden, richtige werte zu
schreiben. Also das Datum und die Zeit. In den beiden Zeilen, die mit
1
// unnoetige felder beschreiben
kommentiert sind.
Die dummy Werte sind 0x01010101, also 4 Byte als Hex.
Wo jetzt genau Datum und Zeit steht, müsste ich selber mal genau
nachschauen. In der Lib werden 12 Byte mit den dummy werten beschrieben,
da irgendwo muss das hin :)
Grüße Daniel
Dann folgende Funktionen mit zusätzlichem Parameter unsigned long
datetime ausrüsten: ffopen, ffclose, ffmkdir, flushFileData,
fat_makeFileEntry, fat_makeRowDataEntry.
Nun fat_makeRowDataEntry abändern:
*bytesOfSec++=datetime>>16;//datum des letzten zugriffs lowbyte
25
*bytesOfSec++=datetime>>24;//datum des letzten zugriffs highbyte
26
27
vsector=&fat.sector[row+20];
28
*(unsignedshort*)vsector=(cluster&0xffff0000)>>16;// low word von cluster
29
30
bytesOfSec+=2;// 2 überspringen (für low word von cluster)
31
*bytesOfSec++=datetime;//zeit der letzten änderung lowbyte
32
*bytesOfSec++=datetime>>8;//zeit der letzten änderung highbyte
33
34
*bytesOfSec++=datetime>>16;//datum der letzten änderung lowbyte
35
*bytesOfSec++=datetime>>24;//datum der letzten änderung highbyte
36
37
vsector=&fat.sector[row+26];
38
*(unsignedshort*)vsector=(cluster&0x0000ffff);// high word von cluster
39
40
vsector=&fat.sector[row+28];
41
*(unsignedlongint*)vsector=length;// laenge
42
}
Natürlich sind die Werte für Erstellung, letzer Änderung und letztem
Zugriff auf die Datei gleich. Ist das nicht gewünscht, muss man halt
noch 2 weiter parameter übertragen.
Mfg,
Kurt
Hallo,
das mit dem Formatieren ist nicht so einfach,
mach das lieber mit einem Pc :)
Man müsste die Register der Karte auslesen, um herauszufinden wieviele
Sekoren die hat. Dann berechnen wieviele Fat Sektoren man braucht, wo
dann das Root-Dir hin muss usw.
Dann ist immer noch die Frage ob man das so gemacht hat, dass ein
Betriebssystem das auch lesen kann...
Grüße Daniel
Hallo,
hier eine neue Version.
Neu ist:
- SDHC Unterstützung
- Eine Funktion die den freien Platz in Bytes ermittelt
"fat_getFreeBytes()"
- Zeit Stempel Unterstützung beim Anlegen und ändern von
Dateien/Ordnern,
dazu müssen 2 Funktionen mit leben gefüllt werden. "fat_getDate()" und
"fat_getTime()" in der fat.c, dort ist auch dokumentiert wie das Format
der Zeit und des Datums auszusehen haben.
- Kleinere Optimierungen
Viele Grüße
Daniel
Im Anhang: die Lib mit Linux Makefile
Hallo!
Ich hab das ausprobiert, also die neuste AVRStudio Variante. Eigentlich
klappts prima, allerdings bekomme ich z.B. die Funktion:
ffrm( unsigned char name[])
nicht aufgerufen ... also nicht so daß der Compiler einverstanden ist.
Ich habe u.a. versucht:
ffrm(file_name0);
Ging nicht, auch sämtlichen sinnvollen Ansätze die ich probiert habe,
gingen nicht, woran mag das liegen, verwenden einen ATmega32
Hallo zusammen,
habe nen Mega32L, ne 4GB SDHC, und nen 3,7V Lipo.
meint ihr es gibt Probleme mit der um 0,4V zu hohen Spannung um das
ganze prinzipiell zu betreiben?
Mfg Tobi
Hallo,
also ich würde dir empfehlen, einen Stepup-Wandler für die
Versorgungsspannung zu benutzen. Der Akku wird mit der Zeit mit der
Spannung runter gehen. Mit nem Stepup könnte man bei um die 1V
Akkuspannung noch arbeiten. Also das ganze mit nem Stepup auf 3,3V und
gut is.
Generell kann man mit nem SD-Kommando die Karte fragen was sie für ne
Spannung mitmacht. 3,3 Volt machen alle, aber es geht eventuell auch
weniger.
Grüße Daniel
Hy Daniel,
also der Lipo wäre bei 1V schon lange dahin.
In einer späteren Version werde ich die Spannung sicherlich eh auf 3,3V
stabilisieren, zumal ich in einem anderen Stromzweig eh nen Wandler auf
3,7V->5V verbaut habe.
Mir geht es in einem ersten Versuch nur mal darum die Kommunikation
Mega32L + SD Karte durch einen Versuchsaufbau zu testen. Dabei würde ich
gerne erst einmal direkt alles brücken können. Wäre prinzipiell ja auch
möglich da alles mit 3,3V versorgt werden will. Wenn ich wüsste ob die
3,7V die SD Karte kaputt machen müsste ich nämlich für den
Versuchsaufbau die Spannung auch schon wandeln was ich gerne für erste
Versuche erst einmal vermeiden möchte.
mfg tobi
Hallo,
ich hab keine Ahnung von Lipo Akkus :)
Bezugnehmend auf die Simplifyied SD-Spezifkation 2.0, die ich jetzt
nochmal rausgekramt hab.
Also man übergibt der Karte mit CMD8 die Spannung in der man sie
betreiben möchte, in dem Fall der Lib wären das 2,7-3,6 Volt. Antwortet
die Karte korrekt, kann man diese Spannung anlegen. Nur wenn die Karte
korrekt antwortet initialisiert die Lib die Karte.
Soviel dazu. Ob jetzt 0,1 Volt mehr tödlich für die Karte sind bezweifle
ich mal stark ;)
Vielleicht hält sich aber auch dein Kartenhersteller nicht genau an die
Spezifikation...
Hab aber auch schon gehört, dass Leute MMC/SD Karten einfach mit 5V
betrieben haben, ohne das die kaputt gegangen wären. In der Regel sind
das ja alles werte, unter denen das dann garantiert läuft...
Grüße Daniel
Genau diese Angaben mit 2,7-3,6V habe ich auch in meiner SD
Spezifikation.
Das mit dem CMD8 wusste ich noch nicht. Allgemein vermisse ich irgendwie
eine Zusammenfassung der gazen Commands. Zwar sind auch einzelne
Commands in der SPezifikation, jedoch irgendwie etwas unübersichtlich.
Ich vermute auch das 0,1V mehr nicht viel ausmacht. Hatte gehofft hier
Erfahrungsberichte zu finden, da sich grundsätzlich ein Lipo von der
Spannung her ja anbietet und ich ja sicher ned der erste bin der so
einen verwendet :)
Das mit den 5V wäre ja schonmal beruhigend zu wissen, da hätte ich nicht
gedacht das das die Karte lange mitmacht.
Ansonsten ist ja auch kein Vermögen zerstört wenn so eine Karte hops
geht :)
Ich denke ich werds einfach mal probieren, wenn ich einen Kartenleser
auftreiben kann der meine Karte liest um herauszufinden ob die Karte
schon formatiert ist oder dies noch tun muss.
Danke für deine Ausführungen.
MfG Tobi
Hallo zusammen!
Ich habe mal ne Frage bezüglich einer Abfrage ob eine Datei schon
existiert. Und zwar will ich überprüfen ob eine Datei mit einem Namen
schon in dem Verzeichniss existiert. Ist so etwas möglich?
Grüße
Alex
"file_flag" ist jetzt TRUE wenn die Datei schon existiert oder FALSE
wenn eben nicht. Nach dem Aufruf von "fat_loadFileDataFromDir(name)"
sind sogar alle möglichen Daten über die Datei schon bekannt, wenn die
Datei existiert...
Siehe auch "ffopen()" in der file.c
Grüße Daniel
Danke schon für die tatkräftige Hilfe! ich habe auch noch eine weitere
Frage. Und zwar kann man auslesen wie groß der gesamte Speicherplatz der
Fat ist?
Gruß
Alex
Ich denke du meinst wieviele Sektoren von der Fat belegt werden?
Das ist schon schwieriger.
1
unsignedlongintfatSz;
2
3
4
mmc_read_sector(0,fat.sector);
5
6
void*vsector=&fat.sector[454];
7
fatSz=*(unsignedlongint*)vsector;
8
if(fatSz==0x6964654d){
9
fatSz=0;
10
}
11
else{
12
mmc_read_sector(fatSz,fat.sector);
13
}
14
15
16
if(fat.fatType==32){
17
vsector=&fat.sector[36];
18
fatSz=(*(unsignedlongint*)vsector)-1;
19
fatSz*=128;
20
}
21
else{
22
vsector=&fat.sector[22];
23
fatSz=(*(unsignedshort*)vsector)-1;
24
fatSz*=256;
25
}
Jetzt ist auf der Variable "fatSz" die Anzahl der Sektoren gespeichert,
die eine bzw. die erste Fat belegt. Der erste Sektor, also ab wo die Fat
los geht steht auf der Variable "fat.fatSec".
Der hier gepostete Code ist aus der Funktion "fat_getFreeBytes()" aus
der fat.c...
Grüße Daniel
Danke dir! Aber eigentlich meinte ich die Anzahl der Bytes :). Aber das
war doch Anz. Der Sektoren * 512 oder? Kann auch sein das ich mich da
irre.
Gruß Alex
Hallo,
ja Anzahl der Sektoren * 512.
Ich weiß ja nicht was du vor hast, aber zur Sicherheit solltest du evtl.
noch einen Sektor dazu zählen wenn du irgendwas nach der Fat machen
möchtest.
Falls es irgendwas mit der Fat ist wird da schon ein Sektor abgezogen,
um auf garkeinen Fall über das Ende der Fat hinaus zu kommen.
Upps, ich seh grad da bekommst du die Cluster Anzahl raus die in einer
Fat stehen. Bei dem Code oben muss einmal das "fatSz*=128;" und das
"fatSz*=256;" weg !
Also so:
Hi,
ich habe grad ein verzwickes Problem.
Ich würde gerne in eine Datei, die schon einen Text enthält, Text
einfügen.
BSP:
aus:
"Hallo, dieser text steht schon drin."
soll:
"Hallo, dieser text steht schon 1234567890 drin."
werden.
Man könnte jetzt natürliche den restlichen Text überscheiben und neu
schreiben. Aber das geht nicht, da der Text hinter dem, was eingefügt
werden soll mehrere MB groß ist und zum Auslagern fehlt mir zum einen
der Platz und zum anderen die Zeit...
Gibts dafür eine Lösung?!
Gruß,
Matze
Hallo,
nein dafür gibt es so noch keine Lösung.
Man müsste Prinzipiell wie in dem an gehangenen Bild vorgehen.
Allerdings müsste das noch weiter verallgemeinert werden.
Also auf Cluster anstelle von 512 Byte Sektoren und auf größere
einzufügende Sektoren/Cluster.
Mal sehen wie sich das optimal einbauen lässt.
Da komme ich aber auch wohl erst in 2 Wochen dazu, wird auch nicht so
einfach werden, da das ziemlich tief in die Sektor/Cluster Verwaltung
eingreift.
Grüße Daniel
müsste das nich so sein... ich meine, man will ja evtl mehr als 512 byte
einfügen. außerdem müsste es zwischen zwei blöcken geschrieben werden.
dein zeichnung würde "ersetzen mit einem anderen sector" bedeuten.
aber sonst meinen wir das selbe! und cool, daß du das machen willst, ich
steige da nämlich nicht so richtig durch...!
gruß und danke schon mal,
matze :)
Hallo,
hm wo ich so darüber nachdenke, könnte das übler werden als ich dachte.
Wenn man nicht genau 512 Bytes dazu macht, oder ein ganzes vielfaches
davon, läuft das wohl doch auf ein wildes kopieren hinaus. Man hat
irgendwie immer ein paar Bytes über...
Muss ich mal in Ruhe darüber nachdenken.
Grüße Daniel
naja, ob das so weit gehen muss?! Ja, ok, schön wäre es, jedes Bit auf
der Karte auszunutzen, aber sein wir doch mal ehrlich, wer Datenmengen
kleiner als 512 Byte schreiben will, schreibt eh nur Text und der ist eh
meistens kurz. von daher verschenk man nur wenig, selbst wenn man nur 1
Byte / Sector schreibt.
Auf der anderen Seite: wenn man, so wie ich das Plane, ca. 175.000
Einfügevorgänge machen wird, ist schon eine ganze Ecke an verschwendetem
Speicherplatz (ich habs mal überschalgen: etwas mehr als 80MB - wenn ich
mich nicht verrechnet habe).
Jedoch, bei der verfügbaren Kapazität heutiger Speicherkarten auch nicht
mehr so viel... :)
Mach dir also nich so einen Kopf drüber. Die Abfrage, welcher Sektor
wieviele Bytes noch übrig hat, ist, denke ich, unnötig und
wahrscheinlich eh viel zu langsam - bzw. wenn man es in eine Variable
schreibt, viel zu Speicheraufwendig (bei knapp 4,2 mio Sektoren auf
einer 2GB Speicherkarte)
Grüße,
Matze
Danke für die hilfe :)
aber leider Funktioniert das noch nicht so wirklich. Ich überprüfe z.B.
die Größe einer Fat auf einer 2 Gig SD Karte. Die Fat hat die volle
Größe.
Der Quelltext den du oben geschrieben hast also gibt mir für fatSz 3742
zurück.
unsigned long int fatSz;
mmc_read_sector(0,fat.sector);
void *vsector=&fat.sector[454];
fatSz=*(unsigned long int*)vsector;
if(fatSz==0x6964654d){
fatSz=0;
}
else{
mmc_read_sector(fatSz,fat.sector);
}
if(fat.fatType==32){
vsector=&fat.sector[36];
fatSz=(*(unsigned long int *)vsector)-1;
}
else{
vsector=&fat.sector[22];
fatSz=(*(unsigned short*)vsector)-1;
}
Noch einen vorschlag ? (Fehlt hier vielleicht noch ne multiplikation
oder soetwas ?
Gruß Alex
This field is only defined for FAT32 media and does not exist on
4
FAT12 and FAT16 media. This field is the FAT32 32-bit count of
5
sectors occupied by ONE FAT. BPB_FATSz16 must be 0.
,das korrespondiert mit der Prüfung:
1
if(fat.fatType==32){
2
vsector=&fat.sector[36];
3
fatSz=(*(unsignedlongint*)vsector)-1;
4
}
jetzt sollte auf der Variablen fatSz laut Spezifikation die Anzahl der
Sektoren stehen die von einer Fat belegt werden. Wenn du ja genauer
schreiben würdest wozu du das überhaupt brauchst könnte ich da
vielleicht auch mehr zu sagen :)
Wenn du jetzt die Anzahl der Bytes haben willst musst du deine 3742 ja
noch mit 512 Multiplizieren.
Grüße Daniel
Hallo Daniel,
also das passt nicht wirklich. Die Partition ist 2 Gig groß und 3742 *
512 hat einen Wert von unter 1 MB. Was ich machen will ist, eine
durchnummerierung von Dateien. Quasi bei 1 Anfangen ...dann 2 dann 3.
Jede Datei ist hierbei 1 MB groß. Falls ich nun am Ende der Fat
angekommen bin. Also bei ner 2 Gig Platte zirka bei guten 2000 dann soll
der wieder von vorne anfangen und die erste überschreiben. Das klappt
auch eigentlich schon recht gut wenn ich das ganze mit einer statischen
größe mache, besser wäre das aber wenn ich das mit verschiedenen Karten
machen könnte die jeweils eine andere Größe haben. Aber danke schonmal
danke für die Tatkrääftige unterstüzung
Gruß
Alex
Aha,
da musst du anders ran gehen.
Auf FatSz steht jetzt die Anzahl der Sektoren die eine Fat belegt.
In einem Sektor der von der Fat belegt wird, können 128 Cluster
"Adressiert" werden.
Wenn man jetzt fat.secPerClust*512 rechnet, bekommt man die Anzahl der
Bytes die einem Cluster zugeordnet werden.
Die Anzahl der Sektoren die zu einem Cluster zusammengefasst werden ist
immer eine 2er Potenz. Wahrscheinlich bei einer 2Gb Karte 4 oder 8.
Damit ist die kleinste Zuordnung 2048 oder 4096 Bytes groß.
Damit solltest du jetzt rechnen können :)
Also:
FatSz*128 = Anzahl Cluster auf der Karte
512 * fat.secPerClust = Bytes in einem Cluster
1MByte / Bytes in einem Cluster = nötige Cluster Anzahl, für die 1 MByte
Anzahl Cluster auf der Karte / nötige Cluster Anzahl für die 1 MByte =
Maximale Anzahl der der 1 MByte Dateien
Stimmst du dem zu? Könnte mich auch verrechnet haben, war jetzt nur so
auf die schnelle...Man müsste auch mal schauen wie man rundet um da
überall save zu sein ;)
Grüße Daniel
Das mit den Bytes auf der Fat werde ich die Tage mal ausprobieren und
dir ein Feedbag geben :). Ich habe allerdings immoment auch noch ein
ganz anderes Problem. Ich habe folgenden Quellcode
unsigned long int sd_ausgabe_zaehler;
filenamelan = 1;
char ordner[13];
ordnerName(filenamelan,ordner);
ffcdLower();
if(TRUE == ffcd("1 ")...//--> Gibt true zurück
char zwischenspeicher[5]; // Zwischenspeicher für die Umwandlung
itoa(filenamelan, zwischenspeicher,10);
char dateiname[12]=" CSV";
for(uint8_t i=0;i<strlen(zwischenspeicher);i++)//)i<=3;i++)
{
dateiname[i]=zwischenspeicher[i];
}
if(MMC_FILE_EXISTS==ffopen((unsigned char *)dateiname)) // --> Datei
exist
sd_ausgabe_zaehler=file.length;
char zwischenspeicher3[10];
ultoa(sd_ausgabe_zaehler,zwischenspeicher3,10);
ausgabe(zwischenspeicher3); // Hier gibt er ziemlich große Zahlen aus
Das Problem was ichhabe ist das mit file.length für 10 kB Dateien zum
Beispiel den Wert 640000000 zurückgibt, was ja nicht kann. Sieht jemand
warum der das macht und nicht wie erwartet 104800 irgendwas an Bytes
zurückgibt?
Grüße
Alex
hi
ich hätte eine frage zu deinem code
ich bekomme über die serielle schnittstelle strings mit der länge von
2048 zeichen und würde nun gerne wissen wie das geht das ich diese 2048
zeichen dann schreibe
wenn ich nur 512 zeichen lange Blöcke bekomme geht es wunderbar
hoffe du kannst mir helfen
danke und mfg alex
Hallo,
du könntest eine Ringpuffer machen. Dessen Größe müsstest du dann noch
ermitteln, damit da nichts schief geht. So könnten dann schonmal 512
Bytes geschrieben werden, während noch weitere abgeholt werden (falls du
einen Interrupt zum abholen der Daten benutzt).
Siehe auch:
http://de.wikipedia.org/wiki/Warteschlange_(Datenstruktur)#Implementierung_als_Ringpuffer
Das es nicht klappt könnte auch daran liegen, dass du die Schnittstelle
ohne Flow-Control verwendest, vermute ich mal.
Während die Daten auf die Karte geschrieben werden kommen ja über die
serielle Schnittstelle neue Daten an die werden aber wohl nicht abgeholt
während die Lib noch Daten auf die Karte schreibt. Das schreiben der
Daten auf die Karte benötigt ja eine gewisse Zeit.
Falls dir das nicht weiterhilft, könntest du mal etwas Code Posten,
damit könnte man sich einen besseren Überblick verschaffen.
Viele Grüße
Daniel
ich hätte mir vorgestellt das ich die 2048 zeichen was ich als einen
string bekomme auf mehrere kleine strings mit 256 zeichen oder so
aufteile und dann schreibe. wäre das prinzipell möglich?
Hallo,
so bin zu der Berechnug der Anzahl von Dateien gekommen. Habe das wie
folgt gemacht :
uint32_t anzahlDateienerrechnen(uint32_t size)
{
uint32_t anz_Cluster_Karte = size * 128;
uint32_t byte_pro_Cluster = 512 * fat.secPerClust;
uint32_t noetige_Cluster_fuer_1_MB = 1048576/byte_pro_Cluster;
uint32_t anz_Dat = anz_Cluster_Karte/noetige_Cluster_fuer_1_MB;
return (anz_Dat);
}
Mit
size = fatSz kommt die Richtige Anzahl an 1 MB Dateien raus.
Danke für die Hilfe (fatSz muss man ja vorher berechnen) Aber da ist ja
schon oben der Quelltext angegeben.
Grüße
Alex
hi ich wenn ich einen block mit 512 byts schreiben will. geht das bei
mir nicht und es kommt auf der seriellen schnittstelle ein neues boot.
was kann da sein
ich lese die 512 byts über die serielle schnittstelle ein. ich kann
maximal 256 byts auf einmal schreiben mit deinem code
Hallo zusammen.
@ Alex (Gast), schön das es jetzt klappt :)
@ Alex Glaser (almalex) ,welchen Mikrocontroller benutzt du denn? Wenn
da erneut "Boot..." steht vermute ich mal einen Reset wegen Ramknappheit
?!? Poste doch mal ein bisschen Code, damit man sehen kann was du da
genau machst und wie du das machst. Am besten sogar den ganzen Code.
Grüße Daniel
hab das problem schon gfunden. habe ein bit zuviel gesendet und dadruch
hat der buffer nicht gepasst. verwende einen 644 aber trotzdem danke
jetzt wende ich mich dem problem das ich einen string von 2048 zeichen
empfangen will und denn dann schreiben will und dann einen bit zurück
senden will wann der nächste gesendet werden soll
Hallo Daniel,
ich habe noch einen kleinen Fehler in der Funktion
fat_getFreeBytes() gefunden.
Dort wird mit mmc_read_sector(0,fat.sector)
der erste Sektor der Karte in den Buffer gelesen, ohne dass
fat.currentSectorNr dadurch verändert wird.
Später wird mit
fat_getNextCluster(count) der sektor gelesen. Wenn 'count' jetzt
identisch mit 'fat.currentSectorNr'ist(was durchaus vorkommt) wird der
Sektor nicht in
den Buffer gelesen.
meiner Meinung nach müsste es ausreichen wenn man Sektor 0 nicht mit
mmc_read_sector(0,fat.sector) liest sondern statt dessen
fat_loadSektor(0) verwendet.
Kannst du dir ja noch mal anschauen.
Grüße
Jürgen
Hi
ich hab ne frage
ich habe es jetzt geschafft 2048 Zeichen auf die SD karte zu schreiben
wenn ich die daten über die serielle schnittstelle vom PC schicke. wenn
ich nun die selben Daten über den 2ten µC erzeuge und zu dem sende der
es auf die SD karte schreiben soll, funktioniert es nicht. ich poste mal
den code. die main.c ist die datei die auf den µC gespielt wird, welcher
die daten zu dem 2ten sendet.
main_simple.c ist deine datei nur wenig verändert
hoffe du kannst mir helfen
Hallo zusammen.
@ Juergen (Gast)
Ja stimmt, ich bin davon ausgegangen, dass man nur am Anfang die freien
Sektoren bestimmt...
Das wird geändert. Dein Vorschlag funktioniert so.
@ Alex Glaser (almalex)
Um mir das genauer anzuschauen fehlt mir momentan einfach die Zeit.
Vielleicht so in 1,5-2 Wochen, sorry.
Es gibt auch noch einen kleinen Bug, der nur auftritt wenn man die Lib
im Read-Only Modus betreibt. Dann hat nämlich ffopen evtl. nicht immer
einen Rückgabewert... Ist aber eigentlich kein Funktionaler Fehler.
Grüße Daniel
Hay Leute
Ich habe nun auch mal versucht unter Codevision zum Laufen zu bekommmen.
Aber leider ohne erfolg.
Ich habe mir die CodeVision_SDLIB_v0.4.4.zip runter geladen und an den
Mega128 Angepasst. Ich nutze zwar den Mega1281 Aber der ist gleich den
128 nur mit mehr S-Ram.
Habe das ganze System unter 3,3V laufen den AVR sowie auch
Verständlicherweisse die SD-Karte.
Kann mir jemand mal einen code in Codevision Posten der Funktioniert.?
Die mmc_init() bzw. die INIT sieht so aus
if(mmc_init() !=0)
{
LED_Rot^=1;
while(1);
}
LED_Gruen^=1;
Aber es bleibt immer auf Rot nie auf Grün und sagt keine SD Karte
Eingesteckt.
Kann mir jemand weiter helfen.?
Vielen Dank schon mal
Hallo,
erstmal solltest du besser die neuste Version auf Codevision portierten.
Dann ist das so nicht richtig wie du das machst. So wird nur ein mal
versucht die mmc/sd karte zu initialisieren...
Das wäre richtig:
1
while(0!=mmc_init()){
2
LED_Rot^=1;
3
}
4
LED_Gruen^=1;
jetzt wird rot bei jedem versuch getoggelt und grün nach erfolgreichem
initialisieren...
Grüße Daniel
jup das war es nun geht die init Funktion. Danke @Daniel R.
Ich nutze die CodeVision_SDLIB_v0.4.4
nun habe ich auch die filefat.c Eingebunden.
habe auch alle fehler soweit Korrigiert und angepasst.
Nur meckert er mich bei dieser geschichte voll
Error: filefat.c(635), included from: Neu.c: expression must be a
pointer to a complete object type
in der Zeile steht das hier
*(unsigned char*)firstCluster++=sector[row+26];
und das macht er durch weg. :-(
MFG: Andre
Klappt da was von?
Das ist wegen dem CodeVision Compiler, da müsste man mal raus finden
warum der den void Pointer so an meckert..
Mit nimm die neuste Version zum anpassen meinte ich die Version 0.5.7
Grüße Daniel
So gut soweit habe ich nun versucht erstmal die mmc.c, mmc.h und
config.h eingebunden.
nun habe ich dort das problem das er mir das hier anmeckert
loop_until_bit_is_set(SPSR,SPIF);
Error: mmc.c(418), included from: Neu.c: undefined symbol
'loop_until_bit_is_set'
MFG: Andre
Ich glaub ich bleib weiter bei der CodeVision_SDLIB_v0.4.4 den da habe
ich die wenigsten fehler und so.
Den das nimmt ja hier garkein ende mit den ganzen ram. :-)
MFG: Andre
ist ein Makro aus der avr-libc, SPSR ist ein Register und SPIF ist ein
Bit in dem Register. Das Makro ist sehr schnell, daher benutze ich es.
Dahinter steckt eigentlich:
Ändere mal das Makro so wie hier beschrieben. Dann wirst du
wahrscheinlich noch nen Haufen anderer Fehler bekommen wegen den
unterschiedlichen Register Namen, die musst du alle ändern.
Poste doch mal die Fehlermeldungen, vielleicht kann man dann mehr sagen.
Du kannst ja die Teile die in der CodeVision_SDLIB_v0.4.4 stehen
vergleichen mit den stellen aus der 0.5.7 die nicht auf Anhieb laufen...
Oder du fragst mal nett bei "Lolipop Er (lolipoper)" ob er nicht
nochmal die 0.5.7 auf CodeVision portieren mag. Oder du nimmst den
avr-gcc anstelle von CodeVision :)
Viele Grüße Daniel
Persönliche Nachricht an "Lolipop Er (lolipoper)" :
http://www.mikrocontroller.net/user/show/lolipoper
Hallo,
wie schnell kann man mit dieser Bibliothek auf einer SD-Karte
schreiben?Wie lange brauche ich z.B. um 10 MB zu schreiben?
Danke im Vorraus und Grüße
Bernd
Hallo,
der Matze hat es schon erwähnt, es hängt von verschiedenen Faktoren
ab...
Ich sage mal so, mit einer neueren SD Karte und im Multiblock-write
Modus, bei 10 MHZ SPI Takt etwa 40 Sekunden für 10 MBytes.
Hallo,
ich benutze die Fat32 in einer Portierung auf den XMega. Leider ist in
der Applikation öfter mit dem Wegbrechen der Versorgungsspannung zu
rechnen und der Controller schreibt ständig in wachsende Dateien.
Gibt es ausser einer Pufferung der Versorgungsspannung eine Möglichkeit
ein korruptes Dateisystem zu vermeiden?
Ständige ffclose() Aufrufe gefolgt von erneutem öffnen der Datei sind
denke ich nicht so gut.
Hallo,
wenn man jetzt so etwas wie "flush" beim schreiben machen würde, also um
den Dateieintrag zu updaten und die aktuell gepufferten Daten zu
schreiben, müsste man genau die Dinge machen, die bei einem ffclose
auftreten. Das einzige was man evtl. übergehen könnte wäre das suchen
der Datei im Verzeichnis, beim erneuten öffnen. Das wirkt sich aber nur
bei vielen Dateien in einem Verzeichnis aus.
Generell mach ich mir aber mal Gedanken ob da nicht was zu machen ist.
Umgehen könnte man dass, wenn man nicht nur 512 Bytes puffern würde,
sondern 1024 Bytes. Dann wären die Möglichkeiten wesentlich größer, aber
so muss alles durch den 512 Bytes Puffer.
In FAT32 ist ein Journal nicht vorgesehen, wie es bei allen neueren
Dateisystemen Standard ist. Da muss man dann über dem Standard selber
was machen...
Viele Grüße
Daniel
Hallo,
nein mit dem Tool WinHex, das läuft auch unter Linux gut.
Generell muss man aber nur alle Sektoren einer Karte in eine Datei
packen, das reicht dann schon...
Grüße Daniel
hallo
tolles projekt!
ich habe diese library auf einem mega328 im einsatz. wobei daten die
ausgewertet wurden auf einem lcd angezeigt werden und auf die sd karte
geschrieben werden. und noch immer mehr als die hälfte an speicher platz
;-)
möchte noch zusätzlich gps implementieren, wie könnte man das am
einfachsten realisieren?
kann ich hierbei die uart so verändern, damit sie nur mit dem gps modul
kommuniziert oder ist diese systembedingt erforderlich?
und wie kann man den syste der einträger in der txt verändern, zb dass
durchnummerierungen erfolgen
Hallo,
ja die UART kann man einfach benutzen, es wird nur SPI von der Lib
benutzt.
>und wie kann man den syste der>einträger in der txt verändern, zb dass>durchnummerierungen erfolgen
Wie meinst du das?
Willst du eine große Datei erstellen in der alle NMEA Einträge stehen?
Dann musst du die Lib im überschreiben Modus benutzen, dann kannst du
einfach die Datei öffnen und was anhängen...
Grüße Daniel
super!
hab gesehn, man kann echt viel mit deinen libs anstellen ;-)
wie wirkt es sich aus, wenn der ffwrites(text) oder andere aktivitäten
der sd von einem interrupt unterbrochen werden?
habe zb einen interrupt laufen der jede ms ausgelöst wird, brauch diese
zeit um die flanken eines externen interrupts zu messen.
auf die karte sollte im sek takt geschriben werden. habe bemerkt, dass
nach einiger zeit anscheinend der schreib prozess wesentlich länger
braucht. macht sich bemerkbar da das lcd in der selben schleife hängt
und manchmal 5sek und länger nicht aktualisiert wird. liegt das
vielleicht an interrupts?
nur wenn ich die interrupts deaktiviere für den sd schreib prozess, kann
ich einige sekunden keine messwerte empfangen.
Das ist so schwer zu sagen, da ich nicht genau sehen kann wie du die Lib
in deinem Code benutzt.
Aber wenn du die Anbindung an die Karte mit Hardware SPI machst, sollte
eine Unterbrechung keine Probleme machen, da SPI per Definition Clock
hörig ist. Also könnte man zwischen 2 zu Übertragenden Bytes auch Pausen
einlegen. Ich gehe mal davon aus, dass wenn man ein Byte auf die
Hardware SPI gibt, dies auch nicht von Interrupts unterbrochen wird,
weil Hardware...
Schließt und öffnest du die Datei in die du schreibst bei jedem
Messwert?
Grüße Daniel
da ich derzeit noch am erproben bin, verwende ich deine lib im großen
und ganzen original nur leichte anpassung für mega328. aufrufe werden
nach der mainsimple vorlage gemacht, wobei die datei auch jedesmal
geschlossen wird
mir ist in der nacht noch etwas eingefallen. da ich noch freien speicher
habe, könnte ich ca 60sek am mega328 speichern und dann gesammelt
übetragen mit intterupt disable (2-3fehlende werte in einer min ist
nicht so schlimm)
kann sein, dass das spulen zum dateiende nach einiger zeit länger
dauert?!
1
2
sprintf(text,"%u",(int)heartbeat_output);
3
4
// Dateinamen müssen in diesem Format sein !
5
unsignedcharfile_name[20]="TEST TXT";
6
7
// string zum in die datei schreiben schreiben
8
//unsigned char str[13]="Hallo Datei!";
9
// unsigned char str[13]="heartbeat_output";
10
11
12
// Datei existiert nicht, also anlegen !
13
if(MMC_FILE_NEW==ffopen(file_name)){
14
15
// schreibt String
16
//ffwrites(str);
17
ffwrites(text);
18
19
// neue Zeile in der Datei
20
ffwrite(0x0D);
21
ffwrite(0x0A);
22
23
// schließt Datei
24
ffclose();
25
}
26
27
28
29
// Datei existiert, also anhaengen !
30
else{
31
32
ffseek(file.length);// spult bis zum Dateiende vor um anzuhaengen !
33
34
// schreibt String
35
//ffwrites(str);
36
ffwrites(text);
37
38
39
// neue Zeile in der Datei
40
ffwrite(0x0D);
41
ffwrite(0x0A);
42
43
// schließt Datei
44
ffclose();
45
}
46
47
48
// Datei existiert, also kann man lesen.
49
if(MMC_FILE_EXISTS==ffopen(file_name)){
50
51
// setzen einer Variable und dann runterzaehlen geht am schnellsten !
Hallo,
>kann sein, dass das spulen zum dateiende>nach einiger zeit länger dauert?!
Das kommt auf die Datenmenge an, da man sich durch die schon verketteten
Cluster suchen muss. Ist die Datei um die mehreren MB oder sogar GB kann
das dauern.
>..und manchmal 5sek und länger..
5 Sekunden ist ne verdammt lange Zeit. Stimmt da vielleicht irgend etwas
anderes nicht? In 5 Sekunden würde man wenn es gut läuft 1,3 Millionen
Bytes auf eine Karte schreiben können.
Blockiert der Interrupt sich selber oder so?
Poste doch mal den ganzen Code, als Datei Anhang. So kann ich da nicht
viel dazu sagen. In dem von dir gezeigten Code sehe ich keinen Fehler...
Grüße Daniel
Daniel R. schrieb:> 5 Sekunden ist ne verdammt lange Zeit. Stimmt da vielleicht irgend etwas> anderes nicht? In 5 Sekunden würde man wenn es gut läuft 1,3 Millionen> Bytes auf eine Karte schreiben können.> Blockiert der Interrupt sich selber oder so?>> Poste doch mal den ganzen Code, als Datei Anhang. So kann ich da nicht> viel dazu sagen. In dem von dir gezeigten Code sehe ich keinen Fehler...
hab mich ein bisschen herumgespielt.
habe testweise werte nacheinander auf die karte geschrieben, mit
systemzeit in ms. dabei ist mir aufgefallen, dass der datenstring sehr
schnell ca.20ms auf die karte geschrieben wird.
also am schreiben kanns nicht liegen.
testweise, habe ich die datei nicht geschlossen, selbes problem, je
länger die datei wird desto länger hält sich der mega328 mit der sd
karte auf.
und dann ist mir eingefallen, dass in deinem beispiel die datei über den
uart wieder ausgelesen wird. diese funktion ist zwar in meinem code auch
vorhanden, nur wird sie nicht gebraucht!
und na klar nach 30x25 Zeichen braucht das auslesen über den uart schon
ne zeit...
also auslesen raus und alles super toll jetzt! danke für den support
hier und tolle libs für die sd-card hast du geschrieben, die tadelos
funktioniern!! danke!
der fehler war mein programm...
der fehler war wie immer menschlich ;-)
Schön das es jetzt klappt :)
Oft muss man Geduld haben wenn etwas nicht klappt und man nicht richtig
Debuggen kann wegen fehlender Geräte wie z.b. Spektrum-Analyzer oder
Logik-Analyzer... Da ist Kreativität gefragt ;)
Viele Grüße
Daniel
Weißt du, daß es hier auf dem Forum svn gibt, in das man solche Projekte
einchecken kann?
Beitrag "Hinweis: Artikelsammlung"
Das macht es deutlich einfacher, die aktuelle Version zu finden ;-)
Hm, ja hatte mir das mit dem SVN auch schon mal überlegt.
Werde das mal in Angriff nehmen.
Auf http://www.mikrocontroller.net/articles/AVR_FAT32 unter "4. Der
Code"
ist aber auch immer die neuste Version verlinkt.
Aber stimmt schon SVN wäre schöner.
Viele Grüße
Daniel
Hi,
vielen Dank für die Library. Ich habe dazu eine Frage:
Warum wird ein anderer Pin als der Hardware SPI SS für MMC_Chip_Select
verwendet? Funktioniert das nicht mit dem SPI SS?
Bei meinen Board ist das CS der SD Karte an dem SPI SS angeschlossen.
Ich habe das Problem, dass meine 2 GB Sandisk MicroSD Karte nicht
erkannt wird. Ich habe Karten von zwei verschiedenen Herstellern
getestet. Bei MMC_Chip_Select habe ich den Pin von SPI SS angegeben.
SDHC ist auf false. Sonst ist es der gleiche Code wie im Wiki Eintrag.
Vielen Dank & Gruß
Mark
Hallo,
das mit dem MMC_Chip_Select Pin hatte ich einfach so von Ulrich Radig
übernommen, ohne viel darüber nachzudenken. Warum genau es nicht klappt,
wenn man den richtigen SPI SS Pin nimmt weiß ich nicht genau. Müsste man
mal im Datenblatt nachschauen, vielleicht muss man da nur noch was
einstellen, damit es klappt.
Kannst du nicht einfach einen anderen Pin nehmen?
Grüße Daniel
Das ist mir schön öfter aufgefallen. Manche Leute haben regelrecht Angst
vor dem SS Pin. Könnte das evtl. mit dem (berechtigterweise) miserablen
Image des Namens zu tun haben?
:-\
Hallo,
Neue Dateien werden nich angelegt, append funktioniert wenn die Datei
nicht leer ist. Habt ihr ne Idee?
SanDisk MicroSD 2GB(+Adapter), 3.3V LM317, Pagelwandler - 3.3K,1.8K
ATMega32, 16MHz
stable-mmc-0.5.7
Mfg,
Amega
Hallo,
zeig mal den Code, hast du in der config.h etwas geändert?
Besorg dir für 20 Cent nen HC4050 als Pegelwandler oder lass den Atmega
mit 3,3 Volt laufen.
Du könntest auch mal probieren ob die Einstellung in der config.h,
So, es gibt jetzt ein SVN-Repository für die Bibliothek.
Dort wird immer die Neuste Version zu haben sein.
Immer als AvrStudio Projekt und mit Linux Makefile.
Das jetzige Update enthält eigentlich nur 2 Fixes.
1. Ein return wert ist dazu gekommen in der Funktion ffopen
2. In der fat_getFreeBytes wird der Sektor anders geladen.
Zusätzlich sind noch ein paar Funktionen static geworden.
Viele Grüße
Daniel
Link zu allen SVN:
http://www.mikrocontroller.net/svn/list
Link zur Bib.:
http://www.mikrocontroller.net/svnbrowser/avr-fat32
Hi,
ffopen->fat_loadFileDataFromDir kommt nicht zurück - endloss Schleife?
Hab die SD-Karte under Linux formatiert (fat16,fat32):
fdisk (type 6,b,c), dann mkfs.vfat .
Wie ich schon gerschrieben habe, funktioniert nur wenn die Datei da ist
und nicht leer.
Ich kann versuchen auch unter Windows die Karte zu formatieren.
Mfg
Nachdem ich unter Windows die Karte formatiert habe, wird nun neue Datei
angelegt, die bleibt aber leer.
Wenn ich noch mal versuche, dann gibts die Datei doppelt.
Wie funktioniert bei auch? Habt ihr mit 2GB Karte getestet?
Bin aber trotzdem froh, dass sich was bewegt :)
Hallo,
klappt es denn jetzt?
Mit Linux hab ich es nie hin bekommen, dass bei einer frisch
formatierten Karte das Root Directory mit 0x0fffffff abgeschlossen wird.
Linux hat da, immer 0x08ffffff oder so draus gemacht. Wenn das Dir dann
nicht mehr leer ist, ist korrekter Weise 0xffffffff draus geworden.
Kannst du dir die Sektoren der Karte anschauen? Wenn ja sieh mal nach
wie der Root-Dir Cluster in der Fat aussieht. Hilfreiches Tool dafür
WinHex. Läuft auch unter Linux.
Viele Grüße
Daniel
Servus,
Amega schrieb:
>Wie funktioniert bei auch? Habt ihr mit 2GB Karte getestet?
Ich verwende 3 unterschiedliche Karten, zb. Verbatin Micro 2 Giga
Die Karten funktionieren einwandfrei.
Betreibe meine Karte mit einem Atxmega128a3 mit 16Mhz. SPI-Takt 8Mhz.
fat_getFreeBytes() benötigt bei einer 2 Giga Karte gerademal 200 mS.
Bin voll zufrieden.
Gruß GG
Hallo,
mkfs.vfat formatiert das komisch... hast du keinen Windows Rechner zum
Formatieren zur Hand?
Es liegt an dem blöden Eintrag für das Root-Dir.
Grüße Daniel
Hab die Funktion fat_loadFileDataFromDir geändert und nun filegt das
Ding :)
fat.c@172
while(!(( (i>=0x8ffffff && i<=0xfffffff )
&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){// prueft ob weitere
sektoren zum lesen da sind (fat32||fat16)
Bin neugierig, ob linux-formatierte Karte unter Winx lesbar ist.
Und noch was:
http://www.pjrc.com/tech/8051/ide/fat32.html
Also, the end-of-file number is actually anything equal to or greater
than 0xFFFFFFF8, but in practive 0xFFFFFFFF is always written.
>ups 0x#FFFFFF8 != 0x8ffffff !?!?
Kommt auf die Endianness an ;)
>fat.c@172> while(!(( (i>=0x8ffffff && i<=0xfffffff )>&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){// prueft ob weitere>sektoren zum lesen da sind (fat32||fat16)
Ja sollte so laufen, bläht das den Code auf? Keine Ahnung wie viel mehr
Aufwand ein größer gleich im Gegensatz zu gleich ist...
>append funktioniert bei mir nicht>wenn die Datei leer ist.
Das schau ich mir mal an. Aber eigentlich sollte das kein Problem sein,
weil ans Ende spulen bei Dateigröße 0 kein Problem ist.
file.c@168
while( offset>=512 ){ ...
offset ist hier die Byte Stelle zu der man spulen möchte. Bei Dateigröße
0 ist das 0 und 0 ist nicht >= 512, also wird in ffseek nichts
sinnvolles gemacht...
Nur um sicher zu gehen, du appendest ;) ja so oder?
Ja krass, das hatte ich doch tatsächlich immer überlesen.
Wird geändert werden, danke.
Gewundert hatte es mich doch schon warum Linux das so seltsam formatiert
:)
Grüße Daniel
kann es sein das man bestimmte ascii zeichen nicht schreiben kann? weil
ich schicke den richtigen string, und wenn ich die zeichen einzeln
ausgebe stimmen sie auch, nur auf der sd karte stehen sie nicht
danke mfg alex
Wenn du Strings mit der Funktion ffwrites schreibst, darf in dem String
logischerweise kein '\0' alias 0x00 vorkommen, da dies ja ein String
Ende markiert. Bei anderen Steuerzeichen bin ich mir nicht sicher ob die
gehen.
Mit ffwrite kannst du jedes Byte Zeichen auf die Karte schreiben.
Falls das immer noch nicht geht, müsstest du mal ein bisschen Code
zeigen und die Zeichen die du schreiben möchtest.
Viele Grüße
Daniel
Hi,
ich hab ne allgemeine Frage: Warum verwendest du für Strings unsigned
char* anstatt char*? Die Ascii Tabelle geht doch nur bis 127 und dadurch
gibt es bei mir viele Warnings.
Da kann ich nur aus dem eigenen Nähkästchen plaudern: signed char ist
einfach nur krank, wenn es Zeichen und keine int-Werte enthält.
Aber vielleicht ist es auch Gewohnheitssache, mit den Abstrusitäten von
signed char - Vergleichen zurecht zu kommen.
habe heute versucht daten über den uart einzulesen, lib ist ja
vorhanden.
verwende ich jedoch
1
ugetc();
zum auslesen, dann bekomme ich beim kompilieren folgenden fehler
:369: undefined reference to `ugetc'
1
#include"uart.h"
ist im maincode geaddet und initalisieren und
1
uputc(ffread());
funktioniert im main programm auch, beim kompilieren dabei gibts auch
keine fehler. nur wenn ich ugetc aufrufen möcte schreit er eine
fehlermeldung.
kann das bitte mal wer testetn obs ähnliche fehler gibt?!
mfg
low
Hm,
hab ich da was überlesen oder geht es im Prinzip nur um vfat, also mit
langen Dateinamen?
Das die da so auf dem fat noch herumreiten, wird wohl eher irgendwie
exFat mit Zusammenhängen ?!?
Fat16/32 ist ja schon ziemlich in die Jahre gekommen. Wenn man mal so
moderne Dateisysteme sieht...
hallo
wenn ich einen string mit vielen zeichen schreiben will hängt sich das
programm auf. hab schon vieles probiert. \0 macht auch keinen
unterschied. anscheinend gibt es ein limit für die stringlänge?! denn
mit strings die kürzer sind funktioniert alles problemlos. anbei ein
beispiel für eine länge die bei mir nicht mehr klappt.
hat wer einen tipp?!
ps. fat32 formatierte karten klappen derzeit auch nicht, kann man das wo
umstellen?!
speicher ist eigentlich noch da
Program: 14360 bytes (43.8% Full)
(.text + .data + .bootloader)
Data: 1528 bytes (74.6% Full)
(.data + .bss + .noinit)
Hallo,
ich vermute mal Ram Überlauf. Wo in deinem Programm kommst du auf die
1528 bytes Ramverbrauch??
Pack den String mal ins Flash und probier das nochmal.
Oder mach ein kleines Array und schreib das wiederholt auf die Karte...
Mit was Fat32 Formatiert? Mit Windows?
Welche Version der Lib nutzt du?
Was genau meinst du mit klappt nicht ?!?
Wenn du ein CharArray so erstellst brauchst du das '\0' am Ende nicht!
Das wird dann automatisch mit dran gemacht.
Daniel R. schrieb:> Hallo,> ich vermute mal Ram Überlauf. Wo in deinem Programm kommst du auf die> 1528 bytes Ramverbrauch??>> Pack den String mal ins Flash und probier das nochmal.> Oder mach ein kleines Array und schreib das wiederholt auf die Karte...>> Mit was Fat32 Formatiert? Mit Windows?> Welche Version der Lib nutzt du?> Was genau meinst du mit klappt nicht ?!?>> Wenn du ein CharArray so erstellst brauchst du das '\0' am Ende nicht!> Das wird dann automatisch mit dran gemacht.>>
1
>charmap_start[]="awedaweree";
2
>
>>> Welchen Controller benutzt du?>> Grüße Daniel
ok, mal wieder ein programmfehler meinerseits ;-)
anscheinend is das ram übergelaufen. habe mal die ganzen strings ins
eeprom des avr (atmega328p) abegelegt und jetzt klappts das beschreiben
mit langen strings auf die sd problemlos.
mein ram ist so voll weil ich große array habe ca. 100 uint16_t array
und dann noch lcd/sd/gps. und alles sehr unaufgeäumt.
das mit fat32 muss ich noch testen, aber ich tipp mal drauf es
funkt.formatiert ist jedenfalls alles it windows.
bin derzeit ganz zufieden mit fat16 läuft alles super und prima!! danke
daniel!!
hab das programm jetzt soweit geschireben, dass ich auf der sd-karte ein
kml file für google earth erstelle und die gps koordinaten reinschreib.
mfg low
Hallo
ich würde gerne meine gps Datensammlung gerne speichern
und bin auf diesen Foren Beitrag gestoßen
Das was hier angeboten wird ist ein bischen viel
kann mir jemand sagen welche DAteien und Methoden ich brauche, um nur
die Datensammlung zu speichern.
benutze einen atmega16
mfg aga
Hallo,
orientier dich einfach an dem Beispiel in der main.c
Oder hier dran:
http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel
Da ist ein einfaches Beispiel wie man die schreib/lese Funktionen
benutzt.
Wenn du speziellere Hilfe möchtest, musst du schon ein bisschen mehr
verraten :)
Oder noch besser ein wenig Code Posten, zu dem man Hilfestellung geben
kann.
Grüße Daniel
Hallo Daniel,
erstmal meinen herzlichsten Dank für deine Arbeit an diesem Projekt, das
über die Zeit wirklich hervorragend geworden ist!
@alle: Mein Dank gilt natürlich auch für alle anderen, die sich an
diesem Projekt beteiligt haben oder wertvolle Vorarbeit geleistet haben!
Ich verwende die SD-Library (leicht angepasst) auf einem ATmega64 unter
IAR und soweit läuft auch alles perfekt mit unterschiedlichsten
SD-Karten.
Nun sind mir aber 3 Dinge/fehler aufgefallen, die ich hier mal
ansprechen wollte, weil ich die in den bisherigen Diskussionen noch
nicht finden konnte.
1.) Fehler in der Funktion "fat_loadFileDataFromCluster"?
Beim Vergleich des Dateinamens werden in der folgenden Zeile nur 10
Zeichen verglichen, obwohl der Dateiname aus 11 Zeichen besteht.
Folglich wird also das letzte Zeichen ignoriert, wodurch "MEINFILE1.TXT"
und "MEINFILE1.TX2" im Vergleich identisch sind!
Bisher:
1
if(0==strncmp((char*)file.name,(char*)name,10)){
Korrigiert:
1
if(0==strncmp((char*)file.name,(char*)name,11)){
2.) Fehler in der Funktion "fat_loadSector"?
Am Ende der Funktion steht "return FALSE;" wobei diese Stelle niemals
erreicht werden kann. Diese Funktion kann in der bestehenden Form nur
"TRUE" zurückgeben, weshalb sich eine Prüfung auf Fehler bisher auch
völlig erübrigt. Bei welcher Bedingung, hätte denn FALSE zurückgegeben
werden sollen?
3.) Hier (http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten)
steht:
"Nachdem die Karte deselektiert wurde (/CS auf high), die Taktleitung
noch einige Male pulsen, damit die Karte DO hochohmig/tri-state schaltet
(vgl. Chans Erläuterungen)."
Das wird in der SD-Library bisher noch nicht gemacht, weshalb ich das
bei mir noch eingefügt habe. Das könnte z.B. folgendermaßen gelöst
werden. An jeder Stelle, wo im Source "MMC_Disable()" steht, müsste nur
ein Schreibbefehl folgen, oder?. So z.B.:
1
MMC_Disable();// CS High
2
mmc_write_byte(0xFF);// dummy write, 8 CLK-Pulse nachdem CS High, damit die Karte DO tri-state schaltet
Hallo.
@ Nig G. (nig)
Bei Punkt 1 und 2 hast du recht, ist mir irgendwie durchgegangen :)
Wird geändert.
Zu Punkt 3, diese Karten sind SPI hörig, also brauchen eigentlich für
alles einen CLK um was zu machen, zumindest die meisten. Das mit dem "DO
hochohmig/tri-state" wirkt sich aber auch nur aus, wenn man mehrere
"Geräte" am selben SPI Bus hat, sonst wäre das egal.
Wird aber geändert.
Danke für die Unterstützung.
@ test (Gast)
Man kann jede Karte nehmen, auch so ganz billige für 2-3 Euro. Wichtig
nur, es müssen MMC, SD oder SDHC Karten sein.
Viele Grüße
Daniel
Ach ja, ich überlege grade die Prüfung in fat_loadSector ganz raus zu
nehmen, ist zwar nicht so schön ohne Fehler Prüfung, aber so wie es bis
jetzt immer war bringt es ja auch nix...
Mal als Zwischenlösung:
ich bekomme immer die Fehlermeldung aus der funktion ffclose:
../file-0.3.c:119: error: 'kb_buffer' undeclared (first use in this
function)
Damit liegt der Compiler auch völlig richtig, kb_buffer wurde da
nirgendwo deklariert, aber hab natürlich nichts verändert, einfach nur
eure Codebeispiele kopiert.
Muss ich was im Projekt bei AVR Studio einstellen?
Makefile benutze ich nämlich keine...
Hallo,
oha du versuchst da die Version 0.3 zu kompilieren...
Nimm die aus dem SVN und dann sollte das ohne Probleme gehen.
Viele Grüße
Daniel
PS: In der SVN Version ist auch eine AVR-Studio Projektdatei dabei...
Aktuelle Version: 0.5.9
http://www.mikrocontroller.net/svnbrowser/avr-fat32
Moin,
ich experimentiere derzeit auch mit SD-Karten an einem ATmega32. Derzeit
noch mit dem Code von Ulrich Radig.
Würde gerne mal am WE diesen Code ausprobieren.
Gibt es schon Unterstützung für LFN?
Beste Grüße, Marek
Hi,
nein gibt es noch nicht.
Hab da aber eine Idee, wie man da tatsächlich reguläre Unterstützung für
lange Dateinamen hin bekommt ohne nochmal 256 Byte Ram zu brauchen :)
Aber vor Mitte Juli wird da nix draus werden...
Aber es ist jeder herzlich eingeladen mit zu entwickeln. Ich pflege das
dann in die Lib ein.
Viele Grüße
Daniel
Hallo,
ich hab nun auch endlich die Software erfolgreich zum Laufen bekommen.
Der Kasus Knaxus war bei mir, dass ich die Software-SPI verwendet habe,
welche eben so schnell läuft, wie es der Prozessortakt hergibt. Bei
18,432MHz ist das für die SD-Karte einfach zu schnell. Ich habe ein paar
zusätzliche Delays eingebaut und dann ging es.
Von meiner Seite dann auch nochmals vielen Dank, für die ganze Mühe, die
du bisher hier rein gesteckt hast.
Gruß Thorsten
Hallo,
kannst du mal zeigen an welchen Stellen du da delays reingebaut hast,
weil eigentlich ist selbst 20 MHz SPI nicht zu schnell für SD/MMC
Karten...
Viele Grüße
Daniel
Servus,
Thorsten J. schrieb:> ich hab nun auch endlich die Software erfolgreich zum Laufen bekommen.>> Der Kasus Knaxus war bei mir, dass ich die Software-SPI verwendet habe,>> welche eben so schnell läuft, wie es der Prozessortakt hergibt. Bei>> 18,432MHz ist das für die SD-Karte einfach zu schnell. Ich habe ein paar>> zusätzliche Delays eingebaut und dann ging es.
ich betreibe meine SD-Card (Verbatim Micro 2 GB) hardwaremäßig mit 20
MHZ!
Proz. Atxmega
Prozessortakt 2*10 MHz,keine SPI-Teilung, also 20 MHZ am SPI. Das ist
eine nachweisbare Geschwindigkeit.
Deine Aussage: „Ein paar zusätzliche Delays“ kann heißen: 1,2 oder xx
Mhz.
Wei schnell ist der SPI-Takt nun wirklich?
Gruß GG
Ich hab in der mmc_read_byte() und mmc_write_byte()
1
MMC_Write&=~(1<<SPI_Clock);//erzeugt ein Clock Impuls (Low)
ergänzt zu
1
_delay_us(SOFT_SPI_DELAY_US);
2
MMC_Write&=~(1<<SPI_Clock);//erzeugt ein Clock Impuls (Low)
3
_delay_us(SOFT_SPI_DELAY_US);
und hab dann getestet. Die Funktion _delay_us() stammt dabei aus der
<util/delay.h>.
Für SOFT_SPI_DELAY_US waren Werte größer 0.3 notwendig, damit die Karte
arbeitet. Das ergibt einen Takt von etwa 300kHz, der jedoch einen hohen
Jitter aufweist.
Wenn ich das noch recht im Hinterkopf habe war es auch so, dass die
Karten zur Initialisierung mit maximal 400kHz betrieben werden dürfen.
Bei Verwendung der Hardware-SPI wird dem auch Rechnung getragen und erst
nach erfolgter Initialisierung auf volle SPI-Geschwindigkeit geschaltet.
Gruß
Thorsten
Hallo,
ja guter Einwand. Die Initialisierung im Software SPI Modus schau ich
mir nochmal an. Bin eh grade eine ordentliche Platine für eine SD Karte
am machen. Wenn das fertig ist, gibt es eine neue Version...
Danke und viele Grüße
Daniel
// der SS pin des SPI ports wird nicht benutzt! also da nich die karte anschließen, sondern an MMC_Chip_Select !
2
3
#if defined (__AVR_ATmega2560__)
4
#define SPI_MISO 3 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist (DO)
5
#define SPI_MOSI 2 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist (DI)
6
#define SPI_Clock 1 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
7
#define MMC_Chip_Select 0 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist (CS)
8
#define SPI_SS 0 //Nicht Benutz muß aber definiert werden
9
#endif
10
11
#if defined (__AVR_ATmega128__)
Bei diesem Board ist die CS-Leitung der SD-Karte direkt mit dem SS-Pin
des Controller verbunden.
Daher hab ich einfach mal ganz "blauäugig" den entsprechenden Portpin in
die obigen Definitionen eingetragen.
Das mitgelieferte Beispielprogramm liefert "Boot..OK"
Ich hab zur Fehlersuche noch weitere "uputs" eingebaut, und schon der
nächste Aufruf meldet sich nicht mehr zurück: (keine augabe von uputs)
Anpassungen für ATMega2560:
Ich hab das Library um Support für ATMega2560 CPUs erweitert.
Im Anhang sind die geänderten Files.
Harry
<edit>
Mein Fehler!
nicht mmc.c, sondern mmc.h wurde angepasst.
Hi,
unter Linux gibt es die Möglichkeit zu sagen das nur mit 1 er Fat
formatiert werden soll... Unter Windows geht das so glaube ich nicht.
Viele Grüße
Daniel
Ich habe das bis jetzt immer mit GParted unter ubuntu gemacht, da habe
ich die Option nur 1 Fat anzulegen noch nicht gefunden. Könntest du mir
bitte ein Stichwort geben wonach ich besser googlen kann.
Hi, ich habe auch mal wieder ein Problem:
Ich will grade die neuste Version einbinden (von 0.5.7 auf 0.5.9).
Ich rufe in meinem Programm an manchen Stellen die ffwrites-Funktion wie
folgt auf
1
ffwrites("huhu");
jedoch bekomme ich nun zu jedem Schreibbefehl die Nachricht, daß da was
mit den Definitionen nicht passt. Hier einer der vielen gleichen Fehler:
Ich habe etwas geforscht und an jeder Ecke steht in der neuen Version
"unsigned". Und daran wird es wohl auch liegen. Warum wurde das denn
umgestellt?!
Aber was mir viel wichtiger ist, was kann ich gegen diesen Fehler
machen?
Vielen Dank für alle guten Ratschläge!! :)
So nun habe ichdas zweite Problem: ich kann weder mit der alten (0.5.7)
noch mit der neuen (0.5.9) Version auf meine SD-Karten schreiben. Obwohl
SDHC aktiv ist.
Als Speicherkarten benutze ich die zwei im Foto.
Ich formatiere mit WindowsXP Pro.
Ich habe jeweils mit den Beispiel programmen ausprobiert.
Komisch ist, daß in der neuen Version machmal (jedes 15-20ste Mal) durch
die
1
mmc_init
gegangen wird (die drei Punkte erscheinen), jedoch erscheint nie das
"OK".
Bei der alten Routine klappt noch nicht mal der erste Schritt.
Die Hardware die ich benutze ist ein ATmega128 mit 7,3728Mhz.
Angeschlossen ist alles richtig, sonst würden ja die drei Punkte auch
nich erscheinen - wurde aber dennoch schon x-Mal kontrolliert.
Kann mir jemand helfen?!
Grüße aus Hannover
Hallo,
so Fehler wie irgendwas klappt manchmal und manchmal nicht, sind
meistens Hardware Fehler... Benutzt du Software SPI oder Hardware, wie
lang sind die Kabel, Welche Spannungs Pegel...
Mach mal ein Bild vom Aufbau, dann kann ich evtl. mehr sagen
Viele Grüße
Daniel
hmm... ich habe eben noch mal alle Lötstellen kontrolliert und
vorsichtshalber alle nachgelötet - geht aber immer noch nichts.
ich betreibe die karte:
- ohne treiber baustein
- direkt an einem ATmega128
- bei 3,3V.
Meinen Eagleplan habe ich angehängt. Ich hoffe, ich hab keinen Fehler in
der Verschaltung gemacht :)
Viele Grüße und schon mal besten Dank für deine Hilfe!
ich habe eben einfach mal zwei 10k Ohm Pull-Up-Widerstände an die CS-
und die MISO eingebaut (siehe Anhang), weil ich das hier gelesen hatte:
http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten. aber das
hilf auch nichts! Ich verzweifel noch!!! Hilfe!
Hallo,
du steckst doch den SPI Programmer aus wenn du die Karte testest oder?
Mehr fällt mir grad nicht ein, schaue aber später nochmal genauer...
Viele Grüße
Daniel
Hm, Schaltplan sieht Ok aus.
Jetzt könnte der Fehler immer noch in der Software liegen oder im
Tatsächlichen Aufbau der Schaltung.
Ich hab selber so eine 2GB Scandisk Karte und mit der funktioniert es...
Hast du was in der config.h geändert oder in der mmc.h ?
Wie sieht die Initialisierung genau aus?
Mach doch mal ein Foto der fertigen Schaltung.
Viele Grüße
Daniel
Hi danke für deine Mühe!!!
Ich denke nich, daß es an der Software liegt. Ich hab nichts in deinem
Beispielprogramm geändert. Ich will morgen noch mal die Schaltung in
schön aufbauen - sieht echt nach Kraut und Rüben aus.
Wenns fertig is, lade ich ein paar Fotos hoch.
Grüße und genieß das schöne Wetter - in Hannover sind noch 30°C und ich
muss raus: hier drinnen sind die nämlich auch ;)
Grüße,
Matze
Hi es lag wirklich nich an der Software. Ich habe zwei Sachen geändert:
1) beim ATmega128 geht der ISP nicht über den SPI sondern tw. über den
USART0. Ich habe meinen UART-RS232 von dieser doppelbelegten
Schnittstelle abgelötet.
2) Ich habe gleichzeitig den µC gewechselt. Hatte noch nen zweiten
mega128.
Ich habe eben nochmal den neuen µC mit eingesteckter RS232 Schnittstelle
programmiert. Geht trotzdem. Lag also wohl an einem def. µC... Jetzt
gehts aber!!!
Aber warum mich das jetzt vier Tage meines Lebens kosten musste, weiß
ich auch nich.. ich hasse diese Kleinigkeiten an denen es immer hängt!
Dennoch vielen Dank für deine Hilfe!
Hi,
ich habe da etwas ganz komisches grad festgestellt. Ich kann in eine
Datei mit einer Funktion nichts schreiben.
Ich will in eine Datei für eine Log-Datei bevor die Daten aufgezeichnet
werden eine Startsequenz schreiben (Funktion: sd_geschw_start(void)).
Ich habe in die Datei eine UART-Ausgabe ("start") eingebaut; diese
erscheint auch auf meinem Terminal, aber es steht kein "huhu" in der
Datei. Nur ein "ende"... WARUM zu Teufel?!
Hat jemand ne Idee?
Grüße,
Matze
Hallo,
bei dem Stück Code das du gepostet hast, zähle ich ~95 Bytes nur an
Ascii Zeichen... Das ist ziemliche Ram Verschwendung...
Bin mir jetzt da grad nicht sicher, aber benutzt du fat_str richtig?
Versuche mal an ffopen einen festen Dateinamen zu übergeben, um das
Problem einzugrenzen.
Ach ja und schließt du die Datei auch irgendwann vor verlassen des
Programms auch?!?
Viele Grüße
Daniel
Hi Daniel,
ich habe den Tag über in meinem Wust an Funktion gewütet und vieles
zusammen gestrichen, dabei fiel mir auf, daß in einer anderen Datei an
zwei stellen wirklich das "ffclose()" gefehlte... dennoch danke für
deine Mühe. Jetzt geht alles :D
Morgen gibts dann erste Probeläufe mit meinem neuen Datenlogger :D :D
Gute Nacht,
Matze ;)
So geht alles. Allerdings habe ich grade versucht eine
Verzeichnisstruktur anzulegen. Beim Aufruf von
1
ffmkdir
habe ich aber noch Probleme:
Mein Quelltext dazu sieht wie folgt aus:
1
unsignedcharverzeichnis[13]="TEST";
2
ffmkdir(verzeichnis);
(Natürlich nachdem die Karte initiallisiert wurde :)
Auf meiner SD-Karte taucht auch ein Ordner auf. Allerdings kann ich
diesen nicht Öffnen. Windows XP Pro sagt mir:
1
TEST bezeiht sich auf einen Pfad, der nicht verfügbar ist. Dieser kann auf einer Festplatte dieses Computers [...] sein.Stellen Sie sicher, daß der Datenträger korrekt eingelegt ist, [...]. Und wiederholen sie den Vorgang. ...
Muss ich bei dem Funktionsaufruf irgendwie mehr beachten?!
Achja: wieso funktionieren eigentlich nur Grossbuchstaben sowohl bei
Dateinamen als auch bei Verzeichnissen?!
Danke für deine Hilfe,
Matze ;)
Hallo,
versuch mal "TEST " als Verzeichnisname ( 4 Buchstaben und 7
Leerzeichen). Das mit den Großbuchstaben ist noch aus der DOS Zeit, also
aus der Fat16 Zeit quasi.
Wenn ich lange Dateinamen Unterstützung mit eingebaut habe wird sich das
alles etwas vereinfachen, zumindest in der Anwendung :)
Viele Grüße
Daniel
Hallo,
wenn mir ja jemand sagen könnte wie CodeVision mit void Pointern umgeht
könnte ich da vielleicht was machen... Aber die Dokumentation da finde
ich etwas dürftig. Glaube es hakt da am meisten, der Rest sind ein paar
Register und Kleinigkeiten...
Grüße Daniel
Habe mir mal vor einigen tagen die Neue Light Version von Codevision
gezogen und getestet.
Die haben ja eine Sd Lib drin und die Funktioniert ja auch super.
Nur komme ich nicht ganz zurecht damit.
Kam zwar auf Display den Inhalt der Datei schreiben und auch Ordner etc.
aber ich möchte die Werte für andere Sachen Übernehmen und das geht
irgentwie nicht.
MFG: Andre
Hallo zusammen,
ich wollte gerne wissen, welche Lesegeschwindigkeiten ich bei der
Verwendung dieser FS32-Bibliothek von SD-Karten zu erwarten habe.
Im Einsatz soll ein ATmega168 mit 8 Mhz eingesetzt werden.
SPI in Hardware mit halber Taktgeschwindigkeit.
Und gibt es Möglichkeiten die Leserate zu maximieren, z.B. FAT16 anstatt
FAT32?
MfG
Rene
Hallo,
also wesentlich schneller wird es durch Fat16 nicht werden, da das nur
mit den Fat einträgen selbst in Zusammenhang steht. Also nur bei Fat
lookups ins Gewicht fällt...
Also mit Fat32, multiblock-write und 4 Mhz SPI werden wohl so um die
100-150 k Bytes/Sec gehen. Mit MMC Karten evtl. sogar mehr.
Viele Grüße
Daniel
Hi Daniel,
danke für die prompte Antwort.
Das mit dem Multiblock ist ja so eine Sache, da es wohl nicht von jeder
Karte unterstützt wird.
Wie ist denn die maximal zu erwartende Leserate ohne
Multiblock-Unterstützung?
Ich würde gerne universell bleiben, was die SD-Karten angeht.
MfG
Rene
Hm,
ich hab nur eine uralte Karte die Multiblock nicht unterstützt.
Bei den neueren sollte das wohl immer gehen.
Die Geschwindigkeit hängt auch stark von der Karte ab.
Schätzungsweise wird lesen auch im Bereich 100-150 kBytes/sec liegen...
Viele Grüße
Daniel
Hallo,
hier mal eine kleine Beta der Version 0.6
Falls da mal jemand reinschauen mag :)
Neu:
Lange Dateinamen, kleinere Vereinfachungen.
Was geht noch NICHT:
Root dir bei Fat16 beschreiben wenn dort schon mehrere Einträge sind.
Einen vollen Ordner erweitern.
Was geht:
Dateien mit langem Dateinamen lesen.
Ordner mit langem Dateinamen lesen/wechseln zu.
Beim Anlegen wird wie gesagt noch der Ordner nicht erweitert!
Bei einem leeren Ordner und 4 Sektoren/Cluster könnte man aber
mindestens 4 Dateien mit Dateinamen von 255 Zeichen Länge anlegen ;)
Datei mit langem Dateinamen anlegen löschen.
Ordner mit langem Dateinamen anlegen rekursiv löschen.
Beispiel für den Aufruf:
1
ffopen((unsignedchar*)"langer name test.txt")
So wird wie gehabt, die Datei angelegt wenn nicht vorhanden, oder
geöffnet wenn vorhanden.
Viele Grüße
Daniel
Hallo,
hier mal die zweite Beta.
Lange Dateinamen werden jetzt komplett unterstütz. Bei Ordnern und
Dateien. Das ist allerdings nicht ganz Standard konform. Sollte aber
keine Probleme Machen solange man die Karte mit Geräten liest/schreibt,
die auch lange Dateinamen unterstützen !
Es gibt eine Option in der config.h die heißt "MMC_ENDIANNESS_BIG", wie
der Name vermuten lässt, kann damit die Byteorder umgestellt werden. Wer
mit den void Pointer Probleme hatte sollte das mal ausprobieren :)
Die Funktion "fflushFileData()" kann jetzt während geschrieben wird
aufgerufen werden, sie sorgt dafür, dass die Dateiinformationen
gesichert werden. Allerdings sollte das möglichst selten gemacht werden,
da immer mindestens 2 Sektoren geschrieben werden müssen !
Viele Grüße
Daniel
Soo, ist fertig :)
Wäre schön, wenn ich evtl. ein bisschen Feedback bekommen könnte, falls
irgendwo was schief läuft oder es Verbesserungen gibt.
Das einzige Problem, dass immer noch besteht ist, dass bei Software-SPI
bei der Initialisierung nicht langsamer getaktet wird, da is mir noch
nicht wirklich was schönes zu eingefallen :)
Die neue Version gibts hier:
http://www.mikrocontroller.net/svnbrowser/avr-fat32
Viele Grüße
Daniel
Hallo,
ich bin neu hier und habe es mal ausprobiert.
Die 0.6.0 hat nicht getan !
Ich habe es 1:1 genommen und laufen lassen.
Der Controller konnte wohl schreiben + lesen + zufügen.
Aber in Windows wurde die Datei nicht erkannt. Windows zeigte die Datei
mit "Test.txt." (mit '.' am Ende) mit 0kb an.
Öffnen und Löschen ging nicht. Nur neu formatieren.
Danach bin ich auf die 0.5.9 umgestiegen. Hat geklappt.
Info:
2GB Flash Karte
ATMEGA16 @ 16 MHz
Hallo,
ja ich war irriger weise davon ausgegangen, dass wenn Linux das
ordentlich anzeigt, Windows das auch macht. Macht es aber nicht...
Werde später ein update machen, da gibts dann auch noch mehr neue Sachen
:)
Viele Grüße
Daniel
So neue Version 0.6.1 hochgeladen.
http://www.mikrocontroller.net/svnbrowser/avr-fat32/
Man kann jetzt wesentlich mehr konfigurieren in der config.h
Viele Grüße
Daniel
PS: Als Anhang noch ein Benchmark Programm für atmega168 @ 16 MHZ
Hallo!
Also ich habe getestet 0.6.0 - das Problem mit dem nich lesen können
etc. unter Windows hatte ich auch. Jetzt habe ich 0.6.1 getestet, im
Prinzip funktionierts, wenn die Karte leer ist legt es die Datei an,
allerdings steht dann 2 x "Hallo Datei!" in der Datei, je einmal in
einer Zeile.
Ist das normal / gewollt?
Darüber hinaus, befindet sich eine leere test.txt auf der Karte passiert
nichts bzw. das Programm kommt nicht zum Ende - habe 3 LED zum debuggen,
irgendwo nach dem init bleibts stehen und die Datei bleibt leer, ich
werde berichten wenn ich den Wunden Punkt gefunden habe ...
Ich verwende einen ATmega2561 @ 16MHz, sandisk 1GB bzw. Platinum 2GB
Aber ne tolle Sache ischs in jedem Fall
Gruß Jens
Hallo,
>Darüber hinaus, befindet sich eine leere>test.txt auf der Kart
das ist nicht normal soweit ich verstehe was Du machst. Zu welcher Datei
befindet sich die leere test.txt auf der Karte?
Grüße Daniel
PS: Bin für jede Anregung dankbar !
nein nein, weil 0.6.0 nicht funktioniert hatte hab ich etwas rumprobiert
- u.a. hatte ich eine leere test.txt angelegt, nach dem Durchlauf des
Programms war die dann immernoch leer, das war dann aber auch bei 0.6.1
so.
Werde mich noch n bissi mehr damit beschäftigen, vielleicht kann ich ja
noch was konstruktives beitragen ;)
Grüßle
...kann mir jmd. ein wenig behilflich sein?? Ich habe Version 0.6.1
heruntergeladen, im AVR-Studio meinen Controller (XMeaga 64A3)
eingestellt und compiliert. Es hagelt gleich einige Fehlermeldungen:
../mmc.c:128: error: 'DDRB' undeclared (first use in this function)
../mmc.c:128: error: (Each undeclared identifier is reported only once
../mmc.c:128: error: for each function it appears in.)
../mmc.c:128: error: 'SPI_MISO' undeclared (first use in this function)
../mmc.c:129: error: 'SPI_Clock' undeclared (first use in this function)
.
.
.
Ich denke, es fehlen ein paar einstellungen für den Controller. Aber ich
weiss nicht wo und was...
Hallo,
ich kenne die Atxmegas nicht.
Wie setzt man denn da einen Pin auf 1 bzw. 0 ?
In der mmc.h müssen die Pins an der die Karte hängt eingestellt werden.
Wenn aber bei einem xmega die Pins anders angesteuert werden müsste man
da noch mehr anpassen...
Viele Grüße
Daniel
Hallo,
Uwe S. schrieb:> fehlen ein paar Einstellungen für den Controller
in der mmc.h sind einige Atmega vordefiniert! Aber kein Atxmega.
Wenn du mit solchen Kaliebern arbeitest, solltest du schon etwas
Hintergrundwissen über die Hard- und Software besitzen.
Dir jetzt einen fertigen Code zuliefern ist nicht die richtige
Vorgehensweise. Wenn dir der Befehl DDRB z.B. nichts sagt, ist das
Betreiben einer SD-Card am XMEGA schon aussichtslos.
Sollte dennoch Intresse bestehen, melde dich nochmals.
Gruß GG
...nein - DDRB sagt mir jetzt so aus dem Kopf nix. Mit Atmels arbeite
ich zum ersten mal. Ich habe vorher mit ARM9 (davor SAB509, PIC, ...)
gearbeitet. Ich muss jetzt wohl hoffen, dass mir der XMega dann nicht
zu gross wird ;-)
@Daniel R.: bei den XMega ist die IO-Struktur neu gemacht - es gibt ein
paar Register mehr. Ist hier ganz gut beschrieben:
http://www.stromflo.de/dokuwiki/doku.php?id=xmega-c-tutorial
Ok, sollte sich ganz einfach portieren lassen.
Schau ich mir später mal an.
Mit Deiner Hilfe Uwe S. wird das schon werden. Ich selber habe keine
atxmega da.
Du könntest schon mal rausfinden an welchen Pins die SPI Schnittstelle
liegt und in welchen Registern man die einstellt...
Viele Grüße
Daniel
...so - da bin ich wieder. Ich widme mich dem Thema nur sehr
unregelmässig - je nachdem, wie ich Zeit habe.
In der mmc.h und der uart.h werden wohl durch die Compilerdirectiven die
prozessorspezifischen Einstellungen vorgenommen - richtig? Ich denke, da
müsste mann den XMega "reinzaubern".
"#if defined (_AVR_ATXmega64a3_)" oder so ähnlich - weisst du, wie das
festgelegt werden muss?
An meinem Board ist ja der 64A3 drauf und für die SD-Karte wurde
folgende Konfig. verwendet:
CS - PB1
MOSI - PC5
MISO - PC6
SCK - PC7
-> also SPIC
Als nächstes müsste ich deine Einstellungen mal vergleichen mit dem
Manual:
http://www.atmel.com/dyn/resources/prod_documents/doc8077.pdf ab S. 229
sind die Register beschrieben. Leider weiss ich nicht, in wie fern die
sich mit dem ATMega decken.
LG
Uwe
Hallo,
also ich bin ab morgen erstmal ein paar Tage weg :)
Wegen
>#if defined (AVR_ATXmega64a3)
weiß ich selber nicht genau wie das mit den Xmegas geht, weiß aber hier
sicher jemand anderes im Forum.
Also so wie ich das sehe, müsste in der mmc.h das in etwa so geändert
werden:
1
#define MMC_Write PORTB
2
#define MMC_Read PINB
3
#define MMC_Direction_REG DDRB
zu
1
#define MMC_Write PORTC.OUT
2
#define MMC_Read PORTC.IN
3
#define MMC_Direction_REG PORTC.DIR
Jetzt ist das Problem, dass der CS Pin auch an Port C sein sollte, geht
das irgendwie bei Deinem Board?
1
#if defined (_AVR_ATXmega64a3_)
2
#define SPI_MISO 6
3
#define SPI_MOSI 5
4
#define SPI_Clock 7
5
#define MMC_Chip_Select (zusätzlicher Pin von PORTC)
6
#define SPI_SS 0
7
#endif
Dann gibt es noch 2 Stellen in der mmc.c die geändert werden müssten
So wie ich das sehe, brauchst Du nur das Register CTRL vom Xmega. Dann
sollte das laufen...
Viel Spass beim Basteln.
Bis die Tage dann
Viele Grüße
Daniel
Servus,
Daniel R. schrieb:> So wie ich das sehe, brauchst Du nur das Register CTRL vom Xmega. Dann>> sollte das laufen...
ich habe dir ein lauffähiges Projekt eingestellt.
Atxmega128a3, SPIC(SD-CARD), USART 115200 USARTF0
SPIC(SD-CARD) sollte auf allen XMEGA laufen!
Gruß xmega
bei mir läuft es nun auch super. Vielen Dank für alles.
Die neue Version braucht viel weniger Platz (ca. 4kb) als die 0.5.9.
Es tuts auch der ATMEGA8
ATMEGA8 @ 8Mhz + 2GB SD-Card
Hallo.
Danke erstmal an Daniel für den Code!
In den Bemühungen den Code v.0.6.1 für eienn Mega8 auszudünnen, bin ich
inzwischen bei 84% Speicherbelegung. Nur leider funktioniert es nicht,
wenn ich LFN an und abschalte. Jednefalls ändert sich nach
Neukompilierung nicht die Speichergröße.
Das zweite Problem hat wohl mit dem ersten zu tun. Ich habe den Plan
eine START.TXT in Windows zu erzeugen, auslesen zu lassen und das in
eine TEST.TXT (mehrmals) hineinzuschreiben. Nur für Testzwecke. Wenn ich
mir das Ergebnis danach unter Windows anschaue, finde ich zwei
START.TXT. Ich habe das Gefühl, dass er die Datei nochmal neu anlegt,
wohl weil er die existierende nicht erkennt. Den Inhalt kann er aber
lesen und schreibt ihn auch brav in die TEST.TXT
Was habe ich hier falsch gemacht?
Gruß, fiete
Hallo, bin wieder da :)
@ xmega (Gast)
Danke dafür, muss ich mir mal in ner ruhigen Minute zu Gemüt führen.
@ Friedrich K. (fiete)
Klingt nach Benutzerfehler. Man kann beispielsweise nicht 2 Dateien
gleichzeitig öffnen. Poste mal den Code der bei Dir Probleme macht. Dann
kann ich bestimmt mehr dazu sagen.
Viele Grüße
Daniel
// Versuch Karte zu Initialisieren, bis es klappt. Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.
15
while(FALSE==mmc_init())
16
{
17
nop();
18
}
19
20
PORTD=0xC8;
21
22
23
// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !
24
if(TRUE==fat_loadFatData())
25
{
26
27
unsignedcharstart_dat[]="START TXT";
28
29
// if(MMC_FILE_EXISTS == ffileExsists(start_dat))
30
{
31
if(MMC_FILE_EXISTS==ffopen(start_dat))
32
33
{
34
35
// lesen eines chars und Ausgabe des chars.
36
// solange bis komplette Datei gelesen wurde.
37
38
for(i=0;i<19;++i)
39
{
40
dat[i]=ffread();
41
}
42
43
ffclose();
44
PORTD=0xC0;
45
46
}
47
}
48
49
unsignedcharfile_name[]="LOG TXT";
50
51
52
53
54
// Datei existiert nicht, also anlegen !
55
if(MMC_FILE_NEW==ffopen(file_name))
56
{
57
58
// Schreibt String auf Karte ! Nur richtige Strings koennen mit ffwrites geschrieben werden !
59
ffwrites(dat);
60
61
// Neue Zeile in der Datei
62
ffwrite(0x0D);
63
ffwrite(0x0A);
64
65
// Schließt Datei
66
ffclose();
67
}
68
69
// Datei existiert, also anhaengen !
70
if(MMC_FILE_EXISTS==ffopen(file_name))
71
{
72
73
ffseek(file.length);// Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !
74
75
// schreibt String
76
ffwrites((unsignedchar*)dat);
77
78
// neue Zeile in der Datei
79
ffwrite(0x0D);
80
ffwrite(0x0A);
81
82
// schließt Datei
83
ffclose();
84
}
85
PORTD=0x00;
86
87
}
88
89
}
Und ein Auszug aus der config.h, damit du weißt, was ich ein und
ausgestellt hab.
1
#define MMC_WRITE TRUE // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
2
#define MMC_OVER_WRITE FALSE // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien überschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
3
#define MMC_MULTI_BLOCK FALSE // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber möglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
4
#define MMC_SDHC_SUPPORT FALSE // TRUE, dann mit sdhc unterstuetzung, wenn FALSE, dann nur mmc/sd karten. siehe : http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29
5
#define MMC_ENDIANNESS_LITTLE TRUE // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
6
#define MMC_LFN_SUPPORT FALSE // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
7
#define MMC_RM_FILES_ONLY TRUE // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
8
9
// schalter die explizit funktionen mit kompilieren oder nicht!
10
#define MMC_TIME_STAMP FALSE // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
11
#define MMC_RM FALSE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
12
#define MMC_SEEK TRUE // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
13
#define MMC_MKDIR FALSE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
14
#define MMC_GET_FREE_BYTES FALSE // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
15
#define MMC_LS FALSE // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
16
#define MMC_CD FALSE // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
17
#define MMC_FILE_EXSISTS TRUE // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
18
#define MMC_WRITE_STRING TRUE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.
Ich habe mir ein paar LED's als Kontrolle eingebaut und der Code, so wie
er ist, läuft zumindest danach zu urteilen durch. Ich muss dazu sagen,
dass meine C-Kenntnisse auch eher dürftig sind...
Gruß, Fiete
Hallo,
ohne den Code jetzt laufen zu lassen würde ich da schon ein paar Dinge
als potentielle Probleme sehen.
Also das ist so ein Kandidat:
1
for(i=0;i<19;++i)
2
{
3
dat[i]=ffread();
4
}
das sollte besser "for(i=0; i<19; i++)" heißen. Dann sollte dat
mindestens "unsigned char dat[20]" sein, weil du 19 Elemente und das
'\0' speichern willst.
Dann noch:
1
ffwrites(dat);
Das funktioniert nur problemlos, wenn auf dat jetzt wirklich ein String
steht. In C ist ein String immer mit '\0' terminiert, dafür musst Du
sorgen. Ist das nicht so, schreibt die Funktion ffwrites Ram Inhalt auf
die Karte bis sie auf eine 0 alias '\0' im Ram trifft.
Sonst sieht das eigentlich Ok aus.
Viele Grüße
Daniel
Danke Daniel,
das Array ist eigentlich richtig definiert, aber der letzte genannte
Punkt könnte Probleme bereitet haben, das habe ich noch nicht bedacht.
Ich probiere es mal aus...
Gruß, Fiete
Japp, fehlenden Terminal-zeichen lag es wohl. Ich bin nun ein ganzes
Stück weiter, allerdings habe ich nun wieder Schwierigkeiten:
Es soll ein Datenlogger werden, der zwei Kanäle loggt und das auch in
zwei files schreiben soll. Damit er nicht bei jedem furz schreibt, soll
er erstmal pro Kanal 95Byte in den RAM schreiben, und dann den String
aus dem RAM auf die Karte wegschreiben.
Also habe ich zwei Arrays definiert (und somit, wenn ichs recht verstehe
auch den RAM reserviert):
unsigned char kanal_0 [95];
unsigned char kanal_1 [95];
in einer for-Schleife schreibe ich diese nun voll und wenn sie voll
sind, dann wird ffwrites aufgerufen:
1
for(unsignedintj=0;j<20;j++)
2
{
3
kanal_0[j+w*20]=dat[j];
4
}
5
6
w++;
7
if(w==5)
8
{
9
// Datei existiert, also anhaengen !
10
if(MMC_FILE_EXISTS==ffopen(filename_knal_0))
11
{
12
PORTD=0x80;// <----- Fehlerkontrolleuchte
13
ffseek(file.length);// Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !
14
15
// schreibt String
16
ffwrites((unsignedchar*)kanal_0);
17
18
19
// schließt Datei
20
ffclose();
21
22
PORTD=0x00;// <------ Fehlerkontrolleuchte
23
w=0;
24
}
Analog für Kanal 1.
Wenn NUR Kanal 0 angesprochen wird, dann funktioniert das wunderbar,
wenn NUR Kanal 1 angesprochen wird auch, aber wenn beide angesprochen
werden, dann ist eine der beiden Files meist nicht mehr lesbar und die
Strings in der Datei haben kaputte Stellen drin (irgendwelche Zeichen,
die da nicht hingehören). Das pikante ist, dass das Problem wohl nicht
im RAM auftritt, denn wenn ich z.B. 5x von kanal 1 auf die SD-Karte
schreibe, und dann einmal von kanal 2, dann treten Fehler an Stellen
auf, die vorher schon geschrieben wurden. Daher vermute ich, dass die
FAT irgendwie Probleme macht oder ich irgendetwas anderes nicht bedacht
habe...
Interrupts kommen eigentlich auch nicht in Frage für das Problem, weil
ich erst wieder die Kanäle auslese, wenn alles andere abgeschlossen ist.
Jetzt hab ich überlegt, dass der Stack eventuell Probleme machen könnte,
aber ich bin ja noch knapp 300Byte übrig für den Stack. Ich kann mir
nicht vorstellen, dass das Probleme bereitet.
Ein weiters Problem ist, dass der Controller nur Dateinen beschreiben
kann, die er selber angelegt hat, und auch leider nicht mehr nach einer
Neuinitialisierung. D.h. ich muss die kanal.txt immer löschen, bevor ich
das Programm nochmal duchlaufen lassen kann. Könnte es vielleicht auch
damit zusammenhängen?
Bin für Tipps dankbar.
Besten Gruß aus Heidelberg,
fiete
Hallo,
also eigentlich puffert die Lib schon. Um genau zu sein 512 Bytes, da
das genau ein Sektor ist. Da könntest Du Dir den ganzen Quatsch mit dem
Puffern der Kanäle sparen.
Das ist so gefährlich
1
for(unsignedintj=0;j<20;j++)
2
{
3
kanal_0[j+w*20]=dat[j];
4
}
Wenn w 5 ist und j 20, dann ist 20+5*20 = 120, also deutlich über der
Array Grenze hinaus. Damit überschreibst Du was weiß ich im Ram...
Was für Daten kommen den so vor bei den Kanälen? Falls da Steuerzeichen
vorkommen, also z.B. integer 0, dann geht das mit ffwrites NICHT.
Also noch mal ganz deutlich: NUR Strings sollten mit ffwrites
geschrieben werden! Ein String wird mit '\0' terminiert. Also Ascii Code
Buchstaben und Zahlen im Ascii Code quasi.
Mein Vorschlag wäre im http://de.wikipedia.org/wiki/CSV_(Dateiformat)
Format die beiden Kanäle in eine Datei zu schreiben, aber in zwei
Spalten in der Datei. Dann brauchst Du Dir um puffern keine Gedanken
mehr zu machen, da das ja schon die Lib macht.
>Ein weiters Problem ist, dass der>Controller nur Dateinen beschreiben>kann, die er selber angelegt hat...
Ich vermute das Programm kommt vorher schon durcheinander, oder der
Dateiname entspricht nicht den Konventionen.
Viele Grüße
Daniel