Datum:
Angehängte Dateien:hallo,
hier mal meine fat16/fat32 lib für atmel atmegas.
noch ich sag mal im alpha 2 status ;)
was geht ist:
- auslesen eines MBR ( muss im code eingestellt werden...)
- datei anlegen open('w',rstr);
- datei schreiben ffwrite(c);
- datei anhängen open('a',rstr);
- datei lesen c=ffread();
- datei löschen ffrm(fileName);
- direktory wechseln ffcd(dirName); (immer nur eins nach dem anderen)
- direktory anzeigen ffls();
- datei seek ffseek(234); (ab stelle 0, nur beim lesen)
- commando promt hier kann komplette funktionalität getestet werden !
- umwandeln von "t.txt" -> "T TXT" fat_str("t.txt);
mit einem atmega168 @ 20 mhz schafft man lesend ~ 220.000 bytes/sec,
mit einem atmega32 @ 8 mhz schafft man lesend ~ 20.000 bytes/sec,
bei fat 32 mit größeren clustern wird es immer schneller ;)
würde mich über anregungen, oder verbesserungsvorschläge freuen !
ps: hab Ulrich Radigs mmc.h/mmc.c etwas erweiter, an dieser stelle danke
für die veröffentlichung dieser dateien.
grüße daniel
Datum:
Angehängte Dateien:hallo, einige bug-fixes sind gemacht, eine lib zum einlesen von tastatureingaben, über eine at-tastatur ist jetzt dabei. nur falls es jemanden interessiert ;)
Datum:
g das thema interessiert doch immer. wie sieht es mit dem speicherbedarf aus? funktioniert der code auch - read only - auf einem atmega16 (1kb ram)?
Datum:
mich würde nicht nur der quelltext, sondern auch deine quellen interessieren, gerade spezifikation, umsetzung mit atmega etc.
Datum:
hallo, @ Alexander D. würde sogar mit write funktionieren, man müsste nur in der main auf ein paar sachen verzichten, wie den commando prompt und so. nur die fat-0.x.c und file-0.x.c sind auch super so zu gebrauchen. @ gast quellen sind einmal die Fatgen103.pdf spezifikationen von MS gewesen und https://www.pjrc.com/tech/8051/ide/fat32.html entickelt hab ich das ganze mit linux. habe mir raw images von mmc/sd karten gemacht und das mit low-level-datei-lese funktionen mit linux gcc geschrieben, da kann man dann schön debugen. zu dem code, das einzige problem, warum read und write nich z.b. auf einem atmega8 läuft ist, weil nicht genügend flash da ist, ram würde locker reichen.
Datum:
Angehängte Dateien:hallo, neue optimierungen und bugs beseitigt beim schreiben ! fat16 schreiben von 60.000 bytes in 1,421 sec -> 41KB fat16 lesen von 60.000 bytes in 0,823 sec -> 71KB fat32 schreiben von 60.000 bytes in 1,249 sec -> 46KB fat32 lesen von 60.000 bytes in 0,747 sec -> 78KB die werte, mit atmega32 @ 8 mhz (interner takt). status: ist jetzt voll funktionsfähig ! grüße daniel
Datum:
Hallo Habs zwar noch nicht testen können, sieht aber Klasse aus !! Tolle Arbeit !!! Noch einen schönen Abend Gruß Siegmar
Datum:
>#include "fat-0.3.c" >#include "file-0.3.c" Das macht man nicht ;) Gibt nur Probleme. Bastel dir mal eine fat.h und file.h.
Datum:
hallo, @ Siegmar danke, hört man gerne :) wenn du zum testen kommst, laß doch mal hören wo es hinkt, wenn es hinkt ;) @ holger ja werd ich machen. nur noch keine lust gehabt... ist mir auch noch ein kleines rätsel warum das unbedingt nötig ist. würde es reichen nur die funktionen in einer *.h datei "bekannt" zu machen, die von anderen *.c dateien aus aufgerufen werden ? das würde für mich am meisten sinn machen. wäre dann quasi sowas wie private oder public. also private nur in der *.c selber als prototyp, public in der *.h...
Datum:
Da ich mich momentan auch gerade mit dem Thema befasse, werde ich die Library mal ausprobieren. Ich hab aber gehört, dass FAT32 auf SD-Karten nicht funktioniert ? Oder ist nur ein Gerücht ?
Datum:
hallo, @ kalhou es kommt auf die größe der karte an. manche sind zu klein um sie mit fat32 zu formatieren. andere wieder sind zu groß um sie mit fat 16 zu formatieren... welchen controller willst du denn benutzen und wie willst du die karte anschließen? grüße daniel
Datum:
Angehängte Dateien:hallo, kleinere änderungen, grad der optimierung erhöht. ohne lcd, tastatur und benchmark teil, jetzt 709 bytes statischer ram (bei lesen und schreiben mit commando prompt) und 10127 bytes an flash speicher verbrauch. mit allem 740 ram und 11796 flash. compiler optimierung 2 besser als s... grüße daniel
Datum:
Die Karte hängt an einem atmega128 momentan ist sie über hardware spi angeschlossen... d.h. 1Gb sollte mit FAT32 funktionieren ?
Datum:
So... hab jetzt die Library mal ausprobiert. Zuerst hatte ich Probleme, da ich das Ganze in AVR-Studio probierte und daher kein Makefile verwendete, dass mir Studio diverse Fehler zurückgab, die sich mit der Einbindung eines Makefiles praktisch in Luft auflösten. Trotzdem wäre es von Vorteil wenn es auch ohne die Einbindung eines externen Makefiles funktionieren würde ;) Weiter habe ich dann probiert ein paar Zeichen aus einer Datei zu lesen.
#include <stdlib.h> #include <string.h> #include <avr/io.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #define F_CPU 14745600UL #include <util/delay.h> #include "uart-0.1.h" #include "mmc-0.2.h" #include "fat-0.3.h" #include "file-0.3.h" #define BUFF_SIZE 15 unsigned char kb_buffer[BUFF_SIZE]; int main(void){ DDRA = 0xFF; PORTA = 0x00; uinit(); uputs("Boot ok\n\r"); if (mmc_init() == 0){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten uputs("SD Init ok\n\r"); } else{ uputs("SD Init failed\n\r"); } if(0==fat_initfat()){ uputs("FAT Init ok\n\r"); } else{ uputs("FAT Init failed\n\r"); } //Datei lesen ffopen('r',"delme.txt"); uputc(fread()); uputc(fread()); uputc(fread()); uputc(fread()); uputc(fread()); uputc(fread()); uputc(fread()); uputc(fread()); uputs("\n\r"); ffclose(); for(;;){ PORTA = 0xFF; } } |
Das Init Zeugs hat funktioniert und wurde mir auch schön auf der UART angezeigt. Scheint das lesen der Datei nicht zu funktionieren. Was ich noch vermisse ist eine Funktion zum beschreiben der Dateien, sowie eine Funktion zum lesen ganzer Strings ;)
Datum:
hallo, @ kalhou also beschreiben einer datei würde wie folgt laufen:
//1 ffopen('w',"DELME TXT"); //2 unsigned char str[22]="das soll auf die karte"; unsigned char i=0; //3 do{ ffwrite(str[i]); i++; }while(str[i]!='\0'); //4 ffclose(); |
-1 die funktion ffopen erwartet als datei bezeichnung einen string im
8.3 format, alles großgeschrieben ! man kann zum wandeln von z.b.
delme.txt" die funktion fat_str nutzen, die macht aus "delme.txt" "DELME
TXT".
-2 str enthält 22 bytes die auf die karte sollen, i ist nur ein index
zähler für den str
-3 in der schleife wird auf die karte geschrieben, der ganze string
-4 schließt die datei (erst hier wird die datei tatsächlich angelegt,
vorher werden nur die daten der datei auf die karte geschrieben)
noch zu 1:
es gibt auch noch ffopen('a',"DELME TXT"); das würde die datei zum
anhängen öffnen, wird dann ab letztem zeichen weiter geschrieben.
nur öffnen zum lesen wäre ffopen('r',"DELME TXT"); und dein obiger
code
Datum:
Zum Verständniss: verwendet habe ich die aktuellste Version "mmc-0.3.1.zip" dort findet sich leider keine Funktion "fat_str"
#include <stdlib.h> #include <string.h> #include <avr/io.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #define F_CPU 14745600UL #include <util/delay.h> #include "uart-0.1.h" #include "mmc-0.2.h" #include "fat-0.3.h" #include "file-0.3.h" #define BUFF_SIZE 15 unsigned char kb_buffer[BUFF_SIZE]; int main(void){ DDRA = 0xFF; PORTA = 0x00; uinit(); uputs("Boot ok\n\r"); if (mmc_init() == 0){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten uputs("SD Init ok\n\r"); } else{ uputs("SD Init failed\n\r"); } if(0==fat_initfat()){ uputs("FAT Init ok\n\r"); } else{ uputs("FAT Init failed\n\r"); } //Datei schreiben //1 ffopen('w',"DELME TXT"); //2 unsigned char str[22]="das soll auf die karte"; unsigned char i=0; //3 do{ ffwrite(str[i]); i++; }while(str[i]!='\0'); //4 ffclose(); for(;;){ PORTA = 0xFF; } } |
Das Beispiel hier funktioniert nur soweit ich keine Datei auf der Karte habe die "delme.txt" heisst! Wenn ich eine Datei "delme.txt" auf der Karte habe und dann mit dem Modus 'a' den String dranhängen will, klappt das nicht und der Kontroller bleibt hängen (zu sehen an den LEDS (PORTA) die nie angehen. Das lesen schlug in beiden fällen Fehl. 1. Heisst das also, dass man soweit nur Files in Grossbuchstaben ablegen kann ? 2. Warum wurde die fat_str Funktion nicht direkt in fopen integriert ? 3. Wird es in naher Zukunft noch Funktionen geben zum direkten Lesen/Schreiben von Strings ? 4. Wird es ebenfalls in naher Zukunft die Möglichkeit geben mehrere Dateien zu öffnen ? Wäre ja eigentlich keine Sache, da man nur bei fopen eine File Struktur zurückgeben und bei jeder Funktion wie fread auf den Zeiger auf diese Struktur zugreifen müsste :)
Datum:
hallo, sieh dir mal mit einem hex editor die daten auf der karte an. da wirst du sehen, dass dort 8.3 einträge und lange datei namen drauf sind. bei allen 8.3 datei namen werden großbuchstaben sein. wenn der datei name bzw. die endung nicht 8 bzw 3 zeichen haben, wird mit leerzeichen aufgefüllt, bis 8.3 erfüllt ist! wenn du mit dem pc eine datei auf der karte anlegst, dann wird es bei dem beispiel "delme.txt" einen 8.3 eintrag geben der "DELME TXT" lautet. nur mit diesen 8.3 namen arbeitet die library. fat_str ist aus dem grund nicht in ffopen integriert, weil es auch ohne läuft und ich das ganze so schrumpfen möchte, das es irgendwann auf einen mega8 passt. -1. egal was für eine datei du anlegst, es wird immer ein großbuchstaben 8.3 name mit angelegt. von jedem betriebssystem, dass ich kenne. -3. da ist die funktion zum schreiben von strings...
ffwriteString(unsigned char str[],unsigned char name[], unsigned char option){ ffopen(option,name); unsigned long int i=0; do{ ffwrite(str[i]); i++; }while(str[i]!='\0'); ffclose(); } |
nur so aus dem kopf, sollte aber gehn :) -4. mehrere dateien wird es erstmal nicht geben, aus ram gründen. aber du hast doch schon einen weg aufgezeigt wie es gehen könnte. wenn du es änderst, poste doch einfach mal eine ergebnisse :) zu dem problem mit dem anhängen, werd ich später mal ausprobieren...
Datum:
hallo, bei mir gibt es mit folgendem code keine probleme:
// löscht datei, wenn vorhanden... ffrm("DELME TXT"); // schreibt in die datei (kann nur schreiben wenn nicht vorhanden ist) ffwriteString("das soll in die datei","DELME TXT",'w'); // anhängen von daten ffwriteString(", mehr noch","DELME TXT",'a'); |
benutzt wird die ffwirteString von siehe oben... wegen dem einlesen von strings kannst du dir ja nach dem beispiel was basteln... grüße daniel
Datum:
lesen und schreiben habe ich jetzt soweit geschafft.. werde morgen mal weiter schauen... eine letzte frage bleibt: bei langen dateinamen < 8 zeichen wird das ja mit ~1 gemacht.. also z.b. aus "langer-dateiname" wird "langer~1.txt" wie funktioniert das allerdings wenn ich zwei "ähnliche" dateinamen habe ? also z.b. "langedatei1" und "langedatei2" würden ja dann beide mit "langed~1" abgekürzt... geht das überhaupt ?
Datum:
daraus wird dann: langed~1, langed~2 usw... ist dann etwas unübersichtlich ;) vorallem wenn es so etwas ist wie langedatei-wichtig-von-chef.txt und langedatei-wichtig-von-frau.txt weil daraus auch langed~1 und langed~2 wird
Datum:
also wenn ich jetzt "langedatei-wichtig-von-chef.txt" und "langedatei-wichtig-von-frau.txt" auf der sd habe wie weiss ich dann welche datei ich mit "langed~1" resp. "langed~2" anspreche ? gruss
Datum:
> wie weiss ich dann > welche datei ich mit "langed~1" resp. "langed~2" anspreche ? Öffnen und nachgucken?
Datum:
Dürfte wohl für den Controller weniger einfach werden, anhand des Inhaltes einer Datei darauf zu schliessen, wie der originale Dateiname lautet. Es sei denn der originale Dateiname steht versteckt irgendwo in der Datei, was ich mir aber nicht vorstellen kann! Das Problem ist ja, dass wenn ich die Datei "langedatei-wichtig-von-frau.txt" öffnen will, nicht beide Dateien "langed~1" und "langed~2" aufmachen sollte, um herauszufinden welche der beiden jetzt die Datei ist die ich brauche.
Datum:
Auf lange Dateinamen sollte man beim uC grundsätzlich verzichten. Die Auswertung benötigt eine Menge RAM. Man kommt mit den 8.3 Dateinamen eigentlich immer klar. Unter DOS war das früher auch nicht anders ;)
Datum:
Das Problem ist nur, wenn ich auf meinem MP3-Player eine Datei in Form von "Interpret - Titel" ablege, bekomme ich schon mächtig Probleme, da z.b. ein Album 10 Lieder drauf hat "Interp~1...10" wird schon ein wenig schwierig zum auslesen.
Datum:
>wenn ich auf meinem MP3-Player eine Datei
Ich wusste das du das sagen würdest!
Gut, da macht das Sinn. Welcher 8.3 Name zum
langen Dateinamen gehört ist relativ einfach
rauszufinden: Der 8.3 Eintrag steht direkt hinter
den Einträgen des langen Dateinamens.
Datum:
oder id3-tags auslesen ;)
Datum:
das problem bei den id3 tags ist nur, dass sie unterschiedlicher nicht sein könnten. die einen stehen am anfang, die anderen am ende.. di einen beginnen mit TAG, die anderen mit id3 etc. das tag auszuwerten ist ja noch einfach, da immer 30 bytes reserviert sind.... werds wohl trotzdem irgendwie versuchen alle möglichkeiten auszulesen :o
Datum:
hallo, das problem von langen dateinamen ist das die auch mal 255 zeichen lang sein können. ich finde, wenn man z.b. einen mp3 player baut, sollte der auch die id3 tags anzeigen wenn er die lieder spielt. es git doch pc programme, die die mp3 sammlungen sortieren und ordentlich tagen... grüße daniel
Datum:
So, hab jetzt ein bisschen mit der Library herumexpermientiert. Was ich probiere zu machen ist z.b. mit ffls(); alle Dateien eines Verzeichnisses auszulesen und statt mit uart an den PC zu senden, die Dateinamen in einer weiteren Datei zwischenzuspeichern. Ist sowas theoretisch möglich oder müsste ich dafür mehrere Files offen haben ? Hab schon ein wenig probiert die Funktionen auf mehrere Files umzuschreiben, aber zu der File Struktur die ich jedesmal als Zeiger übergeben muss kommt auch noch die Fat Struktur dazu, die ja atm. auch statisch ist und welche ich wohl auch irgendwie über einen Zeiger mitgeben müsste, aber um das umzuschreiben bin ich mir zu wenig mit dem FAT Dateisystem vertraut... Jemand eine Idee ? Gruss
Datum:
hallo, die funktion "lsRowsOfClust(unsigned long int start_sec)" in file-0.3.c bekommt einen start sektor eines clusters übergeben und arbeitet dann selbständig den cluster ab (also die sektoren). und in dieser funktion benutzt du einfach anstatt der uart ausgaben, einen teil in dem du die namen oder was auch immer dich interessiert von der datei woanders speicherst. in dem teil wo die uart ausgaben sind ist die aktuelle datei auf dem struct:file zu finden, mit allen möglichen angaben. in dem struct:fat ist der aktuell geladenen sektor zu finden. macht zusammen: name, attribut, reihe in sektor, den sektor selber, größe, länge, 1.cluster. also alles was man zur weiteren verarbeitung braucht. hilft das? güße daniel
Datum:
Das Problem ist nur, dass wenn ich dort wo die UART Ausgaben gemacht werden, probiere ein anderes File zu öffnen, dies nicht zu funktionieren scheint da er wohl immernoch etwas in der Fat struct am rumschreiben ist und ffopen ja schliesslich auch auf diese zugreift ? Was mir gerade vorhin aufgefallen ist, dass die ffls Funktion mir die Dateien mehrmals ausgibt wenns mehr als nur ein paar auf der Karte hat. z.b. habe ich 3 Ordner gemacht und er hat mir diese 3 Ordner einige Male aufgelistet und dazwischen immer Punkte ausgegeben z.b. wie folgt ORDNER1 ORDNER2 ORDNER3 . . .. .. . ORDNER1 ORDNER2 ORDNER3 . . .. .. . etc.
Datum:
1) In eine Codesammlung gehört fertiger, funktionsfähiger Code. Sagt ja der Name schon. 2) Gute Programmierkenntnisse der verwendeten Sprache sind dafür zwingend erforderlich.(#include "fat-0.3.c") 3) Es gibt bereits (erprobte) Libs hier in dieser Codesammlung die SD/MMC + FAT unterstützen. Wozu das Rad neu erfinden?
Datum:
hallo, @ Torsten S. sieh mal in meinen ersten post, 4. zeile... #include "fat-0.3.c" funktioniert doch oder? übersichtlicher ist das auslagern von prototypen in *.h dateien auf jeden fall nicht ! c standart ist, dass jede datei auch einzelnd compilierbar sein soll. ist doch so auch gegeben. warum das rad neu erfinden? weil ich mein eigenes rad will! zudem hat ja wohl selber machen noch den größten lerneffekt. so wie theorie und praxis halt ! @ kalhou schick mir ein image von der karte und dem von dir verwendeten code, dann kann ich dir genau sagen woran es liegt. sonst must bischen selber probieren. bei mir läuft es, das einzige problem sind mit linux formatierte karten, weil die komischerweise das root dir, wenn es nur 1 cluster groß ist mit 0x0ffffff8 als ende markiert haben... und dachte es ist eindeutig, man kann IMMER nur eine datei zum lesen/schreiben/anhängen öffnen! man kann aber durchaus mehrere nacheinander öffnen usw...
Datum:
Daniel Platte wrote: > warum das rad neu erfinden? weil ich mein eigenes rad will! zudem hat ja > wohl selber machen noch den größten lerneffekt. so wie theorie und > praxis halt ! OK. Warum nicht. Aber bitte erst wenns fertig ist in die Codesammlung. > #include "fat-0.3.c" funktioniert doch oder? übersichtlicher ist das > auslagern von prototypen in *.h dateien auf jeden fall nicht ! Ein großer Fehler, diplomatisch ausgedrückt. Sei froh, das noch keiner von den C-Experten seinen Senf dazugegeben hat. Bitte meine Posting nicht als rumnörgeln betrachten, sondern als konstruktive Kritik um Dich auf den "richtigen" Weg zu bringen. Torsten
Datum:
hm, meiner meinung nach ist der code schon durchaus brauchbar. vielleicht im falschen forum, mag sein. dann möge es bitte jemand verschieben. bei der letzten version mmc-0.3.zip läuft bei mir mit verschieden formatierungen und cluster größen alles gut. warum sind *.h dateien denn so wichtig? bzw der richtige weg (hatte es ja auch schon geändert..)? bin offen für verbesserungen und anregungen, ist ja der sinn weshalb der code hier öffentlich rumsteht :) güße daniel
Datum:
Könnte ich Morgen mal machen.. hab den code allerdings ein wenig abgeändert. Man sollte allerdings rausfinden was es ist. Zu dem Prototypen: Hab es auch so gelernt, dass man die Prototypen in das Headerfile auslagert und im zugehörigen c File dann einfach das Headerfile dazunimmt. Was wirklich richtig ist weiss ich auch nicht. Vielmehr stört micht, das wenn ich in einem c File z.b. strings.h benutze und im main-File dann eine Funktion aus diesem c File aufrufen will ich dann nochmals strings.h includen muss.
Datum:
Angehängte Dateien:Hier ist mein Beispielcode! Habe gewisse Anpassungen an den Libraries vorgenommen z.b. die Struktur für Fat und File im Headerfile definiert etc. aber der Code sollte allgemein verständlich sein. Auf der SD Karte hatte ich lediglich 3 Ordner (ORDNER1,2,3). Die Karte ist eine 1GB SanDisk und ist mit FAT32 formatiert. Der Code wurde im AVRStudio compiliert, daher stammt auch das Makefile, welches noch im Ordner enthalten ist. Gruss [EDIT] hab gerade gesehen, dass die Karte mit FAT16 mit Vista formatiert war. Hab sie dann FAT32 formatiert und ging gleich. Allerdings bleibt mein Problem das ich während der Funktion ffls(); statt der UART Ausgabe eine Datei und dann den Namen der aktuellen Datei dort reinschreiben will ;)
Datum:
hallo, werd mir deinen code und den fehler bei fat16-ffls mal ansehen, allerdings leider erst sonntag. bin übers wochenende weg.. grüße daniel
Datum:
hallo,
hab mir den code angesehen, läuft bei mir problemlos. schade das du kein
image von der karte gemacht hast, mit der es nicht ging. so ist der
fehler für mich nicht reproduzierbar.
zu deinem problem, was du möchtes ist eine datei suchen um dann etwas
damit zu machen oder?
wenn ja:
die funktion ffopen gibt 0 zurück wenn die datei die du lesen/anhängen
willst in dem aktuellen verzeichniss vorhanden ist. wenn 0 zurück kommt,
ist die datei auch schon fürs lesen oder anhängen "vorbereitet", also
mit ffread() / ffwrite() zugänglich. kommt 1 bei ffopen('w',dateiName")
zurück ist die datei vorhanden und muss gelöscht werden vor dem
schreiben.
wenn nein:
hab ich keine ahnung was du machen willst ;)
dann erkläre es mal...
grundsätzlich sollten die datei-operation funktionen in file-0.x.c nur
extern genutzt werden, da so sicher gestellt ist, das alle flags und
structs richtig geladen/gesetzt sind. das war nämlich das problem bei
dem was du wolltest...
z.b. wenn man file.name benutzen will aber dann ffopen aufruft, läd
ffopen was neues auf file.name, weil ffopen eben auch ein dir auf eine
datei durchsucht, und alles mögiche auf file.name landet bevor man das
hat was man will...
grüße daniel
Datum:
genau gesagt möchte ich alle files eines ordner auslesen und statt dann die filenamen über usart auszugeben, würde ich gerne den filenamen in eine liste eintragen, die dann etwa so aussieht " DATEI1 MP3; Interpret1; Titel1 DATEI2 MP3; Interpret2; Titel2 DATEI3 MP3; Interpret3; Titel3 DATEI4 MP3; Interpret4; Titel4 " das ganze wäre z.b. in einer txt datei eingetragen: Also soll er eigentlich jedes File in dieser Form in eine Liste eintragen (ID3 Tag Erkennung habe ich schon gemacht) wenn ich mehrere Files offen haben könnte wäre das ja kein Problem, da aber die Funktion lsRowsOfClust() selbst auf die File/Fat Struktur zugreifft gibt es ein Problem solange ich nur eine Datei offen haben kann. Was mir in diesem Zusammenhang aufgefallen ist: Du hast ja anfänglich gesagt du würdest kein Support für mehrere Files die offen sind anbieten, da damit möglichst wenig Ressourcen gebraucht werden, allerdings sieht es so aus als wäre in fat-0.x.c eine statische Variable
extern unsigned char sector[512]; |
vorhanden die immer 512bytes Platz wegnimmt, ob man nun eine Datei offen hat, oder nicht..
Datum:
hallo, wieso willst du so eine datei anlegen? ist doch doppelt, weil es diese struktur doch eigentlich schon in dem ordner gibt... man könnte das ganze so erweitern, dass id3 tags ausgelesen werden und mit angezeit werden, anstatt z.b. die länge der datei. ps: hab grade getestet, läuft auch problemlos auf atmegas die nur 1kB ram haben.
Datum:
Hallo, kann man mit der Lib auch formatieren?
Datum:
hallo, nein kann man nicht und wird man auch erstmal nicht.
Datum:
Daniel Platte (zerrome) Danke für Deine Beiträge in Groß-/Kleinschreibung.
Datum:
> Danke für Deine Beiträge in Groß-/Kleinschreibung.
Da klemmen noch mehr Tasten. Beispiel:*(unsigned char*)vi++=*bytesOfSec++; |
Datum:
"sUpEr Kommentare"
Datum:
Warum fehlen in so vielen Libs die Formatier-Routinen? Sind die so aufwendig? Kann doch jedes Handy/Kamera außerdem erspart man sich damit die "Kompatibilitätsprobleme" mit Windows etc.
Datum:
hm, hab mir ehrlich gesagt noch nie gedanken darum gemacht eine formatier routine zu schreiben, wäre sicher nicht besonders schwer. gut, bei gelegenheit mach ich das mal :) groß/kleinschreibung ist einfach nur nervig. ich schreibe außerdem sehr viel jeden tag, da bin ich froh wenn ich mal meine kleinen finger etwas schonen kann (die betätigen shift bei 10 finger tippen).
*(unsigned char*)vi++=*bytesOfSec++; |
mit einem gecasteten void pointer byteweise auf 4 byte große variablen zu schreiben ist bis jetzt noch die eleganteste lösung meiner meinung nach... güße daniel
Datum:
> Warum fehlen in so vielen Libs die Formatier-Routinen? > Sind die so aufwendig? Man muss für jede Kartenkapazität die passenden Werte (Clustergröße etc.) festlegen. Windows benutzt hierzu noch aus den alten DOS-Zeiten entstandene Werte. Nimmt man willkürlich andere Kombinationen, kann es Kompatibilitätsprobleme mit Windows geben. Deshalb ist es besser, gleich auf einem PC zu formatieren. Außerdem sind alle SD-Karten werkseitig mit FAT16/32 vorformatiert. > Kann doch jedes Handy/Kamera Handy und Kameras können viel. Zum Beispiel auch nette Bildchen und Menüs auf Displays anzeigen. Ist aber kein Problem. Gib einem Mikrocontrollerfreak 0,01 Cent für jedes je verkaufte Handy oder jede Kamera, und er wird Dir jede erdenkliche Funktion in der Lib implementieren ;-) Ich selbst habe z.B. noch nie eine Karte in einer Kamera formatiert. Wozu soll das gut sein? (Fotografiere sehr viel mit Canon EOS 20D) > außerdem erspart man sich damit die "Kompatibilitätsprobleme" mit Windows etc. Wenn man selbst formatiert und nicht alles genau richtig macht, fangen die Kompatibilitätsprobleme mit Windows etc. erst an! Joachim
Datum:
Angehängte Dateien:hallo, hier nochmal eine etwas verbesserte version. bug in run_cmd behoben. benchmark teil kann mit #define benchmark 0 oder 1 ein oder aus geschaltet werden. grüße daniel
Datum:
Angehängte Dateien:bug beim leere datei lesen beseitigt. so das wäre es dann erstmal.
Datum:
Angehängte Dateien:hallo, die neuste version ist erweitert um: ffmkdir - legt verzeichniss in aktuellem verzeichniss an. ffrm - kann jetzt auch ordner löschen. löscht rekursiv ! in der fat-0.3.h ist ein define : #define smallFatSys 1 wird es auf #define smallFatSys 0 gesetzt, dann passt der code in einen atmega8 , mit schreib und lese unterstüzung und kommando prompt ! falls jemand fehler findet, bitte melden !
Datum:
Angehängte Dateien:bugfix in ffrm...
Datum:
Hallo Daniel, erst einmal Danke für die Arbeit die du dir machst. Allerdings habe ich noch ein Problem: (Vorneweg: Ich benutze die Version 0.3.1 und den CodeVisionAVR-Compiler. Ich habe also den Code an einigen Stellen angepasst. Dies betraf in den meisten Fällen jedoch nur Variablendeklaration u.ä..) Also: Ich erstelle eine Datei mit
temp = ffopen('w',dateiim8.3format); |
, was auch wunderbar funktioniert. Nun möchte ich an diese Datei jeweils verschiedene Daten (Strings) anhängen (z.B. Datum Uhrzeit ...) und die TXT-Datei später im PC auslesen.
temp = ffopen('a',dateiim8.3format); ffwrite('irgendeinzeichen'); ... ffclose; |
Das funktioniert auch noch, allerdings nur bis die Datei eine Größe von 512Byte überschreitet. Lese ich nun die Datei im PC aus, sehe ich nur die Zeichen, die auf den neuen Sektor geschrieben wurden. Dies ist bei allen Vielfachen von 512 der Fall. (Also bei jedem neuen Sektor?) Nun würde mich mal interessieren, ob das ein allgemeiner Fehler ist oder ob ich beim Anpassen an CodeVision einen Fehler gemacht habe. Wenn das der Fall ist, wäre ich für Tips dankbar, wo ich zu suchen habe. ;)
Datum:
Angehängte Dateien:hallo, ja danke. dicker bug in ffwrite und was blödes in ffopen. ist geändert ! och als arbeit würde ich das nicht umbedingt bezeichnen ;) macht doch spass
Datum:
Ok, schon mal Danke fürs Ändern. Mit meinem CodeVision bekomme ich nun leider in so fern Probleme, das beim Linken die Fehlermeldung: "Error(s) occured" during assembly." erscheint. Könntest du mir sagen, an welchen Funktionen Du für die Version 0.4.2 etwas geändert hast, damit ich nicht alles noch mal portieren muss?! also in ffopen, ffwrite & fat_setCluster hab ich schon was gefunden.. schon mal vielen Dank...
Datum:
Mir ist nun mein ForumPW wieder eingefallen, deswegen nicht mehr Timo,
sondern nun LoLiPoPer.
Ich habe nun einfach noch mal die komplette Version 0.4.2 nach CV
portiert.
Jetzt klappt es schon besser. Aber es läuft noch nicht ganz rund.
Jetzt steht in der Datei, die ich wie oben beschrieben anlege, der erste
Teil (die ersten 512 Bytes) drin, dann ist eine Pause von 512 Byte(nur
Leerzeichen)und ab hier gibt es noch kleine Fehler jeweils wenn die
Vielfachen von 512Bytes erreicht werden.
Kleine Fehler in so fern, dass immer ein paar Zeichen verloren gehen.
Das ganze sieht in der TXT in etwa so aus:
<----512Byte----><----512Byte----><----512Byte----><----512Byte----><---
--...
"text text text "" ""text text tex" "text text t"
| | |
große Lücke kleine Lücke kl. Lücke
Wenn du da noch mal schauen könntest, wäre das klasse..
Macht ja Spaß ;)
Datum:
Angehängte Dateien:hallo, eben erst zurück gekommen... da ist wohl noch eine variable falsch gesetzt gewesen. danke für deine mithlife und geduld. bin selbst die ganze zeit schon am bugs suchen, aber je mehr mitmachen umso besser wird es werden. ist ein wenig umständlich hier nur den auszug zu posten, deshalb als anhang die geänderte file-0.3.c geändert nur eine zeile in ffopen in dem teil:
if(option=='a' && file_flag==0){ |
und zwar fehlte die angabe(nach zeile 94):
cntSecOfClust=s+1;
|
die für ffwrite nötig ist, um zu wissen in welchem sektor des clusters man sich grade befindet. die berechnung ist da auch noch etwas umständlich, wie auch in ffseek...
Datum:
Angehängte Dateien:Servus..
bei der Menge an Code ist es ja ganz klar, dass man mal ne Kleinigkeit
übersieht. Alles klein Problem..
Die von mir beschriebene "große Lücke" ist nun weg. Die kleinen gibt es
allerdings immer noch.
Ich hänge als Anhang mal die Textdatei an, damit du dir selbst n Bild
machen kannst.
In der Datei werden immer Datensätze in dieser Form:
#;NUMMER;DATUM;UHRZEIT;MESSWERT (für Import in Excel)
aneinandergereit. An einigen Stellen fehlen eben einige Daten.
(Wenn du die Datei mit Excel öffnest ist das auch ganz gut zu erkennen.)
Was mir noch aufgefallen ist:
Wenn ich mit ffopen('w',"DATEINAMTXT"); eine Datei anlegen will, diese
jedoch schon existiert, bekommen ich von ffopen nicht immer den
Rückgabewert 1 geliefert. d.h. die Datei wird neu angelegt und befindet
sich dann zwei mal auf der SD-Karte. Die Inhalte sind jeweils die
gleichen und es geht auch nix verloren. Schön is das aber nicht. ;)
Ab und zu ist der Rückgabewert aber korrekterweise auch 0.
So, das sollte erst mal genug sein.. ;)
Datum:
hallo,
woher kommen die daten die auf die karten sollen denn? sind die auf
jeden fall korrekt? werde morgen nochmal exzessiv testen mit großen
datenmengen und hin und her kopieren von dateien usw...
hattest du die karte neu formatiert, als du den neuen code verwendet
hattest?
wenn nicht könnten so sachen mit ffopen('w',"DATEINAMTXT"); passieren.
werde ich mir morgen aber auch nochmal genau anschauen.
güße daniel
Datum:
Angehängte Dateien:hallo, kann die bugs nicht bestätigen. habe mehrere dateien mit w erstellt, mit a sachen angehangen in verschiedenen größe (vielfachache von 512 usw). läuft immer alles ok. kommen deine daten über den uart? poste doch mal die funktionsaufrufe wie du sie machst. vielleicht werd ich daraus schlauer. als anhang nochmal das aktuellste programm
Datum:
hmm.. wenns bei dir so läuft, kann es ja eigentlich nur an mir liegen.
Ich poste mal die Funktionsaufrufe, evtl. ist ja dort ein Schnitzer
drin.
Ansonsten kann es ja immer noch sein, dass beim Portieren nach CV was
falsch gelaufen ist.
Vorweg: Die SD-Karte ist eine ScanDisk 512MB.
Formatiert habe ich diese mit WindowsXP Prof. als FAT und auch
mal
als FAT32. (Ich formatiere die Karte auch bei ca. jedem 2.
Versuch
neu.)
Hier jetzt die Aufrufe:// External Interrupt 6 service routine // Interrupt wird ausgelöst, wenn entweder die SD-Karte rausgezogen oder // eingesteckt wird. Entsprechend wird SD_ONLINE = 0 gesetzt oder die // Initialisierung durchgeführt und SD_ONLINE = 1 gesetzt. interrupt [EXT_INT6] void ext_int6_isr(void) { char temp; delay_ms(500); //Warten, bis Karte richtig ein- / ausgesteckt if(((SD_Detect)==0)&&(SD_WriteProtect==0)){ puts1(SDKartegefunden); puts1(SDInit); temp = mmc_init(); if(temp==0){ puts1(OK); puts1(FATInit); temp = fat_initfat(); if(temp==0){ puts1(OK); puts1(messdatatxterstellen); temp = DV_MESSDATATXTerstellen(); if(temp==0)puts1(OK); else puts1(Dateibereitsvorhanden); SD_ONLINE = 1; } else puts1(Fehler); } else puts1(Fehler); } else { puts1(SDKartenichtgefunden); SD_ONLINE = 0; } } |
dazu die Funktion DV_MESSDATATXTerstellen();
char DV_MESSDATATXTerstellen(){ char temp=0; temp = ffopen('w',messdatatxt); if(temp==1) return(1); //Datei existiert bereits do{ ffwrite(messdatatext[temp]); temp++; } while(messdatatext[temp]!='\0'); ffclose(); return(0); } |
Diese Funktion wird in der mainloop jede Sekunde aufgerufen:
char DV_MessungSpeichern(int Nummer){ char temp; char TEMP[4]=" "; unsigned long int Abstand; unsigned char Abstand_ASCII[32]; #asm("cli"); itoa(Nummer,TEMP); temp = ffopen('a',messdatatxt); if(temp==1) return(1); //Datei nicht vorhanden ffwrite('#'); //Zeilenführungszeichen ffwrite(';'); ffwrite(TEMP[0]); ffwrite(TEMP[1]); ffwrite(TEMP[2]); ffwrite(';'); ffwrite(Tag_ASCII[0]); ffwrite(Tag_ASCII[1]); ffwrite('.'); ffwrite(Monat_ASCII[0]); ffwrite(Monat_ASCII[1]); ffwrite('.'); ffwrite(Jahr_ASCII[0]); ffwrite(Jahr_ASCII[1]); ffwrite(Jahr_ASCII[2]); ffwrite(Jahr_ASCII[3]); ffwrite(';'); ffwrite(Stunde_ASCII[0]); ffwrite(Stunde_ASCII[1]); ffwrite(':'); ffwrite(Minute_ASCII[0]); ffwrite(Minute_ASCII[1]); ffwrite(';'); ffwrite(';'); ffwrite('\n'); ffwrite('\r'); ffclose(); #asm("sei"); MessungNr++; return(0); } |
Die Variablen Sekunde_ASCII, usw. sind globale Variablen, die aus einem RTC-Chip stammen. Die Variablen gebe ich im mainloop jeweils zur Kontrolle per UART aus.(Da stimmen die Daten immer.) messdatatxt ist ein globaler String:char* messdatatxt="MESSDATATXT"; Ich hab jetzt noch mal rumprobiert. Folgende Fehler treten auf: - Ein Datenblock 512Byte fehlt ganz(kommt sehr selten vor). - Einige Datensätze fehlen teilweise. - MESSDATA.TXT wird mehrfach erstellt Hoffentlich hab ich hier was falsch gemacht. Sonst wirds ungemütlich..
Datum:
hallo, also die karte sollte nur dann abgezogen werden, wenn ganz sicher keine schreib/anhäng operation gemacht wird. also besser einen pin mit schalter versehen und erst nachdem der schalter gedrückt wurden und sicher ist, dass die karte nichts mehr macht raus ziehen. oder irgnedwie anders sicher stellen, dass keine operation läuft während man den strom wegnimmt. grundsätzlich sieht dein code ok aus. benutzt du die letzte version der lib? habe mit: fat32 und 4 sektoren pro cluster fat16 und 1 sektor pro cluster fat16 und 4 sektoren pro cluster, getestet. hab über das programm dateien auf die karte geschrieben, angehangen, ausgelesen usw. alles ohne probleme. kannst du evtl. noch fat und file *.c dateien posten, dann schau ich mir mal die änderungen dort an. hast du ein delay in der main, um DV_MessungSpeichern aufzurufen, oder mit timer? güße daniel
Datum:
Angehängte Dateien:moin moin... jipp, den Taster hab ich drin. Bevor ich die Karte abziehe setze ich über einen Taster SD_ONLINE = 0; und DV_MessungSpeichern(); kann nur bei SD_ONLINE ==1; aufgerufen werden.
if(SD_ONLINE){
temp = DV_MessungSpeichern(MessungNr);
} |
Ich hab jetzt mal etwas umprogrammiert. Und zwar beim EXTINT6 mit einigem Erfolg:
// SD-Card initialisation // FAT-File System initialisation if(((SD_Detect)==0)&&(SD_WriteProtect==0)){ puts1(SDKartegefunden); puts1(SDInit); temp = mmc_init(); if(temp==0){ puts1(OK); puts1(FATInit); temp = fat_initfat(); if(temp==0){ puts1(OK); puts1(messdatatxterstellen); temp = ffopen('r',messdatatxt); ffclose(); if(temp==1){ DV_MESSDATATXTerstellen(); puts1(OK); SD_ONLINE = 1; } else puts1(Dateibereitsvorhanden); } else puts1(Fehler); } else puts1(Fehler); } else puts1(SDKartenichtgefunden); |
sprich: Ich mache die Abfrage, ob eine Datei schon vorhanden ist, indem
ich versuche sie zu lesen.
Was merkwürdig ist: Auch wenn die Datei vorhanden ist, liefert
ffopen('r',..); anscheinend immer 1 zurück.
Damit wird DV_MESSDATATXTerstellen(); jedesmal ausgeführt. ABER:
Es bleibt bei EINER Datei!! (verstehe im mom nicht wirklich warum, aber
das Ergebnis ist das Erwünschte!)
Das Problem reduziert somit auf einen einzigen Fehler:
Wenn ich weniger als 1024Bytes in eine TXT-Datei schreibe klappt alles
wunderbar. SChreibe ich jedoch mehr als 1024Byte in die Datei fehlen die
2. 512Bytes (bzw sind diese mit Nullen(Leerzeichen) aufgefüllt). Danach
ist wieder alles OK.
DIe Lib ist die 0.4.2!
Ahja, und DV_MessungSpeichern(); wird nach einem delay aufgerufen.
(Das auch nur zur Probe. Später soll das dann per Taster laufen.)
Im Anhang sind noch die File.c & die FAT.c. Allerdings in einer
TXT-Datei, da ich den Code erst mal einfach in die MAIN.c geknallt habe.
Hoffe, du musst nich zu viel Aufwand betreiben..
ALso schon mal Danke..
Datum:
hallo,
ich kanns nicht sehen, aber du sorgst doch dafür, dass bei programmstart
file_flag mit 0 initialisiert wird(ein ffclose macht das auch..)? es
gibt nämlich nur 3 möglichkeiten warum ffopen('r',datname); 1 zurück
gibt.
1. wenn file_flag nicht 0 ist.
2. wenn die datei nicht im aktuellen verzeichniss gefunden wurde.
3. wenn das laden des 1. sektors der datei fehl schlägt.
ich habe in der option bei ffopen im write teil etwas geändert,
erscheint mir sicherer, änder das auch noch grad.
if(option=='w' && file_flag==0){ if(1==fat_loadFileDataFromDir(name)){ ... ... ... return(0); } } |
warum bei daten größer 1024 dieser bug bei dir auftritt ist mir grad noch ein rätsel, schau ich mir aber noch genau an. nach dem delay hatte ich nur gefragt, um sicher sein zu können, dass da kein interrupt irgendwo reinpfuscht :) für mich wäre noch interessant, wieviele sektoren pro cluster hat die karte mit fat32 formatiert? wenn du das so grad nicht nachsehen kannst, mach einfach mal sowas nach der fat init:
char tmp[12]; ultoa(fat.secPerClust,tmp,10); uputs("secPerClust: "); uputs(tmp); |
ach was mir grad noch einfällt, wie ist die karte an den avr angeschlossen? da können auch mal ein paar bytes verloren gehen wenn die kabel zu lang oder so. bin selber jetzt auch auf einen 74hc4050 umgestiegen um die karte zuverlässiger anzuschließen (kostet 40 cent). grüße daniel
Datum:
Mal wieder Hallo!;)
Das file_flag hatte ich nicht expliziet mit 0 initialisiert. Ich dachte,
sowas läuft über die Initialisierung von fat_initfat();
Probiert hab ich das jetzt aber mal (auch mit ffclose(); beim
Programmstart), bringt aber keine Änderung.
Den Teil in ffopen hab ich aktualisiert.
Am Anschluss der Karte kann es eigentlich nicht liegen, da ich das
"Savvy128"-Board von chip45.com verwende.
Interrupt verwende ich schon, allerdings schalte ich die bei jedem
Zugriff auf die Karte mit #asm('cli'); aus.
(Ext. Interrupt vom RTC-Chip)
Deinen Code zur Sektorenbestimmung liefert bei FAT32 den Wert "8" und
bei FAT den Wert "16".
hmm.. mit dem Umweg über ffopen('r',..); zur Dateienerstellung kann ich
leben, nur das Löschen der Daten wenn ich mehr als 1024 Byte schreibe
stört schon.
Datum:
also, nach nochmaligem debugen kann ich einen fehler da aussließen. wichtig ist einfach nur die reihenfolge: 1. ffopen 2. ffwrite/ffread 3. ffclose dann kann da nix schief gehen. irgendwo fehlt warscheinlich eine kleinigkteit in deinem code, irgend eine änderung die ich gemacht habe, die du aber nicht gemacht hast. probier mal einfach so in einem test programm, die funktionalität der fat-lib (neuste version mmc-0.4.3.zip). so kommst du vielleicht auf den fehler. hab auch nicht deinen ganzen code um mir das mal anzusehen. z.b. hast du
unsigned char ffwrite(unsigned char c){ unsigned long int clusterOld; clusterOld=currentCluster; ... ... |
das so geändert. da wird beim schreiben von einem byte immer direkt auch eine unnötige long int operation gemacht (4 byte operation), das ist ungünstig. die von dir beschriebene lücke klingt für mich so, als wenn da ffclose irgendwo falsch aufgerufen wird. grüße daniel
Datum:
Angehängte Dateien:hallo, als anhang mal eine ganz einfache nutzung der lib. erstellt eine datei, schreibt daten rein und hängt daten an. erstellt einen ordner und erstellt die datei nochmal darin. grüße daniel
Datum:
Hallo, saubere Arbeit! Vielleicht wäre es bald übersichtlicher einen wiki Artikel zu schreiben, wo auch Minimal und Optimalschaltplan drin sind und immer die neuste Version drin steht. Eine SD Lib für Codevision wäre super, poste also bitte mal den Code sobald er läuft. Viel Spaß noch Kai
Datum:
hallo, @ Lolipop Er wie siehts denn jetzt aus bei dir? läuft es oder nicht? wenn es dir nichts ausmacht, poste doch auch mal so eine mini version mit den änderungen für codevision. falls das noch nicht läuft, können ja vielleicht auch andere mal mitschauen. @ Kai Franke zum thema wiki, hab ich noch nie gemacht. interesse scheint auch nicht allzu groß zu sein. übersichtilicher wäre es allerdings schon ;) grüße daniel
Datum:
hey Daniel, jetzt rennt er!! ;) Ich habe noch mal die Version 0.4.3 neu portiert. Anscheinend war die Kleinigkeit, die Du da geändert hast ausschlaggebend. Bevor ich das online stelle, möchte ich noch mal ein bisle mit den Ordneroperationen rumspielen um zu sehen ob das auch fehlerfrei funktioniert. Und alles n bisle ordentlich machen. (also *.c - & *.h files erstellen.) Müsste ich bis heut Abend hinbekommen. bis dann..
Datum:
Angehängte Dateien:hallo, äh ja, ordner operationen da gibt es noch was... tritt selten auf, aber hier der bugfix, sorry. muss man denn viel ändern zu codevision? ist doch auch ein standart c compiler, oder?
Datum:
Da ich bis zum 15. meinen Artikel für den Artikelwettbewerb fertig haben muss, werde ich wohl bis dahin auch wissen wie man einen wiki Artikel erstellt und biete an auch für diesen Artikel einen zu erstellen. Ich sage dann nochmal Bescheid, dann könnt ihr mir ja beide eure Errungenschaften schicken und ich vereine sie im wiki. Editieren und hinzufügen wird ja jeder hinbekommen :P Gruß Kai
Datum:
Angehängte Dateien:Soo.. denn stelle ich mal den Code online. So viel ist nicht zu ändern für CV. Hauptsächlich die Variablendeklarationen. Ist aber schon immer etwas Aufwand. Aber nun hab ichs noch mal mit der V0.4.4 gemacht. (Allerdings hab ich die Funktionen nicht noch mal sauber formatiert.) Wenn da noch irgendwo was zukommt, änder ichs auch gern noch mal.(Wäre natürlich schöner, wenn ich wüßte in welchem Teil was geändert wurde, dann muss ich nicht alles neu machen.) Der Code wurde auch nicht in irgendeiner Weise extrem optimiert. Wichtig war mir in erster Linie, dass alles einwandfrei funktioniert und das ist, soweit ich weiß, auch gegeben. @Daniel: Wenn Fehler gemeldet werden, wäre es klasse, wenn du da mit nachschauen könntest und ich übernehme die Änderungen für CV.
Datum:
hallo, @ Kai Franke fänd ich super, wenn du daraus einen wiki artikel machen würdest. ich schreibe gerne ein paar allgemeine sachen zur fat oder auch speziell zu dem code oder so... @ Lolipop Er werde die änderungen die ich jetzt ab version 0.4.4 mache in den dateien dokumentieren. angepeilt ist so ab version 0.5.x dass die statische variable sector[512] dynamisch übergeben wird. so könnte man, wenn das programm grade nicht den fat teil nutzt, 512 bytes ram sparen. werde mir später mal deine umsetzung ansehen. grüße und danke für die aktive teilnahme daniel
Datum:
Hi. Leider funktioniert das schreiben nicht bei mir. Er hängt sich immer bei ffopen auf... Was ist da los? Gruß Flo
Datum:
hallo, seltsam, also die initialisierung klappt? was benutzt du für eine karte und wie ist die karte angeschlossen? wie lautet der genaue aufruf von ffopen, also mit welchen parametern usw. du benutzt die aktuelle version (mmc-0.4.4.zip)? grüße daniel
Datum:
Ich benutze version 0.4.4.
Habe den ATMega128.
Die SD karte ist am Hardware SPI interface angeschlossen.
ffopen gibt 1 zurück.
//**********************************************************************
*******************************************
int main(void){
lcd_init();
lcd_string("Computer start",0);
RoteLED();
set_cursor(0, 3);
lcd_string("0%",0);
//----------sd-karte initialisieren----------
if(mmc_init() !=0)
{
lcd_clear();
lcd_string("Keine SD-Karte ist eingesteckt.",0);
while(1);
}
//----------sd-karte initialisieren----------
set_cursor(0, 2);
for(int i=0;i<16;i++)
{
lcd_data(0xff);
_delay_ms(10);
}
set_cursor(0, 3);
lcd_string("100%",0);
_delay_ms(1000);
lcd_clear();
//----------fat initialisieren----------
if(fat_initfat()!=0)
{
lcd_clear();
lcd_string("Fat konnte nicht gelesen werden!",0);
while(1);
}
//----------fat initialisieren----------
lcd_string("FAT-16 gelesen",0);
if(ffopen('w',"DELME TXT")==1)
{
lcd_clear();
lcd_string("File konnte nicht angelegt werden!",0);
while(1);
}
//2
unsigned char str[22]="das soll auf die karte";
unsigned char i=0;
//3
do{
ffwrite(str[i]);
i++;
}while(str[i]!='\0');
//4
ffclose();
set_cursor(0, 2);
lcd_string("Fertig",0);
while(1);
return 0;
}
Ist da was falsch?
Gruß Flo
Datum:
hm, ffopen mit option 'w' gibt auch 1 zurück wenn die datei schon vorhanden ist. versuch mal ein
ffrm("DELME TXT");
|
vor dem öffnen mit ffopen. das würde die datei löschen für den fall das sie da ist. sieht sonst richtig aus...
Datum:
ach was ich grad sehe, der code von dir ist teilweise aus einem blöden beispiel... der string str[22] müsste 23 zeichen lang sein, weil "das soll auf die karte" sind 22 zeichen.
Datum:
Also habe den Code nun geändert. Jetzt geht das Programm glatt durch (ohne Fehlermeldungen). Doch auf dem PC wird keine datei angezeigt. (Auch im Hex-editor sehe ich keine neuen einträge!) Irgendwas stimmt da nicht... Gruß Flo
Datum:
hm das ist mal komisch. ist die karte vielleicht partitioniert? dann muss man das umstellen auf: #define superfloppy 0 in der fat-0.4.h standartmäßig ist das so eingestellt, das die karte unpartitioniert ist. würde erklären warum der pc keine daten sieht, aber die initialisierung der karte am mc durchläuft und auch geschrieben werden kann. bei fat_initfat() wird nicht auf sinnigkeit der ausgelesenen daten geprüft. ergo landen die daten an merkwürdigen stellen der karte, weil die bereiche der fat falsch ausgelesen werden...
Datum:
JUHUHUHU es klappt. Genau der Fehler war es... ^ Einfach #define superfloppy auf 0 stellen und ich kann lesen und schreiben!! Vielen Dank. Gruß Flo
Datum:
hallo, schön das es klappt. muss mir mal überlegen wie ich erkennen kann ob im sektor 0 ein mbr steht oder der erste sektor der fat, dann könnte man das automatisieren... grüße daniel
Datum:
ein neues update. die änderungen sind in den *.c dateien dokumentiert. änderungen nur in der fat-0.4.c und file-0.4.c. grüße daniel
Datum:
Angehängte Dateien:äh hier auch noch die dateien...
Datum:
Hallo, mich würde interessieren ob ihr auch solche Probleme mit dem Compiler habt in AVR-Studio. Mit jedem Fehlermeldung die ich beseitige, erscheinen 10 andere. Das ist ja nichts besonderes :D aber irgendwann war ich mit meinem Latein am Ende... Hat einer von euch eine fehlerfreie AVR-Studio version? lg alex
Datum:
Ich nochmal, das Problem mit den mit AVR-Studio lag wohl am Projekt an sich. Nach einem Computer-Neustart und eines neuen Projekts hat das compiling fehlerfrei funktioniert. Bei meinem ATmega88 bedeutet das mit -0s Program: 7498 bytes (91.5% Full) mit smallFileSys 0. Habe noch zwei Fragen: 1. Wie wirkt sich smallFileSys auf den Funktionsumfang aus? 2. Gibt es ein switch für NUR Schreibzugriff? Bzw. welche Funktionen kann ich weglassen um mehr Programmspeicher zu haben. lg alex
Datum:
hallo,
bei "smallFileSys 0" fällt das löschen von dateien und das rekursive
löschen von ordnern weg, das anlegen von ordnern und das wechseln in
einen höheren ordner auch ("cd.." quasi). der rest ist dabei.
einen schalter um nur schreib bzw lese zugriffe zu machen hatte ich auch
schon vor. werd ich auch die tage noch machen. das problem dabei ist,
dass einige funktionen die zum lesen gebraucht werden auch zum schreiben
gebraucht werden, ich kann grad nicht so abschätzen wieviel kleiner das
wird. nur lesen wird man wohl auf weniger als 3 kByte bekommen.
bei mir gab -O2 den kleinsten code
gruß daniel
Datum:
also, ich bekomme eine nur lesen version auf 3618 bytes code gedrückt, ohne weitere optimierungen und ohne tolle ff-funktionen wie ffseek usw. eine nur schreiben variante wird aber nicht viel kleiner werden können als 5990 bytes an code. das liegt daran, dass man ja auf jeden fall auch das dateisystem lesen muss um schreiben zu können... will man ein verzeichniss wechseln können, muss der ganze lese kram mit rein... möchte man nur einen daten logger bauen, so wird wohl ein atmega88 oder 8 mit 8 kBytes flash reichen, will man da mehr, braucht mann mehr flash. grüße daniel
Datum:
Hallo, das hört sich ja sehr gut an :D Ich bin an der nur schreiben variante interessiert, wäre nett wenn du das mal bei gelegenheit zu verfügung stellst. viele Grüße alex
Datum:
Angehängte Dateien:hallo, sorry hat etwas gedauert... die änderungen sind nicht wild... avr-size main_.hex mit den schaltern (nur schreiben ohne große datei funktionen) :
#define smallFileSys 0 #define write 0 |
gibt nach dem kompilieren 6538 bytes an code an. sind doch 500 mehr, weil ich übersehen hatte das man beim schreiben auf jeden fall auch noch ffseek braucht. mit den schaltern (komplette unterstützung):
#define smallFileSys 1 #define write 0 |
wird der code 8228 bytes groß. mit den schaltern (minimal system, nur lesend):
#define smallFileSys 1 #define write 1 |
wird der code 3618 bytes groß. güße daniel
Datum:
Hallo!
Danke für die Bibliothek!
Insgesamt laufen die Funktionen ganz gut. Mit 2 Sachen habe ich jedoch
noch einige Probleme:
1. Die Funktion ffopen('w', ...) braucht bestimmt 10 Sekunden um zu
Entscheiden, dass die Datei nicht vorhanden ist, und eine neue angelegt
werden muss. Ist das normal? ffopen('a', ...) braucht nämlich nur wenige
ms.
2. Die Funktion ffopen('a', ...), bzw. das zugehörige ffclose schließt
die Datei nicht korrekt, sodass sie anschließend am PC (oder MAC) mit
1,32 GB Größe angezeigt wird. Eine Idee, wodran das liegen könnte?
(Atmega 2560 mit 2GB SD und 64MB MMC Karte).
MfG Thomas
Datum:
hallo, -1 nein das ist alles andere als normal. es sei denn man möchte eine datei in einem ordner anlegen in dem es schon sehr sehr viele dateien/ordner gibt. -2 poste doch mal eine funktionsaufrufe damit ich mir ein bild davon machen kann woran es liegt. wie sind die karten formatiert, also mit fat32 oder fat16? mit welchem betriebssystem sind die karten formatiert worden? hast du sie vor der benutzung der lib neu formatiert? klingt ein bischen so als würde fat_loadFileDataFromDir irgendwie ne macke haben, weil alle drei optionen/funktionen diese funktion nutzen, also ffopen (w/a) und ffclose auch, wenn mit ffopen(a) geöffnet war... schau ich mir mal genauer an...
Datum:
Hey, der ganze Aufruf sieht in etwa so aus:
if( mmc_init() == 0 ) { if(0 == fat_initfat()) { //Fat initialisation successful LCD1.LCDBuffer[1] = 0 + 48; printLCDBufferToGraphic(1); unsigned char j = 0; unsigned char datei[12]="TEST PTL"; // neu erstellen wenn nicht vorhanden und reinscheiben if(ffopen('w',datei) == 1) { ffopen('a',datei); } for(j=0;j<5;j++) { ffwrite('b'); } ffclose(); } } |
Ich benutze die KArten mit FAT16, mit FAT32 funktioniert es nicht. Formatiert mit Windows, jedoch formatiere ich die Karten nicht nach jedem Versuch neu. (Ist ja eigentlich auch nicht der Sinn der Sache) Einstellung für:
#define superfloppy 0 #define smallFileSys 1 |
Ansonsten arbeite ich mit Version 0.4.4, da die Änderung zu 0.4.5 nicht groß genug schienen. Habe relativ viel an den Header Dateien geändert, um sie schön einzubinden. (Von wegen - wer darf was sehen, und warum / warum nicht) - komme von Java, und da ist das alles etwas schöner.
Datum:
hm, die header dateien sind relativ egal denke ich. es kann sein das wegen der partition irgendwo ein bug ist. versuch mal die karte unpartitioniert zu benutzen, dass sollte auf jeden fall problemlos funktionieren. ich komme erst später heute abend zum testen... ich gehe mal davon aus das nur die header dateien geändert wurden, falls nicht, müsste ich mal den ganzen code sehen. güße daniel
Datum:
hallo, es gab keine bugs in dem partitions bereich, hätte mich sonst vorher mal gemeldet. hier trozdem mal eine neue version, ist schneller geworden, aber auch etwas gefährlicher ;) es ist jetzt umbedingt erforderlich zu prüfen ob richtig geöffnet wurde bevor man schreibt ! ein beispiel:
// neu erstellen wenn nicht vorhanden und reinscheiben if(0==ffopen('w',datei)){ // prüfen ob öffnen erfolgreich for(z=0;z<60000;z++){ ffwrite('a'); } ffclose(); } |
nur wenn ffopen null zurück gibt wird ffwrite aufgerufen. ffwrite prüft nicht mehr ob öffnen erfolgreich war. zudem ist ffwrite und ffread inline geworden. code ist allgemein kleiner geworden durch vielfache optimierungen ! durchschnittswerte mit einem atmega168 @ 16 mhz: 165 kByte lesend 146 kByte schreibend
Datum:
Angehängte Dateien:...
Datum:
hier mal noch der erste wiki versuch... http://www.mikrocontroller.net/articles/FAT32 werde da noch weiter daran arbeiten. jeder der zu fat etwas beitragen kann/möchte ist eingeladen dort mitzuarbeiten... grüße daniel
Datum:
Angehängte Dateien:Hallo Daniel Ich finde deinen Quelltext für die SD-Karte eine gute Idee. Habe allerdings aber auch meine Probleme damit. Ich verwende: AVR-Studio ATmega32 mmc-0.3.1.zip Mein Problem: Trotz intensiver Fehlersuche habe ich es bis jetzt nicht schaffen können ein Hexfile mit deinem Quelltext zu erstellen. Habe die 0.3.1 Version genommen weil dort auch die Routine für ein LCD dabei ist. Ich bekommen immer Fehlermeldungen. Habe deinen Quelltext nicht verändert. Die Fehlermeldungen habe ich in den Anhang gepackt. Wäre nett wenn du oder jemand anderes sie mal anschauen könnte. Weiß gerade nicht mehr weiter, ist bestimmt nur ein dummer Fehler aber steh da jetzt auf dem Schlauch. Gruß Alex
Datum:
hallo, ja hm das avr-studio... hab da letztens auch mal die dateien kompilieren wollen, ging aber nicht. irgendwie löst das die c abhänigkeiten nicht alleine?!?. am einfachsten ist es wenn du das makefile das bei meiner lib babei ist benutzt. beim avr-studio kann man in den projekt eigenschaften ein externes makefile angeben. dann gehts. außerdem ist dringend davon abzuraten eine ältere version als 0.4.5 zu nutzen (besser 4.5.6), da doch noch einige fehler in den vorherigen versionen waren. um ein lcd zu nutzen, könntest du einfach die lcd routinen mit übernehmen... güße daniel
Datum:
Danke Werde ich gleich mal ausprobieren. Gruß Alex
Datum:
In file-0.4.h >extern unsigned char ffmkdir(char name[]); // legt ordner in >aktuellem verzeichniss an. > >#include "file-0.4.c" So etwas tut man nicht! *.c Dateien sollte man nicht per #include einfügen.
Datum:
also über das makefile oder wie? bist du Holger Klabunde?
Datum:
Angehängte Dateien:Naja zumindest habe ich jetzt nicht mehr so viele Fehlermeldungen aber. Aber er erstellt mir kein Hexfile. Woran kann das denn liegen? Hab mal mein ganzes Prog angefügt vieleicht weißt du ja Rat. (alles Unveränderte Dateien von dir) Danke für deine Bemühungen Gruß Alex
Datum:
hallo, hab grad kein windows da um avr-studio zu starten. aber ich meine mich zu erinnern, dass ein projekt und die haupt c datei gleich heißen müssen. also solltest du ein projekt namens main_ erstellen und da dann alle dateien einfügen... gruß daniel
Datum:
Ne hat leider auch nicht funktioniert. Trotzdem danke Versuche noch ein bischen rum wenn ich ne Lösung finde poste ich die. Alex
Datum:
Angehängte Dateien:probier mal das hier. wenn das nicht geht ist dein avr-studio schrott
Datum:
hm, nee seh grad mit meinem avr-studio projekt kann das auch nicht gehn, weil der pfad zu den dateien nicht stimmt und der pfad zum kompiler warscheinlich auch nicht. na ja was auf jeden fall geht ist ein neues projekt mit namen main_ zu erstellen, dann avr-studio schließen und die dateien main_.c usw in das projekt verzeichniss kopieren, dort die vom avr-studio erstellte datei main_.c überschreiben. dann das studio wieder starten. eventuell noch das externe makefile einstellen.
Datum:
So hab noch lange rumprobiert aber leider keinen Erfolg gehabt. Mit der Version 0.4.6 lässt sich kein Hex File erstellen. Jedoch mit der Version 0.3.1 ist dies kein Problem. Wieso das so ist weiß ich nicht und kann ich mir auch schlecht erklären. Hab die AVR Progs extra neu runtergeladen und neu installiert, sogar auf anderen PC´s probiert. Leider alles ohne erfolg vielleicht hat ja jemand anders noch nen Rat. Würde ja gerne wissen was das Problem genau ist. Gruß Alex
Datum:
Angehängte Dateien:hab jetzt mal die header dateien so umgebaut wie die portierbarkeit wohl am größten ist. leider zu lasten der ausführungsgeschwindigkeit. alleine durch die header dateien gehen 20KBytes pro sekunde lesend verloren...seltsamerweise wird der code kleiner aber auch langsamer... @ Alex probier mal die neue version, damit sollte es besser klappen. ich denke es liegt nicht am code der 0.4.6 sondern am einbinden im avr-studio, daher könnte es mit der 0.4.7 einfacher sein. grüße daniel
Datum:
Die wenigsten werden WinAVR unter /opt/cross installiert haben ;) CC = /opt/cross/bin/avr-gcc OBJCOPY = /opt/cross/bin/avr-objcopy OBJDUMP = /opt/cross/bin/avr-objdump SIZE = /opt/cross/bin/avr-size NM = /opt/cross/bin/avr-nm
Datum:
hmmm... 20kB/s weniger ist schon interessant. Wahrscheinlich konnte der Compiler bei deiner ersten Version (wo er ja alles in einer einzigen Datei bekommt) besser optimieren durch z. B. Inlining (was den größeren Code erklärt). Durch die Aufteilung ist es jetzt allerdings besser in die Verwaltung von IDEs wie dem AVRStudio einzubeziehen. Btw. Super Sache, dass du deinen Code zur Verfügung stellst. Steffen.
Datum:
hab das Makefile mal umgeschrieben und volgendes verändert # Define programs and commands. SHELL = sh CC = /WinAVR/bin/avr-gcc #OBJCOPY = /WinAVR/bin/avr-objcopy #OBJDUMP = /WinAVR/bin/avr-objdump #SIZE = /WinAVR/bin/avr-size #NM = /WinAVR/bin/avr-nm AVRDUDE = avrdude REMOVE = rm -f COPY = cp so kriege ich auch ein hexfile erstellt aber ob das jetzt auf dem atmega läuft werde ich dann später erst sehn. Oder könnte es sein das es ohne die auskommentierten Pfade nur so scheint als sollte es Funktionieren? Warte noch auf den uc momentan hab ich leider keinen da. Danke für eure Hilfe. Gruß Alex
Datum:
geht das nicht auch so? # Define programs and commands. SHELL = cmd.exe CC = /WinAVR/bin/avr-gcc.exe OBJCOPY = /WinAVR/bin/avr-objcopy.exe OBJDUMP = /WinAVR/bin/avr-objdump.exe SIZE = /WinAVR/bin/avr-size.exe NM = /WinAVR/bin/avr-nm.exe AVRDUDE = avrdude.exe REMOVE = del -f COPY = copy bei "del -f" bin ich mir nicht sicher ob del den parameter f kennt, warscheinlich nicht, da müsste man mal nach adequatem ersatz suchen. "rm -f" -> "Löschen. Ignorieren nicht vorhandener Dateien, keine Nachfragen." copy müsste aber so gehn gehn.. grüße daniel
Datum:
lol moment bei windows wird das warscheinlich eher c:\WinAVR\bin\avr-gcc.exe heißen... mit optimierung s wird der code jetzt wieder kleiner als mit 2 und der geschwindigkeitsverlust geht auf 10KBytes /sec zurück. also von 165 auf 155KB damit kann ich leben (atmega 168 @ 16mhz).
Datum:
Der Pfad zu Winavr wird doch in die Path-Variable eingetragen, sollte es nicht reichen die *.exe anzugeben? Er wird sich dann schon einen Pfad suchen... Hab es nicht probiert! Steffen.
Datum:
Angehängte Dateien:neue version kleine änderungen. mit windows und linux makefiles usw..
Datum:
Moin Daniel, wollte mich heute auch mal näher mit deinem SD-Code beschäftigen, nachdem meine Platine ansonsten funktioniert. Die Funktionsweise sieht verständlich aus. Was mich momentan am Einsatz hindert ist, dass SPI, Usart wie auch die Command-Shell fest mit dem eigentlichen Code verbunden ist. Da ich hierfür bereits eigene Bibliotheken habe.... wie kann ich diese auf Dauer am besten einbinden und zwar so, dass der Wartungsaufwand bei einer Codeaktualisierung deinerseits nicht zu umständlich wird? Oder hast du schon einmal überlegt, die ganzen relevanten #defines in eine Config.h auszulagern. Hierin könnten z. B. Methodennamen für Usart und SPI definiert sein oder auch, ob file.h->methode() auf den Usart ausgeben soll.... Und diese Datei wäre dann problemlos anpassbar durch einen anderen Anwender. Anders gefragt - wenn ich dir einen entsprechenden Patch schicke würde, hättest du Interesse? cu, Michael
Datum:
Angehängte Dateien:Ich nochmal.... anbei als zip eine kleine Abwandlung deiner Lib mit einem globalem Config-Header-File. Es kompiliert; ausprobiert habe ich es aber nicht. Zur Idee: In mmc_defs.h werden für uart, spi und spi hardware die entsprechenden Methodennamen als #define angegeben. Beispiel Uart:
#include "uart.h" #define MMC_UART_INIT uinit #define MMC_UART_PUTC uputc #define MMC_UART_PUTS uputs #define MMC_UART_GETC ugetc #define MMC_UART_GETS ugets |
Möchte ich einen anderen Uart-Code verwenden, so include ich die entsprechende Header-Datei und passe die Methodennamen an. - ugets wird z. Zt. nicht verwendet. - Die SPI Methoden sollte man nochmal überdenken... da wollte ich dein Feedback abwarten bevor ich deinen Code vollständig verstehen will Somit kann ich flexibel unterschiedliche Basisfunktionen für die Peripherieansteuerung verwenden (buffered, unbuffered usart; hardware spi, software spi; evtl. debug Lösungen) und bin deutlich flexibler, was die gesamte Konfigurierbarkeit anbetrifft. Die restlichen Code-Dateieen enthalten jetzt nur noch die SD-Card-Logik allein. Was hälst du davon? Michael
Datum:
hallo Michael, gute idee das so zu ändern, dass man unterschiedliche "unterbauten" nehmen kann, würde es auch einfacher machen das ganze auf andere controller zu portieren. eine globale "hardware" header datei zu machen, wo die funktionen vom spi und die funktionen des uart, also der hardware anbindung der karte und der ausgabe, definiert werden ist eine gute lösung. die von dir beschriebenen vorteile sind es wert. leider komme ich vor freitag wohl kaum zur umsetzung, weil ich umziehe und lernen mich voll in beschlag nimmt. bis spätestens sonntag sollte es aber ohne probleme drin sein, wie im einzelnen, werde ich mir noch überlegen. weitere ideen sind sehr willkommen ! grüße daniel
Datum:
Angehängte Dateien:Moin Daniel,
Das klingt ja sehr schön :-) Wenn du Zeit hast, dann schau dir meine
Abwandlung mal an... vielleicht sind ja ein paar brauchbare Ideen drin.
Eine "globale" Hardware-header-Datei würde ich zuerst mal auf die
mmc-lib beschränken. Warum? Viele dürften für die Ansteuerung der
peripherie etc. bereits eigene Code-Sammlungen haben. Die mmc-lib müsste
dann nur noch an diese Libs angedockt werden.
Die SPI Ports und Pins könnte man auch nochmal in eine weitere
Config-Datei auslagern. So habe ich es jedenfalls bei mir gemacht, siehe
Attachement SpiDefs.h
Zweite Idee: Ein Debug-Switch. Ist dieser gesetzt, so wird an eine
ebenfalls frei definierbare Debug-Funktion die aktuelle Aktion (open
file, read directory etc.) gesendet. Sowas kann man schön so
programmieren:
#define MMC_DEBUG 0
#if defined(MMC_DEBUG)
logDebug("bla");
#endif
Anyway, denn erstmal viel Erfolg beim Lernen und Umziehen....
Michael
Datum:
Hallo, interessant wäre, wenn der SPI-Teil umgearbeitet wird, gleich zu überlegen, ob nicht eine "universellere" Variante erarbeitet wird. Ziel könnte sein, dass mehrere Komponenten am SPI (-Bus) hängen und nicht SS sondern ein Portpin für CS verwendet wird. Beim Senden und Empfangen muss dann zusätzlich noch mitgeliefert werden, welche SPI-Peripherie angesprochen werden soll (SPI-Parameter müssen für jeden Baustein gespeichert werden und evtl. vor dem Senden/Empfangen neu angepasst werden). So könnte z.B. ein zusätzlicher CAN-Baustein oder HC595 angeschlossen werden ohne eine Software-SPI zu benötigen. Besonders, wenn einzelne SPI-Komponenten nur selten benötigt werden (Config.ini auf SD Karte nur zum Start notwendig, HC595 für Relaisansteuerung einmal pro Sekunde...). Steffen.
Datum:
Moin! Wieso sollte dies ein Problem sein? In der MMC-Config kannst du imho frei definieren, welchen Pin du als SS-Pin verwenden willst. Ob dies nun der "offizielle" SS-Pin des AVRs oder ein anderer Pin ist spielt hierbei keine Rolle. Somit kannst du auch problemlos mehere SPI-Chips oder -Geräte an den AVR anschließen solange du die gleiche Ansteuerungslogik (send_byte etc.) verwendest. Aufwändiger wird es allerdings, wenn du unterschiedliche Busgeschwindigkeiten fahren willst. Da hast du recht. Michael
Datum:
>Aufwändiger wird es allerdings, wenn du unterschiedliche >Busgeschwindigkeiten fahren willst. Da hast du recht. Genau dort sehe ich der Herausforderung. An der Stelle ist es wahrscheinlich sinnvoll "eine" SPI-Routine zu verwenden. Dann kann man sich merken, ob eine Parameteränderung durchgeführt werden muss oder nicht.
Datum:
>#define MMC_DEBUG 0 > >#if defined(MMC_DEBUG) > logDebug("bla"); >#endif Das geht auch noch eleganter. In der Headerdatei:
#define MMC_DEBUG_SECTORS_READ #define MMC_DEBUG_SECTORS_WRITE #ifdef MMC_DEBUG_SECTORS_READ #define DEBUG_MMC_SECTORS_READ printf #else #define DEBUG_MMC_SECTORS_READ(...) #endif #ifdef MMC_DEBUG_SECTORS_WRITE #define DEBUG_MMC_SECTORS_WRITE printf #else #define DEBUG_MMC_SECTORS_WRITE(...) #endif |
Im C-Code:
... DEBUG_MMC_SECTORS_READ("RS %lu 0x%08lX\n",sector,sector); ... ... DEBUG_MMC_SECTORS_WRITE("WS %lu 0x%08X\n",sector,sector); ... |
So kann man mehrere Debugausgaben einzeln gezielt ein und ausschalten. Es wird eben nur das benutzt was man gerade benötigt. Das was man nicht haben möchte einfach in der Headerdatei auskommentieren:
//#define MMC_DEBUG_SECTORS_READ
|
Im C Code spart man sich dann auch das
#if defined(MMC_DEBUG)
Ausgabe("text");
#endif
Die Debugausgabe benötigt nur eine Zeile Code statt drei.
MMC_DEBUG("text");
Datum:
hallo, leider hab ich doch extrem weniger zeit als ich dachte. bugs würden geändert werden, aber mehr ist momentan nicht drin, sorry. nächste woche hab ich wohl etwas mehr zeit, hoffe ich... grüße daniel
Datum:
Hi Forum, ich hab das nun auch mal ausprobiert mit dem FAT-Treiber... Das Init funktioniert noch einwandfrei - danach geht nicht mehr viel: z.B. ffls() - da hängt er ziemlich lange in einer Schleife, der Grund ist, dass die Variable fat.dataDirSec bei mir auf -2 steht... Wie ist das bei Euch? Ich hab meine Karte unter Win mit FAT16 und FAT32 formatiert - jedesmal mit dem selben Ergebnis... Habt Ihr eine Idee an was das liegen kann? Die eine Karte ist eine MMC 512 MB von Transcend, bei der anderen Karte (Sandisk 2GB) steht in der FAT-Strukur nur Käse - liegt wohl an der Grösse... Schon mal danke für Eure Tipps... Andi
Datum:
hallo, ist die karte partitioniert? wenn ja musst du #define superfloppy ändern (in der fat.h). -2 ist auch ein komischer wert für einen unsigned long int... grüße daniel
Datum:
Daniel, hast du inzwischen ein bisschen Zeit gefunden, die Debug- und sonstigen Änderungen einzuarbeiten? Dann könnte ich meine selbstgestrickten Dinge verwerfen und zurück zu deinem Code wechseln :-) Michael
Datum:
hallo, bin momentan bis oben hin zu mit arbeit... ich hab auch die karten meist selber nur mit linux gedebugt, da hatte ich mir auch eine kleine mmc.c und mmc.h geschrieben, der rest code ist platformunabhänig... das ist die bequemste art den code zu testen. zudem kann man mit programmen wie WinHex auch images von datenträger machen und so kann man sogar ganz ohne mmc karten code debugen und testen. einfach immer eine mmc.c und mmc.h an die hardwaremäßige plattform anpassen, schon ist die lib portiert (sofern standart c darauf läuft). daher tendiere ich momentan dazu die debug geschichte erst in den semesterferien mal anzusehen (wie gesagt, debug mit linux ich wesentlich komfortabler). den rest, also die uart und die mmc/spi geschichte so umzubauen, dass andere bibliotheken genutzt werden können mach ich über weihnachten, als kleines present ;) spass beiseite, da werd ich wohl endlich ein wenig zeit haben mich meinem hobby zu widmen... grüße daniel
Datum:
Hi, ich versuche gerade die Dateien aus mmc-0.4.8.zip unter Linux zu kompilieren. Das geht auch Problemlos, nur wenn ich den Schalter write auf 1 (read only) setze bekomme ich folgende Fehlermeldungen:
~/sd_test/main_.c:50: undefined reference to `ffmkdir' ~/sd_test/main_.c:53: undefined reference to `ffmkdir' ~/sd_test/main_.c:68: undefined reference to `ffwrite' command.o: In function `run_cmd': ~/sd_test/command.c:94: undefined reference to `ffrm' ~/sd_test/command.c:101: undefined reference to `ffmkdir' ~/sd_test/command.c:149: undefined reference to `ffwrite' make: *** [main_.elf] Fehler 1 |
Ist das ein Bug oder habe ich etwas übersehen. Bei "read only" werden diese Funktionen natürlich nicht gebraucht, aber ich dachte der write Schalter berücksichtigt diese Option. Danke Andi
Datum:
hallo, besser spät als nie ^^ also, in der main_.c wird auf die schreib funktionen zugegriffen, genauso wie in der command.c . den schalter auf nur lesend setzen funktioniert nicht, wenn man dann doch auf die schreib funktionen zugreift. in der bibliothek selber stimmt das soweit alles. wenn du nur lesen möchtest, musst du dir eine main schreiben und nur auf die lesen funktionen zugreifen... grüße daniel
Datum:
Hallo, da ich BMPs auf meinem S65-Display ausgeben möchte, die auf der SD_Card liegen, wäre es für mich auch interessant direkt auf sector[] zuzugreifen. Die Funktion ffread() ist dafür zu umständlich. Wie könnte man dies realisieren? Güße Martin
Datum:
Hallo, also du könntest z.B. aus der fat.c direkt die Funktion:
unsigned char fat_loadSector(unsigned long int sec) |
aufrufen. Als Parameter bekommt die Funktion den zu ladenden Sektor übergeben. Danach ist der Sektor auf sector[]. Setzt allerdings Voraus, dass du den Sektor kennst. Wenn du damit BMP's lesen möchtest, muss du ja auch die folge Sektoren kennen. Deshalb ist die ffread etwas umständlicher. Im Regelfall, gibt es aber ja aber nur einen Index der erhöht wird und eine Abfrage... erst wenn man 512 Bytes gelesen hat wird es etwas umständlicher, wegen dem Problem der folge Sektoren. Grüße Daniel
Datum:
Hallo Daniel, wenn ich Dich recht verstehe, habe ich die Datei *.BMP mit ffopen() zu öffnen. Der der erste Sector befindet sich nun in sector[]. Da die größe der Datei bekannt ist, kann man mit sec++ und fat_loadSector(sec) den nächsten Sector in den Buffer sector[] laden. Dies wiederholt man, bis die ganze Datei geladen ist und schließt die Datei mit ffclose(). P.S Danke für die schnelle Antwort Gruß Martin
Datum:
Also Prinzipiell schon, aber es kann mehrere Sektoren in einem Cluster geben, diese Cluster können auch nicht aufeinanderfolgen. Deshalb muss man zwischendurch in der Fat nach dem folge Cluster suchen, diesen auf Sektoren umrechnen und dann weiter lesen... Wenn Du das alles beachtest, bist Du genau bei dem was ffread macht. Das Prinzip wie Fat funktioniert habe ich versucht im Wiki Artikel FAT32 zu erklären. PS: Ist Dir ffread nicht schnell genug? Wieso willst Du da was selber machen? Grüße Daniel
Datum:
Hallo Daniel, ich hatte am Anfang vermutet, dass ffread zu langsam sei. Inzwischen habe ich die Funktion aber benutzt und musste feststellen, das sie für den Bildaufbau schnell genug ist. Dieser dauert für die 176x132 Pixel (1Pixel=2Byte) ca. 1 Sekunde (gefühlt). Mit dieser Geschwindigkeit kann ich leben. Was mir aber noch Sorgen bereitet ist das Schreiben auf SD-Card. Dabei wird die FAT so verändert, dass man die Dateien in Windows zwar noch angezeigt bekommt aber das Löschen wird verweigert. Gruß Martin
Datum:
Hi Martin, das mit der 1 Sekunde ist seltsam wenn du mit 16 Mhz @ Avr arbeitest, weil mit Deiner Angabe komm ich auf 371712 Bit, ist ja 46464 Byte/Bild, da sollte wesentlich mehr drin sein, oder hab ich mich verrechnet? Zu dem Windows, welches benutzt Du? Vista? Ich bin da nicht ganz Spezifikations-konform, weil normalerweise müsste man die Uhrzeit der Zugriffszeiten (erstellen/lesen...) richtig eintragen. Der Einfachheit halber schreib ich Nullen rein... Hatte beim Testen aber dieses Problem auch nie. Würde Vista ähnlich sehen, beim Datum 00-00-0000 nicht klar zukommen ^^ Güße Daniel
Datum:
Hallo Daniel, da ich mit 3,3V Versorgungsspannung arbeite, zwecks der einfacheren Anbindung von SD-Card und Display, läuft mein m32 nur mit 12MHz. Nachdem ich zwei Byte von SD-Card gelesen habe muß ich sie in ein Integer umwandeln und noch zum Display schicken, das kostet zusätzlich Zeit. Meine Zeitangabe ist auch nur eine grobe Schätzung, der Bereich ist irgendwo zwischen 0,5 und 1s. Zur SD-Card: Ich habe es mit XP und Linux getestet. Beide behaupten die Karten seinen schreibgeschützt. Das habe ich mit 3 unterschiedlichen Readern getestet, auf die richtige Einstellung des mechanischen Schreibschutz habe ich auch geachtet. Die Dateien die mit 'a' beschrieben wurden seien 1,5GB groß, das behauten beide BS, obwohl die Karten nur 256 bzw. 512MB groß sind. Als Software benutze ich Deine mmc-0.4.8. Hardwareprobleme kann ich zu 90% ausschliessen, da das Lesen einwandfrei funktioniert, das einmalige schreiben auch. Nur das anhängen von Daten an eine bestehende Datei produziert den Fehler. Das Anhängen muß ich aber nochmal genau überprüfen, wenn mir weitere SD-Cards zu Verfügung stehen. Mit meiner letzten mache ich nur noch Lesetests. Gruß Martin
Datum:
Hallo, nur um mal abzuklopfen, Du hast den Code nicht geändert oder so und Du achtest darauf, dass ffclose() aufgerufen wurde bevor du den Strom von der Karte nimmst, bzw. diese aus der Halterung ziehst (beim schreiben, beim lesen egal). Mich würde dann auch der Aufruf und so interessieren, um abschätzen zu können wo da vielleicht der Fehler liegt. Hab den Code so in der 0.4.8 Version selber im Gebrauch und mit Datei Größen noch nie Probleme gehabt. Grüße Daniel
Datum:
Hallo Daniel, ich habe Deine Version komplett übernommen und mit meinen Funktionen erweitert. So im nachhinein betrachtet kann ich aber das Abziehen der Stromversorgung bevor ein ffclose stattgefunden hat nicht ausschliesen. Das geht halt in der Softwareentwicklnugsphase nicht immer. Ein reaktivieren der SD-Cards unter Windows blieb bis jetzt erfolglos, Windows meldet immer einen aktivierten Schreibschutz oder behauptet das die Datei text.txt ein Verzeichnis sei. Meine letzte Hoffnung ist nun Linux. Ich könnte auch mal probieren, die Datei mit ffrm() zu löschen. Gruß Martin
Datum:
Hallo, also auch beim Versuch die Karten zu Formatieren gibt es Fehlermeldungen? Generell ist das sehr seltsam. Eigentlich geht Schreibschutz über Software nur mit einem bestimmten Kommando an die Karte, was aber auch nicht jede Karte unterstützt... Einen Versuch die Datei mit ffrm() zu löschen ist es auf jeden Fall wert. Schlimmstenfalls bleibt ein bisschen Datenmüll in der Fat über. Sollte aber mit einem Scandisk Tool zu beheben sein. Ich vermute, dass im Dateieintrag der Datei irgendwas steht was keinen Sinn macht. Hast Du einen Hex-Editor mit dem Du Dir die Rohdaten auf der Karte ansehen kannst? Davon ein Screenshot wäre super :) Um soetwas zu verhindern, könnte man einen Taster anschließen, der einen Interrupt auslöst und ffclose() aufruft.
Datum:
Hallo, ich habe es nun mit Linux probiert, alles ohne Erfog. Fdisk und mkfs.msdos werden zwar augeführt (ohne Fehlermeldung) aber danach ist alles beim Alten. Die Dateien sind also noch vorhanden, selbst ein dd if=/dev/zerro of=/dev/sdb brachte keinen Erfolg. Es sieht für mich so aus, als ob der Speichercontroler auf der SD-Karte auf read only steht. Das Komische ist nur, dass es bei zwei unterschiedlichen SD-Cards aufgetreten ist. Einen Hex-Editor habe ich natürlich, was genau soll ich Dir übermitteln? Auf die Idee mit der Interruptroutiene bin ich auch schon gekommen, die wird mir aber nur was bringen, wenn das Programm in einer Endlosschleife fest sitzt. Bei einem Zugriff auf eine falsche Speicherstelle und der nachfolgende Sprung ins Nirvana wird mir die ISR die SD-Card nicht schützen können, weil sie wahrscheinlich nicht mehr ausgeführt wird. Gruß Martin
Datum:
Hi, also das mit dem Sprung ins Nirvana versteh ich nicht. Wenn Du sagen wir mal konstant Daten wegspeicherst, und ein ffclose wird aufgerufen, wird halt nur die Datei ordentlich geschlossen, also die aktuelle Größe usw. geschrieben. Macht jedes Betriebssystem ähnlich... Also Daten Direkt schreiben und den Fat und Datenbereich zum Schluss aktualisieren. Deshalb kann man bei Usb-Sticks die einfach so herausgezogen wurden (beim schreiben) die Daten meist recovern. Da Du keinen Code gepostet hast, kann ich nicht genau sagen wo der Fehler eigentlich liegen kann... Rechne Dir das mal durch, wie oft man eine Zelle beschreiben kann und wie oft du Tatsächlich schreibst. Interessant wäre für mich der Sektor des Ordners in dem der Dateieintrag steht. Die einzige Möglichkeit eine Karte mit der Lib zu zerstören wird zu oft schreiben auf die Karte sein, dass ist definitiv sicher. Wäre aber auch mit einem großen Betriebssystem nicht anders ! Wenn Du mit Linux und mkfs keinen Erfolg beim Formatieren der Karten hast ist da was ganz anderes im argen. Aber interessehalber, schick mir mal eine. Dann schau ich da nach. Das glaub ich nämlich irgendwie nicht, formatieren mit Linux und dann sind da noch Daten so lesbar?!? Güße Daniel
Datum:
Hallo, die Screeshots sind noch in der Mache. Habe soeben feststellen müssen, dass WinHex keine Screenshots zulässt. Schicken kann ich Dir auch eine, ich habe schlieslich zwei Defekte. Ich bräuchte halt nur die Adresse. Zum Nirvana: Wenn der Prozessor eine falsche Speicherstelle liest und versucht den Befehl dann auszuführen, wird eine Exception ausgelöst, fals der Befehl nicht bekannt ist. Schlimmer ist es aber, wenn an dieser Stelle ein ausführbarer Befehl steht, der aber nichts mit dem Programm zu tun hat. Das kann den Programmcounter und den Stack verändern. Der Prozessor befindet sich dann in einem nicht definierten Zustand. Wenn jetzt ein Interrupt ausgelöst wird kann alles mögliche passieren, aber bestimmt etwas sinnfreies. Nach dem Formatieren unter Linux habe ich auch ganz blöd aus der Wäsche geschaut, als ich die Dateien wieder gesehen habe. Der Fortschrittsbalken beim Formatieren unter Windows bewegt sich auch bis zum Ende und dann meldet Windows erst einen Fehler. Sinngemäss "Befehl konnte nicht zum Abschluß gebracht werden". Ich denke das war der verify. Ich such mir jetzt einen besseren HexEditor und mache die Screenshots. Kannst Du einen empfehlen? Gruß Martin
Datum:
Also ich nehm auch immer winhex. Musste halt nen gesamt Screenshot machen... Was hat der Prozessor mit der mmc/sd karte zu tun? Die ganze Geschichte kommuniziert ja über SPI, also AVR <-> mmc/sd Karte. Da hat keiner direkten Zugriff auf Stack oder so des anderen.. Schick mir ne Mail an zerrome aT gmail PunKt com, dann schick ich Dir meine Adresse. Meinst du mit Daten gesehen, dass Du die Daten mit dem Hex-Editor gesehen hast? Wäre klar, weil Formatieren nur den Fat Bereich ändert, sonst müsste ja immer die Ganze Karte platt gemacht werden. Grüße Daniel
Datum:
Hi, der Screenshot [Alt]+[Druck] bzw. nur [Druck] legt bei mir unter WinHex nichts in der Zwischenablage ab, also nichts mit cut and paste! Der Prozessor arbeit doch wohl die Befehle ab, somit auch die, die für das lesen und schreiben auf SD-Card zuständig sind. Der Stack ist der letzte Speicherbereich im Ram. Dieser wird benutzt um Daten, die einer Funktion übergeben werden sollen aufzunehmen, aber auch die Rücksprungadresse um wieder ins Hauptprogramm oder in die aufrufende Funktion zurückzukehren. Der Stackpointer enthält die letzte benutzte Adresse auf dem Stack. Nachdem ich einen Dateibrowser geöffnet habe, hat mir dieser die Dateien und Verzeichnisse wieder angezeigt. Das sollte nach einer Formatierung eigentlich nicht so sein.top Die Mail schreibe ich heute Abend. Gruß Martin
Datum:
Hallo, jetzt versteh ich glaube ich endlich was Du mit dem Nirvana meinst... Klar, nach der ISR nochmal ins normale Programm zu springen macht in dem Fall keinen Sinn. Da wäre dann in der ISR ein exit() oder so angebracht. Wenn Du einen Screenshot vom gesamten Bildschirm machst wenn Winhex offen ist geht nichts in die Zwischenablage? Versuchs mal mit dem tool Printkey... Grüße Daniel
Datum:
Hallo Daniel, ich bin nun so weit, dass mein "AVR-Portable" BMPs mit 24Bit Farbtiefe dank Deiner Lib lesen und auch auf dem Display des S65 anzeigen kann. Ein einfaches Spiel (Pong) habe ich auch schon am Laufen. Was ich nun gerne noch realisieren möchte, ist das Abspeichern von Spielständen. Nun zu meiner Frage: Gibt es eine Möglichkeit mit ffread den Namen eines Spielers auszulesen um den Pointer auf die richtige Stelle hinter dem Namen zu positionieren und dann mit ffwrite den Spielstand zu speichern? Gruß Martin
Datum:
Hallo, ich glaube ich würde das an Deiner Stelle so machen, ein struct anlegen mit Spielername, Score usw. Für sagen wir, die Top 10. Jetzt aus einer Datei die Daten auslesen und ins struct schreiben. Wenn jetzt ein Spiel vorbei ist, einfach den Score überprüfen und wenn nötig einen aus den Top 10 rauswerfen und den aktuellen Spieler ins struct schreiben. Zuletzt noch das aktualisierte struct wieder in die Datei schreiben. Das Problem ist ja, dass man lese und schreib Vorgänge trennen muss, weil nur eine Datei zum schreiben oder lesen geöffnet werden kann. Wäre mit dem oben beschriebenen Beispiel kein Problem. Denkbar wären auch noch andere Möglichkeiten, solange man lesen und schreiben trennt... Werde mir da mal was überlegen, weil es ja schon schick wäre, eine Datei zu öffnen und dann lesen und schreiben zu können... muss man halt bisschen aufpassen was man macht ^^ Das Problem ist ja nicht das überschreiben von alten Daten (da ändert sich ja nix am Datei Eintrag in FAT und Ordner), sondern wenn über das alte Datei Ende hinweg neu geschrieben wird. Da muss dann ne menge mehr gemacht werden... Grüße Daniel
Datum:
Hallo, deine SD Karten sind angekommen. Die Controller darauf sind OK. Aber es sind massenhaft kaputte Sektoren. Zu viele. Ich vermute ja bei so billig Herstellern, dass die keine Algorithmen zum mappen von logischen auf physikalische Sektoren einbauen... mkdosfs wirft in der Standart ausgabe (Konsole) keine Fehler, aber dmesg liefert die ganzen Fehler... Die eine Karte kann man sogar an manchen stellen noch beschreiben, die andere weigert sich einfach. Ist eindeutig kaputter Flash, weil die Controller sich noch ordnungsgemäß verhalten. Bin gerade an einer neuen Version der Lib... die 0.5, da wird es große Änderungen geben. Es wird dann auch möglich sein zu lesen und schreiben auf einer geöffneten Datei. Muss aber viel umbauen dafür... Grüße Daniel
Datum:
Hallo Daniel, die SD-Cards kannst Du behalten, die brauche ich nicht mehr. Was aber komisch ist, sind die haufenweise def. Sektoren, denn die Teile wurden kaum benutzt. Ich bin schon gespannt auf die neue Lib. und stelle mich gerne als Betatester zur Verfügung. (So lange ich noch SD-Cards zum Schießen habe ;-) ) Gruß Martin
Datum:
Hallo Martin, wenn du magst kann ich die Karten auch zurück schicken, dann kannste Dir die vielleicht auch nochmal ansehen. Mit Massenhaft kaputten Sektoren meinte ich, dass so bei 10 gemeckert wurde. Das ist schon viel, weil eine gute Karte normalerweise noch Reserven hat, die benutzt werden wenn wenn defekte entdeckt werden. Es ist auf jeden Fall Vorsicht geboten bei Flash Speicher.. Die Lib ist jetzt soweit fertig. Bin am testen und Debuggen. Es entfällt der Parameter beim öffnen einer Datei. Also 'w','r', und 'a' sind nun überflüssig. Es wird entweder die vorhandene Datei geöffnet oder wenn nicht vorhanden eine erstellt. Diese kann man dann lesen und beschreiben. Will man an eine Datei etwas anhängen, wird diese einfach geöffnet und mit ffseek(file.length) ans ende gespult. Dann einfach schreiben... Dazu und zu anderen neuen Aspekten aber noch Code Beispiele. Denke ich werde Sonntag die Version mmc-0.5 Posten können. Grüße Daniel
Datum:
Es gibt noch Probleme bei fragmentierten Fat-Tabellen. Wenn ich das in den Griff bekommen habe ists fertig :) Im Idealfall, wo die FAT unfragmentiert voliegt, kann man 256000 Byte-Blöcke in einem Rutsch lesen. Sollte also auch alles schneller werden. Beim schreiben ähnlich...
Datum:
Hallo Daniel, wie gesagt, Du kannst die SD-Cards behalten. Ich denke die kannst Du in der Testphase ganz gut gebrauchen. Das hört sich ja schon sehr vielversprechend an. Wie heisst es doch so schön:" Gut Ding will Weile haben!". In diesem Sinne wünsche ich Dir viel Spass und natürlich auch Erfolg. Gruss Martin
Datum:
Hallo, also wenn ich teste, dann eh nur mit images von Karten, nie mit den Karten selber... Wäre auch viel zu umständlich da immer neu zu Formatieren und Dateien drauf zu kopieren um auf einen definierten Zustand zu kommen. So is das ne Sache von 2 Sekunden... Grüße Daniel edit: Man stelle sich vor, eine schleife läuft Amok und das über mehrere Sekunden/Minuten oder so -> defekte Karte...
Datum:
Hallo Daniel, das mit den Images von Karten habe ich nicht verstanden, wo laufen die den? Klär mich auf! Gruß Martin
Datum:
Hallo, also ich mache ein Image von einer Karte (z.B. mit winhex), also von allen Sektoren. Dieses Image öffne ich in meinem c-Programm als Datei (c-Programm auf PC). Diese Datei hat ja die Struktur der Karte und kann somit genau so benutzt werden. Jetzt braucht man nur noch eine angepasste mmc.c und schon kann man problemlos Testen, ohne Karten zu gefährden und bequem am PC. Abschließende Tests mit realer Hardware kommen dann natürlich dazu, aber da geht es nicht mehr so darum ob der Code das macht was er soll... Grüße Daniel
Datum:
Angehängte Dateien:Sooo, ist fertig. Ist gut geworden, schneller und kleiner... Viel Spaß damit. Werde morgen oder so mal das Wiki mit bisschen Doku undso füttern. Wer den Link noch nicht kennt: http://www.mikrocontroller.net/articles/FAT32 Grüße Daniel
Datum:
Hi, ich bin blutiger Anfänger, zumindest was SD-Karten angeht. Deswegen auch nen Anfängerfrage :) Wie beschalte ich denn so eine SD-Karte? Kann mir mal jemand nen Schaltplan hochladen? Wär total nett! Gruß Matze
Datum:
Hallo, hab grad keinen Schaltplan da. Das Problem ist ja meistens, dass die Karte 3,3 V braucht und so ein MC meist mit 5 V läuft. Da muss man also Level shiften. Ich mache das immer mit nem HC4050, ist ein Digital IC, dass wenn man es mit 3,3 Volt betreibt auch 3,3 Volt an den Ausgängen hat. Ist aber bis 15 V Tolerant an den Eingängen. Ein Eingang hängt mit einem Ausgang zusammen. Geht glaub ich bis 20 Mhz Frequenz und kostet 20 Cent. Den Ausgang der Karte kann man direkt an den MC machen, da 3,3 V reichen für logisch 1. mc -> hc4050 -> karte (für SCLK,DI,CS) karte -> mc (für DO) Grüße Daniel PS: hab da in der ffmkdir() etwas übersehen, also noch bisschen Vorsicht beim Ordner anlegen...fix kommt bald...
Datum:
aller besten dank für die hilfee bei der beschaltung! ich habe zwar keine ordner operationen vor, aber ich werde aufpassen :) was den einstieg vielleicht für alle anfänger erleichern würde, wäre ein beispielprogramm, in dem die meisten / wichtigsten funktionen einmal durchlaufen werden (Datei erstellen und öffnen, daten hinein schreiben und anhängen, etc (natürlich auch für ordner)). ähnlich wie die libraries von fleury und seine testprogramme - muß aber nich soo ausführlich und allumspannend sein. ich denke, ein atmega8 hat jeder zuhause rumfliegen... ich muß nämlich gestehen, daß die fülle von dateien und die auf den ersten blick recht kryptischen befehlsnamen einen echt abschrecken können :) gruß, matze
Datum:
Ja kann ich verstehen, sieht wahrscheinlich echt seltsam aus wenn man sich die fat.c oder so ansieht (und erst der ganze doku Text ^^)... habe da für mich möglichst sprechende und lange Namen genommen... Letztendlich sollen ja für einen normalen Anwender nur die Funktionen aus der file.c sein. Wie ffopen, ffclose, ffseek, ffwrite usw... Ah nicht zu vergessen noch zwei elementare Funktionen mmc_init und fat_initfat, sonst nur Funktionen aus file.c... Mache morgen oder eher Dienstag so ein Mini Beispiel. Bin für Anregungen immer zu haben. Wollte im Rahmen der Dokumentation auch noch eine Beschaltung von MMC/SD Karten (Schaltplan und Fotos) machen. Leider fehlt mir momentan die Zeit um mich richtig aus zu leben in meinem Hobby ^^ Grüße Daniel
Datum:
Das klingt doch gut. Ich muß nämlich für die Uni Messwerte auf eine SD-Karte bannen und deine Library ist goldwert. - aber einen kleinen Denkanstoß brauche ich wohl noch :) Ich habe vielleicht auch gleich noch eine Anmerkung (bitte versteh mich nicht falsch, ich finde deine Arbeit klasse und ziehe den Hut!): So wie ich das verstehe, kann die Funktion ffwrite nur ein einzelnes Zeichen auf die Karte schreiben. Für viele Anwendungen ist es aber häufig nötig gleich einen ganzen String zu schreiben. Man müßte also jeden "Buchstaben" einzeln anweisen. Wäre es nicht pfiffiger einfach eine Funktion alla:
void ffwrites(const char *s ) { while (*s) ffwrite(*s++); } |
zu schreiben bzw.in die file.c zu packen?! gruß matze
Datum:
Hallo Daniel, ich habe die neue LIB in meine alten Programme eingebaut. Alle funktionierten auf Anhieb. Zum intensieveren Testen komme ich in den nächsten Tagen. Tolle Arbeit, Danke dafür! Gruß Martin
Datum:
Angehängte Dateien:Hallo zusammen, danke das ihr mit testet. Die angesprochene Funktion ffwrites ist aufgenommen. Zudem ist in der fat.c noch eine Funktion fat_str hinzu gekommen, die sonst immer woanders untergebracht war. Mit dieser Funktion kann man einen String von "test.txt" in "TEST TXT" wandeln, so muss ja schließlich alles auf die karte... Anbei sind jetzt, wie ich denke einfache Beispiele zur Benutzung der Lib, für einen atmega8. Der is leider ein bisschen zu klein für den vollen Umfang der Lib (z.B. Ordner Rekursiv löschen und anlegen). Der Bug in ffmkdir ist behoben. Keine weiteren Bugs bekannt... Was mich noch stört, ist die Tatsache, dass mehr als 100 KBytes schreiben möglich wären, aber durch einen blöden Vergleich von zwei unsigned long int (ist nötig wegen der überschreiben Funktionalität) nur 80-85 KBytes geschrieben werden... Muss mal sehen ob das nicht einfacher geht... Grüße Daniel
Datum:
Hi, ich verzweifel langsam. ich komm einfach nicht durch die mmc_init. ich denke, es liegt an meiner verkabelung. hier eine kleine ascii-skizze :) (ATmega162) --------\ 09 (NC) \ 01 (CS) | ---------- (PB1) 02 (DI) | ---------- MOSI (PB6) 03 (GND) | -------------------------- (-) 04 (VCC) | -------------------------- (+) 05 (CLK) | ---------- SCK (PB7) 06 (GND) | -------------------------- (-) 07 (DO) | ---------- MISO (PB5) 08 (NC) | --------- Ich habe den ATmega162 mit 3,3V laufen, daher kein HC4050 dazwischen. Ich hoffe, daß ist soweit richtig und ich habe nur ein brett vorm kopf. Als quellcode habe ich das beispiel von "mmc_0.5.1" genommen. oder mache ich was falsch, wenn ich mein ISP kabel, das ja die selben ports benutzt, dranlasse? ich komm echt nicht weiter und brauche wirklich hilfe! gruß und danke, matze
Datum:
Hi, bist du sicher, das überhaupt das Programm drauf ist? Ist ISP nicht mit 5 Volt? Sieht nämlich sonst Ok aus. Wie lang sind die Kabel vom MC zur Karte? Und ja, besser ISP Stecker abmachen. Grüße Daniel
Datum:
So, habe den fehler nach langem probieren gefunden. irgendwie hat der uart nicht geklappt, wenn der isp nicht angeschlossen war. ich habe jetzt als work-around einfach die masse, an der es lag, von PC zum uC extra gezogen. jetzt geht alles. aber wie zum kuckkuck mach ich nen zeilenumbruch? ich hab schon alles probiert: \n und \r sogar schon den 0x0D (ascii code für zeilenumbruch). hilfe. danke, matze
Datum:
Angehängte Dateien:Hallo,
schön das es jetzt klappt.
Zeilenumbruch wo? Im Terminal Programm?
Je nachdem welches du benutzt musst du das auf vt100 oder so
umstellen... dann sollte uputc('\n') oder uputs("\n") auf jeden Fall
gehen.
Anbei ein Funktionsübersichts Diagramm der ganzen Lib.
Krieg leider die Größe nicht in den Griff. Also hier die Warnung: 2412 x
7946 Pixel :)
Datum:
ne, im terminalprogramm weiß ich das (ich mach das immer mit 0x0D). aber in der*.txt auf der SD karte. Ich kriegs einfach nicht hin. gruß matze
Datum:
Hallo, also mein hex Editor sagt bei Windows Zeilenumbruch: 0x0D 0x0A für neue Zeile... Das ist der Hex Code
746573740D0A7A65696C650D0A6E65750D0A |
für
test zeile neu |
Grüße Daniel
Datum:
Update, bei Linux ist ein Zeilenumbruch nur 0x0A...
Datum:
Ich möchte jedemenge einfache Bytes in eine Textdatei schreiben. Das klappt auch alles gut, ich mache mir nur gedanken um die Lebensdauer der Karte. Wäre es besser, wenn ich die Bytes nicht direkt mit ffwrite(byte); auf die Karte schreibe, sonderen erstmal in einem großen String speichere und diesen dann später komplett auf die Karte übertrage, oder macht das keinen unterschied? Ich benutzte einen MEGA32, RAM wäre noch genug dar, um z.B. 512Bytes zupuffern.
Datum:
Hallo, nee das ist kein Problem, da ja schon 512 Bytes gepuffert werden. Halt ein Sektor, bevor geschrieben wird. Was allerdings schlecht wäre, ist nach dem schreiben immer direkt ein ffclose (obwohl man später eigentlich noch mehr schreiben will), weil dabei die Datei Daten ein Update erfahren. Dies bedeutet, dass einmal der Sektor wo der Dateieintrag drin steht neu geschrieben wird und evlt. muss auch die FAT geupdatet werden (wenn mehr Bytes geschrieben wurden als über Cluster schon verkettet sind). Und natürlich der Sektor in dem man gerade geschrieben hat auch. Also einfach öffnen und dann immer mal wieder schreiben ist überhaupt kein problem... Ein Problem könnte sein, wenn man oft innerhalb einer Datei hin und her springt. Beispiel: Ich schreibe in Sektor 1928 ein Byte, jetzt springe ich (mit ffseek) zu Sektor 1929 und schreibe wieder ein Byte, weil ich aber Sektor 1928 verlasse und dieser geändert wurde, muss er vorher geschrieben werden. Wenn ich jetzt zurück springe, passiert das gleiche wie vorher mit Sektor 1928 jetzt mit Sektor 1929. Das ist der schlimmste Fall, weil für nur 1 geändertes Byte immer ein ganzer Sektor geschrieben wird... Würde also 512 Sektor schreib Vorgange (also 512*512 Bytes) für 512 Bytes machen. Das wäre schlecht und langsam... Wenn eine Datei angelegt wird, gibt es mindestens 3 Sektor schreib Operationen. 1. Anlegen des Datei Eintrags im Ordner. 2. Mindestens einen Sektor mit Daten beschreiben (auch wenn weniger Bytes geschrieben werden). 3. Update des Datei Eintrags (Größe usw.). Macht 3 beschriebene Sektoren. Das wird so gemacht, weil wenn schon mal ein Datei Eintrag besteht, kann man mit Recovery-Tools möglicherweise bei Datenverlust Daten retten. Dient also rein der Sicherheit. Nötig wären nur 2 Sektor schreib Operationen... Da ein Sektor (512 Bytes) die kleinste Einheit ist die man auf eine Karte schreiben kann werden ja eben 512 Bytes gepuffert. Grüße Daniel
Datum:
Ok, vielen Dank dafür!! Das mit dem ffclose werde ich berücksichtigen. Gruß Christian
Datum:
Hi, ich habe noch einen kleinen Zusatz zur file.c (ist vielleicht etwa übertrieben, aber vielleicht als Addon nicht schlech): Wenn man z.B. Messwerte aufnehmen will, macht ein Zeilenumbruch recht viel sinn. Ich habe in meine file.c daher hinzugefügt:
ffzeilenumbruch ()
{
ffwrite(0x0D);
ffwrite(0x0A);
}
|
Macht zugegebener Maßen nicht in jeder Anwendung sinn, bei mir allerdings schon und ich denke auch bei so mach anderem. Gruß, ein Fan dieser Speicherfressenden Library :) Matze
Datum:
Hallo Daniel, ich habe nun die LIB ausfuehrlich getestet und muss sagen, dass alles rund laeuft. Meine HireScore-Liste laeuft nun auch und wartet auf die Besten. Gruss Martin
Datum:
Hallo, ich hab heute die Souce-Files mit WinAVR (ohne mitgelieferte makefile) compiliert und es kommt tatsächlich ein Hex-File. uc=atmega8 optimierung= -Os smallFileSys 0 write 0 superfloppy 1 Program: 7826 bytes (95.5% Full) (.text + .data + .bootloader) Data: 656 bytes (64.1% Full) (.data + .bss + .noinit) Als hab ich den parameter smallFileSys 1 gesetzt. Die Größe ist aber bei den 7826 byte geblieben. Ich weiß, dass das Problem bekannt ist. Gibt es dazu schon eine Lösung? Viele Grüße C.Alex PS: Die mitgelieferte makefile hat auch keine abhilfe gebracht.
Datum:
Hallo, bin leider noch nicht dazu gekommen, die beiden Optionen von smallFileSys und write wieder einzubauen... Nur superfloppy funktioniert bis jetzt. Wird wohl auch noch ein wenig dauern, weil ich auch alles auf dynamischen Ram verbrauch am umbauen bin... Grüße Daniel
Datum:
Hallo, das erklärt natürlich einiges :) Ich dachte AVRStudio würde wieder rumspinnen. Ich muss auch zugeben, ich hab nicht alle 180 Beiträge oben gelesen... Was aber trotzdem interessant ist: Ich wollte den Code für ATmega88 compilieren und auf einmal hat er nicht mehr draufgepasst (500byte zu groß). Laut Datenblatt sind aber atmega8 und atmega88 von den Speichern her gleich groß. Tja Sachen gibts... Danke für die Info Viele Grüße C.Alex
Datum:
Angehängte Dateien:Hallo zusammen. Jetzt sind wieder alle 3 Schalter in der Lib zu benutzbar. Zudem einige Verbesserungen. Lesend ist bis zu 230 KBytes/s möglich. Beim Roh lesen, also ohne Dateisystem kommt man ungefähr auf 300 KBytes/s. Das ist nur ein relativ geringer Overhead. Schreiben geht jetzt bis zu 140 KBytes/s trotz überschreiben-Funktionalität. Bisschen Doku gibts auch hier : http://www.mikrocontroller.net/articles/AVR_FAT32 PS: Die Zeilenumbruch Funktion wird erstmal nicht aufgenommen, allerdings sind weitere Anregungen erwünscht. Viel Spaß damit :) Grüße Daniel
Datum:
Hallo Daniel, die neue Version passt mit 94% Flash-Auslastung wunderbar auf dem atmega88. Beim ersten Compilieren hat er mit smallFileSys 1 die Funktion fat_str(datei) nicht gefunden. Ich hab dann einfach die Präprozessoranweisung in fat.c geänder in:
#if (smallFileSys==1) // ***************************************************************************************************************** // bereitet str so auf, dass man es auf die mmc/sd karte schreiben kann. // wandelt z.b. "t.txt" -> "T TXT" oder "main.c" in "MAIN C " => also immer 8.3 und upper case letter // VORSICHT es werden keine Prüfungen gemacht ! // ***************************************************************************************************************** char * fat_str(char *str){ . . . } #endif |
Viele Grüße C.Alex
Datum:
Hallo, mit welchem Programm muss ich meine SD-Karte formatieren, damit ich sicher gehen kann, dass es fehlerfrei formatiert ist. Hintergrund ist, dass ich ein LowLevel-Format gemacht hab um den Speichervorgang nachvollziehen zu können. Anschließen mit Windows formatiert in FAT16. Seit dem schlägt die Fat-Initialisierung fehl. Also: Boot... Vorher ging es.
#include <stdlib.h> #include <avr/io.h> #include "main.h" #include "file.h" #include "fat.h" #include "hardware.h" void beispiele(void); // kleine datei operations-beispiele //***************************************************************************************************************** void main(void){ uinit(); // uart initialisierung uputs((unsigned char*)"\nBoot"); while (mmc_init() !=0){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten ; } uputs((unsigned char*)"... "); if(0==fat_initfat()){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten uputs((unsigned char*)"Ok\n"); // wenn auf dem terminal "Boot... OK" zu lesen ist, ist init ok. jetzt kann man schreiben/lesen beispiele(); // beispiel 0-4 , da nur atmega8, keine ordner anlegen und ordner rekursiv löschen... } } // ***************************************************************************************************************** void beispiele(void){ char datei[12]="test.txt"; // hier muss platz für 11 zeichen sein (8.3), da fat_str diesen string benutzt !! fat_str(datei); // wandelt "test.txt" in das fat format 8.3 der form: "TEST TXT" muss immer dieses Format haben, auch ordner !! // 1.) ______________anlegen und schreiben____________________________________________________________________ /* öffnet datei, wenn nicht vorhanden, legt ffopen datei an (rückgabewert = 1 datei existiert, also nur öffnen, 2 = angelegt). */ uputc('\n'); uputs((unsigned char*)"Datei anlegen\n"); ffopen( datei ); /* schreibt string */ ffwrites((char*)"Hallo Datei :)"); // neue zeile in der datei ffwrite(0x0D); ffwrite(0x0A); /* schließt datei */ ffclose(); uputs((unsigned char*)"Ende\n"); } //***************************************************************************************************************** |
Ich hab doch im Prinzip nichts falsch gemacht? oder? C.Alex
Datum:
Hallo @Daniel weiter oben schreibst Du, dass Du einen HC4050 als Levelshifter verwendest. Ist der wirklich geignet? Im Datenblatt steht das VCC -0,5 bis 7V sein kann (also VCC=3,3V). DC Input Voltage -0,5V to Vcc+0,5V. Das wären dann aber bis 3,8V, also keine 5 V. Das der das eventuell ohne kaputt zu gehen kann ist ne andere Sache! Oder habe ich da was falsch verstanden? Danke für ne Klärung Achim
Datum:
Hallo zusammen. @Alex Wahrscheinlich ist die Karte jetzt nicht mehr partitioniert, du musst also in der fat.h "superfloppy 1" ändern. @sucher Ausschnitt Datenblatt: "The 74HC4050 provides six non-inverting buffers with a modified input protection structure, which has no diode connected to VCC. Input voltages of up to 15 V may therefore be used. This feature enables the non-inverting buffers to be used as logic level translators, which will convert high level logic to low level logic, while operating from a low voltage power supply. For example 15 V logic (“4000B series”) can be converted down to 2 V logic." Das verstehe ich so, dass da eine irgendwie geartete Eingangssicherung besteht, damit der Eingang nicht kaputt geht. Deshalb kann man bis zu 15V auf den Eingang machen selbst wenn das Ding nur mit 2V betrieben wird. Rest vom Datenblatt gibt das auch so her... Grüße Daniel
Datum:
Hallo @Daniel, Danke für die Antwort. Es gibt da wohl verschieden Datenblätter ( Deins ist Philips?). Bei Reichelt könnte man das nich rauslesen http://www.reichelt.de/?;ACTION=6;LA=3;ARTICLE=322... (Thomson) Es geht mir nicht ums rechthaben, sondern ich möchte es verstehen. MfG Achim
Datum:
Hallo Daniel, die Initialisierung der Karte und FAT funktionieren jetzt wieder, allerdings bleibt das Beilspielprogramm gleich in dem ersten Funktionsaufruf hängen. Also bei:
. . . char datei[12]="TEST TXT"; ffrm(datei); . . . |
Daraufhin hab ich die Signalwandlung mit dem SN74LS07 geprüft, es ist aber alles OK. Hast du eine Idee warum der uC da hängen bleibt? Gleiche Reaktion mit 2 versch. Karten. Danke! C.Alex
Datum:
Hallo. @Achim Tatsache, in dem Datenblatt von Thomson steht nur ein schlanker Satz dazu, im Rest der Daten finde ich das auch nicht so bestätigt.. "The VCC side diodes are designed to allow logic-level convertion from high-level voltages (up to 15 V) to low-level voltages." @C.Alex So wie es aussieht, gibt es möglicherweise Probleme mit FAT16 und nur einem Sektor pro Cluster... hatte ich nicht getestet, sorry. Werd ich aber schleunigst beheben. Bis zum erbrechen hatte ich FAT32 mit mehreren Sektoren pro Cluster getestet... Als workaround, meine Empfehlung: FAT32 mit mehreren Sektoren pro Cluster. Grüße Daniel
Datum:
Hallo Daniel, ich habe beide Karten mit FAT32 formatiert; kein Unterschied zu vorher. Bedenken habe ich im Zusammenhang mit der Formatierung der Karten. Kann man davon ausgehen, dass das Windows Formatier-Tool alles richtig macht? Weil: ich hab die Karte mit Windows formatiert und hatte danach das Problem, dass es nicht mehr gebootet hat :Boot... Daraufhin hab ich es in meine Digicam reingesteckt, der kein System erkannt hat und formatieren wollte, und siehe da: Boot...OK Ich kenn mich nur zuwenig mit FAT aus um dem auf den Grund zu gehen. C.Alex
Datum:
Hallo, also das einzige Problem ist die Formatierung mit Linux, da dabei, warum auch immer, das root-Dir wenn es nur 1 Cluster groß ist als Ende Markierung nicht 0xfffffff0 erhält, sondern 0xffffff80. Ich hatte einfach keine Lust mich mit 3 Ende Markierungen herumzuschlagen. Windows ist manchmal etwas eigen beim Formatieren, da wird schon mal aus einer partitionierten Karte eine unpartitionierte ohne Kommentar ^^ Muss man nachsehen und in der Lib umstellen. Andere Probleme gibt es eigentlich nicht im Zusammenhang mit Formatierungen. Was haben die Karten, die nicht durch den Boot Vorgang kommen, denn für Eckdaten? MB Größe, Sektoren/Cluster und partitioniert oder unpartitioniert? Grüße Daniel
Datum:
Hallo, da wäre: Lexar Media File System: FAT16 Total capacity: 127.090.176 byte Sector count: 248.223 Bytes per Sector: 512 Bytes per Cluster: 2.048 Total Clusters: 61.925 Lexar Platinum II File System: FAT16 Total capacity: 512.880.128 byte Sector count: 1.001.719 Bytes per Sector: 512 Bytes per Cluster: 8.192 Total Clusters: 62.574 Woran kann ich erkennen, ob nach dem formatieren eine Karte partinioniert ist oder nicht? C.Alex
Datum:
Also einmal steht im Sektor 0 die Partitionstabelle oder die Fat Daten. Bei beiden von Dir geposteten Karten sollte angesprochenes Problem mit nur einem Sektor pro Cluster nicht auftreten. Bleibt nur noch die Partitionierung und das Formatieren mit Linux. Das mit der Partitionierung ist schnell getestet... einfach mal umstellen in der Lib und schauen ob es geht. Allerdings besser nur ein lese Test (also auch kein ffrm !). Es kann auch vorkommen, dass die Initialisierung der Fat durchläuft, aber keine sinnvollen Daten enthält. Dann würde sich z.B. ffrm ziemlich aufhängen. Würde zu Deinem Problem Passen. Wäre aber zurückzuführen auf die Falsche Vorgabe des Schalters "superfloppy" in fat.h Grüße Daniel
Datum:
Hallo Daniel, ich hab den Parameter SUPERFLOPPY mit beiden Einstellungen ausprobiert und versucht einer vorher unter Windows erstelle TEST.TXT nur zu lesen und auf dem Terminal darzustellen. Bei einer Einstellung ist der Bootvorgang nicht beendet worden: Boot... und es wurde auch nichts weiteres angezeigt. Mit der anderen Einstellung wurde der Bootvorgang abgeschlossen und das ganze Terminal wurde mit irgendwelchen Daten vollgeschrieben. Unter Linux hab ich noch nicht formatiert. C.Alex
Datum:
Hallo, kann ich absolut nicht bestätigen. Hast du irgendwo den Code geändert? Habe nochmal alles durchgesehen und getestet, dabei ist mir noch ein anderer Bug aufgefallen..in Zusammenhang mit ffseek und dem überschreiben von Daten. Sonst ist da alles im grünen Bereich ! Grüße Daniel
Datum:
Hallo! Ich bin begeistert von der Lib! Wer hätte gedacht, dass das SD-benutzen so einfach wird? =) Alles funktioniert soweit ok. Zum Testen habe ich eine AgfaPhoto 1GB genommen. Ich schreibe mit einem Delay von 10ms 2000 uint_16t Werte und ihre Nummer als String auf eine Textdatei. Geht sauber und schnell. Allerdings scheint es so, dass ich nochmal warten muss (ich hab jetzt 100ms) bevor ich ffclose aufrufe, da sonst die Datei nicht vollständig ist. Vermutlich wegens des Hardware SPI? Vielleicht könnte ffclose selbst solange warten, bis die Datei komplett ist! Bei mir gings auch auf einer 16MB FAT12 Karte, aber da gab es Probleme mit dem Schreiben (hatte keinen delay vor ffclose(), aber es fehlten am Ende 400 Werte!). Zudem wurden andere Dateien durch das Schreiben der Werte verändert. Ich kann ja mal das Image schicken, wenn Interesse für FAT12 Support besteht. (Und mir jemand erklärt, vo unter dev die Datei für meinen SD-Leser steht...) Danke für deine Mühen! StrangeMan PS: Verwende 0.5.2
Datum:
Hallo, also die SPI Routinen sind blockend geschrieben, die warten solange bis das Byte das geschrieben werden soll auch raus ist. Deshalb ist ein delay unnötig. Wenn es aber mit einem delay klappt, klingt das für mich eher so, als ob die SPI Strecke anfällig ist. Vielleicht schwingt da was mit oder so (und beruhigt sich bei einem delay?!?)... Wie steuerst Du die Karten an? Direkt oder über irgendwelche Pegelwandler? Komme momentan nicht richtig zum weiter entwickeln. Was aber definitiv geht ist einfaches lesen und schreiben ohne die etwas ausgefalleneren Funktionalitäten wie ffseek() und überschreiben von Daten. Wobei ffseek() an sich tadellos funktioniert, nur in Zusammenhang mit ffwrite() und dem überschreiben welches über einen Sektor hinaus geht gibt es Probleme, da dann ja der Sektor in dem man jetzt weiter überschreiben möchte noch geladen werden muss... Grüße Daniel
Datum:
Noch zum Thema Zeilenumbruch: Wichtig ist das die Angabe der Zeichenanzahl beim Schreiben auf die SD-Karte!!!! "\r\n" sind nur 2 Zeichen nicht 4!!!!! Bei der Angabe, das es 4 Zeichen sind, werden die letzten 2 Zeichen (nach dem Zeilenumbruch)irgendwelcher Käse. Meist sind da 4ecke enthalten, oder der Inhalt anderer Daten.
Datum:
Hallo ich möchte diesen Thread nicht verwässen und habe deshalb einen neuen Thread gestartet. Wie sieht es mit der Lebensdauer der Karte aus, wenn man pro Sekeunde kleine Einheiten schreibt? Ist das unsinnig? Wie sollte man da vorgehen? MfG Achim siehe ==>Beitrag "SD Card GPS Logger optimieren?"
Datum:
Hallo. @Onit Da ein '\n' halt auch nur ein Char/Byte ist, wird da schon nix doppelt gezählt.. @Sucher Bei meiner Lib werden halt immer 512 Bytes zwischengespeichert, da auch immer 512 Bytes direkt auf die Karte müssen. Daher ist die Langlebigkeit genau so, als wenn ein Pc auf die Karte schreibt...Nur das der vielleicht noch bisschen mehr Puffert als es mit einem MC möglich ist.. Grüße Daniel
Datum:
Hallo @Daniel das heißt, wenn ich kleinere Einheiten als 512 Byte schreibe wird das in deinem Interface gepuffert? Muss man da beim Schreiben dann die Bytegrenzen (512 Byte Blockung) als Anwender beachten? Es wird also solange gepuffert bis 512 Byte erreicht sind. Wenn ich nun einen String schreibe der über die 512 Byte geht wird dann ein 512 Byte String auf die SD Karte geschrieben und der Rest gepuffert? Wenn nur gepuffert wird ist der Schreibvorgang schneller, als wenn eine Blockgrenze überschritten wird und auf die SD geschrieben wird. Wie lange dauert dann dieser Aufruf (klar Proz abhängig)? Wird bei jedem Blockschreiben die FAT auf der SD Karte aktualisiert? Falls ja wäre das ja der kritische Punkt mit dem "kaputt" gehen der SD Karte, oder wird nur beim Schließen des Files aktualisiert? Fragen über Fragen... Vielen Dank Achim
Datum:
Hallo Sucher, ja richtig. In der Lib gibt es einen 512Byte Puffer. Ist dieser voll, wird die Karte mit diesen Bytes beschrieben. Erst bei ffclose() erfährt der Dateieintrag und die Fat eine Aktualisierung. Es werden immer freie Cluster in einer Reihe gesucht, ist diese Anzahl voll, so werden diese auch schon in der Fat verkettet. Wird erst zum Problem, wenn die Fat total fragmentiert ist... Eine Datei bei FAT-Dateisystemen ist Quasi in 3 Teile aufgeteilt: 1. Datei Eintrag mit Name,länge usw in einem Ordner. 2. FAT Einträge 3. Die Daten selber Siehe auch: http://www.mikrocontroller.net/articles/AVR_FAT32 Wer mag kann mit "int i=file.cntOfBytes;" abfragen wie viele Bytes in dem Puffer schon geschrieben sind. Bei 512 wird auf die Karte geschrieben... Wie lange jetzt genau das schreiben eines 512Byte Blocks dauert müsste man mal testen :) Ebenso wie lange es dauert neue freie Cluster aus der Fat zu suchen oder solche Cluster zu verketten... Grüße Daniel
Datum:
Hallo @Daniel noch ne Frage(n): Kann man beim Öffnen ne Dateigrösse angeben, dass die entsprechenden Cluster gleich vekettet werden, ohne dass man da explizit reinschreibt? Oder geht das mit ffseek übers Dateiende hinaus...wird dann reserviert, oder darf bei ffseek der Offset nicht übers Dateiende rausgehen? Gibts dafür ne andere Möglichkeit? Vielen Dank Achim
Datum:
Moin, also ffseek() darf auf keinen Fall über das Dateiende hinaus. Gilt nur für innerhalb einer Datei, bis zum letzten Byte. Also vorher die Datei Größe bestimmen? Wieso? Wäre schon machbar, mir erschließt sich aber nicht der Grund wieso man das machen sollte. Wenn es um Geschwindigkteit geht, einfach dafür sorgen, dass die Fat nicht fragmentiert ist. dann könnten bis zu 65000 Cluster am Strück mit Daten voll gemacht werden, bevor diese verkettet werden müssen (müsste man nur 2 Zahlen in der Lib ändern). Mal mit Zahlen: 4 Sektoren Pro Cluster. 512 Bytes Pro Sektor. 65000 Cluster. Macht 126,95 Mega Bytes am Stück, ohne etwas mit der Fat oder dem Dateieintrag machen zu müssen :) Bei 65000 Clustern, die in der Fat verkettet werden müssen, müssen 508 Fat Sektoren geschrieben werden, macht 206096 Bytes. Also etwa 254 KBytes. Die bekommt man so in etwa 2 Sekunden beschrieben... Grüße Daniel
Datum:
Hallo @Daniel ich bin eben dabei die einzelnen Implementierungen abzuklopfen. In der Implementierung von Roland Riegel wird sowas diskutiert, dass man am Anfang gleich einen großen File allokiert weil sonst das Anfügen lange dauert. zB.:Beitrag "Re: MMC/SD-Karte mit FAT16 an AVR" Ich muß halt mal damit spielen und Erfahrungen sammeln... Vielen Dank Achim
Datum:
Hi Achim, den Code von Roland versteh ich teilweise nicht genau. Aber generell dauert es halt ein bisschen die Fat zu updaten und neue freie Cluster zu suchen. Zuerst hatte ich da auch eine etwas sperrige Methode. Jetzt geht das total schnell, wenn halt die Fat nicht groß fragmentiert ist. Wenn du da irgendwo Vorteile/Nachteile siehst, könnte man das ja mal zusammen tragen und als Vergleich ins Wiki stellen... Grüße Daniel PS: hab mich da oben bei einer Ziffer vertan, muss natürlich 260096 Bytes heißen^^
Datum:
Ich habe noch ein Problem. file.length ist bei mir negativ (-492). Es ist aber eine Datei geöffnet und ich kann ganz ordentlich daraus lesen.
Datum:
Angehängte Dateien:Hallo, sehr seltsam. Wie kommst du denn auf -492 ? Weil eigentlich dachte ich das ein "unsigned long int length" (siehe fat.h) niemals negativ werden kann. Lässt du dir das vielleicht falsch anzeigen? Nimm mal die neue Version, vielleicht wirds dann besser. Hab jetzt auch die bekannten Bugs beseitigt. Es gibt 2 neue Schalter in der fat.h. 1. OVER_WRITE Gibt an ob die Datei überschreiben Funktionalität mit Kompiliert wird. Da wenn überschrieben wird auch immer der zu überschreibende Sektor geladen werden muss, ist meine Empfehlung "OVER_WRITE 0" zu setzen und auf überschreiben zu verzichten. 2.MAX_CLUSTER_IN_ROW Gibt an wie viele verkette bzw. leer Cluster für eine Datei gesucht werden, maximaler Wert, 65 534. Grüße Daniel
Datum:
Inzwischen habe ich es herausgefunden: warum der unsigned long int nun negativ war weiß ich nicht, aber deine Lib hat mir die Datei 4GB groß gemacht, obwohl die Karte nur einen GB hat... nun gehts aber.
Datum:
Angehängte Dateien:Hallo, ja das mit der Dateigröße ist mir dann doch noch klarer geworden. Unter Umständen waren auf file.length noch alte Daten vom durchsuchen von alten Ordnern... hatte da aufgrund von Codegröße alles mögliche gekürzt ^^ Da überschreiben von Daten so kompliziert ist und deshalb relativ langsam, gibt es 2 Funktionen zum schreiben, die über den schon erwähnten Schalter OVER_WRITE in fat.h wahlweise mit ein Kompiliert werden können. Der Code ist diesmal wirklich stabil, da ich ausgiebig Zeit zum testen hatte. Anregungen und Tipps immer willkommen. Als Anhang die neue Version mmc-0.5.3 Es ist dringend zu empfehlen, entweder die Version mmc-0.4.8 oder die neue zu benutzen ! Grüße Daniel
Datum:
Wiki auch geupdatet. Vor allem "Interne Technik" http://www.mikrocontroller.net/articles/AVR_FAT32
Datum:
Hallo @Daniel mal ne blöde Frage "Wann wird eine FAT fragmentiert"? ..doch nur wenn ich eine Datei schließe ne neue öffne und schreibe schließe und die alte Datei öffne und was dran hänge... oder eine Datei lösche und ne neue mit verschiedener Größere schreibe? Macht es da nicht Sinn (meine oben gestellte Frage) dass man beim Öffnen oder seek die Deitei auf eine bestimmte grösse aufblähen kann ohne reinzuschreiben? MfG Achim
Datum:
Hallo Achim, eine Fat fragmentiert, wenn man Daten löscht. weil da wo vorher die Cluster einer Datei in der Fat verkettet waren, nun Cluster frei sind. Die von Dir beschriebenen Probleme sind dann nur die Folge draus... Das Problem ist, ich möchte die Lib so allgemein wie möglich halten. Natürlich müsste man, wenn etwas sehr Zeitkritisch ist testen und ggf. die Lib anpassen. Oder sogar alles auf eine spezielle Gegebenheit umschreiben und zusammen kürzen. Mir geht da z.B. eine Einzige Funktion durch den Kopf, die eine ganze komplett vordefinierte Datei schreibt oder ähnliches... Das mit dem vorher allozieren wäre garkein Problem, nur ich gehe mal davon aus, nicht vorher zu wissen wie lang eine Datei wird. Vielleicht baue ich noch ein, dass man beim schreiben immer mindestens MAX_CLUSTERS_IN_ROW freie bekommt. Und/Oder eine Funktion, die die letzte Datei in der Fat ermittelt und erst danach mit schreiben anfängt. Grüße Daniel
Datum:
Hallo,
ich versuche gerade den Code zu verwenden, leider ohne den gewünschten
Erfolg. Ich habe die letzte Version benutzt und momentan sieht mein Code
so aus:
[c]
int main (void)
{
//wdt_enable(WDTO_1S);
sei();
initUart();
sendEOL();
uartPutS("Serveur de temps");
sendEOL();
if(mmc_init() == 0)
{
uartPutS("SD-Card Inizialisation failed.");
sendEOL();
while(1) {};
}
uartPutS("SD-Card initialized.");
sendEOL();
if (fat_initfat() == 0)
{
uartPutS("FAT initialized.");
sendEOL();
char datei[12]="test.txt";
fat_str(datei);
switch (ffopen(datei ))
{
case 1:
{
uartPutS("Existing file opened.");
sendEOL();
}
case 2:
{
uartPutS("New file created and opened.");
sendEOL();
}
default:
{
uartPutS("Cannot create or open file.");
sendEOL();
}
}
ffwrites((char*)"Hallo Datei :)");
ffwrite(0x0D);
ffwrite(0x0A);
uartPutS("Data written to file.");
sendEOL();
ffclose();
uartPutS("File closed.");
sendEOL();
}
while(1) {};
}
[\c]
Die Initialisierung klappt, nur beim ffopen() bzw genauer in der Routine
unsigned char fat_loadFileDataFromDir(char name[]) hängt der Prozessor
sich auf. Nach meinen bisherigen Nachforschungen sind die ausgelesenen
Sektoren alle '0' und der Prozessor hängt. Auf dem SPI-Bus ist nichts
mehr los. Was mich wundert: Die Karte wird als FAT32 erkannt, auch wenn
sie auf FAT16 formatiert wurde. Ich habe sowohl FAT32 als auch 16
ausprobiert und auch SUPERFLOPPY geändert, ohne Erfolg.
Hat jemand eine Idee, woran es liegt?
Datum:
Ok, die Initialisierung läuft irgenwie auch nicht: Selbst ohne Karte läuft mmc_init() durch... :-(
Datum:
Hallo, also besser ist sowas für mmc_init() :
while (mmc_init() !=0){ ; } |
Da es sein kann das es etwas dauert bis die Karte "anspringt". Sieht sonst OK aus. Vielleicht mal den SPI Takt bisschen runter setzen. Wie hast du die Karte angeschlossen? Grüße Daniel
Datum:
Der SPI-Takt liegt bei etwa 120kHz, die Karte ist direkt an einen Atmega644p angeschlossen, der mit 3,3V läuft. Ein Pull-Up an DO ist dran. Deinen obigen Vorschlag habe ich schon umgesetzt, aus der Schleife kommt der Controller bzw. die Karte nicht raus. Ich lese mir mal die Bedienungsanleitung meines Logigports durch...
Datum:
Mit mmc_init() hatte ich bis jetzt nur Probleme, wenn die Kabel zur Karte zu lang waren, aber bei 120KHz dürfte das kein Problem sein. Vielleicht mal andere Karten ausprobieren, Schaltung überprüfen sonst hab ich keine Ahnung wieso die mmc_init() nicht durchläuft. Hm über was wird die Karte mit Strom versorgt? Da können Peaks bis zu 60mA auftreten, und Ripple auf der Versorgungsspannung ist auch schlecht... Mach doch mal ein Foto von der Schaltung :) Grüße Daniel
Datum:
Hallo Daniel, vielen Dank fuer die Tipps. Auf so einen Mist muss man erst einmal kommen: Der SD-Kartenhalter von ALPS hatte an zwei Pads keinen Kontakt... Da der groesstenteils geschlossen ist, kam man da nicht ran. Das ganze hat lich jetzt eine 2GB-Karte gekostet, aber die sind ja guenstig inzwischen. Jetzt habe ich gerade meine erste Datei angelegt und beschrieben. Wenn der Rest auch so gut laueft, waere das sehr cool. Danke fuer die Bibliothek. :-)
Datum:
Hi, schön, dass es jetzt klappt, schade das ne Karte drauf gegangen ist ^^ Aber sowas kurbelt ja die Konjunktur an :) Grüße Daniel
Datum:
Moin, ich bin grade dabei deine Bibliothek zu testen. Ich habe hier 3 SD-Karten liegen (1x 128MB, 1x 256 MB von toshiba und 1x 2GB von san disk), allerdings gibt es Probleme beim Schreiben. Mein Prozessor ist ein AT90CAN128, welcher mit 3,3V läuft und vom internem Takt versorgt wird. Hier eine genauere Fehlerbeschreibung: -Lesen geht. -Löschen von Dateien geht. -Anlegen einer nicht vorhandenen Datei geht nur jedes 2. mal, wobei die Funktion nie zurückkehrt, egal ob eine Datei auf der SD-Karte angelegt wurde oder nicht. -Schliessen einer Datei, bei der sich Daten geändert haben geht nicht, es werden also nie Daten geschrieben. Alle Schreibversuche auf die SD-Karten enden damit, dass der Prozessor sich dauerhaft mit der SD-Karte unterhält, welcher Befehl übers SPI läuft kann ich leider nicht sagen. Die SD-Karten habe ich zwischendurch immer wieder mit Windows auf FAT32 formatiert. Die Einstellung SUPERFLOPPY habe ich sowohl gesetzt, als auch nicht gesetzt probiert. Eine genauere Beschreibung kann ich mangels JTAG-Interface leider nicht geben. mfg Emperor_L0ser
Datum:
Hallo, hast du irgendwo den Code geändert? Wie rufst du die Funktionen auf? Versuchst du zu überschreiben? Dann muss "OVER_WRITE 1" und "WRITE 1" gesetzt sein. Grüße Daniel
Datum:
ach äh welche Version benutzt du? 0.5.3 ?
Datum:
Moin, ja ich habe den Code geändert, dies beschränkt sich allerdings darauf, dass ich alle Variablendefinitionen aus den for-Schleifen entfernt und an den Anfang der Funktion gepackt habe (ANSI-C99 Standard, mein avr-gcc meckerte). Der AT90CAN128 ist von den Definitionen mit dem ATMega128 kompatibel, ich musste dort nichts ändern. Ich verwende Version 0.5.3 und die Dateien, die dort nicht enthalten sind (main.c, mmc.c und mmc.h) verwende ich aus 0.5.2. Aufrufen tu ich nur die Funktionen, welche in der Beispiel-Funktion der main.c sind. Write ist die ganze Zeit auf 1, sonst sind die Funktionen ja garnicht vorhanden. OVER_WRITE habe ich sowohl gesetzt als auch ungesetzt versucht. mfg Emperor_L0ser PS: ich verwende nicht die Makefile, meine Befehle, wie für alle meine Projekte: if avr-gcc -O2 -mmcu=at90can128 -DF_CPU=1000000 ./*.c then avr-objcopy -O ihex -R .eeprom a.out flash.hex avrdude -p c128 -e -c pony-stk200 -U flash.hex exit 1 fi
Datum:
Hallo, da liegt das Problem, es gibt Funktionen, da muss man noch Code ergänzen, damit man die Definitionen nach oben schreiben kann. Versuch mal dem avr-gcc "-std=gnu99" beizubringen. Dann einfach die Original fat.c und file.c dann läufts... Grüße Daniel
Datum:
Ich hab es jetzt so gemacht, wie du gesagt hast und es läuft, schonmal Danke dafür. Den ersten Teil deiner Antwort versteh ich nicht ganz. Ich würd vor allem den Code gerne auch so schreiben, dass er ANSI-C Konform ist, da ich ja nicht weiss, ob ich drei Jahren noch den GCC-Compiler verwende. mfg Emperor_L0ser
Datum:
Ich bin es von C# und Java gewöhnt überall Variablen zu definieren und Deklarieren, is schön bequem, aber is halt kein ANSI-C von 1986... Eigentlich sollte jeder halbwegs gute Compiler auch ANSI/ISO-C99 können, egal. Hab grad den Code nicht vor Augen, aber man müsste Teile umschreiben, damit man die Definitionen an den Anfang der Funktionen setzen kann. Musst dir mal genau anschauen was da gemacht wird. Grüße Daniel
Datum:
Hallo Daniel, ich habe die Lib zwar noch nicht getestet, scheint aber recht interessant für mich zu sein. Ich frage mich allerdings, wie ich den Inhalt des Directories weiter verarbeiten kann. Eine Ausgabe auf die serielle Schnittstelle hilft mir nicht weiter (ffls), da ich es auf einem direkt angeschlossenen Display ausgeben möchte. Aus einem anderen Beispiel kenne ich zwei folgende Funktionen: * Ermittlung der Anzahl der Directory Einträge * Ermittlung des Namens des x-ten Directory Eintrages Können die beiden Funktionen mit den bereits vorhandenen gebildet werden? Ich habe da nach Durchsicht Deiner Funktionen aber noch keinen Ansatzpunkt gefunden. Wäre es aufwendig, diese beiden Funktionen noch einzubringen? Ggf. könnte ich auch Tips gebrauchen, wie das anzugehen wäre. Für mich wäre das aber recht zeitaufwendig, da ich in C noch nicht so firm bin. Würde ich aber versuchen anzugehen. Danke und Grüße Ralf
Datum:
Hallo Ralf, wäre nicht sonderlich schwierig. Mit den beiden vorhandenen Funktionen könnte man so etwas schon realisieren, komme ich aber momentan nicht dazu. Als Hinweis wenn du da selber schonmal was machen willst, "lsRowsOfClust (unsigned long int start_sec)" geht durch alle Zeilen eines Clusters, ab dem Sektor start_sec. "ffls(void)" geht dann durch alle Cluster eines Ordners. Somit hat man beide logischen Strukturen abgearbeitet... Will man jetzt wissen an welcher "Zeile" welcher Eintrag steht, müsste man einen Zähler haben, der von lsRowsOfClust hochgezählt wird, bis man an gewünschter Zeile ist. Will man wissen wie viele Einträge es gibt, würde es reichen anstatt einer Ausgabe einfach mit zu zählen, wie viele Einträge ausgegeben werden würden. Grüße Daniel
Datum:
Hallo Daniel, vielen Dank, Anzahl der Dateien (über ffls) sollte wirklich gar kein Problem sein. Das andere muss ich mal sacken lassen :) Werde ich mir die Tage mal anschauen. Grüße Ralf
Datum:
Moin, die Lib hat mir viel Arbeit erspart. Habe sie ohne größere Schwierigkeiten auf einen MSP430 portieren können. Mir ist dabei nur eine Sache aufgefallen. Die Initialisierung der FAT erfolgt ja in Abhängigkiet ob "SUPERFLOPPY" 0 oder 1 gesetzt ist. Es ist aber schlecht vorherzusagen ob in das fertige Gerät eine Karte eingesetzt wird, die ein Superfloppy ist oder aber eine Partition enthält. Habe die Initialisierung mal so geändert, das automatisch ermittelt wird ob ein Superfloppy vorliegt.
//Sektor 0 lesen if(0==SDC_Read_Block(SDC_READ_SINGLE_BLOCK, 0, 512)) { vSecOfFirstPartition = (char*)&secOfFirstPartition; //Startsektor bestimmen *(char*)vSecOfFirstPartition++=fat.sector[454]; *(char*)vSecOfFirstPartition++=fat.sector[455]; *(char*)vSecOfFirstPartition++=fat.sector[456]; *(char*)vSecOfFirstPartition++=fat.sector[457]; //Prüfung ob man schon im VBR gelesen hat (0x6964654d = Medi) if(secOfFirstPartition==0x6964654d) return fat_loadFatData(0); //Superfloppy liegt vor else //FAT-Daten aus dem ersten Sektor der Partition lesen return fat_loadFatData(secOfFirstPartition); } return (1); |
Wenn man also eine Karte ausliest und man ist gleich im VBR, dann liest man ja innerhalb dieses Abschnittes: "Datentr„ger entfernenÿ Medienfehlerÿ Neustart: Taste drcken". An den Positionen 454 - 457 steht "Medi", was der Sektoradresse 1768187213 entspricht. Diese Sektoradresse gibt es bei keiner bisher verfügbaren SD - Karte, weshalb man damit auf Superfloppy prüfen kann. mfg Michael
Datum:
Hallo, sehr schön. Hatte ich auch immer mal vor das einzubauen, bin aber nicht dazu gekommen. Wird in die nächste Version aufgenommen. Grüße Daniel
Datum:
Hallo zusammen, das mit dem veröffentlichen für MSP wird wohl nix werden ^^ Anzupassen wären aber ja eigentlich nur die mmc low level Routinen. Also die SPI Geschichten. Hab leider keine Ahnung vom MSP daher schwer abzuschätzen wie viel Arbeit das wirklich ist... Grüße Daniel
Datum:
Moin, die meiste Arbeit haben die Routinen für das Lesen und Schreiben der SD-Karte gemacht (wegen neu schreiben und so). Bei den FAT- und Dateifunktionen habe ich erstmal nur die Void-Pointer (die ICC430 Version die ich nutze kann damit nicht um), die ganzen Zählvariablen angepasst und natürlich die Funktionsaufrufe der Low-Level-Routinen geändert. Eben um zu sehen ob es funktioniert. Und es funtkioniert. Weitere Anpassungen sind sicherlich noch möglich, mach ich irgendwann auch noch. Michael
Datum:
Angehängte Dateien:Hallo zusammen, hier mal eine neue Version, gab da noch Bugs... Zudem ist die SPI schreiben Routine schneller geworden. Generell kompakterer Code. Viel Spaß damit :) Grüße Daniel
Datum:
Angehängte Dateien:Und hier noch der Wiki Artikel als PDF, zum offline lesen :)
Datum:
Hallo, zuerst einmal ein Dank an Daniel dafür, dass er seinen Code hier veröffentlicht hat. Ich möchte sein Beispiel nun bei mir lauffähig bekommen, es funktioniert aber nicht. Auf der UART-Ausgabe sehe ich, dass nach mmc_init() nichts mehr passiert, es muss also ein Fehler in fat_initfat() auftreten. Ich verwende eine microSD Karte mit 128MB, die ich per Windows als FAT formatiert habe. Wo müsste ich wohl ansetzen um den Fehler zu finden?
Datum:
Hallo, wie ist denn die Karte am Controller angeschlossen? Hast Du etwas am Code geändert? Du siehst auf dem Terminal "Boot..." und das OK fehlt? Man sollte wenn alles richtig initialisiert wird ja "Boot...OK" sehen. Wenn das OK fehlt hängt sich das Programm tatsächlich beim Fat auslesen auf. Interessant wäre da der Sektor 0 der Karte. Oder Du könntest einfach mal probieren ob es FAT32 Formatiert klappt, ich glaube bei Windows bedeutet nur Fat FAT16 und sonst halt FAT32. Grüße Daniel
Datum:
Angehängte Dateien:Da ich einen atmega328p verwende, habe ich die mmc.h verändert. CLK von der Karte habe ich über einen HEF4050 mit SCK am µC verbunden, DI auch über HEF4050 an MOSI, CS mit pull-up über HEF4050 an PB1 und DO mit pull-up direkt an MISO. An anderen Stellen habe ich nichts im Code verändert. Ja es erscheint wirklich nur Boot... . Im Anhang ein Bild vom Sektor0, nach dem Versuch darauf zu schreiben.
Datum:
Hallo, also die Karte ist unpartitioniert. Versuch mal folgenden Code, damit man feststellen kann ob es an der fat_initfat() liegt oder schon woanders hakt.
void main(void){ char tmp[10]; uinit(); uputs((unsigned char*)"\nBoot"); while (mmc_init() !=0){ ;} uputs((unsigned char*)"... "); fat_loadFatData(0); // läd fat daten ultoa(fat.rootDir,tmp,10); uputs(tmp); uputc(' '); utoa(fat.secPerClust,tmp,10); uputs(tmp); } |
Jetzt müsste wenn alles funktioniert, "Boot...2 2" zu sehen sein. Wenn dem so ist muss ich mir die fat_initfat() nochmal genauer anschauen. Wenn nicht, liegt das Problem irgendwo ganz anders. Da würde ich eher auf ein Hardware Problem schließen. Im Datenblatt von dem HEF4050 steht nichts von Versorgungsspannung ab 2 Volt wie bei dem HC4050, was bei niedrigeren Frequenzen vielleicht noch klappt aber dann nach der Karten Initialisierung mit vollem SPI speed nicht mehr... Grüße Daniel
Datum:
Als Ausgabe erhalte ich "Boot..." und manchmal "Boot... 0 0" und einmal wurde sogar die txt-Datei erstellt, es liegt also an der Hardware. Eine 2Gb Karte habe ich damit wohl schon zerstört, zumindest reagiert Windows nicht mehr, wenn ich die Karte einlege. Aber das die Karte unpartitioniert ist verstehe ich nicht, habe es im Arbeitsplatz per Rechtsklick und dann auf Formatieren formatiert. Ich werde dann mal die 74HC4050 von reichelt bestellen und alles neu aufbauen. Schonmal danke für die schnelle Hilfe.
Datum:
Mir ist noch keine einzige Karte kaputt gegangen bei meinen Tests. Ich nehmen aber auch immer sofort den Strom weg, wenn was unvorhergesehenes passiert. Unpartitioniert ist ja nicht unformatiert. Keine Ahnung warum Windows mal ne Partition erstellt und mal nicht. Glaube bei kleineren Karten wird nicht partitioniert und bei größeren schon. Du könntest aber auch mal den SPI speed runter setzen und schauen ob es dann mit deiner Hardware stabiler läuft. Einfach in der mmc.c in der Funktion mmc_init () die Zeilen
//SPI Bus auf max Geschwindigkeit SPCR &= ~((1<<SPR0) | (1<<SPR1)); SPSR = SPSR|(1<<SPI2X); |
auskommentieren. Bei deiner Karte die nicht mehr funktioniert, könnte es sein das die mehr als 3,3 Volt abbekommen hat? Mach doch mal ein Foto von der Schaltung :) Grüße Daniel
Datum:
Es liegt tatsächlich an dem Speed der SPI, habe es wohl etwas zu frei aufgebaut^^, aber jetzt funktioniert es endlich . DANKE;-)
Datum:
Schön das es jetzt läuft :)
Datum:
Unterstützt das Programm auch Software SPI oder muss man den Hardware SPI nutzen?
Datum:
ich glaube nur hardware SPI, aber eine software SPI kann man relativ leicht implementieren.
Datum:
Angehängte Dateien:ungetest stelle ich hier mal die software SPI rein.
Datum:
Angehängte Dateien:Dieses Mal hoffentlich ohne Fehler.
Datum:
Hallo mal wieder!
Ich bastel im Moment wieder mit dem SD-Code rum. Soweit alles in
Ordnung. Allerdings ist file.seek bei mir immer Null. Das darf aber
eigentlich nicht sein. Mein Code:
########################################################################
#
int main(void) {
char *tag;
char *value;
char s[10];
lcd_init();
lcd_clear();
sd_init();
lcd_clear();
tag = malloc(30);
value = malloc(30);
char mfile[] = "testdat.txt";
fat_str(mfile);
ffopen(mfile);
// Länge der Datei ausgeben
lcd_string("L: ");
lcd_string(itoa(file.length, s, 10));
lcd_set_cursor(0,1);
// Position ausgeben
lcd_string("S: ");
lcd_string(itoa(file.seek, s, 10));
_delay_ms(2000);
while (file.seek <= file.length) {
tag[0] = '\0';
value[0] = '\0';
lcd_clear();
tpx_read_tag(tag, value);
lcd_string("T: ");
lcd_string(tag);
lcd_string("; S: ");
lcd_string(itoa(file.seek, s, 10));
lcd_set_cursor(0,1);
lcd_string("V: ");
lcd_string(value);
_delay_ms(1000);
}
ffclose();
while(1);
return 0;
}
########################################################################
#
tpx_read_tag ist eine funktion von mir, die eine Art pseudo-xml
realisiert nach dem Muster <tagname=wert>.
Ich brauche file.seek, damit das Auslesen irgendwann mal aufhört.
Noch etwas, ich bekomme warnings:
"./sd/fat.c:96: warning: left shift count >= width of type"
Bis denn dann,
StrangeMan
PS: Am Software-SPI wäre ich auch sehr interessiert! =)
Datum:
Hallo, also so ist file.seek nicht gedacht. Es wird beim lesen garnicht verwendet. Wenn du bis zum Datei Ende lesen möchtest ist die schnellste Variante:
unsigned long int seek=file.length; do{ code zum lesen... }while(--seek); |
Da so nur geprüft wird ob seek==0 ist als Abbruchbedingung... Zu dem angesprochenen warning, das hab ich auch, allerdings "nur" beim avr-gcc, dem normalen gcc macht das nix. Also hat keine Probleme gemacht bei mir. Und den left shift muss man so machen... Grüße Daniel
Datum:
Und wenn ich in dem Moment gar nicht weiß, wo sich der "Cursor" in der Datei befindet? Hmm, da bleibt mir wohl nichts übrig als mir eine globale Variable zu machen, die mitloggt, wo ich bin.
Datum:
Wie wäre es mit der Variablen seek aus meinem Beispiel? Ich habe extra darauf verzichtet in ffread() eine 32 Bit variable wie file.seek bei jedem einzelnen Byte das gelesen wurde zu ändern...das würde bremsen! Besser ist es da die Laufindex Variable (aus dem Beispiel eben, seek) beim Aufruf von ffread() zu benutzen. Wozu genau willst du denn die exakte Position in der Datei wissen? Und wie gesagt, was spricht gegen die Variable seek? Grüße Daniel
Datum:
Hmm, ich hab ein Menüsystem, was auf Basis oben genannter Pseudo-XML-Tags die Menüeinträge ausließt. Wenn ich eine Funktion habe, die nur einen Tag auslesen soll, dann hat die ja keine Ahnung, wo in der Datei sie auszulesen beginnt, wenn ich sie aufrufe. Sie darf aber dennoch nicht über das Dateiende hinauslesen. Wenn ich das so amche, wie im Code oben, dann kann es ja sein, dass sie erst beim 100ertsten Byte anängt zu lesen, weil der "Cursor" da grade war. Dann würde sie 100 Bytes üebr das Dateiende hinauslesen. Was da bei rauskommt habe ich schon gesehen... Zufallsdatan - mehr oder weniger. Aber ich habs jetzt so gelöst, dass ich einfach mitlogge, wo ich bin. Bei jedem ffread() oder ffseek() aktualisiere ich meine globale Varable eben. Das Geschwindigkeitsproblem ist natürlich ein Argument. Aber eventuell kann man so eine Seek-Variable als Compilerschalter mit einbauen. Dann kann man's aktivieren, wenn es benötigt wird. Ich denke, für komplexere Dinge ist sowas schon von Nöten. StrangeMan
Datum:
Ok, überlege ich mal wie man sowas elegant machen kann. Du könntest ja aber einfach file.seek benutzen anstelle deiner globalen variable. Wie das dann mit der Geschwindigkeit aussieht müsste man mal sehen. ffseek() updatet dir file.seek ja auch wenn du vor oder zurück spulst. Kleines Beispiel:
for(file.seek=0;file.seek<file.length;file.seek++){ //code zum lesen... //eventuell sogar ffseek() da dies ja file.seek auch updatet... } |
Grüße Daniel
Datum:
Angehängte Dateien:Hallo mal wieder. Ich hab die mcc.c/mcc.h von Ulrich Radig rausgekramt und den Software-SPI-Modus von ihm wieder übernommen. Allerdings ... naja, es klappt nicht, und ich weiß nicht, obs an meiner Hardware oder am Code liegt. Ich hab meine Version der mcc.c mal angehängt. Eigentlich kann man ja nichts falsch machen. Offensichtilich aber doch... StrangeMan
Datum:
Angehängte Dateien:Ohje, entschuldigt. Die Zeile, in der der Hardware-SPI eingerichtet wird, gehört natürlich entfernt. (nach Zeile 50: stattdessen
#if SPI_Mode //Aktiviren des SPI - Bus, Clock = Idel LOW //SPI Clock teilen durch 128 SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode #endif |
einfügen). Anbei auch noch meine mmc.h. Die Pins habe ich in einer anderen headerdatei. Sie sind
#define SD_INSIDE_PORT PORTA #define SD_INSIDE_PIN PINA #define SD_INSIDE_DDR DDRA #define SD_INSIDE_Pin PA0 #define SD_WRITEPROT_PORT PORTA #define SD_WRITEPROT_PIN PINA #define SD_WRITEPROT_DDR DDRA #define SD_WRITEPROT_Pin PA2 #define SD_PORT PORTA #define SD_P_IN PINA #define SD_DDR DDRA #define SD_DI PA3 #define SD_DO PA6 #define SD_SCK PA1 #define SD_SS PA7 |
Grüße, StrangeMan
Datum:
Ich könnte mir vorstellen, dass es am Timing liegt, da überhaupt keine delays in der SOFT-SPI sind, vielleicht einfach mal ein paar Pausen einfügen.
Datum:
Ja, danke, das klappt. Da die Routinen so bei Ulrich Radig wohl auch gehen, dachte ich, das wär in Ordnung so. Damit geht's erstmal:
//############################################################################ //Routine zum Empfangen eines Bytes von der MMC-Karte unsigned char mmc_read_byte (void) //############################################################################ { unsigned char Byte = 0; #if SPI_Mode //Routine für Hardware SPI SPDR = 0xff; while(!(SPSR & (1<<SPIF))){}; Byte = SPDR; #else //Routine für Software SPI for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First { SD_PORT &=~(1<<SD_SCK); //erzeugt ein Clock Impuls (Low) _delay_us(1); if (bit_is_set(SD_P_IN,SD_DI) > 0) //Lesen des Pegels von MMC_DI { Byte |= (1<<(a-1)); } else { Byte &=~(1<<(a-1)); } SD_PORT |=(1<<SD_SCK); //setzt Clock Impuls wieder auf (High) _delay_us(1); } #endif return (Byte); } //############################################################################ //Routine zum Senden eines Bytes zur MMC-Karte void mmc_write_byte (unsigned char Byte) //############################################################################ { #if SPI_Mode //Routine für Hardware SPI SPDR = Byte; //Sendet ein Byte while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde { } #else //Routine für Software SPI for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First { _delay_us(1); if (bit_is_set(Byte,(a-1))>0) //Ist Bit a in Byte gesetzt { SD_PORT |= (1<<SD_DO); //Set Output High } else { SD_PORT &= ~(1<<SD_DO); //Set Output Low } SD_PORT &= ~(1<<SD_SCK); //erzeugt ein Clock Impuls (LOW) _delay_us(1); SD_PORT |= (1<<SD_SCK); //setzt Clock Impuls wieder auf (High) } SD_PORT |= (1<<SD_DO); //setzt Output wieder auf High #endif } |
Ob das Timing so ideal ist, sei dahingestellt. Ich werde nochmal die Spezifikationen anschauen, aber das mache ich später. Danke, StrangeMan
Datum:
Angehängte Dateien:Neue Version ! Überarbeitete mmc.c und Optimierung des Codes. Jetzt auch Multiblock Operationen möglich. Wird allerdings nicht von allen Karten unterstützt, daher optional als define wählbar. Neuere Doku wird nachgereicht. Wird wie immer hier nachzulesen sein: http://www.mikrocontroller.net/articles/AVR_FAT32 Grüße Daniel
Datum:
Angehängte Dateien:Daniel, ich hab mir heute mal die neue Version deiner Lib zu Gemüte geführt. Wie auch die alten Versionen funktioniert das auf einem zur Zeit in der Mache befindlichen Alleskönner-Board wie geschmiert. Super Arbeit! Und - wie bereits letztes Jahr - ich hab mal wieder ein paar Ideen, die die Lib noch besser machen könnten. Für mich natürlich :-) 1) Sinnvolle Rückgabewerte Viele Methoden geben unsigned chars für Statusinformationen zurück. Sowas in etwa:
if(2==ffopen("TEST TXT")) { ... } |
Hier würde ich mir defines wünschen, die eben diese Statusinformationen sprechend bezeichnen. Sowas z. B.
#define MMC_FILE_NEW 2 if(MMC_FILE_NEW == ffopen("TEST TXT")) { ... } |
Gibt es eigentlich eine Doku für diese Return-Values? 2) Uart-Funktionen per Config einstellen Das hatte ich mir ja schon oben gewünscht, da ich ansonsten jedesmall die Sourcen ändern muss. 3) Status-Signale der SD-Card Bei den meisten Kartenslots kann man neben den wichtigen Pins auch auslesen, ob eine Karte eingelegt ist und ob diese schreibgeschützt ist. Wär doch schön, wenn wie die Lib von Roland Riegel, das auch berücksichtigt werden könnte. Alle Config-Optionen in eine separate Config-Header-Datei geschrieben sieht dann so aus, wie im Anhang zu finden. Die SPI-Pins etc. ziehe ich mir aus einer globalen Hardware-Header für SPI. Die Defines für die Statusinformationen könnten wohl auch woanders hin. cu, Michael
Datum:
Hallo, bin immer offen für Anregungen :) -1.) Mich hat es Tatsache auch schon öfters genervt das man einer 2 nicht ansieht was es genau bedeutet... werde ich ändern. Störend ist nur, dass z.B. folgendes "define TRUE 1" 2 Byte Ram frisst wenn man "TRUE" irgendwo im Code nutzt. Mir war nie die Idee gekommen "define TRUE '1'" zu machen :) ist dann nur ein 1 Byte ... -2.) Da fällt mit keine tolle Lösung ein, na ja mal sehn... -3.) Ich hab so nen Kartenslot nicht, daher kann ich das schlecht testen, müsste mir mal so nen Slot besorgen :) Software SPI möchte ich dann auch noch mich rein packen ins nächste Release. Grüße Daniel
Datum:
Wie wäre es "True" als Bit anzulegen gegebenenfalls mehrere Bitvarriablen/konstanten zu einem Byte zu fassen?
Datum:
Moin Daniel, > Störend ist nur, dass z.B. folgendes "define TRUE 1" 2 Byte Ram frisst > wenn man "TRUE" irgendwo im Code nutzt. Mir war nie die Idee gekommen > "define TRUE '1'" zu machen :) ist dann nur ein 1 Byte ... Ist dem wirklich so? Bis heute dachte ich, dass defines nur durch den Präprozessor verwendet zum ersetzen herangezogen werden und erst danach der compiler einspringt... Zum Uart: Für dich relevant sind ja nur 3 Infos zum Uart. Include-Statement, uputs, uputc. Ich (als Freund der #defines würde das dann wieder per config-Option lösen. Also:
#define UART_INCLUDE /path/uart.h #define UART_UPUTS uputs #define UART_UPUTC uputc |
und dann im Code die ensprechenden defines statt der echten Namen verwenden. Zu 3 - Status Info: Hier müsste man überlegen, wie weit man wirklich dies durchgängig implementieren will. Reicht es, wenn man entsprechende Methoden zum Abtesten anbietet, den eigentlichen Test aber dann den Nutzer durchführen lässt? Oder nur bei mmc_init()? Oder sollen alle Lese- bzw. Schreiboperationen jeweils isAvailable4() oder isProtected() aufrufen? Letzteres eher nein, so würde ich denken. cu, Michael
Datum:
Angehängte Dateien:Hallo,
hier mal ein kleines Update. Der Code ist nur auf anständige Return
Werte umgestellt. Keine Funktionalen Änderungen.
>Ist dem wirklich so?
Ich dachte immer das wenn man "#define KONSTANTE 1" macht, wird das als
Integer behandelt bei der Erzätzung im Code durch den
Präprozessor...deshalb hab ich die defines jetzt einfach mal alle als
chars gemacht, kann ja nicht schaden ^^
Zum Uart, zufriedener jetzt ?
Hast Du so einen Slot und wärst eventuell bereit die Funktionen zu
schreiben und testen? Ich nehme die dann in die Lib auf. Stimme da
nämlich bei Deine Überlegungen zu.
@Winne
Das müsste man ja dann als struct machen, und ich weiß nicht mehr warum,
aber das ist wohl nicht so toll...
Vielleicht weiß da ja einer warum ?!?
Grüße Daniel
Datum:
Moin Daniel > hier mal ein kleines Update. Der Code ist nur auf anständige Return > Werte umgestellt. Keine Funktionalen Änderungen. Wunderbar. Genau so etwas meinte ich. Wie sieht es bei ffopen im OVERWRITE Modus aus? Wird hier auch OPENED_TO_WRITE zurückgeliefert? > Zum Uart, zufriedener jetzt ? Fast :-) Die Defines wie auch eine globale COnfig-Datei sind klasse. Fehlt nur noch, dass die Quellen mmc.c und file.c auf die neue uart-syntax angepasst werden :) > Hast Du so einen Slot und wärst eventuell bereit die Funktionen zu > schreiben und testen? Ich nehme die dann in die Lib auf. Stimme da > nämlich bei Deine Überlegungen zu. Ich hab so einen Slot und ja, ich könnte dies ausprobieren und entsprechend implementieren. Das ganze würde dann über zwei Funktionen in mmc.h / mmc.c implementiert werden. Nämlich: - u08 mmc_present() - u08 mmc_protected() Diese kann der User nach belieben selber aufrufen. Ausserdem werden diese in mmc_init() mit aufgenommen. Sollte keine Karte vorhanden sein bzw (bei write-Funktionalität) diese schreibgeschützt sein, so werden entsprechende Status-Codes zurückgeben. Das ganze wird natürlich per #define abschaltbar :-) Und je nachdem, ob write-Support drin ist oder nicht, werden nur die erforderlichen Methoden kompiliert. Da ich nur am WoE zum Testen komme kann das ganze aber doch 2 bis max. 3 Wochen dauern. Geht halt nicht schneller cu, Michael
Datum:
Erstmal danke für die Lib, funkt sehr gut bei mir. Nur eines, was es
vielleicht Anfängern erleichtern könnte:
In der mmc.h steht:
#if defined (_AVR_ATmega16_)
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte
angeschlossen ist
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte
angeschlossen ist
...
Der Satz "Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
" drückt, denk ich, das Gegenteil von dem aus, was er sagen soll. Weil
SPI_DI ("Data in") der MOSI pin ist, also der Data Output vom Master und
nicht von der Karte. Vice versa für SPI_DO.
Vielleicht kann man einfach MOSI/MISO/SCK/.... in die Comments
schreiben.
Nur so als Vorschlag.
Danke nochmal,
mik
Datum:
Naja, ich dachte da ist der DataIn der Karte gemeint. Aber MOSI/MOSI wäre sicherlich eindeutiger. Eine globale Configdatei würde ich auch befürworten. Ich habe sie mir für mein Projekt selbst angelegt, weil ich da sehr viele verschiedene Defines habe, die ich zentral editieren können will. Wenn man auch in diesem Code hier eine globale Configdatei macht, ließe sich deren Include-Anweisung einfach rauskommentieren um eine eigene Configdatei zu erwenden. StrangeMan
Datum:
HAllo, falls es wer brauchen kann, oder vielleicht kann man es überhaupt in die Lib aufnehmen: habe ein file-exists geschrieben: für die file.c
unsigned char ffexists( unsigned char name[]){ unsigned char file_flag=fat_loadFileDataFromDir(name); if( file_flag==0 ){return 1;} //Datei existiert! else {return 0;} } |
und für die file.h
extern unsigned char ffexists( unsigned char name[]); |
have fun, MM
Datum:
Hallo, zusammen. @Michael Z. (incunabulum) Ja wäre cool wenn du das so machst mit dem Slot. Eilt auch nicht so ... @StrangeMan (Gast) Die mmc-0.5.5.1.zip hat schon eine solche config.h @ Michael M. (mikmik) Du benutzt nicht die Version mmc-0.5.5.1.zip ? Da ist zwar die Dokumentation in der mmc.h noch nicht auf MISO/MOSI usw umgestellt aber mit den defines ist es einfach übersichtlicher Man könnte das noch etwas verkürzen:
unsigned char ffexists( unsigned char name[]){ return fat_loadFileDataFromDir(name); } |
Und als Abfrage:
if(TRUE==ffexists((unsigned char*)"MAIN C "){ irgendwas machen } |
Da das ja aber eigentlich nur eine Zeile ist und man sich wenn man das direkt machen würde wie z.B :
if(TRUE==fat_loadFileDataFromDir((unsigned char*)"MAIN C "){ irgendwas machen } |
auch eine Funktionsaufruf spart hatte ich das nicht extra geschrieben :) Ist zwar fragwürdig ob man bei sowas sparen muss aber egal. Grüße Daniel
Datum:
Ach ja, was mir da noch einfällt, wenn man im Überschreibenmodus eine Datei öffnet bekommt man auch OPENED_TO_READ zurück. Es gibt die Datei ja schon die man überschreiben möchte. Wenn man sich einmal für OVER_WRITE entschieden hat, kann man wild in der Datei rumschreiben... Grüße
Datum:
Angehängte Dateien:Moin Daniel, hier also die entsprechende Erweiterung deiner Lib. Status-Pins (card present, card protected) werden nun berücksichtigt, so entsprechend in config.h aktiviert. Die wichtigen Änderungen meinerseits findest du nach dem Tag // mz: Die eigentliche Konfiguration erfolgt in mmc.h unten. Dort werden die Pins etc. entsprechend gesetzt. Das ist fast 1:1 von Roland Riegel kopiert. In mmc.c sind dann die entsprechendne Methoden definiert und in mmc_init() eingebunden. Anmerkungen: 0) Ich habe einige zusätzliche Return-Werte mittels Define gesetzt. Das macht die Lib imho lesbar. Fehlt nur noch die Doku :-) 1) FALSE sollte immer (int) 0 sein. Ansonsten ist ein Test über if(someBoolMethod()) nicht möglich, sondern es wird immer ein expliziter Vergleich if(true==...) benötigt. 2) defines: Ich habe mal alle Defines umgeändert, so dass diese immer als Präfix MMC_ aufweisen. Dies ist gängige Syntax, da man hierdurch im Code zumindest erraten kann, welches Define für was herangezogen wird. Oder wüsstest du, woher WRITE kommt, so diese Directive in main() vorkommt? 2b) OPENED_TO_READ und OPENEND_TO_WRITE sind imho nicht ganz korrekt. Siehe die Problemtatik bem überschreiben. Ergo habe ich diese wieder unbenannt zu MMC_FILE_NEW, MMC_FILE_EXISTS. Das trifft die Tatsache besser, denke ich. Comments? cu, Michael
Datum:
Hallo, ja sieht soweit gut aus. In der SdCard.h ist das c++ ? Da steht was von namespace ?!? Hatte jetzt noch nicht die Zeit mir alles mal genauer zu Gemüt zu führen, mache ich aber heute Abend. Zu den defines, FILE_NEW und FILE_EXISTS find ich gut. Allerdings hast du ja jetzt alle defines in MMC_xxx umbenannt. Bringt also genau so viel wie gar kein Präfix, oder hab ich da was falsch verstanden? Außerdem gibt es defines die in allen Dateien vorkommen wie z.B. MMC_WRITE (alias WRITE) auf was sollte man sich da jetzt festlegen? Werde das aber aufgreifen und mal sehen ob man das nicht noch etwas bessert ordnen kann. Generell, wenn man etwas in Großbuchstaben sieht ist es ein define und die sind immer in der config.h, das ist doch auch schonmal was :) Danke für die Hilfe und Mitarbeit. Grüße Daniel
Datum:
Moin Daniel, ja, da ich komplett mit C++ entwickel, ist die SdCard.h ein einfacher Wrapper für CPP. Das kannst du also ignorieren. Dieser packt die ganze MMC-Funktionen in einen eigenen Namespace und verwendet eine Methodenbennenung, wie ich sie sonst verwende. Also Camel-Case anstatt Unterstriche. > Zu den defines, > Allerdings hast du ja jetzt alle defines in MMC_xxx umbenannt. Bringt > also genau so viel wie gar kein Präfix, oder hab ich da was falsch > verstanden? Ich glaube ja. Nem mal an, dass du zwei Libs verwendest. a) Deine MMC und b) eine EEPROM Lib. Beide definieren ein #define WRITE. Solltest du nun in main() beide Libs importieren, so hast du das Problem, dass WRITE aus der mmc oder der EEPROM lib kommen kann. Weiterhin kann es sein, dass diese auch noch mit unterschiedlichen Werten definiert ist. Und dann? So, wie ich deine Lib sehe, wird das Problem nicht auftreten, da eben config.h nur von den mmc-headern und sourcen und nicht von "extern" included wird. Dennoch finde ich es für den Fall, dass dies aus "Dummheit" doch jemand machen sollte, eine gute Idee, die Quelle durch das MMC_ Präfix deutlich zu machen. > Außerdem gibt es defines die in allen Dateien vorkommen wie > z.B. MMC_WRITE (alias WRITE) auf was sollte man sich da jetzt festlegen? Äh, das Präfix MMC bedeutet (imho) nicht, dass diese aus der MMC.h stammt, sondern dass es ein define aus deiner mmc-lib ist. So hab ich mir das jedenfalls gedacht :-) > Generell, wenn man etwas in Großbuchstaben sieht ist es ein define und > die sind immer in der config.h, das ist doch auch schonmal was :) Jenau :) > Danke für die Hilfe und Mitarbeit. Ich will ja auch was :-) Nämlich die Funktionen die ich brauch und zwar ohne manuelles Merging bei folgenden Versionen cu, Michael
Datum:
Hi, ich wollte eben die neuste Version der SD-Kartenroutine ausprobieren und bin erschrocken! Warum ist eine UART Routine mit in das Gefecht eingewoben worden?! Macht das Sinn? Ich verpacke doch auch nich in eine UART-Routine ein I²C, nur weil ichs kann. Das is doch am Thema vorbei, ober sehe ich das Falsch? Gruß
Datum:
Hallo, bin immer noch nicht dazu gekommen mir alles anzusehen, aber so viel wurde ja auch nicht geändert... >Warum ist eine UART Routine mit >in das Geflecht eingewoben worden?! >Macht das Sinn? Wie meinst du das ? Es sind ja in der config.h nur defines dazugekommen, mit denen man seine eigene uart lib einbinden kann... Grüße Daniel
Datum:
Aber warum generell UART in einer SD-Karten-Routine? Soll diese Routine nicht nur und ausschließlich für SD-Karten sein? Das bläht das ding nur unnötig auf und wer eine UART überwachung haben will, der kann das doch auch selber, z.b. in seine main.c, schreiben. Ich wundere mich bloß warum in der file.c in zeile 210 plotzlich der dateiname ausgegeben werden soll. wenn ich an meinen UART-Pins aber andere bausteine angeschlossen hab als ein max232, dann kriege ich dadurch probleme! deswegen: warum diese feste UART einbindung?
Datum:
Stimmt schon, müsste nicht unbedingt rein, aber das ist als Beispiel gedacht. Die meisten werden wohl den UART angeschlossen haben um sich z.B. mal Debug Ausgaben zu machen, oder für Bootloader. Mach "MMC_SMALL_FS TRUE" und du bist den UART los. Funktionen wie ffls, also anzeigen von Dateien eines Verzeichnisses, leben nunmal von der Ausgabe auf eine Anzeige, in diesem Fall die UART... Grüße Daniel
Datum:
Naja, aber für eine allgemeingütige routine sollte sie doch so allgemein wie möglich gahalten sein, oder?
Datum:
Aber wie soll man denn den Fall ffls umschiffen? Geht numnal nicht ohne Ausgabe. Vorschläge?
Datum:
Man könnte die Dateinamen mit der Anzahl n und die Größe in zwei Arrays schreiben, z.B. dateien[n*8], groesse[n] und die zwei per Pointer zurückgeben. Dann kann man, wie man will, sich sie per UART, LCD oder sonstwie ausgeben lassen:
for (int i=0;i<8,i++) uart_putc(dateien[i]); |
wäre der erste dateiname
for (int i=11;i<19,i++) uart_putc(dateien[i]); |
wäre der zweite dateiname usw. die größe natürlich äquivalent. oder man schreibt die funktion so um, daß´sie immer nur einen dateinamen zurück gibt, beim nächsten aufruf den zweiten, ... nachdem der letzt ausgegeben wurde eine NULL zurückkgibt. Für die Dateigröße eine zweite funktion, die das selbe macht. Damit wären die speicherfressenden arrays von meiner ersten idee umgangen und man kann die rückgabewerte auf LCD, UART etc ausgeben. grußm matze
Datum:
oh, ich wollte eben mal das sample compilieren. ich bekomme fehler: Compiling: main_simple.c avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -O2 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -mcall-prologues -ffreestanding -Wall -Wstrict-prototypes -Wa,-adhlns=main_simple.lst -std=gnu99 -DF_OSC= -MD -MP -MF .dep/main_simple.o.d main_simple.c -o main_simple.o In file included from main_simple.c:23: SdCard.h:16: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'SdCard' make.exe: *** [main_simple.o] Error 1 zusätlich meckert er bei
uputs((unsigned char*)"\nBoot"); |
wenn man das
(unsigned char*) |
weg nimmt, klappts.
Datum:
Ja, der Michael Z. (incunabulum) hat da ein paar Dinge in dem Projekt gelassen die nicht so funktionieren. Die "Offizielle" Version ist noch diese: http://www.mikrocontroller.net/attachment/58218/st... bzw. für Windows Benutzer : http://www.mikrocontroller.net/attachment/57495/AV... Den Vorschlag die UART quasi in die main.c auszulagern, werde ich denke ich aufgreifen, in der nächsten Version. Wie im einzelnen muss man mal sehen.
Datum:
Hm, je mehr ich darüber nachdenke je besser gefällt mir das mit dem auslagern der UART. Das auslagern würde ja auch das Problem lösen, an die mitgelieferte uart.c/uart.h gebunden zu sein. Man könnte dann ja einfach seine eigene in der main.c includen...
Datum:
Genau so isses. Mal nebenbei: die UART routine läuft auch auf meinem ATmega128 nich... die register heißen anders...

