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
hallo,
einige bug-fixes sind gemacht, eine lib zum einlesen von
tastatureingaben, über eine at-tastatur ist jetzt dabei.
nur falls es jemanden interessiert ;)
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.
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
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...
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 ?
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
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
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.
1
#include<stdlib.h>
2
#include<string.h>
3
#include<avr/io.h>
4
#include<avr/pgmspace.h>
5
#include<avr/interrupt.h>
6
7
#define F_CPU 14745600UL
8
#include<util/delay.h>
9
10
#include"uart-0.1.h"
11
#include"mmc-0.2.h"
12
#include"fat-0.3.h"
13
#include"file-0.3.h"
14
15
#define BUFF_SIZE 15
16
unsignedcharkb_buffer[BUFF_SIZE];
17
18
intmain(void){
19
DDRA=0xFF;
20
PORTA=0x00;
21
22
uinit();
23
24
uputs("Boot ok\n\r");
25
26
if(mmc_init()==0){//ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
27
uputs("SD Init ok\n\r");
28
}
29
else{
30
uputs("SD Init failed\n\r");
31
}
32
33
if(0==fat_initfat()){
34
uputs("FAT Init ok\n\r");
35
}
36
else{
37
uputs("FAT Init failed\n\r");
38
}
39
40
//Datei lesen
41
ffopen('r',"delme.txt");
42
43
uputc(fread());
44
uputc(fread());
45
uputc(fread());
46
uputc(fread());
47
uputc(fread());
48
uputc(fread());
49
uputc(fread());
50
uputc(fread());
51
uputs("\n\r");
52
ffclose();
53
54
for(;;){
55
PORTA=0xFF;
56
}
57
}
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 ;)
hallo,
@ kalhou
also beschreiben einer datei würde wie folgt laufen:
1
//1
2
ffopen('w',"DELME TXT");
3
4
//2
5
unsignedcharstr[22]="das soll auf die karte";
6
unsignedchari=0;
7
8
//3
9
do{
10
11
ffwrite(str[i]);
12
i++;
13
}while(str[i]!='\0');
14
15
//4
16
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
Zum Verständniss: verwendet habe ich die aktuellste Version
"mmc-0.3.1.zip" dort findet sich leider keine Funktion "fat_str"
1
#include<stdlib.h>
2
#include<string.h>
3
#include<avr/io.h>
4
#include<avr/pgmspace.h>
5
#include<avr/interrupt.h>
6
7
#define F_CPU 14745600UL
8
#include<util/delay.h>
9
10
#include"uart-0.1.h"
11
#include"mmc-0.2.h"
12
#include"fat-0.3.h"
13
#include"file-0.3.h"
14
15
#define BUFF_SIZE 15
16
unsignedcharkb_buffer[BUFF_SIZE];
17
18
intmain(void){
19
DDRA=0xFF;
20
PORTA=0x00;
21
22
uinit();
23
24
uputs("Boot ok\n\r");
25
26
if(mmc_init()==0){//ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
27
uputs("SD Init ok\n\r");
28
}
29
else{
30
uputs("SD Init failed\n\r");
31
}
32
33
if(0==fat_initfat()){
34
uputs("FAT Init ok\n\r");
35
}
36
else{
37
uputs("FAT Init failed\n\r");
38
}
39
40
//Datei schreiben
41
42
//1
43
ffopen('w',"DELME TXT");
44
45
//2
46
unsignedcharstr[22]="das soll auf die karte";
47
unsignedchari=0;
48
49
//3
50
do{
51
52
ffwrite(str[i]);
53
i++;
54
}while(str[i]!='\0');
55
56
//4
57
ffclose();
58
59
60
for(;;){
61
PORTA=0xFF;
62
}
63
}
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 :)
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...
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...
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 ?
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
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
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.
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 ;)
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.
>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.
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
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
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
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
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.
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?
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...
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
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
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.
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 ;)
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
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
1
externunsignedcharsector[512];
vorhanden die immer 512bytes Platz wegnimmt, ob man nun eine Datei
offen hat, oder nicht..
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.
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.
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).
1
*(unsignedchar*)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
> 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
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
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 !
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
1
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.
1
temp=ffopen('a',dateiim8.3format);
2
ffwrite('irgendeinzeichen');
3
...
4
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.
;)
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
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...
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ß ;)
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:
1
if(option=='a'&&file_flag==0){
und zwar fehlte die angabe(nach zeile 94):
1
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...
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.. ;)
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
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
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:
1
// External Interrupt 6 service routine
2
// Interrupt wird ausgelöst, wenn entweder die SD-Karte rausgezogen oder
3
// eingesteckt wird. Entsprechend wird SD_ONLINE = 0 gesetzt oder die
4
// Initialisierung durchgeführt und SD_ONLINE = 1 gesetzt.
5
interrupt[EXT_INT6]voidext_int6_isr(void)
6
{
7
chartemp;
8
delay_ms(500);//Warten, bis Karte richtig ein- / ausgesteckt
9
if(((SD_Detect)==0)&&(SD_WriteProtect==0)){
10
puts1(SDKartegefunden);
11
12
puts1(SDInit);
13
temp=mmc_init();
14
if(temp==0){
15
puts1(OK);
16
puts1(FATInit);
17
temp=fat_initfat();
18
if(temp==0){
19
puts1(OK);
20
21
puts1(messdatatxterstellen);
22
temp=DV_MESSDATATXTerstellen();
23
if(temp==0)puts1(OK);
24
elseputs1(Dateibereitsvorhanden);
25
26
SD_ONLINE=1;
27
}
28
elseputs1(Fehler);
29
}
30
elseputs1(Fehler);
31
}
32
else{
33
puts1(SDKartenichtgefunden);
34
SD_ONLINE=0;
35
}
36
}
dazu die Funktion DV_MESSDATATXTerstellen();
1
charDV_MESSDATATXTerstellen(){
2
chartemp=0;
3
temp=ffopen('w',messdatatxt);
4
if(temp==1)return(1);//Datei existiert bereits
5
do{
6
ffwrite(messdatatext[temp]);
7
temp++;
8
}
9
while(messdatatext[temp]!='\0');
10
ffclose();
11
return(0);
12
}
Diese Funktion wird in der mainloop jede Sekunde aufgerufen:
1
charDV_MessungSpeichern(intNummer){
2
chartemp;
3
charTEMP[4]=" ";
4
unsignedlongintAbstand;
5
unsignedcharAbstand_ASCII[32];
6
#asm("cli");
7
8
itoa(Nummer,TEMP);
9
10
temp=ffopen('a',messdatatxt);
11
if(temp==1)return(1);//Datei nicht vorhanden
12
13
ffwrite('#');//Zeilenführungszeichen
14
ffwrite(';');
15
16
ffwrite(TEMP[0]);
17
ffwrite(TEMP[1]);
18
ffwrite(TEMP[2]);
19
ffwrite(';');
20
21
ffwrite(Tag_ASCII[0]);
22
ffwrite(Tag_ASCII[1]);
23
ffwrite('.');
24
ffwrite(Monat_ASCII[0]);
25
ffwrite(Monat_ASCII[1]);
26
ffwrite('.');
27
ffwrite(Jahr_ASCII[0]);
28
ffwrite(Jahr_ASCII[1]);
29
ffwrite(Jahr_ASCII[2]);
30
ffwrite(Jahr_ASCII[3]);
31
ffwrite(';');
32
33
ffwrite(Stunde_ASCII[0]);
34
ffwrite(Stunde_ASCII[1]);
35
ffwrite(':');
36
ffwrite(Minute_ASCII[0]);
37
ffwrite(Minute_ASCII[1]);
38
ffwrite(';');
39
ffwrite(';');
40
41
ffwrite('\n');
42
ffwrite('\r');
43
ffclose();
44
45
#asm("sei");
46
MessungNr++;
47
return(0);
48
}
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..
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
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.
1
if(SD_ONLINE){
2
temp=DV_MessungSpeichern(MessungNr);
3
}
Ich hab jetzt mal etwas umprogrammiert. Und zwar beim EXTINT6 mit
einigem Erfolg:
1
// SD-Card initialisation // FAT-File System initialisation
2
if(((SD_Detect)==0)&&(SD_WriteProtect==0)){
3
puts1(SDKartegefunden);
4
puts1(SDInit);
5
temp=mmc_init();
6
if(temp==0){
7
puts1(OK);
8
9
puts1(FATInit);
10
temp=fat_initfat();
11
if(temp==0){
12
puts1(OK);
13
puts1(messdatatxterstellen);
14
temp=ffopen('r',messdatatxt);
15
ffclose();
16
if(temp==1){
17
DV_MESSDATATXTerstellen();
18
puts1(OK);
19
SD_ONLINE=1;
20
}
21
elseputs1(Dateibereitsvorhanden);
22
}
23
elseputs1(Fehler);
24
}
25
elseputs1(Fehler);
26
}
27
elseputs1(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..
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.
1
if(option=='w'&&file_flag==0){
2
if(1==fat_loadFileDataFromDir(name)){
3
...
4
...
5
...
6
return(0);
7
}
8
}
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:
1
chartmp[12];
2
ultoa(fat.secPerClust,tmp,10);
3
uputs("secPerClust: ");
4
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
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.
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
1
unsignedcharffwrite(unsignedcharc){
2
unsignedlongintclusterOld;
3
clusterOld=currentCluster;
4
...
5
...
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
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
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
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
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..
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?
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
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.
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
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
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.
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
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...
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
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
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
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
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
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
hallo,
sorry hat etwas gedauert...
die änderungen sind nicht wild...
avr-size main_.hex
mit den schaltern (nur schreiben ohne große datei funktionen) :
1
#define smallFileSys 0
2
#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):
1
#define smallFileSys 1
2
#define write 0
wird der code 8228 bytes groß.
mit den schaltern (minimal system, nur lesend):
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
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...
// neu erstellen wenn nicht vorhanden und reinscheiben
13
if(ffopen('w',datei)==1)
14
{
15
ffopen('a',datei);
16
}
17
for(j=0;j<5;j++)
18
{
19
ffwrite('b');
20
}
21
ffclose();
22
}
23
}
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:
1
#define superfloppy 0
2
#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.
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
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:
1
// neu erstellen wenn nicht vorhanden und reinscheiben
2
if(0==ffopen('w',datei)){// prüfen ob öffnen erfolgreich
3
for(z=0;z<60000;z++){
4
ffwrite('a');
5
}
6
ffclose();
7
}
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
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
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
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
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.
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
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
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.
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
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
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
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.
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
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
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).
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.
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
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:
1
#include"uart.h"
2
#define MMC_UART_INIT uinit
3
#define MMC_UART_PUTC uputc
4
#define MMC_UART_PUTS uputs
5
#define MMC_UART_GETC ugetc
6
#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
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
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
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.
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
>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.
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:
1
//#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");
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
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
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
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
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
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:
1
~/sd_test/main_.c:50: undefined reference to `ffmkdir'
2
~/sd_test/main_.c:53: undefined reference to `ffmkdir'
3
~/sd_test/main_.c:68: undefined reference to `ffwrite'
4
command.o: In function `run_cmd':
5
~/sd_test/command.c:94: undefined reference to `ffrm'
6
~/sd_test/command.c:101: undefined reference to `ffmkdir'
7
~/sd_test/command.c:149: undefined reference to `ffwrite'
8
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
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
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
Hallo,
also du könntest z.B. aus der fat.c direkt die Funktion:
1
unsignedcharfat_loadSector(unsignedlongintsec)
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
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
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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
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
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
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
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...
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
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...
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
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
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
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...
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
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
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:
1
voidffwrites(constchar*s)
2
{
3
while(*s)
4
ffwrite(*s++);
5
}
zu schreiben bzw.in die file.c zu packen?!
gruß matze
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
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
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
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
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
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 :)
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.
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
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:
1
ffzeilenumbruch()
2
{
3
ffwrite(0x0D);
4
ffwrite(0x0A);
5
}
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
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
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.
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
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
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
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:
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.
1
#include<stdlib.h>
2
#include<avr/io.h>
3
4
#include"main.h"
5
#include"file.h"
6
#include"fat.h"
7
#include"hardware.h"
8
9
voidbeispiele(void);// kleine datei operations-beispiele
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
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
Hallo Daniel,
die Initialisierung der Karte und FAT funktionieren jetzt wieder,
allerdings bleibt das Beilspielprogramm gleich in dem ersten
Funktionsaufruf hängen. Also bei:
1
.
2
.
3
.
4
chardatei[12]="TEST TXT";
5
ffrm(datei);
6
.
7
.
8
.
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
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
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
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
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
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
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
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
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
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
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.