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.
Hallo
ich möchte diesen Thread nicht verwässen und habe deshalb einen neuen
Thread gestartet.
Wie sieht es mit der Lebensdauer der Karte aus, wenn man pro Sekeunde
kleine Einheiten schreibt?
Ist das unsinnig?
Wie sollte man da vorgehen?
MfG
Achim
siehe ==>Beitrag "SD Card GPS Logger optimieren?"
Hallo.
@Onit
Da ein '\n' halt auch nur ein Char/Byte ist, wird da schon nix doppelt
gezählt..
@Sucher
Bei meiner Lib werden halt immer 512 Bytes zwischengespeichert, da auch
immer 512 Bytes direkt auf die Karte müssen. Daher ist die Langlebigkeit
genau so, als wenn ein Pc auf die Karte schreibt...Nur das der
vielleicht noch bisschen mehr Puffert als es mit einem MC möglich ist..
Grüße Daniel
Hallo
@Daniel das heißt, wenn ich kleinere Einheiten als 512 Byte schreibe
wird das in deinem Interface gepuffert? Muss man da beim Schreiben dann
die Bytegrenzen (512 Byte Blockung) als Anwender beachten?
Es wird also solange gepuffert bis 512 Byte erreicht sind. Wenn ich nun
einen String schreibe der über die 512 Byte geht wird dann ein 512 Byte
String auf die SD Karte geschrieben und der Rest gepuffert? Wenn nur
gepuffert wird ist der Schreibvorgang schneller, als wenn eine
Blockgrenze überschritten wird und auf die SD geschrieben wird. Wie
lange dauert dann dieser Aufruf (klar Proz abhängig)?
Wird bei jedem Blockschreiben die FAT auf der SD Karte aktualisiert?
Falls ja wäre das ja der kritische Punkt mit dem "kaputt" gehen der SD
Karte, oder wird nur beim Schließen des Files aktualisiert?
Fragen über Fragen...
Vielen Dank
Achim
Hallo Sucher,
ja richtig. In der Lib gibt es einen 512Byte Puffer. Ist dieser voll,
wird die Karte mit diesen Bytes beschrieben.
Erst bei ffclose() erfährt der Dateieintrag und die Fat eine
Aktualisierung. Es werden immer freie Cluster in einer Reihe gesucht,
ist diese Anzahl voll, so werden diese auch schon in der Fat verkettet.
Wird erst zum Problem, wenn die Fat total fragmentiert ist...
Eine Datei bei FAT-Dateisystemen ist Quasi in 3 Teile aufgeteilt:
1. Datei Eintrag mit Name,länge usw in einem Ordner.
2. FAT Einträge
3. Die Daten selber
Siehe auch: http://www.mikrocontroller.net/articles/AVR_FAT32
Wer mag kann mit "int i=file.cntOfBytes;" abfragen wie viele Bytes in
dem Puffer schon geschrieben sind. Bei 512 wird auf die Karte
geschrieben...
Wie lange jetzt genau das schreiben eines 512Byte Blocks dauert müsste
man mal testen :)
Ebenso wie lange es dauert neue freie Cluster aus der Fat zu suchen oder
solche Cluster zu verketten...
Grüße Daniel
Hallo
@Daniel noch ne Frage(n): Kann man beim Öffnen ne Dateigrösse angeben,
dass die entsprechenden Cluster gleich vekettet werden, ohne dass man da
explizit reinschreibt?
Oder geht das mit ffseek übers Dateiende hinaus...wird dann reserviert,
oder darf bei ffseek der Offset nicht übers Dateiende rausgehen?
Gibts dafür ne andere Möglichkeit?
Vielen Dank
Achim
Moin,
also ffseek() darf auf keinen Fall über das Dateiende hinaus. Gilt nur
für innerhalb einer Datei, bis zum letzten Byte.
Also vorher die Datei Größe bestimmen? Wieso?
Wäre schon machbar, mir erschließt sich aber nicht der Grund wieso man
das machen sollte.
Wenn es um Geschwindigkteit geht, einfach dafür sorgen, dass die Fat
nicht fragmentiert ist. dann könnten bis zu 65000 Cluster am Strück mit
Daten voll gemacht werden, bevor diese verkettet werden müssen (müsste
man nur 2 Zahlen in der Lib ändern).
Mal mit Zahlen:
4 Sektoren Pro Cluster.
512 Bytes Pro Sektor.
65000 Cluster.
Macht 126,95 Mega Bytes am Stück, ohne etwas mit der Fat oder dem
Dateieintrag machen zu müssen :)
Bei 65000 Clustern, die in der Fat verkettet werden müssen, müssen 508
Fat Sektoren geschrieben werden, macht 206096 Bytes. Also etwa 254
KBytes. Die bekommt man so in etwa 2 Sekunden beschrieben...
Grüße Daniel
Hallo
@Daniel ich bin eben dabei die einzelnen Implementierungen abzuklopfen.
In der Implementierung von Roland Riegel wird sowas diskutiert, dass man
am Anfang gleich einen großen File allokiert weil sonst das Anfügen
lange dauert.
zB.:Beitrag "Re: MMC/SD-Karte mit FAT16 an AVR"
Ich muß halt mal damit spielen und Erfahrungen sammeln...
Vielen Dank
Achim
Hi Achim,
den Code von Roland versteh ich teilweise nicht genau.
Aber generell dauert es halt ein bisschen die Fat zu updaten und neue
freie Cluster zu suchen.
Zuerst hatte ich da auch eine etwas sperrige Methode. Jetzt geht das
total schnell, wenn halt die Fat nicht groß fragmentiert ist.
Wenn du da irgendwo Vorteile/Nachteile siehst, könnte man das ja mal
zusammen tragen und als Vergleich ins Wiki stellen...
Grüße Daniel
PS: hab mich da oben bei einer Ziffer vertan, muss natürlich 260096
Bytes heißen^^
Hallo,
sehr seltsam. Wie kommst du denn auf -492 ?
Weil eigentlich dachte ich das ein "unsigned long int length" (siehe
fat.h) niemals negativ werden kann.
Lässt du dir das vielleicht falsch anzeigen?
Nimm mal die neue Version, vielleicht wirds dann besser.
Hab jetzt auch die bekannten Bugs beseitigt.
Es gibt 2 neue Schalter in der fat.h.
1. OVER_WRITE
Gibt an ob die Datei überschreiben Funktionalität mit Kompiliert wird.
Da wenn überschrieben wird auch immer der zu überschreibende Sektor
geladen werden muss, ist meine Empfehlung "OVER_WRITE 0" zu setzen und
auf überschreiben zu verzichten.
2.MAX_CLUSTER_IN_ROW
Gibt an wie viele verkette bzw. leer Cluster für eine Datei gesucht
werden, maximaler Wert, 65 534.
Grüße Daniel
Inzwischen habe ich es herausgefunden: warum der unsigned long int nun
negativ war weiß ich nicht, aber deine Lib hat mir die Datei 4GB groß
gemacht, obwohl die Karte nur einen GB hat... nun gehts aber.
Hallo,
ja das mit der Dateigröße ist mir dann doch noch klarer geworden. Unter
Umständen waren auf file.length noch alte Daten vom durchsuchen von
alten Ordnern... hatte da aufgrund von Codegröße alles mögliche gekürzt
^^
Da überschreiben von Daten so kompliziert ist und deshalb relativ
langsam, gibt es 2 Funktionen zum schreiben, die über den schon
erwähnten Schalter OVER_WRITE in fat.h wahlweise mit ein Kompiliert
werden können.
Der Code ist diesmal wirklich stabil, da ich ausgiebig Zeit zum testen
hatte.
Anregungen und Tipps immer willkommen.
Als Anhang die neue Version mmc-0.5.3
Es ist dringend zu empfehlen, entweder die Version mmc-0.4.8 oder die
neue zu benutzen !
Grüße Daniel
Hallo
@Daniel mal ne blöde Frage "Wann wird eine FAT fragmentiert"?
..doch nur wenn ich eine Datei schließe ne neue öffne und schreibe
schließe und die alte Datei öffne und was dran hänge...
oder eine Datei lösche und ne neue mit verschiedener Größere schreibe?
Macht es da nicht Sinn (meine oben gestellte Frage) dass man beim Öffnen
oder seek die Deitei auf eine bestimmte grösse aufblähen kann ohne
reinzuschreiben?
MfG
Achim
Hallo Achim,
eine Fat fragmentiert, wenn man Daten löscht. weil da wo vorher die
Cluster einer Datei in der Fat verkettet waren, nun Cluster frei sind.
Die von Dir beschriebenen Probleme sind dann nur die Folge draus...
Das Problem ist, ich möchte die Lib so allgemein wie möglich halten.
Natürlich müsste man, wenn etwas sehr Zeitkritisch ist testen und ggf.
die Lib anpassen.
Oder sogar alles auf eine spezielle Gegebenheit umschreiben und zusammen
kürzen. Mir geht da z.B. eine Einzige Funktion durch den Kopf, die eine
ganze komplett vordefinierte Datei schreibt oder ähnliches...
Das mit dem vorher allozieren wäre garkein Problem, nur ich gehe mal
davon aus, nicht vorher zu wissen wie lang eine Datei wird.
Vielleicht baue ich noch ein, dass man beim schreiben immer mindestens
MAX_CLUSTERS_IN_ROW freie bekommt. Und/Oder eine Funktion, die die
letzte Datei in der Fat ermittelt und erst danach mit schreiben anfängt.
Grüße Daniel
Hallo,
ich versuche gerade den Code zu verwenden, leider ohne den gewünschten
Erfolg. Ich habe die letzte Version benutzt und momentan sieht mein Code
so aus:
[c]
int main (void)
{
//wdt_enable(WDTO_1S);
sei();
initUart();
sendEOL();
uartPutS("Serveur de temps");
sendEOL();
if(mmc_init() == 0)
{
uartPutS("SD-Card Inizialisation failed.");
sendEOL();
while(1) {};
}
uartPutS("SD-Card initialized.");
sendEOL();
if (fat_initfat() == 0)
{
uartPutS("FAT initialized.");
sendEOL();
char datei[12]="test.txt";
fat_str(datei);
switch (ffopen(datei ))
{
case 1:
{
uartPutS("Existing file opened.");
sendEOL();
}
case 2:
{
uartPutS("New file created and opened.");
sendEOL();
}
default:
{
uartPutS("Cannot create or open file.");
sendEOL();
}
}
ffwrites((char*)"Hallo Datei :)");
ffwrite(0x0D);
ffwrite(0x0A);
uartPutS("Data written to file.");
sendEOL();
ffclose();
uartPutS("File closed.");
sendEOL();
}
while(1) {};
}
[\c]
Die Initialisierung klappt, nur beim ffopen() bzw genauer in der Routine
unsigned char fat_loadFileDataFromDir(char name[]) hängt der Prozessor
sich auf. Nach meinen bisherigen Nachforschungen sind die ausgelesenen
Sektoren alle '0' und der Prozessor hängt. Auf dem SPI-Bus ist nichts
mehr los. Was mich wundert: Die Karte wird als FAT32 erkannt, auch wenn
sie auf FAT16 formatiert wurde. Ich habe sowohl FAT32 als auch 16
ausprobiert und auch SUPERFLOPPY geändert, ohne Erfolg.
Hat jemand eine Idee, woran es liegt?
Da es sein kann das es etwas dauert bis die Karte "anspringt".
Sieht sonst OK aus.
Vielleicht mal den SPI Takt bisschen runter setzen.
Wie hast du die Karte angeschlossen?
Grüße Daniel
Der SPI-Takt liegt bei etwa 120kHz, die Karte ist direkt an einen
Atmega644p angeschlossen, der mit 3,3V läuft. Ein Pull-Up an DO ist
dran.
Deinen obigen Vorschlag habe ich schon umgesetzt, aus der Schleife kommt
der Controller bzw. die Karte nicht raus. Ich lese mir mal die
Bedienungsanleitung meines Logigports durch...
Mit mmc_init() hatte ich bis jetzt nur Probleme, wenn die Kabel zur
Karte zu lang waren, aber bei 120KHz dürfte das kein Problem sein.
Vielleicht mal andere Karten ausprobieren, Schaltung überprüfen sonst
hab ich keine Ahnung wieso die mmc_init() nicht durchläuft.
Hm über was wird die Karte mit Strom versorgt? Da können Peaks bis zu
60mA auftreten, und Ripple auf der Versorgungsspannung ist auch
schlecht...
Mach doch mal ein Foto von der Schaltung :)
Grüße Daniel
Hallo Daniel,
vielen Dank fuer die Tipps. Auf so einen Mist muss man erst einmal
kommen: Der SD-Kartenhalter von ALPS hatte an zwei Pads keinen
Kontakt... Da der groesstenteils geschlossen ist, kam man da nicht ran.
Das ganze hat lich jetzt eine 2GB-Karte gekostet, aber die sind ja
guenstig inzwischen.
Jetzt habe ich gerade meine erste Datei angelegt und beschrieben. Wenn
der Rest auch so gut laueft, waere das sehr cool. Danke fuer die
Bibliothek. :-)
Moin, ich bin grade dabei deine Bibliothek zu testen. Ich habe hier 3
SD-Karten liegen (1x 128MB, 1x 256 MB von toshiba und 1x 2GB von san
disk), allerdings gibt es Probleme beim Schreiben. Mein Prozessor ist
ein AT90CAN128, welcher mit 3,3V läuft und vom internem Takt versorgt
wird.
Hier eine genauere Fehlerbeschreibung:
-Lesen geht.
-Löschen von Dateien geht.
-Anlegen einer nicht vorhandenen Datei geht nur jedes 2. mal, wobei die
Funktion nie zurückkehrt, egal ob eine Datei auf der SD-Karte angelegt
wurde oder nicht.
-Schliessen einer Datei, bei der sich Daten geändert haben geht nicht,
es werden also nie Daten geschrieben.
Alle Schreibversuche auf die SD-Karten enden damit, dass der Prozessor
sich dauerhaft mit der SD-Karte unterhält, welcher Befehl übers SPI
läuft kann ich leider nicht sagen.
Die SD-Karten habe ich zwischendurch immer wieder mit Windows auf FAT32
formatiert. Die Einstellung SUPERFLOPPY habe ich sowohl gesetzt, als
auch nicht gesetzt probiert.
Eine genauere Beschreibung kann ich mangels JTAG-Interface leider nicht
geben.
mfg Emperor_L0ser
Hallo,
hast du irgendwo den Code geändert?
Wie rufst du die Funktionen auf?
Versuchst du zu überschreiben? Dann muss "OVER_WRITE 1" und "WRITE 1"
gesetzt sein.
Grüße Daniel
Moin,
ja ich habe den Code geändert, dies beschränkt sich allerdings darauf,
dass ich alle Variablendefinitionen aus den for-Schleifen entfernt und
an den Anfang der Funktion gepackt habe (ANSI-C99 Standard, mein avr-gcc
meckerte). Der AT90CAN128 ist von den Definitionen mit dem ATMega128
kompatibel, ich musste dort nichts ändern.
Ich verwende Version 0.5.3 und die Dateien, die dort nicht enthalten
sind (main.c, mmc.c und mmc.h) verwende ich aus 0.5.2. Aufrufen tu ich
nur die Funktionen, welche in der Beispiel-Funktion der main.c sind.
Write ist die ganze Zeit auf 1, sonst sind die Funktionen ja garnicht
vorhanden. OVER_WRITE habe ich sowohl gesetzt als auch ungesetzt
versucht.
mfg Emperor_L0ser
PS: ich verwende nicht die Makefile, meine Befehle, wie für alle meine
Projekte:
if avr-gcc -O2 -mmcu=at90can128 -DF_CPU=1000000 ./*.c
then
avr-objcopy -O ihex -R .eeprom a.out flash.hex
avrdude -p c128 -e -c pony-stk200 -U flash.hex
exit 1
fi
Hallo,
da liegt das Problem, es gibt Funktionen, da muss man noch Code
ergänzen, damit man die Definitionen nach oben schreiben kann.
Versuch mal dem avr-gcc "-std=gnu99" beizubringen. Dann einfach die
Original fat.c und file.c dann läufts...
Grüße Daniel
Ich hab es jetzt so gemacht, wie du gesagt hast und es läuft, schonmal
Danke dafür. Den ersten Teil deiner Antwort versteh ich nicht ganz. Ich
würd vor allem den Code gerne auch so schreiben, dass er ANSI-C Konform
ist, da ich ja nicht weiss, ob ich drei Jahren noch den GCC-Compiler
verwende.
mfg Emperor_L0ser
Ich bin es von C# und Java gewöhnt überall Variablen zu definieren und
Deklarieren, is schön bequem, aber is halt kein ANSI-C von 1986...
Eigentlich sollte jeder halbwegs gute Compiler auch ANSI/ISO-C99 können,
egal.
Hab grad den Code nicht vor Augen, aber man müsste Teile umschreiben,
damit man die Definitionen an den Anfang der Funktionen setzen kann.
Musst dir mal genau anschauen was da gemacht wird.
Grüße Daniel
Hallo Daniel,
ich habe die Lib zwar noch nicht getestet, scheint aber recht
interessant für mich zu sein.
Ich frage mich allerdings, wie ich den Inhalt des Directories weiter
verarbeiten kann. Eine Ausgabe auf die serielle Schnittstelle hilft mir
nicht weiter (ffls), da ich es auf einem direkt angeschlossenen Display
ausgeben möchte. Aus einem anderen Beispiel kenne ich zwei folgende
Funktionen:
* Ermittlung der Anzahl der Directory Einträge
* Ermittlung des Namens des x-ten Directory Eintrages
Können die beiden Funktionen mit den bereits vorhandenen gebildet
werden? Ich habe da nach Durchsicht Deiner Funktionen aber noch keinen
Ansatzpunkt gefunden. Wäre es aufwendig, diese beiden Funktionen noch
einzubringen? Ggf. könnte ich auch Tips gebrauchen, wie das anzugehen
wäre. Für mich wäre das aber recht zeitaufwendig, da ich in C noch nicht
so firm bin. Würde ich aber versuchen anzugehen.
Danke und Grüße
Ralf
Hallo Ralf,
wäre nicht sonderlich schwierig.
Mit den beiden vorhandenen Funktionen könnte man so etwas schon
realisieren, komme ich aber momentan nicht dazu.
Als Hinweis wenn du da selber schonmal was machen willst, "lsRowsOfClust
(unsigned long int start_sec)" geht durch alle Zeilen eines Clusters, ab
dem Sektor start_sec. "ffls(void)" geht dann durch alle Cluster eines
Ordners. Somit hat man beide logischen Strukturen abgearbeitet...
Will man jetzt wissen an welcher "Zeile" welcher Eintrag steht, müsste
man einen Zähler haben, der von lsRowsOfClust hochgezählt wird, bis man
an gewünschter Zeile ist.
Will man wissen wie viele Einträge es gibt, würde es reichen anstatt
einer Ausgabe einfach mit zu zählen, wie viele Einträge ausgegeben
werden würden.
Grüße Daniel
Hallo Daniel,
vielen Dank, Anzahl der Dateien (über ffls) sollte wirklich gar kein
Problem sein. Das andere muss ich mal sacken lassen :)
Werde ich mir die Tage mal anschauen.
Grüße
Ralf
Moin,
die Lib hat mir viel Arbeit erspart. Habe sie ohne größere
Schwierigkeiten auf einen MSP430 portieren können. Mir ist dabei nur
eine Sache aufgefallen. Die Initialisierung der FAT erfolgt ja in
Abhängigkiet ob "SUPERFLOPPY" 0 oder 1 gesetzt ist. Es ist aber schlecht
vorherzusagen ob in das fertige Gerät eine Karte eingesetzt wird, die
ein Superfloppy ist oder aber eine Partition enthält.
Habe die Initialisierung mal so geändert, das automatisch ermittelt wird
ob ein Superfloppy vorliegt.
//Prüfung ob man schon im VBR gelesen hat (0x6964654d = Medi)
11
if(secOfFirstPartition==0x6964654d)
12
returnfat_loadFatData(0);//Superfloppy liegt vor
13
else
14
//FAT-Daten aus dem ersten Sektor der Partition lesen
15
returnfat_loadFatData(secOfFirstPartition);
16
}
17
return(1);
Wenn man also eine Karte ausliest und man ist gleich im VBR, dann liest
man ja innerhalb dieses Abschnittes: "Datentr„ger entfernenÿ
Medienfehlerÿ Neustart: Taste drcken". An den Positionen 454 - 457
steht "Medi", was der Sektoradresse 1768187213 entspricht. Diese
Sektoradresse gibt es bei keiner bisher verfügbaren SD - Karte, weshalb
man damit auf Superfloppy prüfen kann.
mfg
Michael
Hallo Michael,
hab auch schon daran gedacht die Lib auf den MSP430 zu portieren.
Leider noch keine Zeit gehabt.
Hast Du vor, die an den MSP430 angepaßte Lib zu veröffentlichen ?
Noch einen schöne Tag
MfG
Siegmar
PS: Nochmals: Tolle Arbeit von Daniel !!!!!
Hallo zusammen,
das mit dem veröffentlichen für MSP wird wohl nix werden ^^
Anzupassen wären aber ja eigentlich nur die mmc low level Routinen.
Also die SPI Geschichten.
Hab leider keine Ahnung vom MSP daher schwer abzuschätzen wie viel
Arbeit das wirklich ist...
Grüße Daniel
Moin,
die meiste Arbeit haben die Routinen für das Lesen und Schreiben der
SD-Karte gemacht (wegen neu schreiben und so). Bei den FAT- und
Dateifunktionen habe ich erstmal nur die Void-Pointer (die ICC430
Version die ich nutze kann damit nicht um), die ganzen Zählvariablen
angepasst und natürlich die Funktionsaufrufe der Low-Level-Routinen
geändert. Eben um zu sehen ob es funktioniert. Und es funtkioniert.
Weitere Anpassungen sind sicherlich noch möglich, mach ich irgendwann
auch noch.
Michael
Hallo zusammen,
hier mal eine neue Version, gab da noch Bugs...
Zudem ist die SPI schreiben Routine schneller geworden.
Generell kompakterer Code.
Viel Spaß damit :)
Grüße Daniel
Hallo,
zuerst einmal ein Dank an Daniel dafür, dass er seinen Code hier
veröffentlicht hat. Ich möchte sein Beispiel nun bei mir lauffähig
bekommen, es funktioniert aber nicht. Auf der UART-Ausgabe sehe ich,
dass nach mmc_init() nichts mehr passiert, es muss also ein Fehler in
fat_initfat() auftreten. Ich verwende eine microSD Karte mit 128MB, die
ich per Windows als FAT formatiert habe. Wo müsste ich wohl ansetzen um
den Fehler zu finden?
Hallo,
wie ist denn die Karte am Controller angeschlossen?
Hast Du etwas am Code geändert?
Du siehst auf dem Terminal "Boot..." und das OK fehlt? Man sollte wenn
alles richtig initialisiert wird ja "Boot...OK" sehen. Wenn das OK fehlt
hängt sich das Programm tatsächlich beim Fat auslesen auf. Interessant
wäre da der Sektor 0 der Karte.
Oder Du könntest einfach mal probieren ob es FAT32 Formatiert klappt,
ich glaube bei Windows bedeutet nur Fat FAT16 und sonst halt FAT32.
Grüße Daniel
Da ich einen atmega328p verwende, habe ich die mmc.h verändert.
CLK von der Karte habe ich über einen HEF4050 mit SCK am µC verbunden,
DI auch über HEF4050 an MOSI, CS mit pull-up über HEF4050 an PB1 und DO
mit pull-up direkt an MISO. An anderen Stellen habe ich nichts im Code
verändert. Ja es erscheint wirklich nur Boot... . Im Anhang ein Bild vom
Sektor0, nach dem Versuch darauf zu schreiben.
Hallo,
also die Karte ist unpartitioniert. Versuch mal folgenden Code, damit
man feststellen kann ob es an der fat_initfat() liegt oder schon
woanders hakt.
1
voidmain(void){
2
chartmp[10];
3
4
uinit();
5
6
7
uputs((unsignedchar*)"\nBoot");
8
9
while(mmc_init()!=0){;}
10
11
uputs((unsignedchar*)"... ");
12
13
fat_loadFatData(0);// läd fat daten
14
15
16
ultoa(fat.rootDir,tmp,10);
17
uputs(tmp);
18
uputc(' ');
19
20
utoa(fat.secPerClust,tmp,10);
21
uputs(tmp);
22
23
}
Jetzt müsste wenn alles funktioniert, "Boot...2 2" zu sehen sein.
Wenn dem so ist muss ich mir die fat_initfat() nochmal genauer
anschauen.
Wenn nicht, liegt das Problem irgendwo ganz anders. Da würde ich eher
auf ein Hardware Problem schließen.
Im Datenblatt von dem HEF4050 steht nichts von Versorgungsspannung ab 2
Volt wie bei dem HC4050, was bei niedrigeren Frequenzen vielleicht noch
klappt aber dann nach der Karten Initialisierung mit vollem SPI speed
nicht mehr...
Grüße Daniel
Als Ausgabe erhalte ich "Boot..." und manchmal "Boot... 0 0" und einmal
wurde sogar die txt-Datei erstellt, es liegt also an der Hardware. Eine
2Gb Karte habe ich damit wohl schon zerstört, zumindest reagiert Windows
nicht mehr, wenn ich die Karte einlege. Aber das die Karte
unpartitioniert ist verstehe ich nicht, habe es im Arbeitsplatz per
Rechtsklick und dann auf Formatieren formatiert. Ich werde dann mal die
74HC4050 von reichelt bestellen und alles neu aufbauen. Schonmal danke
für die schnelle Hilfe.
Mir ist noch keine einzige Karte kaputt gegangen bei meinen Tests. Ich
nehmen aber auch immer sofort den Strom weg, wenn was unvorhergesehenes
passiert.
Unpartitioniert ist ja nicht unformatiert. Keine Ahnung warum Windows
mal ne Partition erstellt und mal nicht. Glaube bei kleineren Karten
wird nicht partitioniert und bei größeren schon.
Du könntest aber auch mal den SPI speed runter setzen und schauen ob es
dann mit deiner Hardware stabiler läuft.
Einfach in der mmc.c in der Funktion mmc_init () die Zeilen
1
//SPI Bus auf max Geschwindigkeit
2
SPCR&=~((1<<SPR0)|(1<<SPR1));
3
SPSR=SPSR|(1<<SPI2X);
auskommentieren.
Bei deiner Karte die nicht mehr funktioniert, könnte es sein das die
mehr als 3,3 Volt abbekommen hat? Mach doch mal ein Foto von der
Schaltung :)
Grüße Daniel
Hallo mal wieder!
Ich bastel im Moment wieder mit dem SD-Code rum. Soweit alles in
Ordnung. Allerdings ist file.seek bei mir immer Null. Das darf aber
eigentlich nicht sein. Mein Code:
########################################################################
#
int main(void) {
char *tag;
char *value;
char s[10];
lcd_init();
lcd_clear();
sd_init();
lcd_clear();
tag = malloc(30);
value = malloc(30);
char mfile[] = "testdat.txt";
fat_str(mfile);
ffopen(mfile);
// Länge der Datei ausgeben
lcd_string("L: ");
lcd_string(itoa(file.length, s, 10));
lcd_set_cursor(0,1);
// Position ausgeben
lcd_string("S: ");
lcd_string(itoa(file.seek, s, 10));
_delay_ms(2000);
while (file.seek <= file.length) {
tag[0] = '\0';
value[0] = '\0';
lcd_clear();
tpx_read_tag(tag, value);
lcd_string("T: ");
lcd_string(tag);
lcd_string("; S: ");
lcd_string(itoa(file.seek, s, 10));
lcd_set_cursor(0,1);
lcd_string("V: ");
lcd_string(value);
_delay_ms(1000);
}
ffclose();
while(1);
return 0;
}
########################################################################
#
tpx_read_tag ist eine funktion von mir, die eine Art pseudo-xml
realisiert nach dem Muster <tagname=wert>.
Ich brauche file.seek, damit das Auslesen irgendwann mal aufhört.
Noch etwas, ich bekomme warnings:
"./sd/fat.c:96: warning: left shift count >= width of type"
Bis denn dann,
StrangeMan
PS: Am Software-SPI wäre ich auch sehr interessiert! =)
Hallo,
also so ist file.seek nicht gedacht.
Es wird beim lesen garnicht verwendet. Wenn du bis zum Datei Ende lesen
möchtest ist die schnellste Variante:
1
unsignedlongintseek=file.length;
2
3
do{
4
5
codezumlesen...
6
7
}while(--seek);
Da so nur geprüft wird ob seek==0 ist als Abbruchbedingung...
Zu dem angesprochenen warning, das hab ich auch, allerdings "nur" beim
avr-gcc, dem normalen gcc macht das nix. Also hat keine Probleme gemacht
bei mir. Und den left shift muss man so machen...
Grüße Daniel
Und wenn ich in dem Moment gar nicht weiß, wo sich der "Cursor" in der
Datei befindet?
Hmm, da bleibt mir wohl nichts übrig als mir eine globale Variable zu
machen, die mitloggt, wo ich bin.
Wie wäre es mit der Variablen seek aus meinem Beispiel?
Ich habe extra darauf verzichtet in ffread() eine 32 Bit variable wie
file.seek bei jedem einzelnen Byte das gelesen wurde zu ändern...das
würde bremsen! Besser ist es da die Laufindex Variable (aus dem Beispiel
eben, seek) beim Aufruf von ffread() zu benutzen.
Wozu genau willst du denn die exakte Position in der Datei wissen?
Und wie gesagt, was spricht gegen die Variable seek?
Grüße Daniel
Hmm, ich hab ein Menüsystem, was auf Basis oben genannter
Pseudo-XML-Tags die Menüeinträge ausließt. Wenn ich eine Funktion habe,
die nur einen Tag auslesen soll, dann hat die ja keine Ahnung, wo in der
Datei sie auszulesen beginnt, wenn ich sie aufrufe. Sie darf aber
dennoch nicht über das Dateiende hinauslesen. Wenn ich das so amche, wie
im Code oben, dann kann es ja sein, dass sie erst beim 100ertsten Byte
anängt zu lesen, weil der "Cursor" da grade war. Dann würde sie 100
Bytes üebr das Dateiende hinauslesen. Was da bei rauskommt habe ich
schon gesehen... Zufallsdatan - mehr oder weniger.
Aber ich habs jetzt so gelöst, dass ich einfach mitlogge, wo ich bin.
Bei jedem ffread() oder ffseek() aktualisiere ich meine globale Varable
eben.
Das Geschwindigkeitsproblem ist natürlich ein Argument. Aber eventuell
kann man so eine Seek-Variable als Compilerschalter mit einbauen. Dann
kann man's aktivieren, wenn es benötigt wird. Ich denke, für komplexere
Dinge ist sowas schon von Nöten.
StrangeMan
Ok, überlege ich mal wie man sowas elegant machen kann.
Du könntest ja aber einfach file.seek benutzen anstelle deiner globalen
variable. Wie das dann mit der Geschwindigkeit aussieht müsste man mal
sehen. ffseek() updatet dir file.seek ja auch wenn du vor oder zurück
spulst. Kleines Beispiel:
Hallo mal wieder.
Ich hab die mcc.c/mcc.h von Ulrich Radig rausgekramt und den
Software-SPI-Modus von ihm wieder übernommen. Allerdings ... naja, es
klappt nicht, und ich weiß nicht, obs an meiner Hardware oder am Code
liegt. Ich hab meine Version der mcc.c mal angehängt. Eigentlich kann
man ja nichts falsch machen. Offensichtilich aber doch...
StrangeMan
Neue Version !
Überarbeitete mmc.c und Optimierung des Codes.
Jetzt auch Multiblock Operationen möglich. Wird allerdings nicht von
allen Karten unterstützt, daher optional als define wählbar.
Neuere Doku wird nachgereicht.
Wird wie immer hier nachzulesen sein:
http://www.mikrocontroller.net/articles/AVR_FAT32
Grüße Daniel
Daniel,
ich hab mir heute mal die neue Version deiner Lib zu Gemüte geführt. Wie
auch die alten Versionen funktioniert das auf einem zur Zeit in der
Mache befindlichen Alleskönner-Board wie geschmiert. Super Arbeit!
Und - wie bereits letztes Jahr - ich hab mal wieder ein paar Ideen, die
die Lib noch besser machen könnten. Für mich natürlich :-)
1) Sinnvolle Rückgabewerte
Viele Methoden geben unsigned chars für Statusinformationen zurück.
Sowas in etwa:
1
if(2==ffopen("TEST TXT")){...}
Hier würde ich mir defines wünschen, die eben diese Statusinformationen
sprechend bezeichnen. Sowas z. B.
1
#define MMC_FILE_NEW 2
2
if(MMC_FILE_NEW==ffopen("TEST TXT")){...}
Gibt es eigentlich eine Doku für diese Return-Values?
2) Uart-Funktionen per Config einstellen
Das hatte ich mir ja schon oben gewünscht, da ich ansonsten jedesmall
die Sourcen ändern muss.
3) Status-Signale der SD-Card
Bei den meisten Kartenslots kann man neben den wichtigen Pins auch
auslesen, ob eine Karte eingelegt ist und ob diese schreibgeschützt ist.
Wär doch schön, wenn wie die Lib von Roland Riegel, das auch
berücksichtigt werden könnte.
Alle Config-Optionen in eine separate Config-Header-Datei geschrieben
sieht dann so aus, wie im Anhang zu finden. Die SPI-Pins etc. ziehe ich
mir aus einer globalen Hardware-Header für SPI. Die Defines für die
Statusinformationen könnten wohl auch woanders hin.
cu, Michael
Hallo,
bin immer offen für Anregungen :)
-1.) Mich hat es Tatsache auch schon öfters genervt das man einer 2
nicht ansieht was es genau bedeutet... werde ich ändern.
Störend ist nur, dass z.B. folgendes "define TRUE 1" 2 Byte Ram frisst
wenn man "TRUE" irgendwo im Code nutzt. Mir war nie die Idee gekommen
"define TRUE '1'" zu machen :) ist dann nur ein 1 Byte ...
-2.) Da fällt mit keine tolle Lösung ein, na ja mal sehn...
-3.) Ich hab so nen Kartenslot nicht, daher kann ich das schlecht
testen, müsste mir mal so nen Slot besorgen :)
Software SPI möchte ich dann auch noch mich rein packen ins nächste
Release.
Grüße Daniel
Moin Daniel,
> Störend ist nur, dass z.B. folgendes "define TRUE 1" 2 Byte Ram frisst> wenn man "TRUE" irgendwo im Code nutzt. Mir war nie die Idee gekommen> "define TRUE '1'" zu machen :) ist dann nur ein 1 Byte ...
Ist dem wirklich so? Bis heute dachte ich, dass defines nur durch den
Präprozessor verwendet zum ersetzen herangezogen werden und erst danach
der compiler einspringt...
Zum Uart:
Für dich relevant sind ja nur 3 Infos zum Uart. Include-Statement,
uputs, uputc. Ich (als Freund der #defines würde das dann wieder per
config-Option lösen. Also:
1
#define UART_INCLUDE /path/uart.h
2
#define UART_UPUTS uputs
3
#define UART_UPUTC uputc
und dann im Code die ensprechenden defines statt der echten Namen
verwenden.
Zu 3 - Status Info:
Hier müsste man überlegen, wie weit man wirklich dies durchgängig
implementieren will. Reicht es, wenn man entsprechende Methoden zum
Abtesten anbietet, den eigentlichen Test aber dann den Nutzer
durchführen lässt? Oder nur bei mmc_init()? Oder sollen alle Lese- bzw.
Schreiboperationen jeweils isAvailable4() oder isProtected() aufrufen?
Letzteres eher nein, so würde ich denken.
cu, Michael
Hallo,
hier mal ein kleines Update. Der Code ist nur auf anständige Return
Werte umgestellt. Keine Funktionalen Änderungen.
>Ist dem wirklich so?
Ich dachte immer das wenn man "#define KONSTANTE 1" macht, wird das als
Integer behandelt bei der Erzätzung im Code durch den
Präprozessor...deshalb hab ich die defines jetzt einfach mal alle als
chars gemacht, kann ja nicht schaden ^^
Zum Uart, zufriedener jetzt ?
Hast Du so einen Slot und wärst eventuell bereit die Funktionen zu
schreiben und testen? Ich nehme die dann in die Lib auf. Stimme da
nämlich bei Deine Überlegungen zu.
@Winne
Das müsste man ja dann als struct machen, und ich weiß nicht mehr warum,
aber das ist wohl nicht so toll...
Vielleicht weiß da ja einer warum ?!?
Grüße Daniel
Moin Daniel
> hier mal ein kleines Update. Der Code ist nur auf anständige Return> Werte umgestellt. Keine Funktionalen Änderungen.
Wunderbar. Genau so etwas meinte ich. Wie sieht es bei ffopen im
OVERWRITE Modus aus? Wird hier auch OPENED_TO_WRITE zurückgeliefert?
> Zum Uart, zufriedener jetzt ?
Fast :-) Die Defines wie auch eine globale COnfig-Datei sind klasse.
Fehlt nur noch, dass die Quellen mmc.c und file.c auf die neue
uart-syntax angepasst werden :)
> Hast Du so einen Slot und wärst eventuell bereit die Funktionen zu> schreiben und testen? Ich nehme die dann in die Lib auf. Stimme da> nämlich bei Deine Überlegungen zu.
Ich hab so einen Slot und ja, ich könnte dies ausprobieren und
entsprechend implementieren. Das ganze würde dann über zwei Funktionen
in mmc.h / mmc.c implementiert werden. Nämlich:
- u08 mmc_present()
- u08 mmc_protected()
Diese kann der User nach belieben selber aufrufen. Ausserdem werden
diese in mmc_init() mit aufgenommen. Sollte keine Karte vorhanden sein
bzw (bei write-Funktionalität) diese schreibgeschützt sein, so werden
entsprechende Status-Codes zurückgeben. Das ganze wird natürlich per
#define abschaltbar :-) Und je nachdem, ob write-Support drin ist oder
nicht, werden nur die erforderlichen Methoden kompiliert.
Da ich nur am WoE zum Testen komme kann das ganze aber doch 2 bis max. 3
Wochen dauern. Geht halt nicht schneller
cu, Michael
Erstmal danke für die Lib, funkt sehr gut bei mir. Nur eines, was es
vielleicht Anfängern erleichtern könnte:
In der mmc.h steht:
#if defined (_AVR_ATmega16_)
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte
angeschlossen ist
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte
angeschlossen ist
...
Der Satz "Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
" drückt, denk ich, das Gegenteil von dem aus, was er sagen soll. Weil
SPI_DI ("Data in") der MOSI pin ist, also der Data Output vom Master und
nicht von der Karte. Vice versa für SPI_DO.
Vielleicht kann man einfach MOSI/MISO/SCK/.... in die Comments
schreiben.
Nur so als Vorschlag.
Danke nochmal,
mik
Naja, ich dachte da ist der DataIn der Karte gemeint. Aber MOSI/MOSI
wäre sicherlich eindeutiger.
Eine globale Configdatei würde ich auch befürworten. Ich habe sie mir
für mein Projekt selbst angelegt, weil ich da sehr viele verschiedene
Defines habe, die ich zentral editieren können will. Wenn man auch in
diesem Code hier eine globale Configdatei macht, ließe sich deren
Include-Anweisung einfach rauskommentieren um eine eigene Configdatei zu
erwenden.
StrangeMan
Hallo, zusammen.
@Michael Z. (incunabulum)
Ja wäre cool wenn du das so machst mit dem Slot. Eilt auch nicht so ...
@StrangeMan (Gast)
Die mmc-0.5.5.1.zip hat schon eine solche config.h
@ Michael M. (mikmik)
Du benutzt nicht die Version mmc-0.5.5.1.zip ?
Da ist zwar die Dokumentation in der mmc.h noch nicht auf MISO/MOSI usw
umgestellt aber mit den defines ist es einfach übersichtlicher
Man könnte das noch etwas verkürzen:
1
unsignedcharffexists(unsignedcharname[]){
2
returnfat_loadFileDataFromDir(name);
3
}
Und als Abfrage:
1
if(TRUE==ffexists((unsignedchar*)"MAIN C "){
2
3
irgendwasmachen
4
}
Da das ja aber eigentlich nur eine Zeile ist und man sich wenn man das
direkt machen würde wie z.B :
1
if(TRUE==fat_loadFileDataFromDir((unsignedchar*)"MAIN C "){
2
3
irgendwasmachen
4
}
auch eine Funktionsaufruf spart hatte ich das nicht extra geschrieben :)
Ist zwar fragwürdig ob man bei sowas sparen muss aber egal.
Grüße Daniel
Ach ja, was mir da noch einfällt,
wenn man im Überschreibenmodus eine Datei öffnet bekommt man auch
OPENED_TO_READ zurück. Es gibt die Datei ja schon die man überschreiben
möchte. Wenn man sich einmal für OVER_WRITE entschieden hat, kann man
wild in der Datei rumschreiben...
Grüße
Moin Daniel,
hier also die entsprechende Erweiterung deiner Lib. Status-Pins (card
present, card protected) werden nun berücksichtigt, so entsprechend in
config.h aktiviert. Die wichtigen Änderungen meinerseits findest du nach
dem Tag // mz:
Die eigentliche Konfiguration erfolgt in mmc.h unten. Dort werden die
Pins etc. entsprechend gesetzt. Das ist fast 1:1 von Roland Riegel
kopiert. In mmc.c sind dann die entsprechendne Methoden definiert und in
mmc_init() eingebunden.
Anmerkungen:
0) Ich habe einige zusätzliche Return-Werte mittels Define gesetzt. Das
macht die Lib imho lesbar. Fehlt nur noch die Doku :-)
1) FALSE sollte immer (int) 0 sein. Ansonsten ist ein Test über
if(someBoolMethod()) nicht möglich, sondern es wird immer ein expliziter
Vergleich if(true==...) benötigt.
2) defines: Ich habe mal alle Defines umgeändert, so dass diese immer
als Präfix MMC_ aufweisen. Dies ist gängige Syntax, da man hierdurch im
Code zumindest erraten kann, welches Define für was herangezogen wird.
Oder wüsstest du, woher WRITE kommt, so diese Directive in main()
vorkommt?
2b) OPENED_TO_READ und OPENEND_TO_WRITE sind imho nicht ganz korrekt.
Siehe die Problemtatik bem überschreiben. Ergo habe ich diese wieder
unbenannt zu MMC_FILE_NEW, MMC_FILE_EXISTS. Das trifft die Tatsache
besser, denke ich.
Comments?
cu, Michael
Hallo,
ja sieht soweit gut aus.
In der SdCard.h ist das c++ ? Da steht was von namespace ?!?
Hatte jetzt noch nicht die Zeit mir alles mal genauer zu Gemüt zu
führen, mache ich aber heute Abend.
Zu den defines,
FILE_NEW und FILE_EXISTS find ich gut.
Allerdings hast du ja jetzt alle defines in MMC_xxx umbenannt. Bringt
also genau so viel wie gar kein Präfix, oder hab ich da was falsch
verstanden? Außerdem gibt es defines die in allen Dateien vorkommen wie
z.B. MMC_WRITE (alias WRITE) auf was sollte man sich da jetzt festlegen?
Werde das aber aufgreifen und mal sehen ob man das nicht noch etwas
bessert ordnen kann.
Generell, wenn man etwas in Großbuchstaben sieht ist es ein define und
die sind immer in der config.h, das ist doch auch schonmal was :)
Danke für die Hilfe und Mitarbeit.
Grüße Daniel
Moin Daniel,
ja, da ich komplett mit C++ entwickel, ist die SdCard.h ein einfacher
Wrapper für CPP. Das kannst du also ignorieren. Dieser packt die ganze
MMC-Funktionen in einen eigenen Namespace und verwendet eine
Methodenbennenung, wie ich sie sonst verwende. Also Camel-Case anstatt
Unterstriche.
> Zu den defines,> Allerdings hast du ja jetzt alle defines in MMC_xxx umbenannt. Bringt> also genau so viel wie gar kein Präfix, oder hab ich da was falsch> verstanden?
Ich glaube ja. Nem mal an, dass du zwei Libs verwendest. a) Deine MMC
und b) eine EEPROM Lib. Beide definieren ein #define WRITE. Solltest du
nun in main() beide Libs importieren, so hast du das Problem, dass WRITE
aus der mmc oder der EEPROM lib kommen kann. Weiterhin kann es sein,
dass diese auch noch mit unterschiedlichen Werten definiert ist. Und
dann?
So, wie ich deine Lib sehe, wird das Problem nicht auftreten, da eben
config.h nur von den mmc-headern und sourcen und nicht von "extern"
included wird. Dennoch finde ich es für den Fall, dass dies aus
"Dummheit" doch jemand machen sollte, eine gute Idee, die Quelle durch
das MMC_ Präfix deutlich zu machen.
> Außerdem gibt es defines die in allen Dateien vorkommen wie> z.B. MMC_WRITE (alias WRITE) auf was sollte man sich da jetzt festlegen?
Äh, das Präfix MMC bedeutet (imho) nicht, dass diese aus der MMC.h
stammt, sondern dass es ein define aus deiner mmc-lib ist. So hab ich
mir das jedenfalls gedacht :-)
> Generell, wenn man etwas in Großbuchstaben sieht ist es ein define und> die sind immer in der config.h, das ist doch auch schonmal was :)
Jenau :)
> Danke für die Hilfe und Mitarbeit.
Ich will ja auch was :-) Nämlich die Funktionen die ich brauch und zwar
ohne manuelles Merging bei folgenden Versionen
cu, Michael
Hi,
ich wollte eben die neuste Version der SD-Kartenroutine ausprobieren und
bin erschrocken!
Warum ist eine UART Routine mit in das Gefecht eingewoben worden?! Macht
das Sinn?
Ich verpacke doch auch nich in eine UART-Routine ein I²C, nur weil ichs
kann.
Das is doch am Thema vorbei, ober sehe ich das Falsch?
Gruß
Hallo,
bin immer noch nicht dazu gekommen mir alles anzusehen, aber so viel
wurde ja auch nicht geändert...
>Warum ist eine UART Routine mit>in das Geflecht eingewoben worden?!>Macht das Sinn?
Wie meinst du das ?
Es sind ja in der config.h nur defines dazugekommen, mit denen man seine
eigene uart lib einbinden kann...
Grüße Daniel
Aber warum generell UART in einer SD-Karten-Routine?
Soll diese Routine nicht nur und ausschließlich für SD-Karten sein?
Das bläht das ding nur unnötig auf und wer eine UART überwachung haben
will, der kann das doch auch selber, z.b. in seine main.c, schreiben.
Ich wundere mich bloß warum in der file.c in zeile 210 plotzlich der
dateiname ausgegeben werden soll. wenn ich an meinen UART-Pins aber
andere bausteine angeschlossen hab als ein max232, dann kriege ich
dadurch probleme!
deswegen: warum diese feste UART einbindung?
Stimmt schon, müsste nicht unbedingt rein, aber das ist als Beispiel
gedacht.
Die meisten werden wohl den UART angeschlossen haben um sich z.B. mal
Debug Ausgaben zu machen, oder für Bootloader.
Mach "MMC_SMALL_FS TRUE" und du bist den UART los.
Funktionen wie ffls, also anzeigen von Dateien eines Verzeichnisses,
leben nunmal von der Ausgabe auf eine Anzeige, in diesem Fall die
UART...
Grüße Daniel
Man könnte die Dateinamen mit der Anzahl n und die Größe in zwei Arrays
schreiben, z.B. dateien[n*8], groesse[n] und die zwei per Pointer
zurückgeben.
Dann kann man, wie man will, sich sie per UART, LCD oder sonstwie
ausgeben lassen:
1
for(inti=0;i<8,i++)uart_putc(dateien[i]);
wäre der erste dateiname
1
for(inti=11;i<19,i++)uart_putc(dateien[i]);
wäre der zweite dateiname
usw.
die größe natürlich äquivalent.
oder man schreibt die funktion so um, daß´sie immer nur einen dateinamen
zurück gibt, beim nächsten aufruf den zweiten, ... nachdem der letzt
ausgegeben wurde eine NULL zurückkgibt.
Für die Dateigröße eine zweite funktion, die das selbe macht.
Damit wären die speicherfressenden arrays von meiner ersten idee
umgangen und man kann die rückgabewerte auf LCD, UART etc ausgeben.
grußm
matze
Hm, je mehr ich darüber nachdenke je besser gefällt mir das mit dem
auslagern der UART.
Das auslagern würde ja auch das Problem lösen, an die mitgelieferte
uart.c/uart.h gebunden zu sein. Man könnte dann ja einfach seine eigene
in der main.c includen...
Hallo Daniel,
erstmal danke für die tolle Lib von dir. Habe sie getestet, sie
funktioniert wunderbar.
Nun hätte ich gerne eine ganz kleine Ergänzung in der mmc.h:
statt "#if defined (_AVR_ATmega32_)"
#if defined (_AVR_ATmega32_) || (_AVR_ATmega16_)
weil ich mich erst gewundert habe, wieso es zu fehlern bei meinem
ATmega16 kam.
Weiterhin hätte ich die Frage, ob du mir sagen kannst, wieviele Zyklen
der "ffclose()"-Befehl inklusive der Unterfunktionsaufrufe braucht. Ich
würde das ja selber machen, leider kann ich aber mit assembler nichts
anfangen (die Sprünge in die Unterfunktionen usw. erkenn/versteh ich
nicht).
Die Frage habe ich, weil ich derzeit Daten auf die Karte schreibe
(ffwrites()), und erst bei Knopfdruck den ffclose()-Befehl ausführe.
Wenn aber die Spannungsversorgung zusammenbricht, möchte ich auch
ffclose durchführen (damit ich die Daten auf der Karte sehe) und daher
brauche ich die Zyklenzeit zur Berechnung meiner Kondensatoren in meinem
Spannungsregler.
Hoffe das passt hier hin, gehört ja zu deiner Lib, aber hat halt nicht
direkt damit zu tun.
Gruß
Arne
Guten Morgen,
muss erstmal ein gorßes Lob an Daniel los werden, die Lib läuft bei mir
einwandfrei! Mit den Libs von Roland Riegel etc. bin ich hingegen nicht
zurecht gekommen...
Habe aber trotzdem noch eine Frage:
Wäre es möglich, abzufragen wie viel Speicher auf der SD Card nocht
vorhanden ist? Werde mir gleich im Code von Roland mal ansehen wie er
das abfragt.
Gruß,
Patrick
Hallo zusammen,
@ Arne Z. (Gast)
Das mit dem define, wird aufgenommen, kein Problem.
Die genaue Taktzahl ist schwer zu bestimmen, da sie von mehreren
Parametern abhängt.
Wenn z.B. 256 Cluster am Stück frei waren und du bei ffclose alle
beschrieben hast (aber nicht darüber hinaus !) müssen die ja noch
verkettet werden.
Das macht dann zwei Schreiboperationen von 512 Byte Blöcken in der FAT
aus. Dazu kommt noch das erneute Suchen der Datei im Verzeichnis, was je
nach Größe des Verzeichnisses und Lage der Datei im Verzeichnis immer
unterschiedlich lange dauert. Dann noch schreiben von 512 Bytes um den
Datei Eintrag zu updaten.
Die Zeit für die Schreiboperationen ist nicht wirklich das Problem, aber
die Zeit für das suchen von Dateien schon...
Am besten du ermittelst das Empirisch indem du einen Timer laufen lässt
und verschiedene Szenarien durchspielst.
@Patrick Franken (helipaddi)
Ja ist möglich, man müsste ja nur alle leeren Cluster Nummern in der FAT
zählen, diese mit der Anzahl der Sektoren/Cluster multiplizieren und
schon hätte man das Ergebnis.
Hab momentan leider nicht so viel Zeit, aber werde ich einbauen.
Oder du schaust mal wie weit du kommst und schreibst das, dann nehme ich
es auf :)
Die Funktion "unsigned long int fat_getNextCluster(unsigned long int
oneCluster)" ist da dein Freund.
Spätestens nächste Woche hab ich massig Zeit.
Grüße Daniel
(nun nichtmehr Gast, sondern angemeldet)
Hallo Daniel,
danke für deine Antwort. Dann werde ich wohl mal verschiedene Szenarien
bauen und die Zeiten überprüfen, so dass ich meinen Kondensator
berechnen kann.
Und dann hab ich noch zwei Fragen: und zwar habe ich derzeit eine
Funktion, die vor main() läuft, die die Datei öffnet und ans Ende geht.
Dann wird in der main() alle 1sek bis 8 Stunden in der Datei einen
Messwert aufgezeichnet. Erst wenn ich den Stop-Knopf drücke, wird
ffclose ausgeführt. Gehen meine Daten verloren, wenn ich zu lange kein
ffclose ausführe, oder aktualisiert ffclose nur das fat und verkettet?
(also die Daten sind physisch auf der Karte, nur man sieht sie nicht)
Weiterhin gibt es eine Methode, wenn ich Daten geschrieben habe, aber
nicht ffclose ausgeführt habe, die SD-Karte zu "reparieren", so dass
meine Daten sichtbar werden?
Danke schonmal,
Arne
Hallo,
ja die Daten sind physikalisch auf der Karte. Allerdings nur in 512 Byte
Blöcken.
Wenn du weißt, es passiert 8 Stunden nix, wäre ein ffclose zwischendurch
ja nicht so schlimm.
Soweit mir bekannt ist, gehen Dateisysteme davon aus, dass Cluster die
zu einer Datei gehören immer aufsteigend gesucht werden. Daher habe ich
es so gemacht, dass die Datei schon beim öffnen Physikalisch angelegt
wird, also mit Dateieintrag und Startcluster. Die freien Cluster die für
die Datei dann verkettet werden, werden ab dem Startcluster der Datei
gesucht.
Das bietet den PC Data-Recovery Tools die Möglichkeit der Datenrettung.
Obwohl so einmal mehr der Dateieintrag geschrieben werden muss, am Ende
ja auch wegen der Dateigröße. Funktioniert allerdings nur zuverlässig
bei einer Datei...
Grüße Daniel
Hallo Daniel!
Erst mal hochachtung vor deiner Arbeit. Hab den Code für den
ADUC7024(ARM) portiert.Nach fast 2 Wochen teilweise frustrierender
Arbeit,Schuld sind die Arschlöcher von SD-Karten Herstellern, die keine
vernünftigen Datenblätter herausgeben, läuft das Ganze nun einigermaßen.
Allerdings sind da 2 Punkte, die mich noch etwas beschäftigen:
1.)Nach dem Schreiben eines Sektors(Zeit: ca. 2ms) gibt die Karte
innerhalb eines Bytes 0xE5 (Daten akzeptiert) aus.Danach geht Data out
der SD auf 0(busy) und bleibt dort für gut 5ms.Während dieser Zeit,kann
man keine Kommandos an die Karte senden,sondern muß warten, bis Data out
1 wird. Damit komm ich auf einen Zyklus von ca. 7ms für 512Bytes = ca
70KB/s.Nicht gerade berauschend.Ich hab dann noch eine SanDisk Ultra II
2GB probiert, die ging dann mit ca. 110KB/s(busy-Phase war deutlich
kürzer). Frage: wie kommen die Leute auf 150KB/s und mehr? Mach ich was
falsch?
2.)Es gibt bei mir das Problem, wenn ich immer das selbe File öffne,
Daten hinzufüge und wieder schließe,dass auf einmal falsche Sektoren
beschrieben werden,und das File für den PC unleserlich wird.
Interessanterweise tritt das erst bei einer Filelänge > 0x1000000 (16MB)
auf. Mit 1x öffnen, schreiben und schließen hab ich aber auch schon 50MB
files erzeugt,die der PC lesen konnte. Nach einem rudimentären Debug
könnte der Fehler in ffseek liegen,kanns aber noch nicht genauer
festmachen.
Gesehen hab ich in diesem Tread noch nichts,was auf ein solches Problem
hinweist.Möglicherweise ist's aber auch noch nicht aufgefallen,oder ich
hab beim portieren Mist gebaut.
Ach ja, die verwendete Version ist 5.4,die Karten sind FAT16 formatiert.
Grüße Gebhard
Hallo,
@ geb (Gast)
Hast du die Karte über SPI angeschlossen? Wenn ja mit welcher
Geschwindigkeit? Ich habe hier MMC Karten (die sind meist bisschen
schneller als SD) die machen 200KBytes/sec schreibend und 270KBytes/sec
lesend. Das bei 10 mhz SPI Takt und im nicht überschreiben Modus.
Bei der Version 5.4 gab es tatsächlich ein Problem in ffseek im
Zusammenhang mehrfachem anlegen von Dateien. Nimm am besten die 5.5.1
von hier
http://www.mikrocontroller.net/attachment/58218/stable-mmc-0.5.5.1.zip
,ist aber auch schwer zu sagen ob da nicht vielleicht doch auch beim
portieren was falsch gelaufen ist. Wenn du magst, poste doch mal deine
geänderten Routinen, dann kann man mal drüber schauen :)
So schönen Wahl Sonntag noch :)
Hallo!
Mir ist aufgefallen, dass, wenn ich innerhalb eines Interrupts eine
Datei öffne, sich das Programm nach dem Interrupt resetet. Komisch.
Ich hab's umgangen, indem ich einen Funktionszeiger eingerichtet habe,
der im Interrupt auf die auszuführende Funktion (die, die die Datei
öffnet) gesetzt wird. Das Hauptprogramm prüft in einer Endlosschleife
verschiedene Dinge, und führt dabei immer mal diese Funktion aus. Damit
verlagere ich dieses Öffnen ins Hauptprogramm und die Probleme sind weg.
Ich hab aber keine Ahnung, warum sich der AVR da resetet... Irgendwas
mit dem Stack oder so? Wie gesagt, das reseten passiert am Ende der ISR.
StrangeMan
Hallo Daniel!
Mein Geschwindigkeitsproblem liegt an der langen busy Phase der SD
Karte.
Reine Schreibdauer ca. 2ms/sektor, busy ca. 5ms(lt.
Oszilloscope).Sicher,die max. 3,24Mhz SPI Takt sind auch nicht gerade
berauschend, da hat sich Analog Device nicht gerade mit Ruhm bekleckert.
Ich werd jetzt mal die Vers. 5.5.1 portieren, und wenn das wirklich
stabil läuft,hab ich die Idee, das fread und fwrite als Statemachine
auszuführen und die SPI interruptgesteuert zu verwenden. Damit könnten
diese Funktionen im Hintergrund laufen und würden nur mehr minimale
Prozessorzeit beanspruchen(die meiste Zeit wird ja jetzt eigentlich nur
gewartet).
Grüße Gebhard
Huhu,
Ich habe nun mal gemessen, wie lange ein ffclose() dauert. Dabei kam ich
auf Werte zwischen
216.664 und 378.200 Takte (bei ATMega 16 @ 16MHz).
Im Durchschnitt lag ich bei 260.000 Takten (der große Wert war wohl ein
statistischer "Ausrutscher" ^^).
Die Werte änderten sich zwar immer, aber ob die Karte nun voll war, oder
komplett leer, hatte irgendwie keinen Einfluss.
Daniel, weißt du zufällig, ob das realistische Werte sein können?
Hast du evtl. noch eine Idee für einen "Worst Case" Fall?
Gruß
Arne
Hallo!
Hab die Vers. 5.5.1 für ADUC702x(ARM7) portiert und läuft soweit
fehlerfrei.
Weiters hab ich in mmc.c eine Unterstützung für SDHC Karten eingebaut
und die Schreibperformance durch verkürztes warten auf das Ende der
"busy" Phase verbessert.
Mit den SanDisk Ultra-Karten(SD 2GB und SDHC 4GB) kann ich jetzt doch
150kB/s schreiben, bei 3,24 MHz SPI clock(gähn).
Ich stell mal mein mmc.c hier rein zum testen.
Grüße Gebhard
Hallo zusammen.
@ Arne Z. (theich)
Also ich müsste da selbst mal ein bisschen messen um das zu sehen. Nur
rein theoretisch müsste die Zeit um eine Datei zu finden abhängig von
der Anzahl der Dateien sein die in dem Verzeichnis sind. Je mehr Dateien
umso länger die Such Zeit.
Sagen wir mal man kann mit 200 KBytes/s lesen, das macht dann ungefähr
400 Sektoren und somit 6400 Datei Einträge (weil 16 pro Sektor). Ist die
gesuchte Datei jetzt die letzte, also Datei Nummer 6400, dauert es
mindestens 1 Sekunde um diese zu finden. Man muss die ja aber bei
ffclose finden, um den Datei Eintrag zu updaten, das ist das Dilemma.
Bei deinen Werten habe ich raus, 0,01625 Sekunden also 16,25 ms. Ist
jetzt zwar ne Milchmädchen Rechnung, aber das würde Pi mal Daumen so 6-7
Sektoren bedeuten, also ungefähr 112 Dateien durchsuchen....Oder
weniger, wenn vorher noch paar Daten Sektoren geschrieben wurden.
Mach mal ein Verzeichnis mit sagen wir 2000 Dateien (kleinen Dateien)
und ändere dann die zuletzt drauf geschriebene ab. Da müsste sich der
Overhead des Suchens deutlicher bemerkbar machen :)
@ geb (Gast)
Äh verkürztes warten? Kannst du dazu etwas mehr sagen, bitte.
Unterstützung für SDHC klingt auch gut. Ich werde mir deinen Code mal
genauer anschauen :)
PS:
Hat nich mal irgendwer Lust eine FAQ auf
http://www.mikrocontroller.net/articles/AVR_FAT32 zu machen, wo man mal
so alle Try-and-Error-zum-Erfolg Sachen zusammen trägt? Schön wären ja
auch alle möglichen mmc.c/mmc.h für unterschiedliche Plattformen. Bei
mir geht nächste Woche das Semester wieder los => wenig Zeit...
Grüße Daniel
Hiho,
@Daniel,
habe nun mal 2000 Dateien im Bereich von 1-10KB auf die SD-Karte
geschrieben, als letztes die Datei, in der ich schreiben möchte. Nun kam
ich auf Werte von 7.645.224 bis 10.433.112 Takten.
Wow, dafür habe ich meinen Kondensator nicht ausgelegt, also darf in
meinem Verzeichnis keine andere Datei vorhanden sein, damit ich unter
880.000 Takten bleibe.
---
Übrigens, wenn das Semester los geht, hat man doch gerade viel Zeit,
erst zum Ende hin wird es immer knapp (zumindest ist/war es bei mir so)
---
Gruß
Arne
Hallo.
Ja die Werte sehen realistisch aus, leider.
Es gibt bei Conrad 1F bis 5 Volt Goldcaps für um die 2 Euro, auch in
kleiner Bauform. Davon ein paar und das zeug läuft Minuten lang noch :)
Wenn du jetzt 2000 Verzeichnisse mit nur einer Datei drin hast, wird das
auch nicht besser (nur als Beispiel), eher schlechter. Große
Betriebssysteme indizieren deshalb Dateien, um nur Indizes vergleichen
zu müssen, wie bei Datenbanken...
Man könnte vielleicht auch das suchen etwas beschleunigen indem man z.B.
nur den ersten Buchstaben der Datei überprüft und erst wenn der stimmt
weitere Buchstaben. Da mach ich mir mal Gedanken dazu...
Zeit hab ich leider nie genug und dieses Semester wird noch schlimmer...
Grüße Daniel
Noch ein spassiges Problem ist mir in Verbindung von meinem mmc.c
aufgefallen:
Nach dem Schreiben des letzten sektors (file_Update) warte ich nicht bis
die Karte nicht mehr busy ist.(Der Wert 0xE5 als "Daten akzeptiert" ist
das Letzte was ich von der Karte lese.)
dieser letzte Sektor wird bei manchen Karten z.B. Kingston nicht mehr
ins Flash geschrieben. Damit wird das fclose unwirksam und die letzten
geschriebenen Daten (seit letztem öffnen der Datei) gehen verloren.
Offenbar brauchen diese Karten in der busy-Phase den Clock um die Daten
aufs Flash zu speichern. Sandisk-Ultra Karten haben dieses Problem
interessanterweise nicht.
Abhilfe: letzten sektor bei file-update 2x schreiben, oder hier extra
busy Phase abwarten.
Grüße Gebhard
Hallo Daniel,
ich hab ein kleines Problem beim Schreiben von Daten auf SD-Karte.
Ich möchte eine Datei erstellen, Daten rein schreiben, Datei schließen.
In gewissen zeitlichen Abständen möchte ich diese Datei wieder öffnen,
weitere Daten anhängen und Datei wieder schließen.
Beim Erstellen der Datei und beim Speichern des ersten Datensatzes
klappt auch alles wunderbar. Will ich Datei jedoch zum Anhängen von
weiteren Daten mit
ffstatus = ffopen(file_name);
erneut öffnen, liefert ffopen als Rückgabewert 2 (datei muss angelegt
werden) obwohl sie bereits existiert. Die Daten werden dann auch nicht
in die Datei geschrieben. Es sind nur die Daten des ersten
Schreibzugriffs vorhanden.
Ich benutze die AVR-Studio Version 0.5.5
Gruß Kai
Hallo.
@ geb (Gast)
Man muss doch eh pollen ob die Karte busy ist oder nicht. Damit sendet
man doch schon takte...
Orientier Dich da doch an der orginal mmc.c.
Meinst du mit file-update die Funktion flushFileData() ? Wenn ja, die
ist nur für den internen Gebrauch in der file.c. Der User sollte die
nicht benutzen, na ja vielleicht zu Test Zwecken...
@ Kai J. (tairon)
Das klingt seltsam. Wie sieht der String auf file_name aus?
Zeig doch mal den Code mit dem du zuerst die Datei beschreibst. Hast du
irgendwo etwas am Code geändert?
Grüße Daniel
Das hab ich gemacht. Ich bekomm aber vorher schon bei
ffstatus = ffopen(file_name);
eine 2 als Rückgabewert und nicht eine 1.
Ich schätze aber es liegt an meiner UART Routine. Ich benutze die
Library von Peter Fleury.
Moin,
habe mir einen Code geschrieben, um zu sehen wie lang ein ffseek()
(5.5.1) braucht.
Die Datei "1M.TXT" ist 10240 bytes groß, auf einer 1GB FAT32 Karte.
1
while(second<60){
2
uputc(ffopen("1M TXT"));
3
uputs("S");
4
ffseek(file.length);
5
uputs("D");
6
ffclose();
7
}
Beim ffseek knallts. Ich sehe das "rS", das "D" aber nicht mehr. Bei
einer Dateigröße von 1024 bytes funktioniert der Code tadellos.
Irgendjemand eine Idee?
Hallo,
@ Kai J. (tairon)
Kann ich irgendwie nicht nachvollziehen wieso die Uart lib daran schuld
sein soll. Du hast aber mindestens auch noch "#define SMALL_FILE_SYSTEM"
geändert, sonst geht nämlich ffwrites nicht.
@ Gast (Gast)
Ok, teste ich mal. Mit wie vielen Sektoren/Cluster ist denn das
Formatiert, damit ich gleiche Voraussetzungen habe ?
Grüße Daniel
einschränken können.
Ablauf:
file.c (ca. Zeile 163): fat_getFatChainClustersInRow(fat_getNextCluster(
file.lastCluster )) ;
fat_getNextCluster( file.lastCluster ) klappt soweit, geht dann in
fat_getFatChainClustersInRow() und hängt sich da irgendwo auf.
@Daniel
Das ist eben der springende Punkt,in meiner mmc.c polle ich nach einem
sektor-write nicht auf busy,sondern bereite schon die nächsten daten zum
Schreiben vor. Auf "busy" wird dann beim nächsten write-command
gepollt,in der Hoffnung dass das blöde Ding in der Zwischenzeit die
Daten schon mal geflasht hat. ==>funktioniert bei Sandisk tadellos und
erhöht die Schreibrate um 40%,bei Kingston bringts nichts(ohne CLK
offenbar kein flashen).Schon sehr interessant, wie unterschiedlich die
SD Karten sind.
Grüße Gebhard
Hm, wenn der falsche Sektor geladen wird, geht natürlich nix mehr
(fat_loadSector).
Das ist ja keine Variable, sondern ein void Pointer, der zuerst mal auf
nix zeigt, dann aber auf bytesOfSec=&fat.sector[j] , also auf eine
bestimmte char Adresse im Puffer für einen Sektor.
Von dieser "Start Adresse" wird jetzt je nach FAT Typ auf 2 oder 4 Byte
Größe gecastet.
Mit was Kompilierst du den Code? ich hab da mit dem GCC für linux und
dem AVR-GCC keine Probleme. Kann das irgendwie nicht richtig
reproduzieren, werde da aber mal genauere Tests machen. Bis jetzt kann
ich leider keinen Fehler finden...
@ Gebhard
Ich glaube es ist SD Spezifikation das die Karte "CLK hörig" ist, ist
also ein Geschenk, das es mit Sandisk funktioniert...
Grüße Daniel
@Daniel:
gcc 3.4.6 AVR-CrossPack.
Ich lasse mir vor jedem return in fat_getNextCluster den Wert von
bytesOfSec ausgeben mit:
1
putNum(*(unsignedlongint*)bytesOfSec,'w');
Die Funktion macht nix anderes als den übergebenen Wert (unsigned long
int) als Tausender, Hunderter etc. auszugeben. Das 'w' dient der
Unterscheidung. Die Ausgabe schaut so aus:
w00135
w00136
w00137
w00138
w00139
w�P15
w�P15
Die letzten beiden Werte sind IMHO keine korrekten Werte.
Joa, hab ich.
Auch mit nem image von ner Karte mit 8 Sektoren/Cluster.
Wo hast du den 3.4.6 Compiler her?
So, hab mal folgendes:
1. Mit Linux Kompiliert, Fat-resource als "/dev/mmcblk0" eingebunden und
mit der Lib 5.5.1 getestet. Ohne Probleme.
2. Mit Linux Kompiliert und Fat-resource als Image einer Karte
eingebunden. Mit Lib 5.5.1, ohne Probleme.
Kannst du Vielleicht ein Image der Karte machen und mir schicken, damit
ich mit der gleichen Karte testen kann, aber anderen Kompilern usw.?
Grüße Daniel
Okay, das Problem scheint nur aufzutauchen, wenn ich eine Datei lesen
will, die am PC erstellt wurde. Wenn ich eine entsprechend große Datei
mit der Lib generiere, ist alles ok.
Das ist mal seltsam.
Ist die Datei die du dann mit der Lib erstellt hast, denn auf dem Pc
lesbar usw.?
Was definitiv nicht geht ist eine mit Linux Formatierte Karte, da Linux
aus welchem Grund auch immer das Root-Dir, wenn es nur 1 Cluster groß
ist nicht mit 0xfffffff0 abschließt sondern anders.
Mein Interesse an einem Image der Karte besteht immer noch.
Grüße Daniel
Die Datei ist am PC lesbar, ja. Der einzige Unterschied ist, dass ich
bei einer auf dem Atmega erstellten Datei "0FFFFFFF" als bytesOfSec
sehe, und bei der am Mac erstellten das Ganze zwei mal. D.h. die
Funktion wird unnötigerweise nochmal aufgerufen.
Auf dem Mac macht das die GUI :).
Und die führt den Befehl newfs_msdos mit Optionen aus.
Huhu,
ich habe noch mal eine kleine Frage:
Und zwar möchte ich gerne in einer geöffneten Datei, Werte lesen und
danach wieder ans Ende schreiben, mein Programmablauf sieht wie folgt
aus:
ffopen(datei); -> ffseek(file.length); -> 1 bis x-mal ffwrites(werte);
-> ffseek(file.seek+fat.cntOfBytes - (68*100)); (ist die Stelle der
Datei, von der ich lesen möchte) -> 100-mal ffread() ->
ffseek(file.seek+fat.cntOfBytes);
Mein Problem ist nun, dass er mit dem letzten ffseek nicht an die
richtige Stelle geht, damit ich weiter schreiben kann.
Gibt es nun eine Möglichkeit ohne ffclose() mit gefolgten ffopen(datei),
an die richtige Stelle der Datei zu kommen, damit ich weiter
hineinschreiben kann? Also quasi "Fat aktualisieren / file.length
aktualisieren" ohne neue die Datei zu schließen+öffnen?
Grüße
Arne
ffseek-Problem schrieb:
> So, habe mir das Ganze nochmal genauer angeschaut. Der ffseek() hängt> hier:>> mmc.c, mmc_read_sector(...):>>
1
>while(mmc_read_byte()!=0xFE){};
2
>
> Komischerweise bekommt er nur 0xFE zu lesen.
Sieht nach Compiler bzw. Linker Problem aus.
Versuche einmal ein "make clean" und dann ein "make".
Wenn's danach immer noch nicht geht, versuche eine andere
Toolchain/WinAVR Version.
make clean bringt nichts. Habe mal gcc 4.3.2 genommen. Auch keine
Änderung.
Ein Stack-Overflow kann es nicht sein, da die Funktion, so wie ich das
sehe, vorher mehrfach problemlos betreten und wieder verlassen wird.
@Daniel:
Wie erstelle ich das Image der SD, und wie soll ich es Dir zukommen
lassen?
Hallo zusammen.
Ich habe momentan leider echt viel um die Ohren, komme aber
wahrscheinlich dieses Wochenende trotzdem dazu da nochmal etwas
nachzuforschen.
@ Arne Z. (theich)
Du müsstest "#define OVER_WRITE TRUE" machen und dann zwischen schreiben
und lesen die Dateilänge merken, damit du nach dem lesen ein seek dahin
machen kannst.
Ungefähr so:
ffopen(datei); -> ffseek(file.length); -> 1 bis x-mal ffwrites(werte);
-> unsigned long int tmp=file.seek+fat.cntOfBytes;
->ffseek(file.seek+fat.cntOfBytes - (68*100)); (ist die Stelle der
Datei, von der ich lesen möchte) -> 100-mal ffread() ->
ffseek(tmp);-> weiter schreiben an Dateiende.
Das müsste klappen.
@ ffseek-Problem (Gast)
Ich bräuchte als Image einfach eine Datei, in der alle Sektoren der
Karte stehen, bzw alle Bytes. Ich mache solche Images meistens mit
WinHex. Bei einer 1GB Karte wäre es aber wohl am besten nicht alle
Sektoren in die Datei zu packen, sondern nur die die mit Daten belegt
sind. Also von Sektor 0 bis zu dem letzten Sektor mit Daten...
Wie groß wird diese Datei dann bei dir? Geht die noch per Mail?
Grüße Daniel
@ffseek-problem (Gast)
Image ist soweit Ok. Habe jetzt noch nicht auf realer Hardware getestet,
mach ich aber gleich. Das sieht aber alles soweit Ok aus. Auf Linux mit
dem gcc geht es problemlos, was schonmal bedeutet, das der Code an sich
keinen Fehler verursacht.
Kann dann eigentlich nur am Compiler oder der Hardware liegen.
War die Karte auch schon so formatiert bei diesen Tests
Beitrag "Re: MMC SD library FAT16 FAT32 read write" ?
Bei dem jetzigen Image sind die Cluster [124-148] belegt, mach in Summe
25. Das macht bei 8 Sec/Clust 102400 Bytes. Das kommt alles hin. Die
Cluster sind in der Fat auch richtig verkettet und Terminiert...
Grüße Daniel
@ Daniel:
Ich habe auch noch ein paar Tests gemacht und folgendes festgestellt:
Es ist egal, ob ich die Karte auf einem Mac oder einem Windows Rechner
formatiere. Und es ist egal, ob die Datei als einzige auf der Karte
existiert
oder schon andere Dateien physisch vor der Datei liegen.
Ich weiß jetzt leider nicht mehr, wie die Karte bei den Tests, die Du
meinst, formatiert war. Es sollte aber wegen meiner vorhin beschriebenen
Beobachtung unwichtig sein.
Ich habe inzwischen auch mal eine andere SD-Karte probiert, und das
ganze wegen Stack-Bedenken auf einen Mega32 portiert. Immer mit dem
gleichen Resultat.
Die Hardware möchte ich als Fehlerquelle ausschließen, da Sie nach der
Spec von SanDisk aufgebaut ist. Ich werde als nächstes das Ganze mal mit
WinAVR kompilieren und testen. Kannst Du mir sagen welche Version Du
nutzt?
Negativ. Auch wenn ich es mit WinAVR unter Windows mache gibt es immer
den gleichen Fehler. Habe auch auf von 8MHz auf 4MHz heruntergetaktet.
Kein Unterschied.
Vielleicht hilft Dir das noch weiter.
Im Fehlerfall ist bei FAT32:
- in der Funktion fat_getNextCluster():
i = 0x001FFFFF (2097151 dezimal)
fat.fatSec = 0x00000119 (281 dezimal)
- in der Funktion fat_loadSector(), die ja im Anschluss mit i +
fat.fatSec aufgerufen wird
sec = 0x00200118 (2097432 dezimal)
Bei einer Speicherkarte mit 1 GB hab ich Brutto (1024 1024 1024)
Byte / 512 (Byte / Sektor) = 2097152 Sektoren.
Wenn ich das also richtig sehe, versucht der anschließende
mmc_read_sector() auf einen Sektor (2097432) zuzugreifen, der gar nicht
mehr existiert, da die Speicherkarte nur 2097152 Sektoren hat.
Kann das sein?
Das Problem ist, es gibt verdammt viele Möglichkeiten wie das was schief
gehen kann. file.lastCluster wird in fat_getFatChainClustersInRow()
gesetzt...
Wenn ich jetzt halt deine genaue Anwendung der Lib sehen könnte, hätte
ich das Image und hätte somit alles genau so wie du. Dann wohl auch den
gleichen Fehler.
^^ huch zu langsam ;)
Achso...
AVR Memory Usage
----------------
Device: atmega8
Program: 7218 bytes (88.1% Full)
(.text + .data + .bootloader)
Data: 990 bytes (96.7% Full)
(.data + .bss + .noinit)
Sollte ich mir wegen letzterem Sorgen machen? Immerhin hatte ich das
Problem auch bei einem Mega32, der ja 2K RAM hat.
>Data: 990 bytes (96.7% Full)>(.data + .bss + .noinit)
Ist schon ziemlich eng. Mach doch die Ausgaben kürzer wie z.B
> uputs("main ffclose done\r\n");
zu uputs("mcd\n"); oder so
Okay, ich habe jetzt mal den kompletten Unterbau (mmc, file, fat)
ersetzt durch den aus der 0.5.5.1 Lib. Nur die main() habe ich so
gelassen. Keine Änderung. Ausgabe:
Waiting...
main ffopen
main ffseek
Das war's.
Program: 6182 bytes (75.5% Full)
(.text + .data + .bootloader)
Data: 686 bytes (67.0% Full)
(.data + .bss + .noinit)
Hi Jungs,
verfolge mit Spannung euer Problem.
Vielleicht doch ein Hardwareproblem.
Bricht eventuell die Versorgungsspg zusammen ???
Sollteste mal mit einem DSO überprüfen.
Noch viel Spaß
Gruß
Siegmar
Da bin ich platt. Wohnst du zufällig in der Nähe von Köln?
Die Datei ist auf jeden Fall auch vorhanden?
Lass dir mal die Rückgabewerte der Funktionen ffopen(), ffseek() und
ffclose() anzeigen.
>../mmc/fat.c: In function `fat_loadRowOfSector':>../mmc/fat.c:104: warning: left shift count >= width of type
Ja ist aber nur ein Warning und nicht so wild. Das muss so.
Was der " siegmar (Gast) " da schreibt is mir auch schonmal durch den
Kopf gegangen. Wie ist die Stromversorgung bei der Schaltung?
Du solltest messen, ob die Spg. zusammenbricht.
Diese Möglichkeit muß Du sicher ausschließen und schaue Dir auch die
Flanken der Signale an, ob sie nicht zu rund sind.
Hardwarefehler mußt Du meßtechnisch ausschließen !!
So nun gut Nacht
Gruß
Siegmar
@ Siegmar
Jo, Oszi hab ich nicht. Multimeter grad mal :).
Folgendes passiert:
Waiting...
main ffopen
rmain ffseek
main ffclose
1main ffclose done
main ffopen
Dazu muss ich ein wenig ausholen. Das Ganze funktioniert mit 3V3 wie
folgt.
5V (USB) Vcc -> 3V3 über LDO Regler.
5V (USBasp) Signale <-> 3V3 Signale über Levelshifter.
µC <-> SD über 3V3.
3V3 5V
µC ---- Levelshifter ---- USBasp
SD -+
Zunächst ist der Levelshifter (LS) auf HiZ, damit der USBasp die SPI
nicht beeinflusst. Damit erfolgen die ersten 3 Zeilen der Ausgabe.
Sobald ich den LS aktiviere, erfolgt die Ausgabe der Zeilen 4 bis 6.
ABER gleichzeitig wird der RESET des µC auf GND gezogen (hardwired mit
LS). D.h. eigentlich würde er weitermachen, aber es kommt der Reset
dazwischen.
Werd mal den LS loswerden und die vielen Käbelchen die hier
herumschwirren.
Ein Königreich für ein Oszi.
Scheint also kein Softwareproblem zu sein.
Dennoch fetten Dank an Dich Daniel für die Mühe und Hilfe! Und natürlich
für die Lib!
Joa, kein Problem. Ich habe ja auch Interesse daran, da Fehler zu finden
und an der Qualität zu arbeiten :)
Falls du da weiter kommst, lass von dir hören.
Wenn mir noch was einfällt, meld ich mich auch.
Grüße Daniel
Hallo,
normales Oszi würde Dir da auch nicht so sehr helfen, außer die Flanken
betrachten.Mit einem DSO wäre es kein Problem den Fehler einzugrenzen
bzw. auszuschließen.
Einfach mal einen Referenzaufbau verwenden, der bei Anderen 100%
funktioniert. Daniels Aufbau z.B einfach nachbauen , damit ihr
identische Testbedingungen habt. Die Länge der leitungen zur Karte sind
nicht unkritisch und sollten so kurz wie möglich sein.
Wird schon klappen, bleib dran !
Bin gespannt was es war, laß es uns wissen.
Schönen Sonntsag noch
Gruß
Siegmar
auch bei offset==512 noch einmal durchlaufen, macht der aber nicht, das
Programm stoppt einfach !
Wenn man das "while( offset>512 )" so macht, läuft es durch.
Da muss man mal weiter nachforschen !
Schlimmstenfalls sollte offset mit der >= Bedingung ja 0 werden, was
auch richtig wäre.
So der Bug is weg. Schwere Geburt^^
Der Fehler lag in einer Abfrage in ffseek. Warst da schon auf dem
richtigen Weg.
Es konnte unter Umständen dazu kommen, das da verschiedene Grenzen
aufeinander fallen und dieser Fall nicht abgefragt war.
In der Schleife in ffseek muss bei dem if die Bedingung erweitert
werden...
Es gibt da jetzt auch noch weitere Updates in der Lib.
Zu diesem Thema: Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Was der Arne Z. da machen sollte, kann jetzt wegfallen, solange "#define
MMC_OVER_WRITE TRUE" ist.
Es kann jetzt einfach in der main_simple.c eine eigene uart lib includet
werden, da die funktion ffls() jetzt einen Parameter erwartet. Der
Parameter muss ein Funktionspointer auf eine Funktion sein der Form:
void funktionsName(unsigned char*); zum anzeigen der Daten.
Als Beispiel mit der mitgelieferten uart.c: ffls(uputs); und schon
funktioniert das :)
@ ffseek-Problem (Gast)
Danke für deine Ausdauer und Hilfe.
Ich war nur am Zweifeln, weil ich den Fehler nicht reproduzieren
konnte...
Grüße Daniel
Einwandfrei! Vielen Dank!
PS: Habe die file.h leicht ergänzt:
1
#ifndef _FILE_H
2
3
#define _FILE_H
4
#include"config.h"
Sonst hat er gemeckert:
In file included from ../main.c:8:
../mmc/file.h:22: warning: parameter names (without types) in function
declaration
../mmc/file.h:26: error: syntax error before "unsigned"
Ja doch ein Software Fehler.
Das Problem war, bei mir war der nicht aufgetaucht, da fängt man halt an
wo anders den Fehler zu suchen...
Ich glaube es hatte etwas damit zu tun wie ich besagte 1M.TXT, aus dem
Image gelesen hatte.
Na ja, hat ja dann doch noch geklappt^^
Grüße Daniel
Hallo Johannes,
wie ich lese, beschäftigst Du dich ebenfalls mit dem Thema Soft-SPI und
hast schon eine "Vorab"-Variante am laufen. Daniel möchte das in einer
folgenden Version ja auch generell implementieren.
Ich betreibe hier einen Pollin-AVR mit einer für meine Bedürfnisse
modifizierten Software von ROBUE. Robue hat auf der RADIG-Basis eine
AVR-Steuerung entwickelt. Das funktioniert hier alles prächtig.
Nun möchte ich div. Daten in Tages-Files wegschreiben (Datenlogger).
Hierfür suche ich ein integrierbares "Mini-Dos". Hier scheint gerade
sowas zu "entstehen".
Das MMC/SD Slot (nach RADIG) hängt bei meinem AVR an Port D und
funktioniert mit Radigs Testprogramm im Soft-SPI-Mode (mit invertiertem
Clock-Takt). Nun fehlt nur noch die komplette DOS-Variante als
Soft-SPI-Version. Leider bin ich beileibe kein C-Profi und nicht in der
Lage sowas zu schreiben! Kleine Anpassungen hingegen klappen schon.
Kannst Du mir dein "lauffähiges Projekt" zu Testzwecken zukommen lassen
(d.h. deine xxx.c und xxx.h Dateien im Bundle). Ich könnte dies mal auf
meinem AVR laufen lassen und ggf. einige Schnipsel komplett übernehmen.
Ich arbeite hier mit WIN-AVR.
Herzlicher Gruß aus Franken
Bernhard
Hallo Bernhard.
Was meinst du mit:
>...integrierbares "Mini-Dos". Hier scheint gerade>sowas zu "entstehen".
Meinst du eine Lib die Dateien so auf mmc/sd Karten schreiben kann, dass
die auch am PC gelesen werden können?
Soft SPI sollte kein großes Ding werden. Komme ich sogar dieses
Wochenende dazu, glaube ich zumindest mal.
Grüße Daniel
Hallo Daniel, hallo Bernhard!
Ich hatte für meine Zwecke einfach den Soft-SPI-Code aus der von Ulrich
Radig genommenen mmc.c wieder reinkopiert (den du, Daniel, im Laufe des
Projekts offensichtlich entfernt hattest). Das ging aber nicht (siehe
irgendwo weiter oben) und ich habe einige Delays einfügen müssen -
immer bei den clock-Flanken. Ich hatte dafür einfach _delay_us(1);
genommen, weil es das kleinste Zeitintervall war, was mir einfiel. Diese
Inline-Assembler-delays bekam ich damals auf die Schnelle nicht hin.
Siehe hier: Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Bei deinem Code - ich habe ihn fix im MS-NotePad überflogen - sehe ich
gar keine Delays drin. Wenn es so klappt, dann würde mich interessieren,
wie sicher das läuft. Bei mir ging damals mit ähnlichem (sogar fast
gleichem) Code gar nix.
@Bernhard: Ich kann dir gerne mal das Projekt (bzw. die für dieses Thema
relevanten Dateien - sonst wirds ganz schön viel... ^^) zukommen lassen.
Ich bin nur leider gerade am falschen PC und komme an die Dateien nicht
so schnell ran. Lass mir einfach mal deine Mail-Adresse zukommen.
Grüße,
Johannes Neumann
Daniel, ich schon wieder :-)
Die neuen Config-Optionen wie auch die Idee, den UART als Argument zu
übergeben, ist klasse. Damit ist die Lib schön portabel. Wunderbar &
Danke!
Was mich allerdings wundert ist, wie du den UART-Funktionspointer
definierst und verwendest. Das macht so nicht unbedingt Sinn... Also -
irgendwie definiert wird der Funktor (Funktionspointer) in der Config.h.
Hier:
Warum brauch ich hier den MMC_PRINT_DISPLAY define, wenn danach doch
uputs_ptr direkt aufgerufen wird. Was passiert, wenn ich in der config.h
das entsprechende define ändere?
Andere Ansatz
Warum nicht einfach so etwas:
1
lsRowsOfClust(void(*charHandler)(unsignedcharc)){
2
...
3
(*charHandler)(someChar);
4
...
Die Methode definiert die Signatur des Funktionspointers eindeutig.
Dieser wird in der Methode direkt verwendet. Das #define in config.h ist
unnötig. Und so du willst, so kann dort vielleicht auch noch ein typdef
helfen.
Hallo Johannes,
der Code von Ulrich lief so out of the box nicht bei mir.
Ich dachte es liegt daran, das SCK nicht idle Low ist...aber wo ich so
drüber nachdenke könnte es auch andere Gründe haben.
Für die maximal 8-10 Mhz Soft-SPI Takt der AVR sollte man eigentlich
keine Pause in der Kommunikation brauchen. Da sind die Karten schon
schneller.
Läuft denn http://www.mikrocontroller.net/attachment/60728/soft_spi.zip
das bei dir ohne Probleme? Bei mir mit 5 Verschiedenen Karten schon.
Unterschiedliche Frequenzen hab ich noch nicht ausprobiert, halt nur die
16/20 Mhz...
Daniel, dann bitte auch daran denken, die uputs_ptr calls durch das
übergebene Argument der Methode zu ersetzen :-)
Nur als Hinweis, du machst das schon...
cu, Michael
Hallo mal wieder.
Ich habe eben versucht, die Version 0.5.6 zum Laufen zu bekommen. Dabei
brauche ich aber leider noch einige Hilfestellungen...
Zuersteinmal musste ich bei fast allen ffxxx Funktionen die Argumente
ändern. Denn: Seit der letzten Version, die ich hier genommen hatte,
wurden alle string-Argumente von signed zu unsigned char geändert. Bissl
ärgerlich finde ich, denn jetzt kann man nicht mehr
1
ffcd("ORDNER ");
schreiben, sondern muss das so machen:
1
ffcd((unsignedchar*)"ORDNER ");
Vielleicht kann mir nochmal jemand kurz erklären, wieso das so sein
muss.
Desweiteren bekomme ich massenhaft warnings, die ich nicht einfach so
ignorieren möchte:
1
...
2
In file included from main.c:39:
3
./sd/fat.c: In function 'fat_loadRowOfSector':
4
./sd/fat.c:105: warning: left shift count >= width of type
5
./sd/fat.c: In function 'fat_loadFileDataFromDir':
6
./sd/fat.c:157: warning: comparison is always false due to limited range of data type
7
./sd/fat.c:168: warning: comparison is always false due to limited range of data type
8
./sd/fat.c: In function 'fat_cd':
9
./sd/fat.c:192: warning: comparison is always false due to limited range of data type
10
./sd/fat.c: In function 'fat_loadFatData':
11
./sd/fat.c:527: warning: comparison is always false due to limited range of data type
12
In file included from main.c:40:
13
./sd/file.c: In function 'ffopen':
14
./sd/file.c:29: warning: comparison is always false due to limited range of data type
15
./sd/file.c: In function 'ffmkdir':
16
./sd/file.c:284: warning: comparison is always false due to limited range of data type
17
main.o: In function `flushFileData':
18
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:110: undefined reference to `fat_writeSector'
19
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:113: undefined reference to `fat_setClusterChain'
20
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:115: undefined reference to `fat_makeRowDataEntry'
21
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:118: undefined reference to `fat_writeSector'
22
main.o: In function `ffmkdir':
23
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:288: undefined reference to `fat_getFreeClustersInRow'
24
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:289: undefined reference to `fat_setCluster'
25
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:291: undefined reference to `fat_makeFileEntry'
26
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:301: undefined reference to `fat_writeSector'
27
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:305: undefined reference to `fat_makeRowDataEntry'
28
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:306: undefined reference to `fat_makeRowDataEntry'
29
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:307: undefined reference to `fat_writeSector'
30
Kompilierung fehlgeschlagen.
Diese Vergleichswarnungen kann man so einfach nicht übergehen - immer,
wenn ich so einen hatte, gab es arge Probleme. Was tun? Ist ein FASLE
bzw. TRUE bei meinem avr-gcc was anderes als bei euch? Irgendwelche
Vorzeichenprobleme oder so?
Zudem dieses komische Problem in der ffmkdir und flushFileData: Vor und
hinter diesen Funktionen werden diese angeblichen "undefined references"
aber nicht gemeldet: Warum also findet avr-gcc diese funktionen genau
dort und nur innerhalb dieser Funktonen nicht und wie behebe ich das?
Ich bin ziemlich ratlos...
Danke für Hilfe,
StrangeMan
[EDIT] Oh... ich seh gerade: Mache ich den Schalter für die
Schreibunterstützung an, so verschwinden diese komischen
reference-Fehler...
Ok, nachdem ich alle TRUEs und FALSEs durch mTRUE und mFALSE ersetzt
hatte, gings. Wahrscheinlich hatte irgendeine der Libs, die ich sonst
noch verwende, auch TRUE und FALSE definiert. Nur eben eines der beiden
mit negativem Vorzeichen. Vielleicht sollte innerhalb der mmc-lib ein
eigenes TRUE/FALSE genutzt werden, oder zumindest eine Warnung gemacht
werden, wenn die Werte schon vorher (z.B. von einer anderen lib)
definiert sind.
Nein, ganz ohne delays gehts bei mir nicht. Ich hatte ja oben meinen
Code gepostet. Durch Testen bekam ich heraus, dass man jeweils das
untere der zwei von mir eingefügten Delays in beiden Funktionen
(read/write) entfernen kann. Eins muss aber rein.
Achso: Deine Soft-SPI Routinen gehen bei mir nicht. Kann am
invertiert/nicht-invertiert Problem liegen oder an den (bei mir)
mangelnden Delays. Müsste ich nochmal prüfen (mach ich später).
Könnte man vielleicht einfach in der nächsten Version noch einen
Schalter für das Invertieren einfügen?
Grüße,
StrangeMan
./sd/fat.c:105: warning: left shift count >= width of type
sollte das einzige sein was kommen sollte. Und das ist Ok.
Zu dem TRUE und FALSE, vielleicht mach ich da einfach das "#ifndef" weg,
dann sollte zumindest mal die Compiler Warnung wegen doppeltem
definieren kommen.
Ich muss mal sehen ob ich nicht die Tage mal der SPI Geschichte auf den
Grund gehe. Man müsste das ganze mal mit nem Logic-Analizer zerpflücken,
hab ich aber keinen...
Grüße Daniel
Hallo Daniel, hallo Johannes,
Vielen Dank für Euere Antworten. Soeben habe ich Zeit gefunden um wieder
mal am "Projekt" zu primeln. Habe die SOFT-SPI-Dateien ausgetauscht und
die Pins meines ATMega in der Config angepaßt.
--> FUNKTIONIERTE AUF ANHIEB mit 3 verschiedene Karten (512MB bis 2GB
SanDisk, Transcend, Kodak) sowohl FAT16 als auch FAT32, Super-Arbeit
Daniel!!
Eine Frage hätte ich noch. Ich mußte im File main_simple.c die Zeile:
ffls(uputs);
auskommentieren sonst meckert der Compiler mich wie folgt an:
E:\05_06 mit Soft_spi\default/../main_simple.c:80: undefined reference
to `ffls'
make: *** [MMC-Win.elf] Error 1
Build failed with 1 errors and 1 warnings...
Vermutlich habe ich da nochwas nicht ganz verstanden (eilt aber nicht).
Für Johannes,
vielen dank für das Angebot Johannes, hat sich nun aber erledigt da
Daniel so schnell gearbeitet hat.
Herzlicher Gruß aus Franken
und nochmals MERCI !!
Bernhard
Hallo zusammen!
Bei mir läuft die Library leider noch nicht so reibungslos. Ich habe
auch die SPI erweiterung hinzugefügt. Hat allerdings keine Abhilfe
gebracht Ab und zu erstellt mir der Atmega leider noch kryptische Files
obwohl das eigentlich nicht so sein sollte. Ich benutze dazu folgenden
Quelltext :
unsigned char file_name[11]="LOG TXT";
unsigned char new_log[18]="** New logging **";
...
if(sdiswriteable()&&sd_merker==0)//Überprüfungob Karte steckt
durchSchalter
{
while (mmc_init() == FALSE){
nop();
break;
}
if(TRUE==fat_loadFatData()){
sd_merker = 1;
ffopen(file_name);
ffseek(file.length);
ffwrite(0x0D);
sd_laufer=0;
do{
ffwrite(new_log[sd_laufer]);
sd_laufer++;
}while(sd_laufer<17);0,
ffwrite(0x0D);
}
}
if(!sdiswriteable() && sd_merker==1)// SD-Karte auswerfen
{
ffclose();
sd_merker = 0;
}
if(sd_merker==1)
{
portauslesenLAN(daten);
ffwrites(daten);
}
Eigentlich sollte der hier doch nur die Datei Log.txt anlegen und dort
Daten reinschreiben. Mittels sdiswriteable() wird abgefragt ob ein
Schalter umgelegt ist, damit Daten auf der SD Karte gesichert werden.
Ich benutze auch einen ungeraden Quarz (14745600 Hz) könnte das auch
daran liegen? Weiterhin benutze ich einen ATmega644.
Bin für jede Hilfe dankbar
Gruß
Alex
Hallo Alex!
Thema kryptische Files: Ich hatte eine Zeit lang eine 16MB-Karte
(letztendlich waren es 12MB), die mit einer neuen Kamera geliefert
wurde. Die hatte ein FAT12 Dateisystem (da zu klein für FAT16; das
braucht 16MB+). Sobald ich die Schreibunterstützung aktiviert habe,
kamen bei mir auch desöfteren kryptische Files raus, da der Code eben
für FAT16/32 ist und bei FAT12 offensichtlich die FAT kaputtschreibt.
Dann werden teils Daten von der Karte gelesen, die mit der
entsprechenden Datei eigentlich nichts zu tun haben: Das sind dann die
kryptischen Daten.
Also Achtung mit so kleinen Karten!
Ich hoffe, das kann dir weiterhelfen,
Johannes
Hallo,
bin mir nicht sicher, ob es einzig und alleine daran liegt, aber das
>unsigned char file_name[11]="LOG TXT";
muss mindestens 12 Zeichen lang sein. Also:
1
unsignedcharfile_name[12]="LOG TXT";
Wegen dem \0 was bei einem String noch hinten dran kommt.
Sonst sieht das auf den ersten Blick ja Ok aus was du da gepostet hast.
Besteht der Fehler immer noch, musst du ein wenig mehr über die Daten
schreiben, und ob du noch andere Sachen verändert hast.
Wieviel Ram hat dein Controller?
Am Takt des Controllers wird es glaube ich nicht liegen...
Grüße Daniel
Danke schonmal für die Hilfe.
Ich benutze allerdings ein 2 Gig Karte mit Fat32. Daran sollte es
eigentlich nicht liegen.
Das mit den 12 Zeichen anstelle von 11 habe ich auch geändert. Trotzdem
treten immer noch die gleichen Kryptischen Dateien auf.
Anstelle die Datei zu öffnen erstellt der Mikrocontroller dann eine
Kryptische Datei und schreibt da hinein. (Jedenfalls wird die log.txt
Datei manchmal nicht angefasst.) Manchmal tretten auch noch andere
Fehler auf. Z.B. kann die Datei selber nicht vom Computer gelesen
werden. Könnte ja auch mit den Kryptischen Dateien zusammenhängen wenn
irgendwo was auf der Karte wild geschrieben wird.
Eigenlich habe ich die Library nicht verändert. Die Daten die ich auf
die Karte schreibe sind die Portdaten überführt in Strings (als Basis
für das ganze benutze ich das AVR Webmodul vom Ulrich Radig
(http://www.ulrichradig.de/home/index.php/avr/avr-webmodule).
Gibt es den eine Maximale Stringlänge die ich an ffwrites übergeben darf
? Immoment überprüfe ich ob hier der Fehler liegt. Werde euch auf dem
laufenden halten. Wenn euch noch was einfällt wäre ich sehr verbunden :)
Grüße Alex
Hallo zusammen!
Also ich habe den Fehler gefunden (die SD Karte war komplett mit windows
formatiert; )
Aber der Fehler lag darin, dass die Funktion
void ffwrites( unsigned char *s ){
while (*s) ffwrite(*s++);
fat.bufferDirty=1;
}
irgendwie die falsche länge des Strings ermittelt hat, den ich übergeben
habe. Ich habe das abgeändert, indedm ich nun eine Feste Anzahl von
Zeichen mittels ffwrite auf die SD Karte schreibe und es läuft.
Vielen Dank für eure Hilfe !
Nocheinmal Hallo :)
schon wieder der Alex :). Ich habe noch ein Problem. Ich schreibe Daten
auf eine SD Karte. Hiernach lösche ich die Daten oder Formatiere die
Daten mittels XP (der Löscht die Daten ja nicht richtig sondern nur die
Fat-Entry (auch Formatieren hilft nicht wirklich)).
Nun will ich wieder auf die Datei schreiben. Aber anstelle neue Daten in
eine Datei zu schreiben hängt der die Daten einfach an die alten Datei
an (die durch das Löschen ja eigentlich schon gelöscht sein sollten).
Ein generelles schreibe über alle Dateien ist allerdings auch
unerwünscht. Gibt es eine Möglichkeit zu erkennen, ob die Datei von
Windows gelöscht wurde und so das einfache schreiben in gelöschte
Dateien zu verhindern?
Grüße Alex
Hallo,
also du Formatierst mit Windows die Karte, machst Datenträger sicher
entfernen und dann erkennt die lib die Datei nicht als gelöscht?
Klingt seltsam!
Du könntest aber z.B. auch einfach mit der lib die Datei löschen, bevor
du sie neu anlegst um so sicher zu gehen, das du sie wirklich neu
anlegst...
Grüße Daniel
Hallo zusammen!
Also ich würde sagen das das dann nicht der Fehler ist. Selbst nachdem
ich die SD-Karte mit dem tool formatiert habe ging es nicht. Ich habe
allerdings immer noch Fehler. Wenn ich dem Fehler näher gekommen bin
schreibe ich nochmal :).
Grüße
Alex
Hallo,
was gibt es neues an der Front, Alex?
Hab mir dieses Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Problem von dir mal durch den Kopf gehen lassen, ich wette es lag daran,
dass du keinen String übergeben hattest sondern irgendwelche Daten.
Der Punkt ist, ffwrites() schreibt solange Daten, bis es auf '\0' alias
0 trifft. Was ja das Ende eines Strings in c beschreibt.
Wenn in den Daten keine 0 bzw. '\0' vorkommt, wird der Ram Inhalt ab der
Adresse es übergebenen Pointers geschrieben, bis irgendwann im Ram eine
0 steht :)
Folge: Kryptische Datei
Poste doch mal deinen kompletten Code, dann schau ich mir das mal an.
Das Format Problem schau ich mir jetzt gleich nochmal genauer an. Bin
mir aber sicher, dass bei Fat32 beim Formatieren außer dem Fat Bereich
auch zumindest das Root-Dir mit gelöscht wird. Ist also nicht möglich da
so einfach noch Reste einer Datei zu finden. Zumindest nicht in der von
dir beschriebenen Weise.
Grüße Daniel
Beim Formatieren mit Fat32 und Windows XP wird der Fat Bereich gelöscht
und natürlich auch der Root-Dir Bereich!
Somit gibt es keine Möglichkeit so einfach an die Daten zu kommen, die
aber schon noch auf der Karte sind.
Nochmal der Alex,
also das Problem besteht weiterhin. Habe ich auch gedacht, dass das mit
den Strings (oder mit der Länge der Strings) zusammenhängt. Allerdings
Benutze ich immoment nur Quellcode der nach folgendem Schema aufgebaut
ist also keine ffwrites(); Funktionen
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
Die Kryptischen Dateien sind schon weniger geworden allerdings auch noch
nicht ganz weg. Ich Überprüfe gerade noch ein Paar Möglichkeiten. Mein
nächster Ansatz wird sein, das ich die Zeichenlänge der Strings
irgendwie falsch habe. :) Wenn es Funktioniert sag ich bescheit.
Eine Frage habe ich noch. Und zwar geht es schon meistens relativ gut
aber manchmal kommt es vor das Ich Text finde (ich schreibe nur .txt
Dateien) den ich früher auf die Karte geschrieben habe. Kann es sein das
wenn solch ein Text bei anhängen an die Datei gefunden wird, einfach der
Text mit angehängt wird?
Grüße
Alex
Hmm irgendwie komme ich noch nicht weiter. Ich kann ja mal die wichtigen
Quelltextteile angeben und zeigen was nicht geht.
sd_ms ist sind hierbei Millisekunden(diese werden auch normal in die SD
Karte geschrieben.
unsigned char new_log[18]="** New logging **\0";
unsigned char file_name[12]="LOG TXT";
char after_str[7]="After \0";
char ms_str[4]=" ms\0";
...SD initialisieren...
while(1){
ffwrite(0x0D);
ffwrite(0x0D);
char zwischenspeicher[5];
char* zwischespeicher_pointer;
zwischespeicher_pointer = after_str;
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
itoa(sd_ms, zwischenspeicher,10); // Into to ascii
zwischenspeicher[4]='\0';
zwischespeicher_pointer = zwischenspeicher;
while (*zwischespeicher_pointer)
ffwrite(*zwischespeicher_pointer++);
zwischespeicher_pointer = ms_str; // Text " ms\0";
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
}
Was in die SD-Karte geschrieben wird sieht folgendermaßen aus
After 1 ms
101
201
...
Allerdings sollte doch folgendermaßen Sachen in die SD Karte geschrieben
werden.
After 1 ms
After 101 ms
After 201 ms
Die Frage die ich habe ist warum er nach dem ersten Durchlauf die
Strings z.B. nicht mehr mitausgibt.
Grüße
Alex
Noch eine Anmerkung wenn ich
zwischespeicher_pointer = after_str;
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
in
for(uint8_t i=0;i<11;i++)
{
ffwrite(after_str[i]);
}
umwandel schreibt mir der ATmega alle möglichen Strings auf die SD Karte
die eigenlich für Usart verwendet werden. Das verstehe ich auch noch
nicht.
Gruß Alex
OK Problem gelöst.
Falls ich die Strings folgendermaßen auf die SD-Karte schreibe
ffwrite('A');ffwrite('f');ffwrite('t');ffwrite('e');ffwrite('r');ffwrite
(' ');
geht es ohne Probleme. Ich weiß allerdings nicht wirklich warum :).
Danke für Eure Hilfe!
Gruß
Alex
Hallo Alex!
Ich hab mich jetzt nur kurz mit deinem Problem beschäftigt, aber etwas
ist mir aufgefallen:
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
Da ist doch genau das selbe Problem wie in der ffwrites: Das Ding hört
nur auf, wenn am Ziel des Pointers Null steht (Bedingung der Schleife).
Du sagtest jedoch, dass es an diesem \0-Problem nicht liegen kann, weil
du die ffwrites-Funktion nicht verwendest. Dein Code macht aber genau
das selbe wie diese Funktion.
for(uint8_t i=0;i<11;i++)
{
ffwrite(after_str[i]);
}
Da passiert folgendes: Du greifst auf das i-te Byte nach dem Pointer
"after_string" zu. Da dieser aber nur 7 Byte groß ist, und du hier 11
Bytes liest, liest der uC über das Ende von after_string hinaus. Daher
kommt der Müll von den USART-Routinen, der eben zufällig im Speicher
dahinter liegt.
Keine Ahnung, ob das jetzt so 100% richtig ist, ich habe selbst erst vor
zwei Jahren angefangen mit C. Aber vielleicht hilfts ja doch. =c)
Johannes Neumann
Hallo Johannes
aber wie kommt es dann das auch bei
for(uint8_t i=0;i<11;i++)
{
ffwrite(after_str[i]);
}
Müll rauskommt?
Ich meine der ließt ein Paar bytes rüber aber bei mir auf der SD-Karte
stehen nachher sehr viele Strings die mehr als 3 oder 4 Byte drüber
gehen. Das hat mich so sehr gewundert.
Hallo,
hab heute und morgen nicht viel Zeit...
Lass dir doch mal immer wenn du etwas schreibst, das auch anzeigen, z.B.
über uart, vielleicht grenzt das etwas ein.
>Ich meine der ließt ein Paar bytes rüber aber bei mir auf der SD-Karte>stehen nachher sehr viele Strings die mehr als 3 oder 4 Byte drüber>gehen. Das hat mich so sehr gewundert.
Bist du sicher, dass nicht vielleicht auch alte strings von vorherigen
Versuchen dort stehen?
Grüße Daniel
Sorry das ich nicht eher zurückschreibe. Ein wenig Stressig die letzte
Zeit :). Also die Usart hat mir die gleichen fehlerhafen Ausgaben
gemacht. Darum denke ich das es sich nicht wirklich um ein
Libraryproblem handelt. Es war eher ein Überlauf in einem Array.
Danke für die tatkräftige Hilfe
Alex
Ich hätte allerdings nocheinmal eine Frage:). Ist es möglich mit der
Library auszulesen wieviel Speicherplatz noch auf der Karte frei ist
(will nur Überprüfen ob die Karte voll ist. Lesen schreiben und löschen
von Daten auf der Karte Funktioniert mitlerweile einwandfrei :)
Grüße Alex
Hallo!
Ich nutze auch diese MMC/SD Funktionen und bin damit auch sehr
zufrieden.
Ich möchte jetzt um Zeit zu sparen die Datei öffnen und erst beim
Datumswechsel die Datei schliessen und eine neue Datei erstellen.
Wie kann ich nach einem Schreibvorgang die Daten auf der Karte
aktualisieren ohne die Datei schließen und wieder öffnen zu müssen?
Viele Grüße
Helmut
Hallo zusammen.
@ Alex (Gast)
Schön das es jetzt funktioniert :)
Das mit dem Freien Platz ermitteln wollt ich schon immer mal einbauen,
komme aber nicht dazu. Eigentlich müsste man ja nur die freien Cluster
in der Fat durchgehen und zählen. Das mit Sektoren pro Cluster
multiplizieren und fertig...
@ Helmut (Gast)
Ist es denn so zeitkritisch?
Weil eigentlich muss man ja alles, was beim schließen auch gemacht wird,
bei einem kompletten update der Datei Daten auch machen. Es schadet ja
übrigens auch nicht eine Datei länger geöffnet zu haben.
Grüße Daniel
Soo, hier mal auf die schnelle eine Funktion, die die Anzahl der freien
Bytes bestimmt.
Es sollte aber mindestens ein Cluster frei bleiben am Ende, also nicht
voll schreiben bis zum Anschlag ! Besser wäre sogar einfach 1 MB frei zu
lassen...
1
unsignedlonglongintfat_getCntFreeBytes(void){
2
3
unsignedlonglongintcnt=0;
4
unsignedlongintcount=0;
5
unsignedlongintsecOfFirstPartition;
6
unsignedlongintfatSz;
7
8
if(TRUE==mmc_read_sector(0,fat.sector)){
9
10
// bestimmen des 1. sektors der partition
11
void*vsector=&fat.sector[454];
12
secOfFirstPartition=*(unsignedlongint*)vsector;
13
if(secOfFirstPartition==0x6964654d){
14
secOfFirstPartition=0;
15
}
16
else{
17
mmc_read_sector(secOfFirstPartition,fat.sector);
18
}
19
20
// anzahl sektoren bestimmen die von einer fat belegt werden
>Und was machste mit ner leeren 8GB Karte? ;) Überlauf anzeigen?
Ach was red ich denn da? Du benutzt ja long long int.
Aber mal im Ernst, es sollte eigentlich reichen die
Anzahl der freien kB zu ermitteln. Das spart das long long
Geraffel und benötigt weniger Code.
Hallo...
@ Alex (Gast)
Wow 15 Sekunden das ist lang. Hatte das garnicht auf realer Hardware
getestet muss ich gestehen. Aber 15 Sekunden ist zu viel! Da muss ich
mal überlegen wie das optimaler geht.
@ holger (Gast)
Ja stimmt schon, long long int auf nem AVR 8 Bit :) das muss man nicht
unbedingt haben. Mal sehn was ich da mache...
Wegen der Code Größe ist mir das eigentlich egal, wer so was braucht
muss halt platz haben, aber die Geschwindigkeit sollte stimmen.
Grüße Daniel
Hallo Daniel,
was müsste man ändern, damit Dateien mit korrektem Datum/Uhrzeit
angelegt werden?
Ansonsten gute Arbeit! Deine lib scheint die einzige zu sein, die
wirklich schnelles schreiben auf SD-Karten ermöglicht.
Mfg,
Kurt
Hallo Kurt,
man müsste die Funktion "fat_makeRowDataEntry" in der fat.c dazu
bewegen, da wo jetzt dummy werte geschrieben werden, richtige werte zu
schreiben. Also das Datum und die Zeit. In den beiden Zeilen, die mit
1
// unnoetige felder beschreiben
kommentiert sind.
Die dummy Werte sind 0x01010101, also 4 Byte als Hex.
Wo jetzt genau Datum und Zeit steht, müsste ich selber mal genau
nachschauen. In der Lib werden 12 Byte mit den dummy werten beschrieben,
da irgendwo muss das hin :)
Grüße Daniel
Dann folgende Funktionen mit zusätzlichem Parameter unsigned long
datetime ausrüsten: ffopen, ffclose, ffmkdir, flushFileData,
fat_makeFileEntry, fat_makeRowDataEntry.
Nun fat_makeRowDataEntry abändern:
*bytesOfSec++=datetime>>16;//datum des letzten zugriffs lowbyte
25
*bytesOfSec++=datetime>>24;//datum des letzten zugriffs highbyte
26
27
vsector=&fat.sector[row+20];
28
*(unsignedshort*)vsector=(cluster&0xffff0000)>>16;// low word von cluster
29
30
bytesOfSec+=2;// 2 überspringen (für low word von cluster)
31
*bytesOfSec++=datetime;//zeit der letzten änderung lowbyte
32
*bytesOfSec++=datetime>>8;//zeit der letzten änderung highbyte
33
34
*bytesOfSec++=datetime>>16;//datum der letzten änderung lowbyte
35
*bytesOfSec++=datetime>>24;//datum der letzten änderung highbyte
36
37
vsector=&fat.sector[row+26];
38
*(unsignedshort*)vsector=(cluster&0x0000ffff);// high word von cluster
39
40
vsector=&fat.sector[row+28];
41
*(unsignedlongint*)vsector=length;// laenge
42
}
Natürlich sind die Werte für Erstellung, letzer Änderung und letztem
Zugriff auf die Datei gleich. Ist das nicht gewünscht, muss man halt
noch 2 weiter parameter übertragen.
Mfg,
Kurt
Hallo,
das mit dem Formatieren ist nicht so einfach,
mach das lieber mit einem Pc :)
Man müsste die Register der Karte auslesen, um herauszufinden wieviele
Sekoren die hat. Dann berechnen wieviele Fat Sektoren man braucht, wo
dann das Root-Dir hin muss usw.
Dann ist immer noch die Frage ob man das so gemacht hat, dass ein
Betriebssystem das auch lesen kann...
Grüße Daniel
Hallo,
hier eine neue Version.
Neu ist:
- SDHC Unterstützung
- Eine Funktion die den freien Platz in Bytes ermittelt
"fat_getFreeBytes()"
- Zeit Stempel Unterstützung beim Anlegen und ändern von
Dateien/Ordnern,
dazu müssen 2 Funktionen mit leben gefüllt werden. "fat_getDate()" und
"fat_getTime()" in der fat.c, dort ist auch dokumentiert wie das Format
der Zeit und des Datums auszusehen haben.
- Kleinere Optimierungen
Viele Grüße
Daniel
Im Anhang: die Lib mit Linux Makefile
Hallo!
Ich hab das ausprobiert, also die neuste AVRStudio Variante. Eigentlich
klappts prima, allerdings bekomme ich z.B. die Funktion:
ffrm( unsigned char name[])
nicht aufgerufen ... also nicht so daß der Compiler einverstanden ist.
Ich habe u.a. versucht:
ffrm(file_name0);
Ging nicht, auch sämtlichen sinnvollen Ansätze die ich probiert habe,
gingen nicht, woran mag das liegen, verwenden einen ATmega32
Hallo zusammen,
habe nen Mega32L, ne 4GB SDHC, und nen 3,7V Lipo.
meint ihr es gibt Probleme mit der um 0,4V zu hohen Spannung um das
ganze prinzipiell zu betreiben?
Mfg Tobi
Hallo,
also ich würde dir empfehlen, einen Stepup-Wandler für die
Versorgungsspannung zu benutzen. Der Akku wird mit der Zeit mit der
Spannung runter gehen. Mit nem Stepup könnte man bei um die 1V
Akkuspannung noch arbeiten. Also das ganze mit nem Stepup auf 3,3V und
gut is.
Generell kann man mit nem SD-Kommando die Karte fragen was sie für ne
Spannung mitmacht. 3,3 Volt machen alle, aber es geht eventuell auch
weniger.
Grüße Daniel
Hy Daniel,
also der Lipo wäre bei 1V schon lange dahin.
In einer späteren Version werde ich die Spannung sicherlich eh auf 3,3V
stabilisieren, zumal ich in einem anderen Stromzweig eh nen Wandler auf
3,7V->5V verbaut habe.
Mir geht es in einem ersten Versuch nur mal darum die Kommunikation
Mega32L + SD Karte durch einen Versuchsaufbau zu testen. Dabei würde ich
gerne erst einmal direkt alles brücken können. Wäre prinzipiell ja auch
möglich da alles mit 3,3V versorgt werden will. Wenn ich wüsste ob die
3,7V die SD Karte kaputt machen müsste ich nämlich für den
Versuchsaufbau die Spannung auch schon wandeln was ich gerne für erste
Versuche erst einmal vermeiden möchte.
mfg tobi
Hallo,
ich hab keine Ahnung von Lipo Akkus :)
Bezugnehmend auf die Simplifyied SD-Spezifkation 2.0, die ich jetzt
nochmal rausgekramt hab.
Also man übergibt der Karte mit CMD8 die Spannung in der man sie
betreiben möchte, in dem Fall der Lib wären das 2,7-3,6 Volt. Antwortet
die Karte korrekt, kann man diese Spannung anlegen. Nur wenn die Karte
korrekt antwortet initialisiert die Lib die Karte.
Soviel dazu. Ob jetzt 0,1 Volt mehr tödlich für die Karte sind bezweifle
ich mal stark ;)
Vielleicht hält sich aber auch dein Kartenhersteller nicht genau an die
Spezifikation...
Hab aber auch schon gehört, dass Leute MMC/SD Karten einfach mit 5V
betrieben haben, ohne das die kaputt gegangen wären. In der Regel sind
das ja alles werte, unter denen das dann garantiert läuft...
Grüße Daniel
Genau diese Angaben mit 2,7-3,6V habe ich auch in meiner SD
Spezifikation.
Das mit dem CMD8 wusste ich noch nicht. Allgemein vermisse ich irgendwie
eine Zusammenfassung der gazen Commands. Zwar sind auch einzelne
Commands in der SPezifikation, jedoch irgendwie etwas unübersichtlich.
Ich vermute auch das 0,1V mehr nicht viel ausmacht. Hatte gehofft hier
Erfahrungsberichte zu finden, da sich grundsätzlich ein Lipo von der
Spannung her ja anbietet und ich ja sicher ned der erste bin der so
einen verwendet :)
Das mit den 5V wäre ja schonmal beruhigend zu wissen, da hätte ich nicht
gedacht das das die Karte lange mitmacht.
Ansonsten ist ja auch kein Vermögen zerstört wenn so eine Karte hops
geht :)
Ich denke ich werds einfach mal probieren, wenn ich einen Kartenleser
auftreiben kann der meine Karte liest um herauszufinden ob die Karte
schon formatiert ist oder dies noch tun muss.
Danke für deine Ausführungen.
MfG Tobi
Hallo zusammen!
Ich habe mal ne Frage bezüglich einer Abfrage ob eine Datei schon
existiert. Und zwar will ich überprüfen ob eine Datei mit einem Namen
schon in dem Verzeichniss existiert. Ist so etwas möglich?
Grüße
Alex
"file_flag" ist jetzt TRUE wenn die Datei schon existiert oder FALSE
wenn eben nicht. Nach dem Aufruf von "fat_loadFileDataFromDir(name)"
sind sogar alle möglichen Daten über die Datei schon bekannt, wenn die
Datei existiert...
Siehe auch "ffopen()" in der file.c
Grüße Daniel
Danke schon für die tatkräftige Hilfe! ich habe auch noch eine weitere
Frage. Und zwar kann man auslesen wie groß der gesamte Speicherplatz der
Fat ist?
Gruß
Alex
Ich denke du meinst wieviele Sektoren von der Fat belegt werden?
Das ist schon schwieriger.
1
unsignedlongintfatSz;
2
3
4
mmc_read_sector(0,fat.sector);
5
6
void*vsector=&fat.sector[454];
7
fatSz=*(unsignedlongint*)vsector;
8
if(fatSz==0x6964654d){
9
fatSz=0;
10
}
11
else{
12
mmc_read_sector(fatSz,fat.sector);
13
}
14
15
16
if(fat.fatType==32){
17
vsector=&fat.sector[36];
18
fatSz=(*(unsignedlongint*)vsector)-1;
19
fatSz*=128;
20
}
21
else{
22
vsector=&fat.sector[22];
23
fatSz=(*(unsignedshort*)vsector)-1;
24
fatSz*=256;
25
}
Jetzt ist auf der Variable "fatSz" die Anzahl der Sektoren gespeichert,
die eine bzw. die erste Fat belegt. Der erste Sektor, also ab wo die Fat
los geht steht auf der Variable "fat.fatSec".
Der hier gepostete Code ist aus der Funktion "fat_getFreeBytes()" aus
der fat.c...
Grüße Daniel
Danke dir! Aber eigentlich meinte ich die Anzahl der Bytes :). Aber das
war doch Anz. Der Sektoren * 512 oder? Kann auch sein das ich mich da
irre.
Gruß Alex
Hallo,
ja Anzahl der Sektoren * 512.
Ich weiß ja nicht was du vor hast, aber zur Sicherheit solltest du evtl.
noch einen Sektor dazu zählen wenn du irgendwas nach der Fat machen
möchtest.
Falls es irgendwas mit der Fat ist wird da schon ein Sektor abgezogen,
um auf garkeinen Fall über das Ende der Fat hinaus zu kommen.
Upps, ich seh grad da bekommst du die Cluster Anzahl raus die in einer
Fat stehen. Bei dem Code oben muss einmal das "fatSz*=128;" und das
"fatSz*=256;" weg !
Also so:
Hi,
ich habe grad ein verzwickes Problem.
Ich würde gerne in eine Datei, die schon einen Text enthält, Text
einfügen.
BSP:
aus:
"Hallo, dieser text steht schon drin."
soll:
"Hallo, dieser text steht schon 1234567890 drin."
werden.
Man könnte jetzt natürliche den restlichen Text überscheiben und neu
schreiben. Aber das geht nicht, da der Text hinter dem, was eingefügt
werden soll mehrere MB groß ist und zum Auslagern fehlt mir zum einen
der Platz und zum anderen die Zeit...
Gibts dafür eine Lösung?!
Gruß,
Matze
Hallo,
nein dafür gibt es so noch keine Lösung.
Man müsste Prinzipiell wie in dem an gehangenen Bild vorgehen.
Allerdings müsste das noch weiter verallgemeinert werden.
Also auf Cluster anstelle von 512 Byte Sektoren und auf größere
einzufügende Sektoren/Cluster.
Mal sehen wie sich das optimal einbauen lässt.
Da komme ich aber auch wohl erst in 2 Wochen dazu, wird auch nicht so
einfach werden, da das ziemlich tief in die Sektor/Cluster Verwaltung
eingreift.
Grüße Daniel
müsste das nich so sein... ich meine, man will ja evtl mehr als 512 byte
einfügen. außerdem müsste es zwischen zwei blöcken geschrieben werden.
dein zeichnung würde "ersetzen mit einem anderen sector" bedeuten.
aber sonst meinen wir das selbe! und cool, daß du das machen willst, ich
steige da nämlich nicht so richtig durch...!
gruß und danke schon mal,
matze :)
Hallo,
hm wo ich so darüber nachdenke, könnte das übler werden als ich dachte.
Wenn man nicht genau 512 Bytes dazu macht, oder ein ganzes vielfaches
davon, läuft das wohl doch auf ein wildes kopieren hinaus. Man hat
irgendwie immer ein paar Bytes über...
Muss ich mal in Ruhe darüber nachdenken.
Grüße Daniel
naja, ob das so weit gehen muss?! Ja, ok, schön wäre es, jedes Bit auf
der Karte auszunutzen, aber sein wir doch mal ehrlich, wer Datenmengen
kleiner als 512 Byte schreiben will, schreibt eh nur Text und der ist eh
meistens kurz. von daher verschenk man nur wenig, selbst wenn man nur 1
Byte / Sector schreibt.
Auf der anderen Seite: wenn man, so wie ich das Plane, ca. 175.000
Einfügevorgänge machen wird, ist schon eine ganze Ecke an verschwendetem
Speicherplatz (ich habs mal überschalgen: etwas mehr als 80MB - wenn ich
mich nicht verrechnet habe).
Jedoch, bei der verfügbaren Kapazität heutiger Speicherkarten auch nicht
mehr so viel... :)
Mach dir also nich so einen Kopf drüber. Die Abfrage, welcher Sektor
wieviele Bytes noch übrig hat, ist, denke ich, unnötig und
wahrscheinlich eh viel zu langsam - bzw. wenn man es in eine Variable
schreibt, viel zu Speicheraufwendig (bei knapp 4,2 mio Sektoren auf
einer 2GB Speicherkarte)
Grüße,
Matze
Danke für die hilfe :)
aber leider Funktioniert das noch nicht so wirklich. Ich überprüfe z.B.
die Größe einer Fat auf einer 2 Gig SD Karte. Die Fat hat die volle
Größe.
Der Quelltext den du oben geschrieben hast also gibt mir für fatSz 3742
zurück.
unsigned long int fatSz;
mmc_read_sector(0,fat.sector);
void *vsector=&fat.sector[454];
fatSz=*(unsigned long int*)vsector;
if(fatSz==0x6964654d){
fatSz=0;
}
else{
mmc_read_sector(fatSz,fat.sector);
}
if(fat.fatType==32){
vsector=&fat.sector[36];
fatSz=(*(unsigned long int *)vsector)-1;
}
else{
vsector=&fat.sector[22];
fatSz=(*(unsigned short*)vsector)-1;
}
Noch einen vorschlag ? (Fehlt hier vielleicht noch ne multiplikation
oder soetwas ?
Gruß Alex
This field is only defined for FAT32 media and does not exist on
4
FAT12 and FAT16 media. This field is the FAT32 32-bit count of
5
sectors occupied by ONE FAT. BPB_FATSz16 must be 0.
,das korrespondiert mit der Prüfung:
1
if(fat.fatType==32){
2
vsector=&fat.sector[36];
3
fatSz=(*(unsignedlongint*)vsector)-1;
4
}
jetzt sollte auf der Variablen fatSz laut Spezifikation die Anzahl der
Sektoren stehen die von einer Fat belegt werden. Wenn du ja genauer
schreiben würdest wozu du das überhaupt brauchst könnte ich da
vielleicht auch mehr zu sagen :)
Wenn du jetzt die Anzahl der Bytes haben willst musst du deine 3742 ja
noch mit 512 Multiplizieren.
Grüße Daniel
Hallo Daniel,
also das passt nicht wirklich. Die Partition ist 2 Gig groß und 3742 *
512 hat einen Wert von unter 1 MB. Was ich machen will ist, eine
durchnummerierung von Dateien. Quasi bei 1 Anfangen ...dann 2 dann 3.
Jede Datei ist hierbei 1 MB groß. Falls ich nun am Ende der Fat
angekommen bin. Also bei ner 2 Gig Platte zirka bei guten 2000 dann soll
der wieder von vorne anfangen und die erste überschreiben. Das klappt
auch eigentlich schon recht gut wenn ich das ganze mit einer statischen
größe mache, besser wäre das aber wenn ich das mit verschiedenen Karten
machen könnte die jeweils eine andere Größe haben. Aber danke schonmal
danke für die Tatkrääftige unterstüzung
Gruß
Alex
Aha,
da musst du anders ran gehen.
Auf FatSz steht jetzt die Anzahl der Sektoren die eine Fat belegt.
In einem Sektor der von der Fat belegt wird, können 128 Cluster
"Adressiert" werden.
Wenn man jetzt fat.secPerClust*512 rechnet, bekommt man die Anzahl der
Bytes die einem Cluster zugeordnet werden.
Die Anzahl der Sektoren die zu einem Cluster zusammengefasst werden ist
immer eine 2er Potenz. Wahrscheinlich bei einer 2Gb Karte 4 oder 8.
Damit ist die kleinste Zuordnung 2048 oder 4096 Bytes groß.
Damit solltest du jetzt rechnen können :)
Also:
FatSz*128 = Anzahl Cluster auf der Karte
512 * fat.secPerClust = Bytes in einem Cluster
1MByte / Bytes in einem Cluster = nötige Cluster Anzahl, für die 1 MByte
Anzahl Cluster auf der Karte / nötige Cluster Anzahl für die 1 MByte =
Maximale Anzahl der der 1 MByte Dateien
Stimmst du dem zu? Könnte mich auch verrechnet haben, war jetzt nur so
auf die schnelle...Man müsste auch mal schauen wie man rundet um da
überall save zu sein ;)
Grüße Daniel
Das mit den Bytes auf der Fat werde ich die Tage mal ausprobieren und
dir ein Feedbag geben :). Ich habe allerdings immoment auch noch ein
ganz anderes Problem. Ich habe folgenden Quellcode
unsigned long int sd_ausgabe_zaehler;
filenamelan = 1;
char ordner[13];
ordnerName(filenamelan,ordner);
ffcdLower();
if(TRUE == ffcd("1 ")...//--> Gibt true zurück
char zwischenspeicher[5]; // Zwischenspeicher für die Umwandlung
itoa(filenamelan, zwischenspeicher,10);
char dateiname[12]=" CSV";
for(uint8_t i=0;i<strlen(zwischenspeicher);i++)//)i<=3;i++)
{
dateiname[i]=zwischenspeicher[i];
}
if(MMC_FILE_EXISTS==ffopen((unsigned char *)dateiname)) // --> Datei
exist
sd_ausgabe_zaehler=file.length;
char zwischenspeicher3[10];
ultoa(sd_ausgabe_zaehler,zwischenspeicher3,10);
ausgabe(zwischenspeicher3); // Hier gibt er ziemlich große Zahlen aus
Das Problem was ichhabe ist das mit file.length für 10 kB Dateien zum
Beispiel den Wert 640000000 zurückgibt, was ja nicht kann. Sieht jemand
warum der das macht und nicht wie erwartet 104800 irgendwas an Bytes
zurückgibt?
Grüße
Alex
hi
ich hätte eine frage zu deinem code
ich bekomme über die serielle schnittstelle strings mit der länge von
2048 zeichen und würde nun gerne wissen wie das geht das ich diese 2048
zeichen dann schreibe
wenn ich nur 512 zeichen lange Blöcke bekomme geht es wunderbar
hoffe du kannst mir helfen
danke und mfg alex
Hallo,
du könntest eine Ringpuffer machen. Dessen Größe müsstest du dann noch
ermitteln, damit da nichts schief geht. So könnten dann schonmal 512
Bytes geschrieben werden, während noch weitere abgeholt werden (falls du
einen Interrupt zum abholen der Daten benutzt).
Siehe auch:
http://de.wikipedia.org/wiki/Warteschlange_(Datenstruktur)#Implementierung_als_Ringpuffer
Das es nicht klappt könnte auch daran liegen, dass du die Schnittstelle
ohne Flow-Control verwendest, vermute ich mal.
Während die Daten auf die Karte geschrieben werden kommen ja über die
serielle Schnittstelle neue Daten an die werden aber wohl nicht abgeholt
während die Lib noch Daten auf die Karte schreibt. Das schreiben der
Daten auf die Karte benötigt ja eine gewisse Zeit.
Falls dir das nicht weiterhilft, könntest du mal etwas Code Posten,
damit könnte man sich einen besseren Überblick verschaffen.
Viele Grüße
Daniel
ich hätte mir vorgestellt das ich die 2048 zeichen was ich als einen
string bekomme auf mehrere kleine strings mit 256 zeichen oder so
aufteile und dann schreibe. wäre das prinzipell möglich?
Hallo,
so bin zu der Berechnug der Anzahl von Dateien gekommen. Habe das wie
folgt gemacht :
uint32_t anzahlDateienerrechnen(uint32_t size)
{
uint32_t anz_Cluster_Karte = size * 128;
uint32_t byte_pro_Cluster = 512 * fat.secPerClust;
uint32_t noetige_Cluster_fuer_1_MB = 1048576/byte_pro_Cluster;
uint32_t anz_Dat = anz_Cluster_Karte/noetige_Cluster_fuer_1_MB;
return (anz_Dat);
}
Mit
size = fatSz kommt die Richtige Anzahl an 1 MB Dateien raus.
Danke für die Hilfe (fatSz muss man ja vorher berechnen) Aber da ist ja
schon oben der Quelltext angegeben.
Grüße
Alex
hi ich wenn ich einen block mit 512 byts schreiben will. geht das bei
mir nicht und es kommt auf der seriellen schnittstelle ein neues boot.
was kann da sein
ich lese die 512 byts über die serielle schnittstelle ein. ich kann
maximal 256 byts auf einmal schreiben mit deinem code
Hallo zusammen.
@ Alex (Gast), schön das es jetzt klappt :)
@ Alex Glaser (almalex) ,welchen Mikrocontroller benutzt du denn? Wenn
da erneut "Boot..." steht vermute ich mal einen Reset wegen Ramknappheit
?!? Poste doch mal ein bisschen Code, damit man sehen kann was du da
genau machst und wie du das machst. Am besten sogar den ganzen Code.
Grüße Daniel
hab das problem schon gfunden. habe ein bit zuviel gesendet und dadruch
hat der buffer nicht gepasst. verwende einen 644 aber trotzdem danke
jetzt wende ich mich dem problem das ich einen string von 2048 zeichen
empfangen will und denn dann schreiben will und dann einen bit zurück
senden will wann der nächste gesendet werden soll
Hallo Daniel,
ich habe noch einen kleinen Fehler in der Funktion
fat_getFreeBytes() gefunden.
Dort wird mit mmc_read_sector(0,fat.sector)
der erste Sektor der Karte in den Buffer gelesen, ohne dass
fat.currentSectorNr dadurch verändert wird.
Später wird mit
fat_getNextCluster(count) der sektor gelesen. Wenn 'count' jetzt
identisch mit 'fat.currentSectorNr'ist(was durchaus vorkommt) wird der
Sektor nicht in
den Buffer gelesen.
meiner Meinung nach müsste es ausreichen wenn man Sektor 0 nicht mit
mmc_read_sector(0,fat.sector) liest sondern statt dessen
fat_loadSektor(0) verwendet.
Kannst du dir ja noch mal anschauen.
Grüße
Jürgen
Hi
ich hab ne frage
ich habe es jetzt geschafft 2048 Zeichen auf die SD karte zu schreiben
wenn ich die daten über die serielle schnittstelle vom PC schicke. wenn
ich nun die selben Daten über den 2ten µC erzeuge und zu dem sende der
es auf die SD karte schreiben soll, funktioniert es nicht. ich poste mal
den code. die main.c ist die datei die auf den µC gespielt wird, welcher
die daten zu dem 2ten sendet.
main_simple.c ist deine datei nur wenig verändert
hoffe du kannst mir helfen
Hallo zusammen.
@ Juergen (Gast)
Ja stimmt, ich bin davon ausgegangen, dass man nur am Anfang die freien
Sektoren bestimmt...
Das wird geändert. Dein Vorschlag funktioniert so.
@ Alex Glaser (almalex)
Um mir das genauer anzuschauen fehlt mir momentan einfach die Zeit.
Vielleicht so in 1,5-2 Wochen, sorry.
Es gibt auch noch einen kleinen Bug, der nur auftritt wenn man die Lib
im Read-Only Modus betreibt. Dann hat nämlich ffopen evtl. nicht immer
einen Rückgabewert... Ist aber eigentlich kein Funktionaler Fehler.
Grüße Daniel
Hay Leute
Ich habe nun auch mal versucht unter Codevision zum Laufen zu bekommmen.
Aber leider ohne erfolg.
Ich habe mir die CodeVision_SDLIB_v0.4.4.zip runter geladen und an den
Mega128 Angepasst. Ich nutze zwar den Mega1281 Aber der ist gleich den
128 nur mit mehr S-Ram.
Habe das ganze System unter 3,3V laufen den AVR sowie auch
Verständlicherweisse die SD-Karte.
Kann mir jemand mal einen code in Codevision Posten der Funktioniert.?
Die mmc_init() bzw. die INIT sieht so aus
if(mmc_init() !=0)
{
LED_Rot^=1;
while(1);
}
LED_Gruen^=1;
Aber es bleibt immer auf Rot nie auf Grün und sagt keine SD Karte
Eingesteckt.
Kann mir jemand weiter helfen.?
Vielen Dank schon mal
Hallo,
erstmal solltest du besser die neuste Version auf Codevision portierten.
Dann ist das so nicht richtig wie du das machst. So wird nur ein mal
versucht die mmc/sd karte zu initialisieren...
Das wäre richtig:
1
while(0!=mmc_init()){
2
LED_Rot^=1;
3
}
4
LED_Gruen^=1;
jetzt wird rot bei jedem versuch getoggelt und grün nach erfolgreichem
initialisieren...
Grüße Daniel
jup das war es nun geht die init Funktion. Danke @Daniel R.
Ich nutze die CodeVision_SDLIB_v0.4.4
nun habe ich auch die filefat.c Eingebunden.
habe auch alle fehler soweit Korrigiert und angepasst.
Nur meckert er mich bei dieser geschichte voll
Error: filefat.c(635), included from: Neu.c: expression must be a
pointer to a complete object type
in der Zeile steht das hier
*(unsigned char*)firstCluster++=sector[row+26];
und das macht er durch weg. :-(
MFG: Andre
Klappt da was von?
Das ist wegen dem CodeVision Compiler, da müsste man mal raus finden
warum der den void Pointer so an meckert..
Mit nimm die neuste Version zum anpassen meinte ich die Version 0.5.7
Grüße Daniel
So gut soweit habe ich nun versucht erstmal die mmc.c, mmc.h und
config.h eingebunden.
nun habe ich dort das problem das er mir das hier anmeckert
loop_until_bit_is_set(SPSR,SPIF);
Error: mmc.c(418), included from: Neu.c: undefined symbol
'loop_until_bit_is_set'
MFG: Andre
Ich glaub ich bleib weiter bei der CodeVision_SDLIB_v0.4.4 den da habe
ich die wenigsten fehler und so.
Den das nimmt ja hier garkein ende mit den ganzen ram. :-)
MFG: Andre
ist ein Makro aus der avr-libc, SPSR ist ein Register und SPIF ist ein
Bit in dem Register. Das Makro ist sehr schnell, daher benutze ich es.
Dahinter steckt eigentlich:
Ändere mal das Makro so wie hier beschrieben. Dann wirst du
wahrscheinlich noch nen Haufen anderer Fehler bekommen wegen den
unterschiedlichen Register Namen, die musst du alle ändern.
Poste doch mal die Fehlermeldungen, vielleicht kann man dann mehr sagen.
Du kannst ja die Teile die in der CodeVision_SDLIB_v0.4.4 stehen
vergleichen mit den stellen aus der 0.5.7 die nicht auf Anhieb laufen...
Oder du fragst mal nett bei "Lolipop Er (lolipoper)" ob er nicht
nochmal die 0.5.7 auf CodeVision portieren mag. Oder du nimmst den
avr-gcc anstelle von CodeVision :)
Viele Grüße Daniel
Persönliche Nachricht an "Lolipop Er (lolipoper)" :
http://www.mikrocontroller.net/user/show/lolipoper
Hallo,
wie schnell kann man mit dieser Bibliothek auf einer SD-Karte
schreiben?Wie lange brauche ich z.B. um 10 MB zu schreiben?
Danke im Vorraus und Grüße
Bernd
Hallo,
der Matze hat es schon erwähnt, es hängt von verschiedenen Faktoren
ab...
Ich sage mal so, mit einer neueren SD Karte und im Multiblock-write
Modus, bei 10 MHZ SPI Takt etwa 40 Sekunden für 10 MBytes.
Hallo,
ich benutze die Fat32 in einer Portierung auf den XMega. Leider ist in
der Applikation öfter mit dem Wegbrechen der Versorgungsspannung zu
rechnen und der Controller schreibt ständig in wachsende Dateien.
Gibt es ausser einer Pufferung der Versorgungsspannung eine Möglichkeit
ein korruptes Dateisystem zu vermeiden?
Ständige ffclose() Aufrufe gefolgt von erneutem öffnen der Datei sind
denke ich nicht so gut.
Hallo,
wenn man jetzt so etwas wie "flush" beim schreiben machen würde, also um
den Dateieintrag zu updaten und die aktuell gepufferten Daten zu
schreiben, müsste man genau die Dinge machen, die bei einem ffclose
auftreten. Das einzige was man evtl. übergehen könnte wäre das suchen
der Datei im Verzeichnis, beim erneuten öffnen. Das wirkt sich aber nur
bei vielen Dateien in einem Verzeichnis aus.
Generell mach ich mir aber mal Gedanken ob da nicht was zu machen ist.
Umgehen könnte man dass, wenn man nicht nur 512 Bytes puffern würde,
sondern 1024 Bytes. Dann wären die Möglichkeiten wesentlich größer, aber
so muss alles durch den 512 Bytes Puffer.
In FAT32 ist ein Journal nicht vorgesehen, wie es bei allen neueren
Dateisystemen Standard ist. Da muss man dann über dem Standard selber
was machen...
Viele Grüße
Daniel
Hallo,
nein mit dem Tool WinHex, das läuft auch unter Linux gut.
Generell muss man aber nur alle Sektoren einer Karte in eine Datei
packen, das reicht dann schon...
Grüße Daniel
hallo
tolles projekt!
ich habe diese library auf einem mega328 im einsatz. wobei daten die
ausgewertet wurden auf einem lcd angezeigt werden und auf die sd karte
geschrieben werden. und noch immer mehr als die hälfte an speicher platz
;-)
möchte noch zusätzlich gps implementieren, wie könnte man das am
einfachsten realisieren?
kann ich hierbei die uart so verändern, damit sie nur mit dem gps modul
kommuniziert oder ist diese systembedingt erforderlich?
und wie kann man den syste der einträger in der txt verändern, zb dass
durchnummerierungen erfolgen
Hallo,
ja die UART kann man einfach benutzen, es wird nur SPI von der Lib
benutzt.
>und wie kann man den syste der>einträger in der txt verändern, zb dass>durchnummerierungen erfolgen
Wie meinst du das?
Willst du eine große Datei erstellen in der alle NMEA Einträge stehen?
Dann musst du die Lib im überschreiben Modus benutzen, dann kannst du
einfach die Datei öffnen und was anhängen...
Grüße Daniel
super!
hab gesehn, man kann echt viel mit deinen libs anstellen ;-)
wie wirkt es sich aus, wenn der ffwrites(text) oder andere aktivitäten
der sd von einem interrupt unterbrochen werden?
habe zb einen interrupt laufen der jede ms ausgelöst wird, brauch diese
zeit um die flanken eines externen interrupts zu messen.
auf die karte sollte im sek takt geschriben werden. habe bemerkt, dass
nach einiger zeit anscheinend der schreib prozess wesentlich länger
braucht. macht sich bemerkbar da das lcd in der selben schleife hängt
und manchmal 5sek und länger nicht aktualisiert wird. liegt das
vielleicht an interrupts?
nur wenn ich die interrupts deaktiviere für den sd schreib prozess, kann
ich einige sekunden keine messwerte empfangen.
Das ist so schwer zu sagen, da ich nicht genau sehen kann wie du die Lib
in deinem Code benutzt.
Aber wenn du die Anbindung an die Karte mit Hardware SPI machst, sollte
eine Unterbrechung keine Probleme machen, da SPI per Definition Clock
hörig ist. Also könnte man zwischen 2 zu Übertragenden Bytes auch Pausen
einlegen. Ich gehe mal davon aus, dass wenn man ein Byte auf die
Hardware SPI gibt, dies auch nicht von Interrupts unterbrochen wird,
weil Hardware...
Schließt und öffnest du die Datei in die du schreibst bei jedem
Messwert?
Grüße Daniel
da ich derzeit noch am erproben bin, verwende ich deine lib im großen
und ganzen original nur leichte anpassung für mega328. aufrufe werden
nach der mainsimple vorlage gemacht, wobei die datei auch jedesmal
geschlossen wird
mir ist in der nacht noch etwas eingefallen. da ich noch freien speicher
habe, könnte ich ca 60sek am mega328 speichern und dann gesammelt
übetragen mit intterupt disable (2-3fehlende werte in einer min ist
nicht so schlimm)
kann sein, dass das spulen zum dateiende nach einiger zeit länger
dauert?!
1
2
sprintf(text,"%u",(int)heartbeat_output);
3
4
// Dateinamen müssen in diesem Format sein !
5
unsignedcharfile_name[20]="TEST TXT";
6
7
// string zum in die datei schreiben schreiben
8
//unsigned char str[13]="Hallo Datei!";
9
// unsigned char str[13]="heartbeat_output";
10
11
12
// Datei existiert nicht, also anlegen !
13
if(MMC_FILE_NEW==ffopen(file_name)){
14
15
// schreibt String
16
//ffwrites(str);
17
ffwrites(text);
18
19
// neue Zeile in der Datei
20
ffwrite(0x0D);
21
ffwrite(0x0A);
22
23
// schließt Datei
24
ffclose();
25
}
26
27
28
29
// Datei existiert, also anhaengen !
30
else{
31
32
ffseek(file.length);// spult bis zum Dateiende vor um anzuhaengen !
33
34
// schreibt String
35
//ffwrites(str);
36
ffwrites(text);
37
38
39
// neue Zeile in der Datei
40
ffwrite(0x0D);
41
ffwrite(0x0A);
42
43
// schließt Datei
44
ffclose();
45
}
46
47
48
// Datei existiert, also kann man lesen.
49
if(MMC_FILE_EXISTS==ffopen(file_name)){
50
51
// setzen einer Variable und dann runterzaehlen geht am schnellsten !
Hallo,
>kann sein, dass das spulen zum dateiende>nach einiger zeit länger dauert?!
Das kommt auf die Datenmenge an, da man sich durch die schon verketteten
Cluster suchen muss. Ist die Datei um die mehreren MB oder sogar GB kann
das dauern.
>..und manchmal 5sek und länger..
5 Sekunden ist ne verdammt lange Zeit. Stimmt da vielleicht irgend etwas
anderes nicht? In 5 Sekunden würde man wenn es gut läuft 1,3 Millionen
Bytes auf eine Karte schreiben können.
Blockiert der Interrupt sich selber oder so?
Poste doch mal den ganzen Code, als Datei Anhang. So kann ich da nicht
viel dazu sagen. In dem von dir gezeigten Code sehe ich keinen Fehler...
Grüße Daniel
Daniel R. schrieb:> 5 Sekunden ist ne verdammt lange Zeit. Stimmt da vielleicht irgend etwas> anderes nicht? In 5 Sekunden würde man wenn es gut läuft 1,3 Millionen> Bytes auf eine Karte schreiben können.> Blockiert der Interrupt sich selber oder so?>> Poste doch mal den ganzen Code, als Datei Anhang. So kann ich da nicht> viel dazu sagen. In dem von dir gezeigten Code sehe ich keinen Fehler...
hab mich ein bisschen herumgespielt.
habe testweise werte nacheinander auf die karte geschrieben, mit
systemzeit in ms. dabei ist mir aufgefallen, dass der datenstring sehr
schnell ca.20ms auf die karte geschrieben wird.
also am schreiben kanns nicht liegen.
testweise, habe ich die datei nicht geschlossen, selbes problem, je
länger die datei wird desto länger hält sich der mega328 mit der sd
karte auf.
und dann ist mir eingefallen, dass in deinem beispiel die datei über den
uart wieder ausgelesen wird. diese funktion ist zwar in meinem code auch
vorhanden, nur wird sie nicht gebraucht!
und na klar nach 30x25 Zeichen braucht das auslesen über den uart schon
ne zeit...
also auslesen raus und alles super toll jetzt! danke für den support
hier und tolle libs für die sd-card hast du geschrieben, die tadelos
funktioniern!! danke!
der fehler war mein programm...
der fehler war wie immer menschlich ;-)
Schön das es jetzt klappt :)
Oft muss man Geduld haben wenn etwas nicht klappt und man nicht richtig
Debuggen kann wegen fehlender Geräte wie z.b. Spektrum-Analyzer oder
Logik-Analyzer... Da ist Kreativität gefragt ;)
Viele Grüße
Daniel
Weißt du, daß es hier auf dem Forum svn gibt, in das man solche Projekte
einchecken kann?
Beitrag "Hinweis: Artikelsammlung"
Das macht es deutlich einfacher, die aktuelle Version zu finden ;-)
Hm, ja hatte mir das mit dem SVN auch schon mal überlegt.
Werde das mal in Angriff nehmen.
Auf http://www.mikrocontroller.net/articles/AVR_FAT32 unter "4. Der
Code"
ist aber auch immer die neuste Version verlinkt.
Aber stimmt schon SVN wäre schöner.
Viele Grüße
Daniel
Hi,
vielen Dank für die Library. Ich habe dazu eine Frage:
Warum wird ein anderer Pin als der Hardware SPI SS für MMC_Chip_Select
verwendet? Funktioniert das nicht mit dem SPI SS?
Bei meinen Board ist das CS der SD Karte an dem SPI SS angeschlossen.
Ich habe das Problem, dass meine 2 GB Sandisk MicroSD Karte nicht
erkannt wird. Ich habe Karten von zwei verschiedenen Herstellern
getestet. Bei MMC_Chip_Select habe ich den Pin von SPI SS angegeben.
SDHC ist auf false. Sonst ist es der gleiche Code wie im Wiki Eintrag.
Vielen Dank & Gruß
Mark
Hallo,
das mit dem MMC_Chip_Select Pin hatte ich einfach so von Ulrich Radig
übernommen, ohne viel darüber nachzudenken. Warum genau es nicht klappt,
wenn man den richtigen SPI SS Pin nimmt weiß ich nicht genau. Müsste man
mal im Datenblatt nachschauen, vielleicht muss man da nur noch was
einstellen, damit es klappt.
Kannst du nicht einfach einen anderen Pin nehmen?
Grüße Daniel
Das ist mir schön öfter aufgefallen. Manche Leute haben regelrecht Angst
vor dem SS Pin. Könnte das evtl. mit dem (berechtigterweise) miserablen
Image des Namens zu tun haben?
:-\
Hallo,
Neue Dateien werden nich angelegt, append funktioniert wenn die Datei
nicht leer ist. Habt ihr ne Idee?
SanDisk MicroSD 2GB(+Adapter), 3.3V LM317, Pagelwandler - 3.3K,1.8K
ATMega32, 16MHz
stable-mmc-0.5.7
Mfg,
Amega
Hallo,
zeig mal den Code, hast du in der config.h etwas geändert?
Besorg dir für 20 Cent nen HC4050 als Pegelwandler oder lass den Atmega
mit 3,3 Volt laufen.
Du könntest auch mal probieren ob die Einstellung in der config.h,
So, es gibt jetzt ein SVN-Repository für die Bibliothek.
Dort wird immer die Neuste Version zu haben sein.
Immer als AvrStudio Projekt und mit Linux Makefile.
Das jetzige Update enthält eigentlich nur 2 Fixes.
1. Ein return wert ist dazu gekommen in der Funktion ffopen
2. In der fat_getFreeBytes wird der Sektor anders geladen.
Zusätzlich sind noch ein paar Funktionen static geworden.
Viele Grüße
Daniel
Link zu allen SVN:
http://www.mikrocontroller.net/svn/list
Link zur Bib.:
http://www.mikrocontroller.net/svnbrowser/avr-fat32
Hi,
ffopen->fat_loadFileDataFromDir kommt nicht zurück - endloss Schleife?
Hab die SD-Karte under Linux formatiert (fat16,fat32):
fdisk (type 6,b,c), dann mkfs.vfat .
Wie ich schon gerschrieben habe, funktioniert nur wenn die Datei da ist
und nicht leer.
Ich kann versuchen auch unter Windows die Karte zu formatieren.
Mfg
Nachdem ich unter Windows die Karte formatiert habe, wird nun neue Datei
angelegt, die bleibt aber leer.
Wenn ich noch mal versuche, dann gibts die Datei doppelt.
Wie funktioniert bei auch? Habt ihr mit 2GB Karte getestet?
Bin aber trotzdem froh, dass sich was bewegt :)
Hallo,
klappt es denn jetzt?
Mit Linux hab ich es nie hin bekommen, dass bei einer frisch
formatierten Karte das Root Directory mit 0x0fffffff abgeschlossen wird.
Linux hat da, immer 0x08ffffff oder so draus gemacht. Wenn das Dir dann
nicht mehr leer ist, ist korrekter Weise 0xffffffff draus geworden.
Kannst du dir die Sektoren der Karte anschauen? Wenn ja sieh mal nach
wie der Root-Dir Cluster in der Fat aussieht. Hilfreiches Tool dafür
WinHex. Läuft auch unter Linux.
Viele Grüße
Daniel
Servus,
Amega schrieb:
>Wie funktioniert bei auch? Habt ihr mit 2GB Karte getestet?
Ich verwende 3 unterschiedliche Karten, zb. Verbatin Micro 2 Giga
Die Karten funktionieren einwandfrei.
Betreibe meine Karte mit einem Atxmega128a3 mit 16Mhz. SPI-Takt 8Mhz.
fat_getFreeBytes() benötigt bei einer 2 Giga Karte gerademal 200 mS.
Bin voll zufrieden.
Gruß GG
Hallo,
mkfs.vfat formatiert das komisch... hast du keinen Windows Rechner zum
Formatieren zur Hand?
Es liegt an dem blöden Eintrag für das Root-Dir.
Grüße Daniel
Hab die Funktion fat_loadFileDataFromDir geändert und nun filegt das
Ding :)
fat.c@172
while(!(( (i>=0x8ffffff && i<=0xfffffff )
&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){// prueft ob weitere
sektoren zum lesen da sind (fat32||fat16)
Bin neugierig, ob linux-formatierte Karte unter Winx lesbar ist.
Und noch was:
http://www.pjrc.com/tech/8051/ide/fat32.html
Also, the end-of-file number is actually anything equal to or greater
than 0xFFFFFFF8, but in practive 0xFFFFFFFF is always written.
>ups 0x#FFFFFF8 != 0x8ffffff !?!?
Kommt auf die Endianness an ;)
>fat.c@172> while(!(( (i>=0x8ffffff && i<=0xfffffff )>&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){// prueft ob weitere>sektoren zum lesen da sind (fat32||fat16)
Ja sollte so laufen, bläht das den Code auf? Keine Ahnung wie viel mehr
Aufwand ein größer gleich im Gegensatz zu gleich ist...
>append funktioniert bei mir nicht>wenn die Datei leer ist.
Das schau ich mir mal an. Aber eigentlich sollte das kein Problem sein,
weil ans Ende spulen bei Dateigröße 0 kein Problem ist.
file.c@168
while( offset>=512 ){ ...
offset ist hier die Byte Stelle zu der man spulen möchte. Bei Dateigröße
0 ist das 0 und 0 ist nicht >= 512, also wird in ffseek nichts
sinnvolles gemacht...
Nur um sicher zu gehen, du appendest ;) ja so oder?
Ja krass, das hatte ich doch tatsächlich immer überlesen.
Wird geändert werden, danke.
Gewundert hatte es mich doch schon warum Linux das so seltsam formatiert
:)
Grüße Daniel
kann es sein das man bestimmte ascii zeichen nicht schreiben kann? weil
ich schicke den richtigen string, und wenn ich die zeichen einzeln
ausgebe stimmen sie auch, nur auf der sd karte stehen sie nicht
danke mfg alex
Wenn du Strings mit der Funktion ffwrites schreibst, darf in dem String
logischerweise kein '\0' alias 0x00 vorkommen, da dies ja ein String
Ende markiert. Bei anderen Steuerzeichen bin ich mir nicht sicher ob die
gehen.
Mit ffwrite kannst du jedes Byte Zeichen auf die Karte schreiben.
Falls das immer noch nicht geht, müsstest du mal ein bisschen Code
zeigen und die Zeichen die du schreiben möchtest.
Viele Grüße
Daniel
Hi,
ich hab ne allgemeine Frage: Warum verwendest du für Strings unsigned
char* anstatt char*? Die Ascii Tabelle geht doch nur bis 127 und dadurch
gibt es bei mir viele Warnings.
Da kann ich nur aus dem eigenen Nähkästchen plaudern: signed char ist
einfach nur krank, wenn es Zeichen und keine int-Werte enthält.
Aber vielleicht ist es auch Gewohnheitssache, mit den Abstrusitäten von
signed char - Vergleichen zurecht zu kommen.
habe heute versucht daten über den uart einzulesen, lib ist ja
vorhanden.
verwende ich jedoch
1
ugetc();
zum auslesen, dann bekomme ich beim kompilieren folgenden fehler
:369: undefined reference to `ugetc'
1
#include"uart.h"
ist im maincode geaddet und initalisieren und
1
uputc(ffread());
funktioniert im main programm auch, beim kompilieren dabei gibts auch
keine fehler. nur wenn ich ugetc aufrufen möcte schreit er eine
fehlermeldung.
kann das bitte mal wer testetn obs ähnliche fehler gibt?!
mfg
low
Hm,
hab ich da was überlesen oder geht es im Prinzip nur um vfat, also mit
langen Dateinamen?
Das die da so auf dem fat noch herumreiten, wird wohl eher irgendwie
exFat mit Zusammenhängen ?!?
Fat16/32 ist ja schon ziemlich in die Jahre gekommen. Wenn man mal so
moderne Dateisysteme sieht...
hallo
wenn ich einen string mit vielen zeichen schreiben will hängt sich das
programm auf. hab schon vieles probiert. \0 macht auch keinen
unterschied. anscheinend gibt es ein limit für die stringlänge?! denn
mit strings die kürzer sind funktioniert alles problemlos. anbei ein
beispiel für eine länge die bei mir nicht mehr klappt.
hat wer einen tipp?!
ps. fat32 formatierte karten klappen derzeit auch nicht, kann man das wo
umstellen?!
speicher ist eigentlich noch da
Program: 14360 bytes (43.8% Full)
(.text + .data + .bootloader)
Data: 1528 bytes (74.6% Full)
(.data + .bss + .noinit)
Hallo,
ich vermute mal Ram Überlauf. Wo in deinem Programm kommst du auf die
1528 bytes Ramverbrauch??
Pack den String mal ins Flash und probier das nochmal.
Oder mach ein kleines Array und schreib das wiederholt auf die Karte...
Mit was Fat32 Formatiert? Mit Windows?
Welche Version der Lib nutzt du?
Was genau meinst du mit klappt nicht ?!?
Wenn du ein CharArray so erstellst brauchst du das '\0' am Ende nicht!
Das wird dann automatisch mit dran gemacht.
Daniel R. schrieb:> Hallo,> ich vermute mal Ram Überlauf. Wo in deinem Programm kommst du auf die> 1528 bytes Ramverbrauch??>> Pack den String mal ins Flash und probier das nochmal.> Oder mach ein kleines Array und schreib das wiederholt auf die Karte...>> Mit was Fat32 Formatiert? Mit Windows?> Welche Version der Lib nutzt du?> Was genau meinst du mit klappt nicht ?!?>> Wenn du ein CharArray so erstellst brauchst du das '\0' am Ende nicht!> Das wird dann automatisch mit dran gemacht.>>
1
>charmap_start[]="awedaweree";
2
>
>>> Welchen Controller benutzt du?>> Grüße Daniel
ok, mal wieder ein programmfehler meinerseits ;-)
anscheinend is das ram übergelaufen. habe mal die ganzen strings ins
eeprom des avr (atmega328p) abegelegt und jetzt klappts das beschreiben
mit langen strings auf die sd problemlos.
mein ram ist so voll weil ich große array habe ca. 100 uint16_t array
und dann noch lcd/sd/gps. und alles sehr unaufgeäumt.
das mit fat32 muss ich noch testen, aber ich tipp mal drauf es
funkt.formatiert ist jedenfalls alles it windows.
bin derzeit ganz zufieden mit fat16 läuft alles super und prima!! danke
daniel!!
hab das programm jetzt soweit geschireben, dass ich auf der sd-karte ein
kml file für google earth erstelle und die gps koordinaten reinschreib.
mfg low
Hallo
ich würde gerne meine gps Datensammlung gerne speichern
und bin auf diesen Foren Beitrag gestoßen
Das was hier angeboten wird ist ein bischen viel
kann mir jemand sagen welche DAteien und Methoden ich brauche, um nur
die Datensammlung zu speichern.
benutze einen atmega16
mfg aga
Hallo,
orientier dich einfach an dem Beispiel in der main.c
Oder hier dran:
http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel
Da ist ein einfaches Beispiel wie man die schreib/lese Funktionen
benutzt.
Wenn du speziellere Hilfe möchtest, musst du schon ein bisschen mehr
verraten :)
Oder noch besser ein wenig Code Posten, zu dem man Hilfestellung geben
kann.
Grüße Daniel
Hallo Daniel,
erstmal meinen herzlichsten Dank für deine Arbeit an diesem Projekt, das
über die Zeit wirklich hervorragend geworden ist!
@alle: Mein Dank gilt natürlich auch für alle anderen, die sich an
diesem Projekt beteiligt haben oder wertvolle Vorarbeit geleistet haben!
Ich verwende die SD-Library (leicht angepasst) auf einem ATmega64 unter
IAR und soweit läuft auch alles perfekt mit unterschiedlichsten
SD-Karten.
Nun sind mir aber 3 Dinge/fehler aufgefallen, die ich hier mal
ansprechen wollte, weil ich die in den bisherigen Diskussionen noch
nicht finden konnte.
1.) Fehler in der Funktion "fat_loadFileDataFromCluster"?
Beim Vergleich des Dateinamens werden in der folgenden Zeile nur 10
Zeichen verglichen, obwohl der Dateiname aus 11 Zeichen besteht.
Folglich wird also das letzte Zeichen ignoriert, wodurch "MEINFILE1.TXT"
und "MEINFILE1.TX2" im Vergleich identisch sind!
Bisher:
1
if(0==strncmp((char*)file.name,(char*)name,10)){
Korrigiert:
1
if(0==strncmp((char*)file.name,(char*)name,11)){
2.) Fehler in der Funktion "fat_loadSector"?
Am Ende der Funktion steht "return FALSE;" wobei diese Stelle niemals
erreicht werden kann. Diese Funktion kann in der bestehenden Form nur
"TRUE" zurückgeben, weshalb sich eine Prüfung auf Fehler bisher auch
völlig erübrigt. Bei welcher Bedingung, hätte denn FALSE zurückgegeben
werden sollen?
3.) Hier (http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten)
steht:
"Nachdem die Karte deselektiert wurde (/CS auf high), die Taktleitung
noch einige Male pulsen, damit die Karte DO hochohmig/tri-state schaltet
(vgl. Chans Erläuterungen)."
Das wird in der SD-Library bisher noch nicht gemacht, weshalb ich das
bei mir noch eingefügt habe. Das könnte z.B. folgendermaßen gelöst
werden. An jeder Stelle, wo im Source "MMC_Disable()" steht, müsste nur
ein Schreibbefehl folgen, oder?. So z.B.:
1
MMC_Disable();// CS High
2
mmc_write_byte(0xFF);// dummy write, 8 CLK-Pulse nachdem CS High, damit die Karte DO tri-state schaltet
Hallo.
@ Nig G. (nig)
Bei Punkt 1 und 2 hast du recht, ist mir irgendwie durchgegangen :)
Wird geändert.
Zu Punkt 3, diese Karten sind SPI hörig, also brauchen eigentlich für
alles einen CLK um was zu machen, zumindest die meisten. Das mit dem "DO
hochohmig/tri-state" wirkt sich aber auch nur aus, wenn man mehrere
"Geräte" am selben SPI Bus hat, sonst wäre das egal.
Wird aber geändert.
Danke für die Unterstützung.
@ test (Gast)
Man kann jede Karte nehmen, auch so ganz billige für 2-3 Euro. Wichtig
nur, es müssen MMC, SD oder SDHC Karten sein.
Viele Grüße
Daniel
Ach ja, ich überlege grade die Prüfung in fat_loadSector ganz raus zu
nehmen, ist zwar nicht so schön ohne Fehler Prüfung, aber so wie es bis
jetzt immer war bringt es ja auch nix...
Mal als Zwischenlösung:
ich bekomme immer die Fehlermeldung aus der funktion ffclose:
../file-0.3.c:119: error: 'kb_buffer' undeclared (first use in this
function)
Damit liegt der Compiler auch völlig richtig, kb_buffer wurde da
nirgendwo deklariert, aber hab natürlich nichts verändert, einfach nur
eure Codebeispiele kopiert.
Muss ich was im Projekt bei AVR Studio einstellen?
Makefile benutze ich nämlich keine...
Hallo,
oha du versuchst da die Version 0.3 zu kompilieren...
Nimm die aus dem SVN und dann sollte das ohne Probleme gehen.
Viele Grüße
Daniel
PS: In der SVN Version ist auch eine AVR-Studio Projektdatei dabei...
Aktuelle Version: 0.5.9
http://www.mikrocontroller.net/svnbrowser/avr-fat32
Moin,
ich experimentiere derzeit auch mit SD-Karten an einem ATmega32. Derzeit
noch mit dem Code von Ulrich Radig.
Würde gerne mal am WE diesen Code ausprobieren.
Gibt es schon Unterstützung für LFN?
Beste Grüße, Marek
Hi,
nein gibt es noch nicht.
Hab da aber eine Idee, wie man da tatsächlich reguläre Unterstützung für
lange Dateinamen hin bekommt ohne nochmal 256 Byte Ram zu brauchen :)
Aber vor Mitte Juli wird da nix draus werden...
Aber es ist jeder herzlich eingeladen mit zu entwickeln. Ich pflege das
dann in die Lib ein.
Viele Grüße
Daniel
Hallo,
ich hab nun auch endlich die Software erfolgreich zum Laufen bekommen.
Der Kasus Knaxus war bei mir, dass ich die Software-SPI verwendet habe,
welche eben so schnell läuft, wie es der Prozessortakt hergibt. Bei
18,432MHz ist das für die SD-Karte einfach zu schnell. Ich habe ein paar
zusätzliche Delays eingebaut und dann ging es.
Von meiner Seite dann auch nochmals vielen Dank, für die ganze Mühe, die
du bisher hier rein gesteckt hast.
Gruß Thorsten
Hallo,
kannst du mal zeigen an welchen Stellen du da delays reingebaut hast,
weil eigentlich ist selbst 20 MHz SPI nicht zu schnell für SD/MMC
Karten...
Viele Grüße
Daniel
Servus,
Thorsten J. schrieb:> ich hab nun auch endlich die Software erfolgreich zum Laufen bekommen.>> Der Kasus Knaxus war bei mir, dass ich die Software-SPI verwendet habe,>> welche eben so schnell läuft, wie es der Prozessortakt hergibt. Bei>> 18,432MHz ist das für die SD-Karte einfach zu schnell. Ich habe ein paar>> zusätzliche Delays eingebaut und dann ging es.
ich betreibe meine SD-Card (Verbatim Micro 2 GB) hardwaremäßig mit 20
MHZ!
Proz. Atxmega
Prozessortakt 2*10 MHz,keine SPI-Teilung, also 20 MHZ am SPI. Das ist
eine nachweisbare Geschwindigkeit.
Deine Aussage: „Ein paar zusätzliche Delays“ kann heißen: 1,2 oder xx
Mhz.
Wei schnell ist der SPI-Takt nun wirklich?
Gruß GG
Ich hab in der mmc_read_byte() und mmc_write_byte()
1
MMC_Write&=~(1<<SPI_Clock);//erzeugt ein Clock Impuls (Low)
ergänzt zu
1
_delay_us(SOFT_SPI_DELAY_US);
2
MMC_Write&=~(1<<SPI_Clock);//erzeugt ein Clock Impuls (Low)
3
_delay_us(SOFT_SPI_DELAY_US);
und hab dann getestet. Die Funktion _delay_us() stammt dabei aus der
<util/delay.h>.
Für SOFT_SPI_DELAY_US waren Werte größer 0.3 notwendig, damit die Karte
arbeitet. Das ergibt einen Takt von etwa 300kHz, der jedoch einen hohen
Jitter aufweist.
Wenn ich das noch recht im Hinterkopf habe war es auch so, dass die
Karten zur Initialisierung mit maximal 400kHz betrieben werden dürfen.
Bei Verwendung der Hardware-SPI wird dem auch Rechnung getragen und erst
nach erfolgter Initialisierung auf volle SPI-Geschwindigkeit geschaltet.
Gruß
Thorsten
Hallo,
ja guter Einwand. Die Initialisierung im Software SPI Modus schau ich
mir nochmal an. Bin eh grade eine ordentliche Platine für eine SD Karte
am machen. Wenn das fertig ist, gibt es eine neue Version...
Danke und viele Grüße
Daniel
// der SS pin des SPI ports wird nicht benutzt! also da nich die karte anschließen, sondern an MMC_Chip_Select !
2
3
#if defined (__AVR_ATmega2560__)
4
#define SPI_MISO 3 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist (DO)
5
#define SPI_MOSI 2 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist (DI)
6
#define SPI_Clock 1 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
7
#define MMC_Chip_Select 0 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist (CS)
8
#define SPI_SS 0 //Nicht Benutz muß aber definiert werden
9
#endif
10
11
#if defined (__AVR_ATmega128__)
Bei diesem Board ist die CS-Leitung der SD-Karte direkt mit dem SS-Pin
des Controller verbunden.
Daher hab ich einfach mal ganz "blauäugig" den entsprechenden Portpin in
die obigen Definitionen eingetragen.
Das mitgelieferte Beispielprogramm liefert "Boot..OK"
Ich hab zur Fehlersuche noch weitere "uputs" eingebaut, und schon der
nächste Aufruf meldet sich nicht mehr zurück: (keine augabe von uputs)
Anpassungen für ATMega2560:
Ich hab das Library um Support für ATMega2560 CPUs erweitert.
Im Anhang sind die geänderten Files.
Harry
<edit>
Mein Fehler!
nicht mmc.c, sondern mmc.h wurde angepasst.
Hi,
unter Linux gibt es die Möglichkeit zu sagen das nur mit 1 er Fat
formatiert werden soll... Unter Windows geht das so glaube ich nicht.
Viele Grüße
Daniel
Ich habe das bis jetzt immer mit GParted unter ubuntu gemacht, da habe
ich die Option nur 1 Fat anzulegen noch nicht gefunden. Könntest du mir
bitte ein Stichwort geben wonach ich besser googlen kann.
Hi, ich habe auch mal wieder ein Problem:
Ich will grade die neuste Version einbinden (von 0.5.7 auf 0.5.9).
Ich rufe in meinem Programm an manchen Stellen die ffwrites-Funktion wie
folgt auf
1
ffwrites("huhu");
jedoch bekomme ich nun zu jedem Schreibbefehl die Nachricht, daß da was
mit den Definitionen nicht passt. Hier einer der vielen gleichen Fehler:
Ich habe etwas geforscht und an jeder Ecke steht in der neuen Version
"unsigned". Und daran wird es wohl auch liegen. Warum wurde das denn
umgestellt?!
Aber was mir viel wichtiger ist, was kann ich gegen diesen Fehler
machen?
Vielen Dank für alle guten Ratschläge!! :)
So nun habe ichdas zweite Problem: ich kann weder mit der alten (0.5.7)
noch mit der neuen (0.5.9) Version auf meine SD-Karten schreiben. Obwohl
SDHC aktiv ist.
Als Speicherkarten benutze ich die zwei im Foto.
Ich formatiere mit WindowsXP Pro.
Ich habe jeweils mit den Beispiel programmen ausprobiert.
Komisch ist, daß in der neuen Version machmal (jedes 15-20ste Mal) durch
die
1
mmc_init
gegangen wird (die drei Punkte erscheinen), jedoch erscheint nie das
"OK".
Bei der alten Routine klappt noch nicht mal der erste Schritt.
Die Hardware die ich benutze ist ein ATmega128 mit 7,3728Mhz.
Angeschlossen ist alles richtig, sonst würden ja die drei Punkte auch
nich erscheinen - wurde aber dennoch schon x-Mal kontrolliert.
Kann mir jemand helfen?!
Grüße aus Hannover
Hallo,
so Fehler wie irgendwas klappt manchmal und manchmal nicht, sind
meistens Hardware Fehler... Benutzt du Software SPI oder Hardware, wie
lang sind die Kabel, Welche Spannungs Pegel...
Mach mal ein Bild vom Aufbau, dann kann ich evtl. mehr sagen
Viele Grüße
Daniel
hmm... ich habe eben noch mal alle Lötstellen kontrolliert und
vorsichtshalber alle nachgelötet - geht aber immer noch nichts.
ich betreibe die karte:
- ohne treiber baustein
- direkt an einem ATmega128
- bei 3,3V.
Meinen Eagleplan habe ich angehängt. Ich hoffe, ich hab keinen Fehler in
der Verschaltung gemacht :)
Viele Grüße und schon mal besten Dank für deine Hilfe!
ich habe eben einfach mal zwei 10k Ohm Pull-Up-Widerstände an die CS-
und die MISO eingebaut (siehe Anhang), weil ich das hier gelesen hatte:
http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten. aber das
hilf auch nichts! Ich verzweifel noch!!! Hilfe!
Hallo,
du steckst doch den SPI Programmer aus wenn du die Karte testest oder?
Mehr fällt mir grad nicht ein, schaue aber später nochmal genauer...
Viele Grüße
Daniel
Hm, Schaltplan sieht Ok aus.
Jetzt könnte der Fehler immer noch in der Software liegen oder im
Tatsächlichen Aufbau der Schaltung.
Ich hab selber so eine 2GB Scandisk Karte und mit der funktioniert es...
Hast du was in der config.h geändert oder in der mmc.h ?
Wie sieht die Initialisierung genau aus?
Mach doch mal ein Foto der fertigen Schaltung.
Viele Grüße
Daniel
Hi danke für deine Mühe!!!
Ich denke nich, daß es an der Software liegt. Ich hab nichts in deinem
Beispielprogramm geändert. Ich will morgen noch mal die Schaltung in
schön aufbauen - sieht echt nach Kraut und Rüben aus.
Wenns fertig is, lade ich ein paar Fotos hoch.
Grüße und genieß das schöne Wetter - in Hannover sind noch 30°C und ich
muss raus: hier drinnen sind die nämlich auch ;)
Grüße,
Matze
Hi es lag wirklich nich an der Software. Ich habe zwei Sachen geändert:
1) beim ATmega128 geht der ISP nicht über den SPI sondern tw. über den
USART0. Ich habe meinen UART-RS232 von dieser doppelbelegten
Schnittstelle abgelötet.
2) Ich habe gleichzeitig den µC gewechselt. Hatte noch nen zweiten
mega128.
Ich habe eben nochmal den neuen µC mit eingesteckter RS232 Schnittstelle
programmiert. Geht trotzdem. Lag also wohl an einem def. µC... Jetzt
gehts aber!!!
Aber warum mich das jetzt vier Tage meines Lebens kosten musste, weiß
ich auch nich.. ich hasse diese Kleinigkeiten an denen es immer hängt!
Dennoch vielen Dank für deine Hilfe!
Hi,
ich habe da etwas ganz komisches grad festgestellt. Ich kann in eine
Datei mit einer Funktion nichts schreiben.
Ich will in eine Datei für eine Log-Datei bevor die Daten aufgezeichnet
werden eine Startsequenz schreiben (Funktion: sd_geschw_start(void)).
Ich habe in die Datei eine UART-Ausgabe ("start") eingebaut; diese
erscheint auch auf meinem Terminal, aber es steht kein "huhu" in der
Datei. Nur ein "ende"... WARUM zu Teufel?!
Hat jemand ne Idee?
Grüße,
Matze
Hallo,
bei dem Stück Code das du gepostet hast, zähle ich ~95 Bytes nur an
Ascii Zeichen... Das ist ziemliche Ram Verschwendung...
Bin mir jetzt da grad nicht sicher, aber benutzt du fat_str richtig?
Versuche mal an ffopen einen festen Dateinamen zu übergeben, um das
Problem einzugrenzen.
Ach ja und schließt du die Datei auch irgendwann vor verlassen des
Programms auch?!?
Viele Grüße
Daniel
Hi Daniel,
ich habe den Tag über in meinem Wust an Funktion gewütet und vieles
zusammen gestrichen, dabei fiel mir auf, daß in einer anderen Datei an
zwei stellen wirklich das "ffclose()" gefehlte... dennoch danke für
deine Mühe. Jetzt geht alles :D
Morgen gibts dann erste Probeläufe mit meinem neuen Datenlogger :D :D
Gute Nacht,
Matze ;)
So geht alles. Allerdings habe ich grade versucht eine
Verzeichnisstruktur anzulegen. Beim Aufruf von
1
ffmkdir
habe ich aber noch Probleme:
Mein Quelltext dazu sieht wie folgt aus:
1
unsignedcharverzeichnis[13]="TEST";
2
ffmkdir(verzeichnis);
(Natürlich nachdem die Karte initiallisiert wurde :)
Auf meiner SD-Karte taucht auch ein Ordner auf. Allerdings kann ich
diesen nicht Öffnen. Windows XP Pro sagt mir:
1
TEST bezeiht sich auf einen Pfad, der nicht verfügbar ist. Dieser kann auf einer Festplatte dieses Computers [...] sein.Stellen Sie sicher, daß der Datenträger korrekt eingelegt ist, [...]. Und wiederholen sie den Vorgang. ...
Muss ich bei dem Funktionsaufruf irgendwie mehr beachten?!
Achja: wieso funktionieren eigentlich nur Grossbuchstaben sowohl bei
Dateinamen als auch bei Verzeichnissen?!
Danke für deine Hilfe,
Matze ;)
Hallo,
versuch mal "TEST " als Verzeichnisname ( 4 Buchstaben und 7
Leerzeichen). Das mit den Großbuchstaben ist noch aus der DOS Zeit, also
aus der Fat16 Zeit quasi.
Wenn ich lange Dateinamen Unterstützung mit eingebaut habe wird sich das
alles etwas vereinfachen, zumindest in der Anwendung :)
Viele Grüße
Daniel
Hallo,
wenn mir ja jemand sagen könnte wie CodeVision mit void Pointern umgeht
könnte ich da vielleicht was machen... Aber die Dokumentation da finde
ich etwas dürftig. Glaube es hakt da am meisten, der Rest sind ein paar
Register und Kleinigkeiten...
Grüße Daniel
Habe mir mal vor einigen tagen die Neue Light Version von Codevision
gezogen und getestet.
Die haben ja eine Sd Lib drin und die Funktioniert ja auch super.
Nur komme ich nicht ganz zurecht damit.
Kam zwar auf Display den Inhalt der Datei schreiben und auch Ordner etc.
aber ich möchte die Werte für andere Sachen Übernehmen und das geht
irgentwie nicht.
MFG: Andre
Hallo zusammen,
ich wollte gerne wissen, welche Lesegeschwindigkeiten ich bei der
Verwendung dieser FS32-Bibliothek von SD-Karten zu erwarten habe.
Im Einsatz soll ein ATmega168 mit 8 Mhz eingesetzt werden.
SPI in Hardware mit halber Taktgeschwindigkeit.
Und gibt es Möglichkeiten die Leserate zu maximieren, z.B. FAT16 anstatt
FAT32?
MfG
Rene
Hallo,
also wesentlich schneller wird es durch Fat16 nicht werden, da das nur
mit den Fat einträgen selbst in Zusammenhang steht. Also nur bei Fat
lookups ins Gewicht fällt...
Also mit Fat32, multiblock-write und 4 Mhz SPI werden wohl so um die
100-150 k Bytes/Sec gehen. Mit MMC Karten evtl. sogar mehr.
Viele Grüße
Daniel
Hi Daniel,
danke für die prompte Antwort.
Das mit dem Multiblock ist ja so eine Sache, da es wohl nicht von jeder
Karte unterstützt wird.
Wie ist denn die maximal zu erwartende Leserate ohne
Multiblock-Unterstützung?
Ich würde gerne universell bleiben, was die SD-Karten angeht.
MfG
Rene
Hm,
ich hab nur eine uralte Karte die Multiblock nicht unterstützt.
Bei den neueren sollte das wohl immer gehen.
Die Geschwindigkeit hängt auch stark von der Karte ab.
Schätzungsweise wird lesen auch im Bereich 100-150 kBytes/sec liegen...
Viele Grüße
Daniel
Hallo,
hier mal eine kleine Beta der Version 0.6
Falls da mal jemand reinschauen mag :)
Neu:
Lange Dateinamen, kleinere Vereinfachungen.
Was geht noch NICHT:
Root dir bei Fat16 beschreiben wenn dort schon mehrere Einträge sind.
Einen vollen Ordner erweitern.
Was geht:
Dateien mit langem Dateinamen lesen.
Ordner mit langem Dateinamen lesen/wechseln zu.
Beim Anlegen wird wie gesagt noch der Ordner nicht erweitert!
Bei einem leeren Ordner und 4 Sektoren/Cluster könnte man aber
mindestens 4 Dateien mit Dateinamen von 255 Zeichen Länge anlegen ;)
Datei mit langem Dateinamen anlegen löschen.
Ordner mit langem Dateinamen anlegen rekursiv löschen.
Beispiel für den Aufruf:
1
ffopen((unsignedchar*)"langer name test.txt")
So wird wie gehabt, die Datei angelegt wenn nicht vorhanden, oder
geöffnet wenn vorhanden.
Viele Grüße
Daniel
Hallo,
hier mal die zweite Beta.
Lange Dateinamen werden jetzt komplett unterstütz. Bei Ordnern und
Dateien. Das ist allerdings nicht ganz Standard konform. Sollte aber
keine Probleme Machen solange man die Karte mit Geräten liest/schreibt,
die auch lange Dateinamen unterstützen !
Es gibt eine Option in der config.h die heißt "MMC_ENDIANNESS_BIG", wie
der Name vermuten lässt, kann damit die Byteorder umgestellt werden. Wer
mit den void Pointer Probleme hatte sollte das mal ausprobieren :)
Die Funktion "fflushFileData()" kann jetzt während geschrieben wird
aufgerufen werden, sie sorgt dafür, dass die Dateiinformationen
gesichert werden. Allerdings sollte das möglichst selten gemacht werden,
da immer mindestens 2 Sektoren geschrieben werden müssen !
Viele Grüße
Daniel
Soo, ist fertig :)
Wäre schön, wenn ich evtl. ein bisschen Feedback bekommen könnte, falls
irgendwo was schief läuft oder es Verbesserungen gibt.
Das einzige Problem, dass immer noch besteht ist, dass bei Software-SPI
bei der Initialisierung nicht langsamer getaktet wird, da is mir noch
nicht wirklich was schönes zu eingefallen :)
Die neue Version gibts hier:
http://www.mikrocontroller.net/svnbrowser/avr-fat32
Viele Grüße
Daniel
Hallo,
ich bin neu hier und habe es mal ausprobiert.
Die 0.6.0 hat nicht getan !
Ich habe es 1:1 genommen und laufen lassen.
Der Controller konnte wohl schreiben + lesen + zufügen.
Aber in Windows wurde die Datei nicht erkannt. Windows zeigte die Datei
mit "Test.txt." (mit '.' am Ende) mit 0kb an.
Öffnen und Löschen ging nicht. Nur neu formatieren.
Danach bin ich auf die 0.5.9 umgestiegen. Hat geklappt.
Info:
2GB Flash Karte
ATMEGA16 @ 16 MHz
Hallo,
ja ich war irriger weise davon ausgegangen, dass wenn Linux das
ordentlich anzeigt, Windows das auch macht. Macht es aber nicht...
Werde später ein update machen, da gibts dann auch noch mehr neue Sachen
:)
Viele Grüße
Daniel
So neue Version 0.6.1 hochgeladen.
http://www.mikrocontroller.net/svnbrowser/avr-fat32/
Man kann jetzt wesentlich mehr konfigurieren in der config.h
Viele Grüße
Daniel
PS: Als Anhang noch ein Benchmark Programm für atmega168 @ 16 MHZ
Hallo!
Also ich habe getestet 0.6.0 - das Problem mit dem nich lesen können
etc. unter Windows hatte ich auch. Jetzt habe ich 0.6.1 getestet, im
Prinzip funktionierts, wenn die Karte leer ist legt es die Datei an,
allerdings steht dann 2 x "Hallo Datei!" in der Datei, je einmal in
einer Zeile.
Ist das normal / gewollt?
Darüber hinaus, befindet sich eine leere test.txt auf der Karte passiert
nichts bzw. das Programm kommt nicht zum Ende - habe 3 LED zum debuggen,
irgendwo nach dem init bleibts stehen und die Datei bleibt leer, ich
werde berichten wenn ich den Wunden Punkt gefunden habe ...
Ich verwende einen ATmega2561 @ 16MHz, sandisk 1GB bzw. Platinum 2GB
Aber ne tolle Sache ischs in jedem Fall
Gruß Jens
Hallo,
>Darüber hinaus, befindet sich eine leere>test.txt auf der Kart
das ist nicht normal soweit ich verstehe was Du machst. Zu welcher Datei
befindet sich die leere test.txt auf der Karte?
Grüße Daniel
PS: Bin für jede Anregung dankbar !
nein nein, weil 0.6.0 nicht funktioniert hatte hab ich etwas rumprobiert
- u.a. hatte ich eine leere test.txt angelegt, nach dem Durchlauf des
Programms war die dann immernoch leer, das war dann aber auch bei 0.6.1
so.
Werde mich noch n bissi mehr damit beschäftigen, vielleicht kann ich ja
noch was konstruktives beitragen ;)
Grüßle
...kann mir jmd. ein wenig behilflich sein?? Ich habe Version 0.6.1
heruntergeladen, im AVR-Studio meinen Controller (XMeaga 64A3)
eingestellt und compiliert. Es hagelt gleich einige Fehlermeldungen:
../mmc.c:128: error: 'DDRB' undeclared (first use in this function)
../mmc.c:128: error: (Each undeclared identifier is reported only once
../mmc.c:128: error: for each function it appears in.)
../mmc.c:128: error: 'SPI_MISO' undeclared (first use in this function)
../mmc.c:129: error: 'SPI_Clock' undeclared (first use in this function)
.
.
.
Ich denke, es fehlen ein paar einstellungen für den Controller. Aber ich
weiss nicht wo und was...
Hallo,
ich kenne die Atxmegas nicht.
Wie setzt man denn da einen Pin auf 1 bzw. 0 ?
In der mmc.h müssen die Pins an der die Karte hängt eingestellt werden.
Wenn aber bei einem xmega die Pins anders angesteuert werden müsste man
da noch mehr anpassen...
Viele Grüße
Daniel
Hallo,
Uwe S. schrieb:> fehlen ein paar Einstellungen für den Controller
in der mmc.h sind einige Atmega vordefiniert! Aber kein Atxmega.
Wenn du mit solchen Kaliebern arbeitest, solltest du schon etwas
Hintergrundwissen über die Hard- und Software besitzen.
Dir jetzt einen fertigen Code zuliefern ist nicht die richtige
Vorgehensweise. Wenn dir der Befehl DDRB z.B. nichts sagt, ist das
Betreiben einer SD-Card am XMEGA schon aussichtslos.
Sollte dennoch Intresse bestehen, melde dich nochmals.
Gruß GG
...nein - DDRB sagt mir jetzt so aus dem Kopf nix. Mit Atmels arbeite
ich zum ersten mal. Ich habe vorher mit ARM9 (davor SAB509, PIC, ...)
gearbeitet. Ich muss jetzt wohl hoffen, dass mir der XMega dann nicht
zu gross wird ;-)
@Daniel R.: bei den XMega ist die IO-Struktur neu gemacht - es gibt ein
paar Register mehr. Ist hier ganz gut beschrieben:
http://www.stromflo.de/dokuwiki/doku.php?id=xmega-c-tutorial
Ok, sollte sich ganz einfach portieren lassen.
Schau ich mir später mal an.
Mit Deiner Hilfe Uwe S. wird das schon werden. Ich selber habe keine
atxmega da.
Du könntest schon mal rausfinden an welchen Pins die SPI Schnittstelle
liegt und in welchen Registern man die einstellt...
Viele Grüße
Daniel
...so - da bin ich wieder. Ich widme mich dem Thema nur sehr
unregelmässig - je nachdem, wie ich Zeit habe.
In der mmc.h und der uart.h werden wohl durch die Compilerdirectiven die
prozessorspezifischen Einstellungen vorgenommen - richtig? Ich denke, da
müsste mann den XMega "reinzaubern".
"#if defined (_AVR_ATXmega64a3_)" oder so ähnlich - weisst du, wie das
festgelegt werden muss?
An meinem Board ist ja der 64A3 drauf und für die SD-Karte wurde
folgende Konfig. verwendet:
CS - PB1
MOSI - PC5
MISO - PC6
SCK - PC7
-> also SPIC
Als nächstes müsste ich deine Einstellungen mal vergleichen mit dem
Manual:
http://www.atmel.com/dyn/resources/prod_documents/doc8077.pdf ab S. 229
sind die Register beschrieben. Leider weiss ich nicht, in wie fern die
sich mit dem ATMega decken.
LG
Uwe
Hallo,
also ich bin ab morgen erstmal ein paar Tage weg :)
Wegen
>#if defined (AVR_ATXmega64a3)
weiß ich selber nicht genau wie das mit den Xmegas geht, weiß aber hier
sicher jemand anderes im Forum.
Also so wie ich das sehe, müsste in der mmc.h das in etwa so geändert
werden:
1
#define MMC_Write PORTB
2
#define MMC_Read PINB
3
#define MMC_Direction_REG DDRB
zu
1
#define MMC_Write PORTC.OUT
2
#define MMC_Read PORTC.IN
3
#define MMC_Direction_REG PORTC.DIR
Jetzt ist das Problem, dass der CS Pin auch an Port C sein sollte, geht
das irgendwie bei Deinem Board?
1
#if defined (_AVR_ATXmega64a3_)
2
#define SPI_MISO 6
3
#define SPI_MOSI 5
4
#define SPI_Clock 7
5
#define MMC_Chip_Select (zusätzlicher Pin von PORTC)
6
#define SPI_SS 0
7
#endif
Dann gibt es noch 2 Stellen in der mmc.c die geändert werden müssten
So wie ich das sehe, brauchst Du nur das Register CTRL vom Xmega. Dann
sollte das laufen...
Viel Spass beim Basteln.
Bis die Tage dann
Viele Grüße
Daniel
Servus,
Daniel R. schrieb:> So wie ich das sehe, brauchst Du nur das Register CTRL vom Xmega. Dann>> sollte das laufen...
ich habe dir ein lauffähiges Projekt eingestellt.
Atxmega128a3, SPIC(SD-CARD), USART 115200 USARTF0
SPIC(SD-CARD) sollte auf allen XMEGA laufen!
Gruß xmega
bei mir läuft es nun auch super. Vielen Dank für alles.
Die neue Version braucht viel weniger Platz (ca. 4kb) als die 0.5.9.
Es tuts auch der ATMEGA8
ATMEGA8 @ 8Mhz + 2GB SD-Card
Hallo.
Danke erstmal an Daniel für den Code!
In den Bemühungen den Code v.0.6.1 für eienn Mega8 auszudünnen, bin ich
inzwischen bei 84% Speicherbelegung. Nur leider funktioniert es nicht,
wenn ich LFN an und abschalte. Jednefalls ändert sich nach
Neukompilierung nicht die Speichergröße.
Das zweite Problem hat wohl mit dem ersten zu tun. Ich habe den Plan
eine START.TXT in Windows zu erzeugen, auslesen zu lassen und das in
eine TEST.TXT (mehrmals) hineinzuschreiben. Nur für Testzwecke. Wenn ich
mir das Ergebnis danach unter Windows anschaue, finde ich zwei
START.TXT. Ich habe das Gefühl, dass er die Datei nochmal neu anlegt,
wohl weil er die existierende nicht erkennt. Den Inhalt kann er aber
lesen und schreibt ihn auch brav in die TEST.TXT
Was habe ich hier falsch gemacht?
Gruß, fiete
Hallo, bin wieder da :)
@ xmega (Gast)
Danke dafür, muss ich mir mal in ner ruhigen Minute zu Gemüt führen.
@ Friedrich K. (fiete)
Klingt nach Benutzerfehler. Man kann beispielsweise nicht 2 Dateien
gleichzeitig öffnen. Poste mal den Code der bei Dir Probleme macht. Dann
kann ich bestimmt mehr dazu sagen.
Viele Grüße
Daniel
// Versuch Karte zu Initialisieren, bis es klappt. Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.
15
while(FALSE==mmc_init())
16
{
17
nop();
18
}
19
20
PORTD=0xC8;
21
22
23
// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !
24
if(TRUE==fat_loadFatData())
25
{
26
27
unsignedcharstart_dat[]="START TXT";
28
29
// if(MMC_FILE_EXISTS == ffileExsists(start_dat))
30
{
31
if(MMC_FILE_EXISTS==ffopen(start_dat))
32
33
{
34
35
// lesen eines chars und Ausgabe des chars.
36
// solange bis komplette Datei gelesen wurde.
37
38
for(i=0;i<19;++i)
39
{
40
dat[i]=ffread();
41
}
42
43
ffclose();
44
PORTD=0xC0;
45
46
}
47
}
48
49
unsignedcharfile_name[]="LOG TXT";
50
51
52
53
54
// Datei existiert nicht, also anlegen !
55
if(MMC_FILE_NEW==ffopen(file_name))
56
{
57
58
// Schreibt String auf Karte ! Nur richtige Strings koennen mit ffwrites geschrieben werden !
59
ffwrites(dat);
60
61
// Neue Zeile in der Datei
62
ffwrite(0x0D);
63
ffwrite(0x0A);
64
65
// Schließt Datei
66
ffclose();
67
}
68
69
// Datei existiert, also anhaengen !
70
if(MMC_FILE_EXISTS==ffopen(file_name))
71
{
72
73
ffseek(file.length);// Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !
74
75
// schreibt String
76
ffwrites((unsignedchar*)dat);
77
78
// neue Zeile in der Datei
79
ffwrite(0x0D);
80
ffwrite(0x0A);
81
82
// schließt Datei
83
ffclose();
84
}
85
PORTD=0x00;
86
87
}
88
89
}
Und ein Auszug aus der config.h, damit du weißt, was ich ein und
ausgestellt hab.
1
#define MMC_WRITE TRUE // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
2
#define MMC_OVER_WRITE FALSE // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien überschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
3
#define MMC_MULTI_BLOCK FALSE // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber möglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
4
#define MMC_SDHC_SUPPORT FALSE // TRUE, dann mit sdhc unterstuetzung, wenn FALSE, dann nur mmc/sd karten. siehe : http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29
5
#define MMC_ENDIANNESS_LITTLE TRUE // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
6
#define MMC_LFN_SUPPORT FALSE // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
7
#define MMC_RM_FILES_ONLY TRUE // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
8
9
// schalter die explizit funktionen mit kompilieren oder nicht!
10
#define MMC_TIME_STAMP FALSE // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
11
#define MMC_RM FALSE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
12
#define MMC_SEEK TRUE // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
13
#define MMC_MKDIR FALSE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
14
#define MMC_GET_FREE_BYTES FALSE // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
15
#define MMC_LS FALSE // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
16
#define MMC_CD FALSE // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
17
#define MMC_FILE_EXSISTS TRUE // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
18
#define MMC_WRITE_STRING TRUE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.
Ich habe mir ein paar LED's als Kontrolle eingebaut und der Code, so wie
er ist, läuft zumindest danach zu urteilen durch. Ich muss dazu sagen,
dass meine C-Kenntnisse auch eher dürftig sind...
Gruß, Fiete
Hallo,
ohne den Code jetzt laufen zu lassen würde ich da schon ein paar Dinge
als potentielle Probleme sehen.
Also das ist so ein Kandidat:
1
for(i=0;i<19;++i)
2
{
3
dat[i]=ffread();
4
}
das sollte besser "for(i=0; i<19; i++)" heißen. Dann sollte dat
mindestens "unsigned char dat[20]" sein, weil du 19 Elemente und das
'\0' speichern willst.
Dann noch:
1
ffwrites(dat);
Das funktioniert nur problemlos, wenn auf dat jetzt wirklich ein String
steht. In C ist ein String immer mit '\0' terminiert, dafür musst Du
sorgen. Ist das nicht so, schreibt die Funktion ffwrites Ram Inhalt auf
die Karte bis sie auf eine 0 alias '\0' im Ram trifft.
Sonst sieht das eigentlich Ok aus.
Viele Grüße
Daniel
Danke Daniel,
das Array ist eigentlich richtig definiert, aber der letzte genannte
Punkt könnte Probleme bereitet haben, das habe ich noch nicht bedacht.
Ich probiere es mal aus...
Gruß, Fiete
Japp, fehlenden Terminal-zeichen lag es wohl. Ich bin nun ein ganzes
Stück weiter, allerdings habe ich nun wieder Schwierigkeiten:
Es soll ein Datenlogger werden, der zwei Kanäle loggt und das auch in
zwei files schreiben soll. Damit er nicht bei jedem furz schreibt, soll
er erstmal pro Kanal 95Byte in den RAM schreiben, und dann den String
aus dem RAM auf die Karte wegschreiben.
Also habe ich zwei Arrays definiert (und somit, wenn ichs recht verstehe
auch den RAM reserviert):
unsigned char kanal_0 [95];
unsigned char kanal_1 [95];
in einer for-Schleife schreibe ich diese nun voll und wenn sie voll
sind, dann wird ffwrites aufgerufen:
1
for(unsignedintj=0;j<20;j++)
2
{
3
kanal_0[j+w*20]=dat[j];
4
}
5
6
w++;
7
if(w==5)
8
{
9
// Datei existiert, also anhaengen !
10
if(MMC_FILE_EXISTS==ffopen(filename_knal_0))
11
{
12
PORTD=0x80;// <----- Fehlerkontrolleuchte
13
ffseek(file.length);// Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !
14
15
// schreibt String
16
ffwrites((unsignedchar*)kanal_0);
17
18
19
// schließt Datei
20
ffclose();
21
22
PORTD=0x00;// <------ Fehlerkontrolleuchte
23
w=0;
24
}
Analog für Kanal 1.
Wenn NUR Kanal 0 angesprochen wird, dann funktioniert das wunderbar,
wenn NUR Kanal 1 angesprochen wird auch, aber wenn beide angesprochen
werden, dann ist eine der beiden Files meist nicht mehr lesbar und die
Strings in der Datei haben kaputte Stellen drin (irgendwelche Zeichen,
die da nicht hingehören). Das pikante ist, dass das Problem wohl nicht
im RAM auftritt, denn wenn ich z.B. 5x von kanal 1 auf die SD-Karte
schreibe, und dann einmal von kanal 2, dann treten Fehler an Stellen
auf, die vorher schon geschrieben wurden. Daher vermute ich, dass die
FAT irgendwie Probleme macht oder ich irgendetwas anderes nicht bedacht
habe...
Interrupts kommen eigentlich auch nicht in Frage für das Problem, weil
ich erst wieder die Kanäle auslese, wenn alles andere abgeschlossen ist.
Jetzt hab ich überlegt, dass der Stack eventuell Probleme machen könnte,
aber ich bin ja noch knapp 300Byte übrig für den Stack. Ich kann mir
nicht vorstellen, dass das Probleme bereitet.
Ein weiters Problem ist, dass der Controller nur Dateinen beschreiben
kann, die er selber angelegt hat, und auch leider nicht mehr nach einer
Neuinitialisierung. D.h. ich muss die kanal.txt immer löschen, bevor ich
das Programm nochmal duchlaufen lassen kann. Könnte es vielleicht auch
damit zusammenhängen?
Bin für Tipps dankbar.
Besten Gruß aus Heidelberg,
fiete
Hallo,
also eigentlich puffert die Lib schon. Um genau zu sein 512 Bytes, da
das genau ein Sektor ist. Da könntest Du Dir den ganzen Quatsch mit dem
Puffern der Kanäle sparen.
Das ist so gefährlich
1
for(unsignedintj=0;j<20;j++)
2
{
3
kanal_0[j+w*20]=dat[j];
4
}
Wenn w 5 ist und j 20, dann ist 20+5*20 = 120, also deutlich über der
Array Grenze hinaus. Damit überschreibst Du was weiß ich im Ram...
Was für Daten kommen den so vor bei den Kanälen? Falls da Steuerzeichen
vorkommen, also z.B. integer 0, dann geht das mit ffwrites NICHT.
Also noch mal ganz deutlich: NUR Strings sollten mit ffwrites
geschrieben werden! Ein String wird mit '\0' terminiert. Also Ascii Code
Buchstaben und Zahlen im Ascii Code quasi.
Mein Vorschlag wäre im http://de.wikipedia.org/wiki/CSV_(Dateiformat)
Format die beiden Kanäle in eine Datei zu schreiben, aber in zwei
Spalten in der Datei. Dann brauchst Du Dir um puffern keine Gedanken
mehr zu machen, da das ja schon die Lib macht.
>Ein weiters Problem ist, dass der>Controller nur Dateinen beschreiben>kann, die er selber angelegt hat...
Ich vermute das Programm kommt vorher schon durcheinander, oder der
Dateiname entspricht nicht den Konventionen.
Viele Grüße
Daniel
Hey Daniel,
sehr nett, dass du nachfragst. Aber leider funktionierts noch nicht
zufriedenstellend. Habe mir mal den Beispielcode geschnappt und
stückchenweise modifiziert. Die Idee war dann tatsächlich mit ffwrite
(ohne s) wegzuschreiben und zwar auf knopfdruck == trigger.
Es bleiben dabei zwei Probleme: Ich habe es immernoch nicht geschafft
ausser beim Beispielcode eine Datei nach dem entnehmen der Karte und
neuinitialisierung wieder zu öffen und zu beschreiben.
Das zweite Problem ist mehr eine Frage. Ich konnte nicht ganz ausmachen,
an welcher Stelle des Codes wirklich echt vom RAM auf die Karte
geschrieben wird. Denn ich würde gern auf Knopfdruck ebenfalls den rest
der im RAM steht, auf die Karte schreibt, sodass man sie entnehmen kann.
Wenn ich das recht sehe, dann tut das ffclose nicht allein, sondern
setzt nur die Flags null.
Am besten poste ich mal wie ich den Beispielcode modifiziert habe.
Vielleicht ist da was schief gelaufen, was ich nicht seh...
Was du da siehst, ist meine "wunsch-Konfiguration". Sie funktioniert
nicht. Habe vorher Stückchenweise ausprobiert und sobald ich das ffclose
auf knopfdruck aufrufe, funktionierts nicht mehr. Die Datei kann nicht
gelesen werden unter windows (beschädigt) es wird aber eine realistische
größe angezeigt.
1
while(1)
2
{
3
if(!((PINC&0x01)==0x01))
4
{
5
if((PINC&0x01)==0x01)//<<---- Erst beim Loslassen schreiben.
6
{
7
// Datei existiert, also anhaengen !
8
if(MMC_FILE_EXISTS==ffopen(file_name))
9
{
10
11
// bewusst kein ffseek, weil ja, nicht geschlossen und Flags noch gesetzt
12
13
// schreibt "String" Alternativ While Schleife
14
ffwrite(48);
15
ffwrite(49);
16
ffwrite(50);
17
ffwrite(51);
18
ffwrite(52);
19
ffwrite(53);
20
ffwrite(54);
21
ffwrite(55);
22
ffwrite(56);
23
ffwrite(51);
24
25
26
27
// neue Zeile in der Datei
28
ffwrite(0x0D);
29
ffwrite(0x0A);
30
31
/// Bewusst kein ffclose, da erst auf knopfdruck schließen soll
32
33
}
34
}
35
36
}
37
if(!((PINC&0x04)==0x04))// <<--- Kontroll LED
38
{
39
ffclose();
40
PORTD=0xCC;
41
}
42
}
Aber Fortschirtte gibts schon. Das ganze soll ein Wasserzähler werden
der kalt und Warmwsser loggt. Die alte ochsentour mit dem
selbstdefinirtem RAM hat ja einigermaßen fuktioniert, sodass ich ihn
schon 24h hab laufen lassen können. Hab mal das Histogramm angehängt ;-)
Gruß, Fiete
Hallo.
>Ich habe es immernoch nicht geschafft>ausser beim Beispielcode eine Datei nach>dem entnehmen der Karte und>neuinitialisierung wieder zu öffen und zu beschreiben.
Ich vermute mal, dass Du bevor Du die Karte entfernst nicht ffclose
aufrufst. Mach es doch so, dass Du eine LED einschaltest wenn Du ffopen
aufrufst und aus, wenn du ffclose aufrufst. So kannst Du genau sehen ob
die Datei geöffnet oder geschlossen ist.
>Ich konnte nicht ganz ausmachen,>an welcher Stelle des Codes wirklich>echt vom RAM auf die Karte...
Bei einem fflushFileData() wird alles was aktuell im Ram ist auf die
Karte geschrieben. Zudem wird der Dateieintrag geupdatet. Das ist
prinzipiell ein ffclose(), nur dass die Datei danach nicht neu geöffnet
werden muss um weiter zu schreiben. Sollte aber so selten wie möglich
aufgerufen werden, da viele Schreiboperationen auf der Karte gemacht
werden.
Sind die Taster ordentlich entprellt? Vielleicht geht da einiges
durcheinander.
So wie ich das sehe, öffnest Du die Datei mehrfach, bevor Du sie
schließt.
Versuch mal das:
1
if(MMC_FILE_EXISTS==ffopen(file_name))
2
{
3
// Datei existiert, also zum Ende spulen
4
ffseek(file.length);
5
6
// hier Status LED an
7
}
8
9
while(1)
10
{
11
// Pin1 gedrückt?
12
if(!((PINC&0x01)==0x01))
13
{
14
// hier warten bis Taste losgelassen wird!
15
while(!((PINC&0x01)==0x01));;
16
17
// schreibt "String" Alternativ While Schleife
18
ffwrite(48);
19
ffwrite(49);
20
ffwrite(50);
21
ffwrite(51);
22
ffwrite(52);
23
ffwrite(53);
24
ffwrite(54);
25
ffwrite(55);
26
ffwrite(56);
27
ffwrite(51);
28
29
// neue Zeile in der Datei
30
ffwrite(0x0D);
31
ffwrite(0x0A);
32
}
33
34
// Pin4 gedrückt?
35
if(!((PINC&0x04)==0x04))
36
{
37
ffclose();
38
39
// Status LED hier aus, alles OK. Karte kann entfernt werden!
40
41
break;// um aus endlosschleife zu kommen
42
}
43
44
}
Ohne den Code so laufen zu lassen, denke ich sollte das gehen.
Hoffe irgendwas hiervon hilft :)
Viele Grüße
Daniel
Hey Daniel, danke für deine Antwort. Ich werds gleich heute abend mal
ausprobieren.
Zum Prellen: ich habe mir eigentlich entprellte Taster besorgt. Lese
gerade, dass man da noch Vorkehrungen treffen muss. Ich bin bisher immer
davon ausgegangen, das es bei entprellten tastern kein Problem ist...
Vielleicht hat er bei ffclose deshalb probleme bekommen...
Zu Kontroll LEDs: Ja, hab kontroll LEDs eingefügt, bei denen ich seh, wo
er grad ist. Ich konnte sogar sehen, dass er auf die Karte geschrieben
hat, weil er dann läger im ffwrite war und so die LED nen bissel länger
geleuchtet hatte. In dem code den ich dir schickte, sind die LEDs nur
noch zum teil drin. Ich schiebe die immer rum im code, um zu gucken, wo
er grad "hängt".
Zu ffclose: Stört es, wenn ffclose mehrfach aufgerufen wird? Weil die
Verrenkung dass er erst beim Losassen aus der Schleife steigt, hab ich
mir bei ffclose gespart.
Zu fflushFileData: Muss man danach noch ffclose aufrufen? Wenn ichs
recht sehe ja.
Kann es eventuell sein, dass die Karte einen knacks hat?
Ich werde wie gesagt mich heute Abend mal damit auseinander setzen und
bericht erstatten.
Danke nochmal.
Gruß, Fiete
Hallo.
>...Verrenkung dass er erst beim>Losassen aus der Schleife steigt...
Die Verrenkung ist doch nur ein "break;" um aus der Schleife raus zu
kommen. Ob jetzt bei Taste gedrückt oder losgelassen ist ja nur die
Abfrage im if...
>Stört es, wenn ffclose mehrfach aufgerufen wird?
Eigentlich nicht, ist aber unnötig. Muss halt so programmiert werden das
es nicht vor kommt :)
>Zu fflushFileData: Muss man danach>noch ffclose aufrufen? Wenn ichs>recht sehe ja.
fflushFileData ist eigentlich dazu gedacht, dass wenn ein Gerät z.B.
über Tage läuft und Daten loggt, man zwischendurch mal zur Sicherheit
fflushFileData aufruft. So hat man die Daten bis dahin schonmal
gesichert, falls der Strom ausfällt oder ähnliches. Dadurch spart man
sich ein ffclose und ffopen.
Funktioniert die Karte denn unter Windows noch ordentlich? Also
beschreibbar, lesbar und keine Fehler beim Formatieren? Wenn es da keine
Probleme gibt, sollte die Karte noch OK sein.
Viele Grüße
Daniel
Hallo.
Ich bin hier neu im Forum und habe bis jetzt nicht so viel Erfahrung mit
AVRs. Deswegen bitte sich nicht über meine dummen Fragen ärgern.
Ich werde mein Atmega32L mit 3,3V versorgen und mit 8MHz takten. Meine
Karte hat 2GB. Ich möchte Fat32 benutzen.
Soll sie zuerst mit dem PC mit FAT32 formatiert werden oder macht das
dein Programm?
Kanst du mir bitte sagen an welche Pins des Atmega32 ich die SD Karte
anschliesen muss?
Wo soll ich im Code eine Umstellung von Fat16 auf Fat32 machen?
Mit welcher Funktion wird eine neue Datei erzeugt?
Mit welcher Funktion wird eine Datei beschrieben?
Grüße,
Lukas
Hey Lukas,
also das mit den SD-Karten ist nicht so ganz ohne. Du solltest schon
mindestens nen bisschen C mitbringen und das AVR Tutorial wäre auch
nicht schlecht, einfach, damit du nen bissel weißt, was du tust. Es ist
jedenfalls im seltensten Fall so, dass man es einschaltet und alles
funktioniert. Guck dir mal in der Artikelübersicht
http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten da steht
schonmal ne Menge drin.
Gruß, fiete
Hallo.
Man verwendet Belegung wie sie in der "mmc-0.2.H" Datei angegeben ist.
Habe ich das richtig verstanden? Warum wird denn der SPI-Port für den
Anschluss verwendet. Das ist doch unpraktisch, jedesmal die Karte
auszustecken um zu programmieren??
Hast du deine Karte auch an PORTB abgeschlossen?
Grüße,
Lukas
Der SPI-Port stehllt das Protokoll bereit, das mit der Karte
kommuniziert. Das ist eine Bus-Kommuikation. Es können also mehrere
Bauteile angeschlossen werden und nur das, welches aktivirt ist, fühlt
sich auch angesprochen. Aktivirt wird wenn ichs richtig im kopf hab wenn
pin 0 auf high gezogen wird...
Ich versuche gerade die Software mit Keil µVision4 auf einen LPC2148 zu
portieren. Der Compiler spuckt aber Fehler aus. Da soll wohl noch was
umgecastet werden?
1
fat.c(120): error: #852: expression must be a pointer to a complete object type
2
fat.c: vsector+= 6;
3
fat.c: ^
4
fat.c(123): error: #852: expression must be a pointer to a complete object type
5
fat.c: vsector+=2;
6
fat.c: ^
7
fat.c(422): error: #852: expression must be a pointer to a complete object type
8
fat.c: *(unsigned char*)vsector++ = 0x00;
9
fat.c: ^
10
fat.c(431): error: #852: expression must be a pointer to a complete object type
Hallo,
versuch mal "#define MMC_ENDIANNESS_LITTLE FALSE" in der config.h
Damit fliegen überall die void Pointer raus. Ist aber evtl. nicht so
schnell dann.
Es gibt da mit mehreren Kompilern Probleme wegen void Pointern. Verstehe
ich nicht ganz, weil das eigentlich normaler C Standard sein sollte...
Viele Grüße
Daniel
Hi,
ich hab da auch mal wieder ne Frage.
Ich will mit der neuen Version (0.6.1) einen Ordner anlegen. In der
Config.h ist #define MMC_LFN_SUPPORT TRUE. So weit, so gut!
Aber wenn ich nun alle:
ein Verzeichnis anlegen will, dann geht das nicht. Windoofs will da wohl
am ende der Eingabe noch ein abschließedendes Zeichen haben. Kann mir
bitte jemand verraten, welches das ist?
Und mit einem HEX-Editor kann ich leider kein Verzeichnis öffnen... Bei
normalen Dateien kann man ja "spicken" wie bestimmte Steuerzeichen
aussehen. Bei Ordner geht das nich...
Danke für alle guten Tipps!
Matze
Danke Daniel. Das lesen von Dateien geht jetzt ohne Probleme. Aber beim
fclose nach dem schreiben in eine Datei bleibt er hängen. Ein Hardware
Problem schließe ich aus, da das lesen funktioniert. Timing Probleme
dürften es auch nicht sein da ich den Prozessor bis auf 12MHz
runtergetaktet habe.
Im Anhang ist das komplette µVison Projekt, lauffähig mit debug
Ausgaben, und die debug Meldungen. Er bleibt ganz am Schluss zwischen
Kontrollpunkt D und E hängen, obwohl er vorher mehrmals korrekt bis E
durchläuft.
Ich höffe es ist einigermaßen verständlich was ich meine. ;-)
Mfg,
Kurt
PS: Ich habe die Software auch auf einem Mega32 mit 18,x MHz getestet,
da funktionieren lesen und schreiben wunderbar!
Leider waren doch meine SPI (SSP) Funktionen falsch! Also bitte meine
beiden letzten Beiträge ignorieren.
ABER: In der fat_loadSector() ist anscheinend ein return FALSE zuviel?
Mfg,
Kurt
Hallo zusammen.
Wunderbar, dass sich hier alles von selber erledigt :)
Hm, das FALSE da ist wirklich überflüssig... da kommt man ja garnicht
hin.
Wird geändert.
Viele Grüße
Daniel
Hallo,
erstmal: Super Arbeit!
Leider läuft das Schreiben auf die SD-Karte nur sehr langsam.
Ca. 4kB/s! Auf dem Osi sieht man, dass er manchmal 200ms brauch um auf
die Karte zu schreiben.
Aber die Datei wird fehlerfrei geschrieben.
Hat jemand eine Ahnung wodran das liegen könnte, ich verzweifle dran?
Habe schon verschiedene SD-Karten ausprobiert, Takt geändert, immer das
gleiche Problem!
Daten:
Atmega88 @7.3728Mhz @3,3V
das problem hab ich auch manchmal. versuch mal ne andere SD-Karte.
Wenn ich mal ausversehen die SD-Karte im Slot habe, wenn der ISP dran
is, dann kriegt sie wohl einen "Schaden". In anderen Geräten geht sie
dann noch, aber am µC nich mehr. Ich weiß auch nicht, woran das liegt.
Is halt mein "Word-Around"... Nich schön, weil auf dauer teuer, aber was
will man machen ;)
Hmm... habe mich wohl geirrt! Sorry!
Ich hatte ja das selbe Problem: mals liefs und mal nicht. Ich habe immer
mit WinAVR compiliert und bin gestern einfach mal spaßeshalber in das
AVR Studio gewechselt und habe da den selben Code compiliert - jetzt
geht alles und zwar immer... also, wenn du mit dem WinAVR arbeitest:
wechseln ;)
Hallo,
kann mir eigentlich nur vorstellen, dass es mit Kompiler Optionen zu tun
hat oder etwas in dieser Richtung. Vielleicht ist es aber auch wenn das
nur bei einer Karte auftritt eine extrem langsame. Habe hier auch eine
16MB Karte die extrem langsam ist.
Grüße
Daniel
Naja, ich habe am Versuchsaufbau nichts geändert! Sogar die selbe Karte
benutzt. Mit dem ARV Studio geht es nun aber flüssig und vor allem
immer.
Is komisch, ist aber so.
Hallo,
danke für die Anregungen.
Ich arbeite nur mit Avr Studio, also daran lag es nicht.
Habe mal ne ganze Menge an Karten ausprobiert und gemessen. Habe
festgestellt, dass die Noname Karten am Besten funktionieren.
Habe die Benchmark bißchen umgeschrieben. Schreibe 196k-Datein und davon
100 Stück und messe die einzelnen Zeiten! Folgende Ergebnisse:
ScanDisk SD 2Gb (neu):
3.2s für die 1.Datei
10s für die 100. Datei
SD-Formel1 256Mb (hab ich irgendwo ausgegraben):
2,6s für die 1.Datei
2,4s für die 100. Datei
NONAME SD-micro 2Gb (aus meinem Handy)
3.6s für die 1.Datei
3.4s für die 100. Datei
CN Memory SD 8Gb mit SD_HC Support (neu)
3.2s für die 1.Datei
25s für die 100. Datei
Hab da noch paar Karten getestet. Manche werden halt sehr lahm! Hab
keine Ahnung wodran das liegt, benutze einfach die Karten die durchweg
schnell schreiben. Das sind die Karten die sich mit FAT 16k formatieren
lassen. Keine Ahnung, ob das damit zusammen hängt??? Bin noch Laie auf
dem Gebiet!
Welche Karten würdet ihr denn empfehlen? Sind MMC Karten schneller?
Hallo,
stimmen diese Daten?
>SD-Formel1 256Mb (hab ich irgendwo ausgegraben):>2,6s für die 1.Datei>2,4s für die 100. Datei>NONAME SD-micro 2Gb (aus meinem Handy)>3.6s für die 1.Datei>3.4s für die 100. Datei
Die werden schneller bei 100 Dateien?!?
Zeig mal den Benchmark Code !
Ja MMC Karten sind deutlich schneller, keine Ahnung wieso.
Fat16 zu Fat32 macht bei mir keinen so großen Unterschied. Ist im
einstelligen KB Bereich.
Ob ich Multiblock ein/aus schalte macht deutliche Unterschiede.
Deine maximale SPI Geschwindigkeit ist f_cpu / 2 also 7,3728 MHz / 2 =
3,6864 MHz. Das ist jetzt nicht so wahnsinnig schnell. Die Karten sind
für 25 MHz ausgelegt.
Was willst Du denn eigentlich speichern? Muss das so schnell sein?
Viele Grüße
Daniel
Hey,
hab jetzt noch paar MMC Karten getestet, lassen sich so mit 77kB/s
beschreiben. Ich glaub ich werde nun nur MMC benutzen! Funktionieren
alle durchgehend gut.
Daniel R. schrieb:> Die werden schneller bei 100 Dateien?!?> Zeig mal den Benchmark Code !
Hab die benchmark angehängt.
Fand ich auch komisch. Dies tritt nur auf, wenn die Karte formatiert und
relativ alt ist. Sind da schon Daten drauf, schreibt sie durchgehend
konstant. Kann sein das die ersten Sektoren schon beschädigt sind!?
Hab mir jetzt mal ein größeren Controller bestellt. Wird mir hier
einbisschen eng auf dem Atmega88. Dann drehe ich auch die Frequenz auf
16MHz.
Daniel R. schrieb:> Was willst Du denn eigentlich speichern? Muss das so schnell sein?
Muss Strom und Spannung mit 2.5kS/s abtasten und ablegen. Desto
schneller ich speichern kann, desto weniger muss ich Puffern.
Bis dann und vielen Dank für den bereitgestellten Code!
Hallo,
das ist eine verkürzte Schreibweise für eine Abfrage. Wenn C=254 wird c
der Wert hinter dem Fragezeichenzugewiesen. Wenn nicht der Wert hinter
dem : Allerdings bin ich der Meinung, dass es am Ende :c++ heissen
müsste. Ich kenne das Programm nicht, aber das soll wohl eine
Zählvariable sein. Kann aber auch sein, dass sie woanders im Programm
verändert wird. Dann macht diese Art der Abfrage allerdings weniger
Sinn...
Gruß
Bad Urban
>Ich habe mal in der Quelltext geschaut, das müsste wirklich ":c++;">heißen.
Nö.
> ffwrite(c++);> c = c==254 ? 0 : c;
Fällt euch was auf?
Das ist eine kryptische Schreibweise für ein if{}else{}
Sowas gehört in kein C Programm.
Ok, das "ffwrite(c++);" hab ich übersehen. Mein Fehler.
Aber warum sollte ein "c = c==254 ? 0 : c;" nicht in ein c-Programm?
Vorallem die Begründung, daß es kryptisch sei halte ich für arg
schwammig. Ich denke, ich werde es zu meinem Standart für solche Fälle
erklären. Warum sollte ich das nicht dürfen?! Ich finds kurz und
prägnant.
Hey,
hab die defines auf mein CPU Takt angepasst!
Ansonsten, wie gesagt, kaum was an deiner Benchmark verändert.
#define TOP_OCR 0x7A
#define START_TCNT 0x06
#define PRESCALER 0x03
Bis dann!
Hallo,
also mein Timer Rechner sagt mit einer Frequenz von 7.3728 MHZ müssen
die Werte bei einem Überlauf von 1 ms:
1
#define TOP_OCR 0x72
2
#define START_TCNT 0x8D
3
#define PRESCALER 0x03
sein. Der Fehler ist dann 0.174%
Ich benutze dazu diesen Rechner:
http://www.b9.com/elect/avr/kavrcalc/index.html
welcher auch unter Linux mit Wine läuft.
Zur Not könnte man auch die Tick Zeit mal mit einem sleep vergleichen...
Viele Grüße
Daniel
Hey,
hab den Test noch mal mit den genaueren Werten durchgeführt. Fehlmessung
von ca. 1%. Also, danke noch mal für den Tipp!
Noch ne Frage!
Welche Karten (SD und MMC) akzeptieren MMC_MULTI_BLOCK? Hab bisher noch
keine gefunden.
Bis dann!
Hi,
ich benutze auch die Lib hier, hab aber ein Problem. Ich schreib alle 5
Minuten auf die Karte alle 5 Sekunden 2 Werte. Nach ungefaehr 2 Stunden
bricht das schreiben ab, weil entweder der Schreibvorgang hängenbleibt
oder die er beim öffnen der Datei hängen bleibt. Vielleicht einer eine
Idee, woran das liegen könnte? Die Schaltung wird über einen Lf33cf mit
3,3 v versorgt, also auch stabil. Hab mal die main angehangen, ist im
Grunde nur eine Erweiterung des beigefügten Beispiels im svn. Ach so µC
ist ein Atmeg644p.
Grüße Peter
Hallo,
sehe ich das richtig, dass der Atmeg644p 4k Ram hat? Weil eigentlich
würde ich auf Ram Probleme tippen.
Läuft das Programm ohne schreiben auf die SD Karte normal durch?
Versuch mal die Datei einfach geöffnet zu lassen.
Du legst nicht alle 5 Minuten eine neue Datei an oder?
Hab grad nicht die Zeit mir das Programm im Detail anzuschauen, mach ich
aber am Wochenende.
Viele Grüße
Daniel
Hi,
danke für die Antwort, jo der Atmega644p hat 4kb Ram, nur öffnen geht
über viele Stunden, hab es dann irgendwann einfach abgebrochen. Nein ich
öffne nur die existierende Datei immer wieder, schreib rein und
schliesse sie.
Ich teste jetzt erstmal ohne die Datei immer zu öffnen, ob das schreiben
dann über einen längeren Zeitraum funktioniert.
Mfg
Peter
Hallo,
also so nochmal auf die schnelle...
Bist Du Dir sicher, dass nur wirkliche Strings mit ffwrites geschrieben
werden? Wenn da irgendwo das '\0' fehlt geht das schief.
Grüße
Daniel
Hi!
Ich möchte mir einen Datenlogger mit SD bauen.
Gibt es da irgendwelche Beschränkungen?
Also wie groß darf die SD- Karte maximal sein und was für einen µC
braucht man mindestens?
Danke und Gruß
Tobias
>Ich möchte mir einen Datenlogger mit SD bauen.
Wofür?
>Gibt es da irgendwelche Beschränkungen?
Ja. 4GB pro Datei maximal bei FAT32.
Schreibzeiten beschissen wegen sporadischen Aussetzern von
bis zu 500ms. Es sei denn du hast einen Arsch voll RAM.
>Also wie groß darf die SD- Karte maximal sein und was für einen µC>braucht man mindestens?
FAT32 kann ein paar Terabyte.
ATmega mit mindestens 2kB Ram.
>>Ich möchte mir einen Datenlogger mit SD bauen.>> Wofür?
Für eine Wetterstation
>>Gibt es da irgendwelche Beschränkungen?>> Ja. 4GB pro Datei maximal bei FAT32.> Schreibzeiten beschissen wegen sporadischen Aussetzern von> bis zu 500ms. Es sei denn du hast einen Arsch voll RAM.>>>Also wie groß darf die SD- Karte maximal sein und was für einen µC>>braucht man mindestens?>> FAT32 kann ein paar Terabyte.> ATmega mit mindestens 2kB Ram.
Also wenn ich eine 4GB SD- Karte nehme und nen atmega644 mit 4k sram
müsste das kein problem sein oder?
Hi, ich nochmal,
also die Strings die mittels ffwrite geschrieben werden, sind alle mit
\0 terminiert. Hab es jetzt ohne ständiges öffnen uns schliessen
probiert. Brachte auch keinen Erfolg. Brauch nach circa 2h bei einem
ffwrites ab.
Vielleicht haste noch eine Idee woran es liegen koennte. Danke schon
mal.
Peter
Hallo.
@obi (Gast)
Nee das sollte kein Problem sein.
@Peter (Gast)
Hm, Du versuchst das nicht Batterie betrieben oder?
Beim schreiben zieht so eine Karte mal gut strom...
Über welche Datenmenge sprechen wir denn da bei den 2 Stunden?
Viele Grüße
Daniel
Hallo.
@Peter (Gast)
Bist Du da noch dran an dem Problem?
Nur der Vollständigkeit halber, wenn man viel Strom aus einer schwächer
werdenden Batterie zieht, bricht die Spannung ein -> Kontroller Reset...
Hi,
im Grunde schon, habs erstmal nen bisschen weiter nach hinten geschoben,
genug andere Arbeit. Ne ich betreib es mit einem Netzteil, und nen
lf33cv, der sollte eigentlich genug Strom liefern. Ich glaub
mittlerweile auch nicht mehr das es an der Lib liegt, sondern eher an
der Karte, SanDisk Extreme III, hab nur leider keine andere zur Hand.
Gruesse
Peter
Guten Abend,
erstmal: Absolut genial was hier für eine Lib entstanden ist. Da muss
man schon mal den Hut ziehen !
Ich hab allerdings noch ein Problem mit dem Schreiben. Lesen
funktioniert einwandfrei.
Wenn ich ein einzelnes Byte schreiben will (die Datei ist vorhanden und
in ihr war vorher auch nur ein Byte):
1
if(TRUE==fat_loadFatData()){
2
unsignedcharfile_name_offset[]="OFFS KOM";
3
if(MMC_FILE_EXISTS==ffopen(file_name_offset)){
4
ffwrite(0x99);
5
ffwrite(0x99);
6
ffclose();
7
}
8
}
muss ich, wie ihr seht, den Befehl dazu zwei Mal geben. Wenn das zweite
ffwrite auskommentiert ist, tut sich in der Datei gar nichts.
Das Anhängen an die Datei per vorgeschobenem
1
ffseek(file.length)
funktioniert weder mit einem noch mit zwei Befehlen.
Meine Config habe ich mal angehängt.
Bin über jeden Hinweis dankbar.
Grüße Paul
MoinMoin,
es wäre gut, wenn du mal einige Konstellationen von Defines in config.h
ausprobierst! Ich wollte gerade deine Lib mit "readonly" übersetzen und
bekam einige Fehler um die Ohren gehauen. Z.B., wenn man
#define MMC_WRITE FALSE
setzt, kommt:
/home/x/work/x/sd_card/file.c:626: undefined reference to
`fat_setClusterChain'
/home/x/work/x/sd_card/file.c:627: undefined reference to
`fat_getFreeClustersInRow'
Grüße & Danke Uwe
...Zusatz:
wenn man
#define MMC_LFN_SUPPORT FALSE
setzt, stürzt das Beispielprogramm beim Schreiben der Testdatei
reproduzierbar ab...
Du solltest wirklich mal dringenst ein Codereview machen!
Grüße Uwe
Hallo,
bin gerade etwas eng mit der Zeit die ich fürs Hobby zur Verfügung habe.
Das mit dem "readonly" Fehler ist reingekommen, weil ich da die defines
umgebaut hatte.
#define MMC_LFN_SUPPORT FALSE
Das schau ich mir morgen oder die Tage mal an. Glaub ich so nicht
richtig. Läuft bei mir nämlich in anderen Projekten problemlos.
Nur bei schnellen Prozessoren kann es Probleme mit den low level mmc
Funktionen geben hab ich bemerkt. Aber das sind dann auch keine AVR
mehr...
Grüße
Daniel
MoinMoin,
meine Testumgebung ist ein Mega168 mit 16MHz getaktet, also eigentlich
deine Default-Konfiguration...
Daniel R. schrieb:> #define MMC_LFN_SUPPORT FALSE> Das schau ich mir morgen oder die Tage mal an. Glaub ich so nicht> richtig. Läuft bei mir nämlich in anderen Projekten problemlos.>
Das Fehlerbild sieht wie folgt aus: es kommen genau zwei Zeilen des
Dateiinhaltes, auch wenn mehr drin steht.
Grüße Uwe
PS.: für mich wäre es wichtig, wenn die "readonly"-Geschichte
funktioniert. Ich könnte auch selbst am Code rummachen, aber habe keine
Berechtigung, das Zeugs wieder ins SVN zurück zu laden... Deshalb würde
ich es gerne dir überlassen!
MoinMoin,
ein weiterer Fehler:
file.c --> ffls() --> lsRowsOfClust()
Ein Dateiname ist mindestens 11 Zeichen lang. Du deklarierst temp als
Array mit 11 Byte und schreibst an die 11.Stelle eine \0, als
Stringende. Damit geht das letzte Zeichen des Dateinamen verloren...
Grüße Uwe
PS.: sorry, dass ich so penetrant bin. Ich wollte eigentlich deine Lib
zum Einlesen von Basic-Programmen
(http://www.mikrocontroller.net/articles/AVR_BASIC) von einer SD-Karte
benutzen, stolpere aber derzeit leider über die Fehler in der Lib.
MoinMoin,
...siehe
Beitrag "Re: Basic-Interpreter auf einem AVR"
Grüße Uwe
PS.: eine Funktion ffeof() wäre auch ganz nett...
PPS.: aber auch Lob für deine Lib, ich bin trotz einige Ungereimtheiten
relativ schnell zum Ziel gekommen!
Tach auch.
Zuerst einmal: Eine super Bibliothek, die auf Anhieb funktioniert hat.
Top!
Allerdings bin ich nun auf ein Problem gestoßen: Wenn ich eine Datei
(zum Lesen) öffne und sie von Anfang bis Ende mit ffread() auslese, ist
es mir danach nicht mehr möglich eine neue Datei zu öffnen. Egal ob ich
die datei schließe oder nicht. Waron könnte das liegen?
Gruß Sven
Hallo,
wie äußert sich das denn. Bleibt er beim öffnen hängen oder wie?
Versuch mal testweise die Karte vor dem erneuten öffnen neu zu
initialisieren. Wie sieht die config.h aus und die Initialisierung der
FAT/Karte?
Viele Grüße
Daniel
Moin Daniel. Wenn ich die SD-Karte und die FAT neu initialisiere,
funktionierts. Er hatte zuvor gemeldet, die Datei würde nicht
existieren.
An der Initialisierung der SD habe ich nichts geschraubt und so von dir
übernommen. Hier meine config.h:
// schalter die den funktionsumfang aendern bzw, den funktionsumfang einiger funktionen :)
20
#define MMC_WRITE FALSE // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
21
#define MMC_OVER_WRITE FALSE // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien überschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
22
#define MMC_MULTI_BLOCK FALSE // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber möglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
23
#define MMC_SDHC_SUPPORT FALSE // TRUE, dann mit sdhc unterstuetzung, wenn FALSE, dann nur mmc/sd karten. siehe : http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29
24
#define MMC_ENDIANNESS_LITTLE TRUE // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
25
#define MMC_LFN_SUPPORT TRUE // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
26
#define MMC_RM_FILES_ONLY TRUE // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
27
28
// schalter die explizit funktionen mit kompilieren oder nicht!
29
#define MMC_TIME_STAMP FALSE // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
30
#define MMC_RM FALSE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
31
#define MMC_SEEK TRUE // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
32
#define MMC_MKDIR FALSE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
33
#define MMC_GET_FREE_BYTES TRUE // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
34
#define MMC_LS TRUE // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
35
#define MMC_CD TRUE // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
36
#define MMC_FILE_EXSISTS TRUE // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
37
#define MMC_WRITE_STRING TRUE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.
38
39
// vorsicht, da die variable die die sektoren zählt ein short ist (MMC_MAX_CLUSTERS_IN_ROW*fat.secPerClust) !!
40
#define MMC_MAX_CLUSTERS_IN_ROW 256 // gibt an wie viele cluster am stück ohne fat-lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
41
42
// wenn "#define INLINE inline" dann werden die statischen funktionen inline kompiliert. macht code groeßer, aber auch schneller!
Paul P. schrieb:> Das Anhängen an die Datei per vorgeschobenem ffseek(file.length) funktioniert
weder mit einem noch mit zwei Befehlen.
dito bei mir!!!
Hallo.
Leider habe ich momentan keine Zeit wegen dem blöden Weihnachten.
Werde aber kommende Woche dazu kommen mir das alles anzuschauen und die
Probleme zu beheben.
Viele Grüße
Daniel
docean schrieb:> Version 0.5.9 tut!
Interessant, ich habe aber in der zwischenzeit schon einen Workaround
gefunden. Mit der Funktion ffwrites() läuft es weil fat.bufferDirty =
TRUE gesetzt wird. Als habe ich mir eine kleine Funktion hingepfuscht
die das auch nach dem normalen ffwrite() erledigt. Aber mir schwant es
schon, so elegant ist das nicht ;)
Vielleicht hilft es ja bei der Fehlersuche. Schönen Feiertag noch
Hallo Daniel,
mir ist etwas merkwürdiges aufgefallen:
Ich schreibe zuerst 10kB in die Datei. Dann schließe ich sie, öffne sie
erneut und hänge nochmal 10kB hintendran.
Win XP zeigt dann auch den richtigen Inhalt mit 20kB an. Wenn ich chkdsk
laufen lasse werden aber Fehler korrigiert und die Datei hat danach
24kB!
Mega32 @ 8MHz, 5V
Guten Rutsch!
Mfg,
Kurt
Hallo Daniel,
zunächst vielen Dank für die tolle Arbeit.
Ich habe eine ganzen Tag gebraucht, um meine alten 16MB-SD-Karten zum
Laufen zu bringen.
Problem war offensichtlich, dass Windows 16MB-Karten nur mit FAT12
formatiert und diese FAT12 dann beim Schreiben durch den AVR zerstört
wird.
Wenn man in der Console dagegen "format x: /a:2048" verwendet, wird auch
die 16MB-Karte in FAT16 formatiert und nun funktioniert alles. Ein
Hinweis darauf in der Doku wäre nicht schlecht.
Oder vielleicht beim Initialisieren prüfen, ob da auf der Karte
überhaupt eine nutzbare FAT16 oder FAT32 drauf ist, bevor man da was
kaputtschreibt.
Eine andere Frage:
Vermutlich gibt es keine Möglichkeit, die 512Bytes RAM für den
Sektorbuffer irgendwie zu reduzieren?
Mein ATMEGA16 ist da zusammen mit anderen Programmteilen schon extrem
voll und ich hab da ein bissel Angst vor einem Stack Overflow, bei dem
ich dann ewig den Bug suche.
Michael
Michael R. schrieb:> Vermutlich gibt es keine Möglichkeit, die 512Bytes RAM für den> Sektorbuffer irgendwie zu reduzieren?
Bei Flash-Speichern müssen immer 512Byte auf einmal geschrieben werden.
Wenn man alles auf einen Rutsch schreiben will, braucht man eben diesen
Speicher.
Du hast jetzt 2 Möglichkeiten.
Entweder du optimierst den Speicherverbrauch, oder du steigst auf einen
ATmega32 um.
Hallo Daniel,
Ich habe hier auch noch ein seltsames Problem bezüglich Anhängen.
Wenn der AVR frisch startet und an eine bestehende Datei anhängen soll,
dann geht das schief. file.length gibt bei jedem neuen Öffnungsversuch
immer wieder den gleichen Wert zurück, obwohl ich zwischendurch bei
geöffneter Datei mit ffwrites was angehängt habe.
Also folgende Reihenfolge:
-Init-CARD/FAT
-ffopen
-ffseek(file.length) (falls MMC_FILE_EXISTS zurückkommt)
-ffwrites
-ffclose
-Init-CARD/FAT (Ich mach das jedes Mal, zur Sicherheit)
-ffopen
-ffseek(file.length)
-ffclose
Beim zweiten ffseek wird genau das gleich zurückgeliefert, wie beim
ersten ffseek. Die Datei wird einfach nicht größer
Wenn die Datei dagegen frisch angelegt wird, scheint das Verlängern
beliebig häufig zu klappen, bis ich den AVR neu starte, dann geht es
wieder nicht.
Also eine bereits vor AVR-Boot bestehende Datei wird nicht mehr
verlängert, eine gerade selbst angelegte Datei lässt sich immer
verlängern.
Die 16MB-Karte Karte ist so formatiert(chkdsk-Ausgabe):
14,1 MB Speicherplatz auf dem Datenträger insgesamt.
14,1 MB sind verfügbar.
2.048 Bytes in jeder Zuordnungseinheit
7.241 Zuordnungseinheiten auf dem Datenträger verfügbar
16 Bits in jedem FAT-Datensatz.
Irgendwie sieht das so aus, als wird irgendwas nicht richtig
initialisiert.
Michael
Zu dem Anhängen-Problem:
Ich habe mal ein bisschen weiter gewühlt:
Beim Anhängen werden die Daten richtig auf die Karte geschrieben und
sind mit einem Hex-Editor auffindbar. Ändert man mit dem Hex-Editor die
Dateigröße, dann werden die geschriebenen Daten auch für das normale
Windows Notepad sichtbar.
Beim Schließen der Datei wird scheinbar der FAT-Eintrag nicht richtig
aktualisiert. Mindestens die Dateigröße wird falsch geschrieben.
Ich habe zwar die Funktionsaufrufe beim flush bis runter zum
mmc_write_sector( fat.currentSectorNr,fat.sector );
nachvollzogen, konnte aber nicht rausfinden, warum die Dateigröße nicht
oder nicht richtig geschrieben wird. (Habe keinen Debugger, ist sehr
mühsam).
Michael
Soo,
noch ein Stück weiter:
Wenn der AVR die Datei in der aktuellen Sitzung nicht selbst erstellt
hat,
dann enthält "fat.currentSectorNr" beim Aufruf von "fat_loadSector "in
der "fflushFileData" immer 0.
fflushFileData:
1
// dafuer sorgen, dass der sektor mit dem geaenderten dateieintrag geschrieben wird, beim neuladen. datensektor der datei neuladen, falls noch weitere bytes geschrieben werden.
2
fat.bufferDirty=TRUE;
3
fat_loadSector(save_currentSectorNr);
Das führt dazu, dass "fat_loadSector" versucht, die aktuellen Daten nach
Sektor 0 zu speichern:
1
mmc_write_sector(fat.currentSectorNr,fat.sector);// schreiben von sektor puffer
Glücklicherweise geht das wohl irgendwie schief und dem Bootsektor
passiert dadurch offenbar nichts.
Warum "fat.currentSectorNr" nicht die Sektornummer des FAT-Eintrags hat,
kann ich aber nicht mehr nachvollziehen, das wird mir dann zu
unübersichtlich.
Michael
Hallo zusammen,
bei meiner SanDisk SD 2GB 2 tut es leider nicht.
Genaueres:
Bei meiner alten Karte(SanDisk Extreme III) hat es noch getan. Leider
ist diese abgeraucht. Ich habe mir dann die oben gesagte gekauft. Init
läuft durch. Jedoch beim Lesen des 1. Sector gibt es dann einen Zonk.
Unter Windows tut die Karte (FAT32).Im Anhang ist ein Log.
Ich werde mal sehe ob ich noch was rausfinde. Leider habe ich keine 2
Karte zum gegentesten.
Teste gerade die Lib mit verschiedenen Karten.
Bis jetzt funktionieren:
- Sandisk Sd-Card 2 GB
- Kingston SD-Card 256 MB
- Hama SD-Card 256 MB
- Sandisk Mikro-SD 2GB
- Sandisk Mobile Ultra Micro-SDHC 4GB
Mit Verzeichnisse anlegen habe ich noch nichts gemacht. Mir ging es erst
einmal um das Speichern und Lesen von Daten.
Gruß Gerd
Moin,
Meine MMC/SD Ansteuerung verhält sich sehr komisch...
Mit einem AtMega16/8MHz hat es mit einer 4GB/SDHC plötzlich funktioniert
(ein Datenloggen über zwei Stunden ohne Probleme), nachdem ich den LFS
eingeschaltet hatte...
Wegen zu wenig Speicher hab ich den ATMega16 gegen den pinkompatiblen
Atmega32 getauscht. Leider habe ich zwischenduch den Code mal etwas (was
auch immer) modifiziert...
Nach drei Abenden werd ich wohl jetzt frustriert aufgeben:
* mmc_init und load_fat funktionieren
Öffne ich ne Datei in meinem Code mit ffopen ohne was anderes zu tun,
zeigt mein PC die Datei mit 0 Byte an, gut so.
Öffne ich die Datei und schließe sie direkt wieder mit ffclose, dann
gibt es keine Datei, aber der PC kann die Karte noch lesen.
Öffne ich die Datei und schreibe ich etwas mit ffwrites wird die FAT
zerschossen. Egal ob mit oder ohne ffclose.
SPI wird nicht hochgesetzt, ich versorge die Karte mit 3.3V aus einem
Labornetzteil, der ATMega arbeitet allerdings auf 5V mit
Spannungsteilern.
Ich hab mit nem Scope die Signale nachgemessen, alle da und für die
Geschwindigkeit ausreichende Signalintegrität.
Eine andere Karte 2GB/SD läuft gar nicht.
Gruß ka-long
Hallo,
ka-long schrieb:> Ich hab mit nem Scope die Signale nachgemessen, alle da und für die> Geschwindigkeit ausreichende Signalintegrität.
insbesondere die Clock-Flanken bei SPI sind extrem kritisch. Wenn man
keinen integrierten Pegelwandler verwenden möchte, kann man auch einen
kapazitiven Spannungsteiler parallel zum normalen Spannungsteiler
schalten. Folgende Kombinationen sollten funktionieren:
Oberer Kondensator | unterer Kondensator
22p | 12p
27p | 15p
33p | 18p
39p | 22p
47p | 27p
56p | 33p
Wenn ein Tastkopf dranhängt stimmt das Verhältnis wegen der
Tastkopfkapazität aber nicht mehr. Man sieht also nicht mehr das
gleiche, wie die Karte ohne Tastkopf sieht. Man muss sich auf die
Mathematik verlassen.
Michael
Hallo Michael,
Sind die Anstiegs- und Fallzeiten denn irgendwo definiert ?
Ich werd mal auf mmc-lib Sektor-Ebene Daten lesen und schreiben und
schauen, ob es da zu Fehlern kommt oder obs in einer der höheren
Schichten passiert.
So kann ich vielleicht die HW als Ursache ausschließen...
Gruß ka-long
ka-long schrieb:> Sind die Anstiegs- und Fallzeiten denn irgendwo definiert ?
Wenn Du eine matschige CLK-Flanke hast und da noch Rauschen oder
sonstige Spikes drauf sind, kann es passieren, dass der Empfänger 2
Flanken kurz nacheinander sieht und dann auch 2 Bits einliest, obwohl
nur eine Flanke gesendet wurde. In wie weit Doppelflanken unterdrückt
werden, steht vielleicht im Datenblatt der Karte. Wenn die Karte aber
z.B. 50MHz SPI unterstützt, dann muss sie Flanken im Abstand 10ns
erkennen können. Wenn Deine Anstiegszeit aber z.B.100ns ist, dann hält
sich der Pegel doch einige Zeit im kritischen Bereich auf und kann eine
Doppelflanke auslösen, wenn Rauschen/Spikes überlagert ist.
Vernünftig entwickelte Clk-Eingänge haben Schmitt-Trigger-Eingänge und
intelligente digitale Filter drin, die das Problem entschärfen. Aber
gerade das ist wohl selten spezifiziert.
Die Flankensteilheit der Datenleitungen ist dagegen weniger kritisch,
der Pegel muss nur zum Zeitpunkt der jeweiligen CLK-Flanke eindeutig
high oder low sein.
Michael
Hallo,
erstmal Danke für die gute Arbeit. Ich teste seit ein paar Tagen die
Version 0.6.1 mit einem mega644. Leider läuft die main_simple.c nur dann
durch, wenn ich den µC resete.
Schaltet man VCC aus und wieder ein bleibt das Programm in der
fat_loadFatData(); hängen und zwar beim ersten Aufruf von
loop_until_bit_is_set(SPSR,SPIF);" in der mmc_write_byte Funktion
(mmc.c).
Was ich schon getestet habe:
- Verzögerung mit _delay_ms --> ohne Erfolg
- Verschiedene 1 GB sd-Karten --> ohne Erfolg
- Brummspannung auf VCC < 20 mV (Die ganze Schaltung inkl. µC läuft mit
3,3 V)
Ich glaube nicht, dass es ein Hardwareproblem ist.
Komisch ist, dass vor "fat_loadFatData();" noch die mmc_init();
problemlos aufgerufen wird, ohne das das Programm in mmc_write_byte fest
hängt?!
Vielleicht könnt Ihr mir einen Tipp geben, was ich noch versuchen kann,
damit die main_simple.c direkt durchläuft.
Danke.
Gruß
Andi
Hallo zusammen,
ich bin da gerade immer mal wenn ich etwas Zeit habe dran am arbeiten.
Ich habe jetzt einen stm32 mit jtag Debugger, damit arbeitet sich
wesentlich leichter als mit einem avr und Debug Ausgaben über die
Konsole :)
Was wohl auf jeden Fall geändert werden wird, sind die Delay schleifen
in der mmc.c, die werden auf einen Timer umgestellt werden müssen.
Die Initialisierung der Karten wird auch geändert sowie der Ablauf von
den schreibe und lese Funktionen. Also quasi der ganze Unterbau wird
geändert. Zudem noch die Datei öffnen Funktion.
Bitte um etwas Geduld...habe bald Semesterferien, die letzten :) da wird
das wohl spätestens was werden....
Viele Grüße
Daniel
Hallo Daniel,
wenn Du das Timing auf einen Timer umstellst, wird das Einbinden in
verschiedene andere Projekte deutlich schwerer oder unmöglich. Ich habe
Deine lib in einem Projekt drin, in dem keine Timer mehr verfügbar sind.
Super wäre es, erstmal eine stabile weitgehend bugfreie Version zu
schaffen, denn derzeit ist das definitiv nicht der Fall.
Ansonsten finde ich Deine Arbeit echt super, eine Lib, die wenig
Resourcen braucht und einfach einzubinden ist.
Michael
Hallo.
>wenn Du das Timing auf einen Timer umstellst
Genau da ist beispielsweise einer der Bugs. So eine Karte genehmigt sich
schon mal bis zu 200 ms um Daten zu speichern oder um einen Block zu
lesen. Da rasselt man dann einfach aus den warte Schleifen raus,
zumindest so wie die momentan sind.
Ich hab mir das so vorgestellt, dass man einfach eine bestimmte Funktion
im 10 ms Takt aufrufen muss.
Im Beispielcode würde ich dann ein Timer Beispiel machen, wie das dann
letztendlich in einem eigenen Projekt umgesetzt wird muss dann jeder
selber schauen...
Grüße
Daniel
Hallo Daniel,
ich meinte den z.B. den Bug, dass die FAT beim Anhängen nicht richtig
geschrieben wird.
Ansonsten hat Dein Ansatz mit den Timern definitiv Vorteile, da der
Controller in den Warteschleifen nicht blockiert wird.
Du baust also keine Timerfunktionen direkt in die Lib ein sondern
erwartest ein Pollen Deiner Funktionen?
Michael
Hallo,
ich hätte mal eine Frage zur "Superfloppy"-Erkennung. Mit meiner frisch
gekauften 2GB-SD-Karte lief das AVR-FAT-Paket auf meinem Pollin net-io
mit SD-Addon zunächst tadellos. Diese SD-Karte hatte in Sektor 0 einen
MBR mit Partitionstabelle. Nun habe ich die SD-Karte in meinem
Windowsrechner neu mit FAT32 formattiert. Dadurch verschwand der MBR und
die neue Partition beginnt nun ohne Umwege direkt in Sektor 0, die Karte
hat also "Superfloppy"-Format. Wenn ich es richtig verstanden habe,
untersucht die AVR-FAT-Software den Boot-Code der Partition auf die
Zeichenkette "medi", die an der Stelle erwartet wird, wo sonst die
Anfangsadresse der 1.Partition steht. Dies funktioniert bei mir nicht.
Die Zeichenkette "medi" ist um 2 Bytes versetzt, wodurch die
Superfloppy-Erkennung scheitert und alles weitere natürlich auch. Habe
das Debugger-Listing angehängt, in dem der Versatz zu erkennen ist. Habe
ich irgendetwas nicht richtig beachtet ?
Vielen Dank für Tipps
recently
Hallo,
ich bin dazu gekommen mal ein wenig an der Lib zu arbeiten.
Als Anhang mal die frischen Dateien.
Es gibt einige Änderungen.
In der mmc.c ist aufgrund der Portierbarkeit ein eigener SPI Teil dazu
gekommen. Zum anpassen an andere Plattformen müssen jetzt nur noch die
Funktionen,
spi_init
spi_maxSpeed
spi_write_byte
spi_read_byte
und die defines,
#define MMC_CS_LOW GPIO_ResetBits(GPIOA, GPIO_Pin_4)
#define MMC_CS_HIGH GPIO_SetBits(GPIOA, GPIO_Pin_4)
angepasst werden.
Auch in der mmc.c geändert:
Die Initialisierung der SD/MMC Karten.
Die Bestimmung ob Superfloppy oder nicht.
Zeit gesteuerte delay Schleifen beim lesen/schreiben, wegen der Totzeit
der Karten bei diesen Operationen.
Ganz wichtig! Es muss irgendwo eine globale Variable
1
volatileunsignedcharTimingDelay;
geben, die in 10 ms Intervallen bis 0 runtergezählt wird!
In der file.c hat sich ffopen geändert.
Es wird jetzt nicht mehr einfach die Datei angelegt wenn sie noch nicht
vorhanden war. Hat oft zu Verwirrung geführt.
ffopen(name,'r') öffnet die Datei falls vorhanden und gibt
MMC_FILE_OPENED zurück. Oder aber MMC_NOTHING_DONE.
ffopen(name,'c') legt eine Datei an falls es die Datei noch nicht gibt
und gibt MMC_FILE_CREATED zurück. Oder aber MMC_NOTHING_DONE wenn es die
Datei schon gab...
In der fat.c hat sich das suchen nach Dateinamen geändert. Bei kurzen
Dateinamen wird von PC Betriebssystemen manchmal nur ein SFN angelegt.
Das ist jetzt in der Lib angepasst.
Es wird demnächst noch weiter gehen...
Grüße
Daniel
Mit den neuen Modulen ist bei mir nichts mehr compilierbar ... schade,
ob das jetzt wirklich ein Gewinn war ?
Gibt es denn dazu auch eine passendes "main_simple", das nach diesem
Totalaustausch der Quellen noch läuft ? Das man es wenigstens mal
ausprobieren kann ?
Hallo Daniel,
vielen Dank für die neue Version. Die Superfloppy-Erkennung sieht gut
aus. Gibt es denn auch eine AVR-Version ? Die Version im fix-zip-file
scheint für STM32-Hardware ausgelegt ?
Viele Grüße
recently
Hallo,
jetzt sollten alle Fehler behoben sein.
Hier schonmal die STM32 Version. Bisher nur mit lfn Option getestet...
Die AVR Variante braucht noch etwas Zeit,
sollte aber auch relativ einfach aus der SMT32 Version zu portieren
sein.
Viele Grüße
Daniel
Hallo Daniel,
ich beschäftige mich gerade intensiv mit dem AVR-FAT-Code und habe eine
Frage zum Element file.dir : Das Element wird in der Funktion
fat_loadFatData einmal auf 0 gesetzt und dann an verschiedenen Stellen
der Software auf 0 geprüft ... was ist die Bedeutung dieses Elements ?
Hallo,
da wird der 1. Cluster des aktuellen Verzeichnisses gespeichert. Damit
man weiß in welchem Ordner man sich befindet.
Wird nur durch ffcd() und ffcdLower() geändert. Mit ffcd() wechselt man
in ein Verzeichnis und mit ffcdLower() geht man ein Verzeichnis höher
(auch als "cd.." bekannt).
Viele Grüße
Daniel
PS: Die AVR Version ist soweit. Bin nur noch ausgiebig am testen.
Hallo zusammen,
hier jetzt mal die fertigen Sachen.
Es wäre super, wenn ein paar Leute mittesten könnten.
Es gab eigentlich nur einen Bug, den ich selber eingebaut hatte von
0.5.9 auf 0.6.1, dummerweise...
Der ist jetzt weg und es gibt neue Features...
Viele Grüße
Daniel
Hallo Daniel,
mit meinem ATMega32 (der NetIO von Pollin) mit 18.432 MHz bekomme ich
Schwierigkeiten beim compilieren ... Die Taktfrequenz wird im Header
nicht angeboten und weiterhin hat der Mega32 auch kein "TCCR0A" ...
Viele Grüße
recently
Hm, dann musst Du den Timer per Hand einstellen.
Die Timer ISR muss alle 10ms aufgerufen werden.
Für den mega32 werde ich das aber wohl auch noch einbauen...
Grüße
Daniel
Hallo,
ich werde deine Version auch testen.
Ich wollte mal fragen warum du überall "unsigned char var[]" als
Parameter nutzt.
Könnte man da nicht "char *var" nehmen dann muss man nicht immer rum
casten wenn man Standard lib Funktionen nutzt.
Also statt:
extern unsigned char ffopen( unsigned char name[], unsigned char
rw_flag);
ein:
int8_t ffopen(char *name, uint8_t rw_flag);
Vielen dank das du das hier veröffentlicht hast, wie gesagt soll nur ein
Vorschlag sein.
Servus,
Daniel R. schrieb:> Es wäre super, wenn ein paar Leute mittesten könnten.
hab mich mal mit der neuen Version beschäftigt.
Bis jetzt war ich begeistert- aber nun macht es doch erhebliche
Probleme. Insbesondere mit einem neuen Prozessor.
Die Timer-Geschichte mag zwar funktionieren ist aber gegen der
vorherigen Version komplizierter geworden.
Mit den #If, #else, #endif verliert man total die Übersicht.
Trotz alledem bin ich über Deine Vorgängerversion froh, die funktioniert
ohne Probleme auf allen Atmegas/Atxmegas.
Gruß XMEGA
Hallo,
bei der Timer Version ist das einzige komplizierte, dass es eine ISR
geben muss die alle 10ms aufgerufen wird und in der
1
TimingDelay=(TimingDelay==0)?0:TimingDelay-1;
seht.
Sonst hat sich alles nur zum Vorteil geändert.
Besonders bei sfn (short file names) ist es doch wesentlich bequemer
1
unsignedcharfile[]="test.txt";
zu schreiben als
1
unsignedcharfile[]="TEST TXT";
Aber gut, zu dem Timer Punkt werde ich mir etwas überlegen. Vielleicht
hat ja jemand eine Idee, wie man aus F_CPU und ein paar Assembler
Befehlen auch so etwas hinbekommen kann wie gezieltes warten von maximal
200 ms.
Wenn man eclipse als IDE benutze, kann man die #if die nicht benutzt
werden ausblenden lassen, oder sie grau hinterlegen lassen, das ist sehr
übersichtlich.
char * mag ich nicht als Standard Typ verwenden, weil das signed ist und
somit im 2er Komplement. Das ist nicht so Ressourcen schonend...
Viele Grüße
Daniel
Daniel R. schrieb:> char * mag ich nicht als Standard Typ verwenden, weil das signed ist und> somit im 2er Komplement. Das ist nicht so Ressourcen schonend...
Aha, ok wenn du meinst, für String Bearbeitung macht das zwar keinen
unterschied aber nun ja...
Für den Timer währe es sinnvoll wenn man per define einstellen könnte
alle wie viel ms die Zähler runtergezählt wird, so könnte man eine
Bestehende Timer Funktion verwenden.
Den Code versteh ich nicht...
Wie ist das gemeint?
Man kann doch bestehende Timer einfach mitbenutzen... es muss halt nur
TimingDelay im 10ms Takt um 1 runter gezählt werden, bis auf 0.
Um mehr muss man sich nicht kümmern.
Daniel R. schrieb:> es muss halt nur> TimingDelay im 10ms Takt um 1 runter gezählt werden
Und das ist der Punkt. wenn deine Timer mit z.B. 15ms oder 5ms laufen
kannst du sie nicht so einfach benutzen.
Bzw. musst du selber im Timer schauen das du z.B (5ms) nur jedes zweite
mal dekrementierst oder (15ms) jedes zweite mal doppelt dekrementieren
musst.
Ok, ich dachte ja nur, dass ich ein Beispiel der Benutzung gebe.
>..wenn deine Timer mit z.B. 15ms oder 5ms laufen>kannst du sie nicht so einfach benutzen...
Wenn man das dann in ein Projekt einbaut, muss man sich genau um solche
Dinge ja Gedanken machen und ändern.
Mit der Anweisung:
Decrementiere TimingDelay im 10ms Takt um 1, bis auf 0, sollte man ja
klar kommen können.
Man kann aber auch einfach TimingDelay nach 200ms auf 0 setzten und gut
ist. Die Idee ist halt, mindestens 200ms auf die Karten zu warten.
Ich Persönlich würde ja eine Lösung ganz ohne Timer auch besser finden,
hab aber noch nicht die zündende Idee wie man das schön machen könnte.
Hallo,
Allgemeine Frage:
Funktioniert der Code mit MMCplus Karten?
Bekomme nämlich Transcend MMCplus Karten (1GB & 2 GB) nicht ans laufen!
Die Karte kann nicht initialisiert werden. Andere Karten funktionieren!
mfg
Hallo,
ist MMCplus der Standard 3.0 ? Das sollte nämlich gehen.
Wobei ich mehrmals Probleme hatte ist, wenn der MISO Pin keinen Pullup
hat. Das geht mit alten Karten meistens noch, aber mit neuen nicht mehr.
Den Initialisierungs Kram hab ich bei anderen abgeschaut, und nur noch
mal mit den Specs verglichen...
>Man kann aber auch einfach TimingDelay>nach 200ms auf 0 setzten..
Muss ich mir selber etwas widersprechen, ist nämlich einmal nach 200ms
und beim Initialisieren der Karten 1000ms...
Viele Grüße
Daniel
Leider funktioniert trotz MISO PullUP nur eine der 3 Karten. Mit der
0.5.9C hatten die alle funktioniert.
Schade dass ich keine Zeit zur Fehlersuche habe.
Aber jetzt was positives: Die Performance scheint besser geworden zu
sein. Statt 60kB/s sind es nun 80kB/s auf einem Mega32 mit 18,432Mhz.
Mfg,
Kurt
Hallo,
>..0.5.9 hatten die alle funktioniert..
das blöde ist das ich keine Karte habe mit der es nicht klappt, daher
ist das Fehlersuchen nicht möglich.
80kB/s ist aber trotzdem sehr langsam. Benutzt Du software SPI?
Mit 18,432Mhz Quarz und hardware SPI müsste das eine sehr langsame Karte
sein.
Ich hab hier SD Karten die mit 16Mhz 170kB/s machen. Auch welche mit
über 200kB/s...
Alles schreibend, lesend noch schneller...
Außerdem ist an den schreib Routinen eigentlich nichts geändert.
Viele Grüße
Daniel
Nein, ich nutze Hardware SPI.
Wahrscheinlich liegt die geringe Geschwindigkeit daran dass ich immer
nur ein einzelnes Byte schreibe?
Falls sonst niemand Probleme mit den SD Cards hat, habe ich wohl einen
Fehler eingebaut der so offensichtlich ist dass ich ihn immer übersehe.
;-)
Mfg,
Kurt
@ Kurt Bohnen (kurt)
Also wenn Du normal mit ffwrite() schreibst, puffert die Lib eh 512
Bytes zwischen. Da sollte das Problem nicht liegen.
Ach ja, wenn überschreiben an ist, ist das schreiben etwas langsamer...
@ little_man (Gast)
Ja stimmt, ist 4.x, wenn Du da eine Spezifikation findest, schau ich mir
das mal an und setzt das dann um...
Viele Grüße
Daniel
Daniel R. schrieb:> Ich hab hier SD Karten die mit 16Mhz 170kB/s machen. Auch welche mit> über 200kB/s...
Hallo Daniel,
kannst du ein paar Namen nennen?
Mfg,
Kurt
Hallo zusammen
Erstmal vielen Dank fuer die tolle Library. Bin ziemlich neu in der Welt
von uC. Trotzdem habe ich es geschaft dank der Library auf die SD-Karte
zu speichern. Das spricht wohl fuer sich. (super super Sache das)
Ein Problem habe ich aber noch.
1
ffseek(file.length);
Dauert am Anfang ca. 5ms 30min. spaeter 28ms (Datei ist dann 2.85MB
gross)
Habe weiter oben beim Eintrag vom 17.9.2010 gesehen das ffseek nicht
durchgefuehrt werden muesste wenn File nicht geschlossen wird.
Funktioniert bei mir aber leider nicht. (Auf dem SPI-Bus sind noch
andere Teilnehmer. Sollte aber doch nichts ausmachen)
Um meine Frage kurz zu fassen: Wie kann ich die Zeit zum spulen
verkuerzen?
(Sollte doch moeglich sein file.length zu merken aber wie?)
Vielen Dank
@ Kurt Bohnen (kurt)
Muss ich mal nachschauen, bin grad nicht zuhause.
@ Markus K. (Gast)
Schließt Du die Datei beim schreiben immer oder wieso das ffseek?
Du könntest alternativ ein fflush machen anstelle von schließen...
Zeig doch mal ein bisschen code
Viele Grüße
Daniel
Ja ich schliesse sie nach jedem anhaengen wieder. Hab auch mal versucht
sie offen zu lassen doch dann stimmten die Eintraege nicht mehr. Ich
haenge alle 200ms ein paar Daten an.(sollte so eine xml Datei entstehen)
Verstehe ich das richtig:
fflushFileData(); anstelle von ffclose();
und dann kein ffopen(filename); mehr oder?
Vielen Dank.
Ja genau.
>Hab auch mal versucht sie offen zu lassen>doch dann stimmten die Eintraege nicht mehr.
Das müsstest Du mal genauer erklären, bzw zeigen, wie Du die lib
benutzt.
Viele Grüße
Sorry war mein Fehler hab wohl irgendwo im Code vergessen ffclose oder
ffopen auszukommentieren.
Nun funktioniert es mit dem geoeffnet halten der Datei.
Sorry
Nochmals Vielen Dank fuer deine tolle Library
Hallo Daniel.
Danke erstmal für die Lib, grad die Fat Funktionen sind super und Fat32
geht auch einwandfrei.
Ich habe aber immer wieder mit der Karteninitialisierung Probleme.
Kleine Karten < 1GB gingen vom Start weg aber die grossen, bei denen man
im Init in den SDv2-Block läuft machten Probleme.
Ausserdem habe ich einige Karten gehabt, die nicht sofort auf CMD0
reagiert haben. Und auch auf CMD16 reagieren manche nicht sofort.
Hierfür habe ich jeweils eine Schleife eingefügt.
Ich habe die Init-Fuktion etwas angepasst:
TimingDelay=100;// Initialization timeout of 1000 msec
17
18
if(mmc_send_cmd(CMD8,0x1AA)==1){// SDv2?
19
for(n=0;n<4;n++){
20
ocr[n]=spi_read_byte();// Get trailing return value of R7 resp
21
}
22
if(ocr[2]==0x01&&ocr[3]==0xAA){// The card can work at vdd range of 2.7-3.6V
23
24
// while (TimingDelay && mmc_send_cmd(ACMD41, 1UL << 30)); // Wait for leaving idle state (ACMD41 with HCS bit)
25
while(TimingDelay){// Wait for leaving idle state (ACMD41 with HCS bit)
26
mmc_send_cmd(CMD55,0);
27
if(mmc_send_cmd(ACMD41,1UL<<30))
28
break;
29
}
30
ty=CT_SD2|CT_BLOCK;
31
}
32
}else{// SDv1 or MMCv3
33
if(mmc_send_cmd(ACMD41,0)<=1){
34
ty=CT_SD1;
35
cmd=ACMD41;// SDv1
36
}else{
37
ty=CT_MMC;
38
cmd=CMD1;// MMCv3
39
}
40
while(TimingDelay&&mmc_send_cmd(cmd,0));// Wait for leaving idle state
41
}
42
while(TimingDelay&&(mmc_send_cmd(CMD16,512)!=0));
43
if(!TimingDelay)ty=0;
44
}else{j--;}
45
}while(j>0);
46
fat.card_type=ty;
47
mmc_disable();
48
49
if(fat.card_type==0){
50
returnFALSE;
51
}
52
#if (MMC_MAX_SPEED==TRUE)
53
spi_maxSpeed();
54
#endif
55
56
returnTRUE;
57
}
Um SDHC-Karte überhaupt zum laufen zu bewegen (besonders eine
8GB-MicroSD) musste ich die ACMD41-Schleife noch um das vorherige Senden
von CMD55 erweitern, so wie es in der Spec auch gefordert wird.
Die Abfrage auf CMD58 habe ich raus genommen, da diese von keiner meiner
Karten anders als mit 05 (Illigal Command) beantwortet wird.
Bei meinen SDHC Karten mit 4 und 8GB hat das mit
1
ty=CT_SD2|CT_BLOCK;
ganz gut funktioniert, aber jetzt habe ich eine extrememory 2GB bei der
er auch in den SDv2-Block läuft die nur mit
1
ty=CT_SD2;
läuft. Also die Zugriffe der FAT-Funktionen klappen sonst halt nicht
mehr.
Gibt es noch eine andere Möglichkeit als CMD58 hier eine Unterscheidung
zu machen?
Eine 1GB Platinum hingegen läuft auch in diesen Block bleibt jedoch am
ACMD41 hängen: es kommt immer 0x00 zurück, sie kommt also nie in den
Idle-State.
Any Ideas? Gerade bezüglich des CT_SD2 bzw. CT_BLOCK, weil wenn dann nur
noch die Platinum Karte nicht ginge wäre das zu verschmerzen...die
scheinen ja eh etwas tricky zu sein.
Gruß
Fabian
Noch eine Ergänzung:
wenn ich die CMD58 Abfrage vor der CMD55->ACMD41 Kombination sende
bekomme ich eine "Antwort". Die Karten senden dann nicht mehr 05
(Illegal Command) sondern immer 01 (Idle State). Wenn ich danach noch 4
Byte lese bekomme ich für das CCS Bit aber immer 0, egal ob SDHC oder
nicht HC.
Es muss doch noch eine Möglichkeit geben SDv2 von SDHCv2 Karten zu
unterscheiden?!
Gruß
Fabian
Hallo,
hatte gerade mit meinem 8MHz-System Probleme, die SD-Karte zuverlässig
zu initialisieren. Nachdem ich den SPi-Prescaler von 128 auf 64 geändert
habe, gehts jetzt offenbar zuverlässig. Die Initialisierungs-SPI-Clock
wird in der MMC.C fest mit fCPU/128 gesetzt.
Vielleicht wäre es sinnvoller dass diese in Abhängigkeit vom CPU-Takt
gesetzt wird, der in irgendeinem h-file definiert wird.
Laut einigen Quellen müssen die Init-Takte mit 100-400kHz erzeugt
werden, was beim 128er Teiler erst ab 12,8Mhz zutrifft. Vielleicht wäre
es auch sinnvoller, beim AVR standardmäßig den 64er-Teiler zu nutzen.
Das deckt besser die typischen Taktfrequenzen ab.
Michael
Hallo zusammen.
@ Fabian B. (fabs)
Hast Du einen PullUp an MISO?
Wie schnell ist dein Kontroller?
Die Init Routine hab ich selber nur abgeschaut,
die die ich selber geschrieben hatte ist raus geflogen,
obwohl die gut war...vielleicht mach ich das wieder rückgängig.
@ Michael R. (Gast)
Ja werde ich ändern.
Viele Grüße
Daniel
@Daniel: Ich hab noch einen gravierenden Fehler in der Soft gefunden.
Jetzt geht auch CMD58. Alle Karten initialisieren nun korrekt, soweit so
gut.
Nur auf meiner MicroSDHC (8GB) kann ich zwar die Fat initialisieren und
auch ffopen gibt ein Ok, aber ich bekomm keine Dateiinfos (filesize oder
Daten). Dabei ging die Karte vorher ... ich find das aber noch raus
(morgen) und werde die Routine dann posten.
Gruß
Fabian
So.
Ich habe habe jetzt die Init soweit dass alle meine Karte initialisiert
werden. Getestet wurden:
- Canon SD 16MB
- Nokia MMC 32MB (2x)
- extrememory MMC 256MB (mit FAT16 und FAT32)
- Platinum SD 1GB (meldet sich als SDv2)
- extrememory SD 2GB (meldet sich als SDv2)
- SanDisk SDHC 4GB (Ultra II)
- SanDisk MicroSDHC 8GB (2x)
- Noname MicroSDHC 8GB
Hierfür musste ich zwei Änderungen an der mmc.c vornehmen.
Bei den Definitions ganz oben im File war das define für ACMD41 falsch.
Korrekt ist:
1
#define ACMD41 (41) // SEND_OP_COND (SDC)
vorher war dort (0x80+41) definiert.
Ich denke auch bei ACMD13 und ACMD23 müsste dieses (0x80) weg, aber da
ich diese Kommandos nicht selbst brauchte und bisher keine Fehler
diesbezüglich feststellte hab ich das erstmal so gelassen.
Die zweite Modifikation betrifft die Funktion mmc_init. Wie oben schon
geschrieben hatte ich ein paar Karten die nicht sofort auf CMD0
antworten, also habe ich hier eine Schleife drum gelegt. Auch bei
anderen Kommandos war dies notwenig (CMD55->ACMD41, CMD58, CMD16).
Ich poste hier einfach mal die ganze Funktion:
TimingDelay=100;// Initialization timeout of 1000 msec
17
18
if(mmc_send_cmd(CMD8,0x1AA)==1){// SDv2?
19
for(n=0;n<4;n++){
20
ocr[n]=spi_read_byte();// Get trailing return value of R7 resp
21
}
22
if(ocr[2]==0x01&&ocr[3]==0xAA){// The card can work at vdd range of 2.7-3.6V
23
while(TimingDelay){// Wait for leaving idle state (ACMD41 with HCS bit)
24
mmc_send_cmd(CMD55,0);
25
if(!mmc_send_cmd(ACMD41,1UL<<30))
26
break;
27
}
28
29
while(TimingDelay){
30
if(mmc_send_cmd(CMD58,0)==0x00){// Check CCS bit in the OCR
31
for(n=0;n<4;n++){
32
ocr[n]=spi_read_byte();
33
}
34
ty=(ocr[0]&0x40)?CT_SD2|CT_BLOCK:CT_SD2;// SDv2
35
break;
36
}
37
}
38
}
39
}else{// SDv1 or MMCv3
40
if(mmc_send_cmd(ACMD41,0)<=1){
41
ty=CT_SD1;
42
cmd=ACMD41;// SDv1
43
}else{
44
ty=CT_MMC;
45
cmd=CMD1;// MMCv3
46
}
47
while(TimingDelay&&mmc_send_cmd(cmd,0));// Wait for leaving idle state
48
}
49
if(ty!=(CT_SD2|CT_BLOCK)){
50
while(TimingDelay&&(mmc_send_cmd(CMD16,512)!=0));
51
}
52
if(!TimingDelay)ty=0;
53
}else{j--;}
54
}while(j>0);
55
fat.card_type=ty;
56
mmc_disable();
57
58
if(fat.card_type==0){
59
returnFALSE;
60
}
61
#if (MMC_MAX_SPEED==TRUE)
62
spi_maxSpeed();
63
#endif
64
65
returnTRUE;
66
}
Was mir noch auffiel:
Laut Spec muss ein ACMD immer auf ein CMD55 folgen. Im SDv1 or MMCv3
block wird nur so direkt ein ACMD41 versucht. Ich vermute, dass hier
eigentlich auch ein CMD55 vorher noch sein müsste, da ich aber mit keine
Karte, die diesen Block durchläuft Probleme hatte lass ich es so.
Vielleicht kannst du, Daniel, diese Funktion so bei dir einpflegen und
mal testen.
Nicht direkt als Bug zu bezeichnen: ich hatte noch eine
Unregelmässigkeit.
Bei den SanDisk MicroSDHC 8GB konnte ich die Karte korrekt
initialisieren, Fat initialisieren und auch Fileopen lieferte ein Ok,
die Datei hatte laut file.length jedoch eine grösse von 0 und auch ein
"blindes" ffread() lieferte nur Schrott. Da auf der Karte auch vorher
schon Daten waren habe ich sie dann mal formatiert und die Datei wieder
drauf kopiert und dann ging's einwandfrei.
Gibt es da vielleicht Zugriffprobleme auf Dateien ab einer bestimmten
"Position auf der Karte", also weit hinten? Und wäre es vielleicht
sinnvoll ffopen failen zu lassen wenn die Dateigrösse 0 ist?
Ich verwende:
At90Can128, 10MHz, HC4050 als Pegelwandler, 3V3 Regler für SD Karte,
HW-Spi
Gruß
Fabian
Hallo,
ich habe ein Problem mit dem neuen Code:
Wenn ich das richtig verstehe, wartet die Funktion mmc_wait_ready
lediglich solange, bis auf der Miso-Leitung H-Pegel anliegt:
1
staticunsignedcharmmc_wait_ready(void){
2
3
TimingDelay=50;
4
5
do{
6
if(spi_read_byte()==0xFF)returnTRUE;
7
}while(TimingDelay);
8
9
returnFALSE;
10
}
Zur Aktivierung der Karte wird also zunächst CS auf 0 gesetzt und dann
getestet, ob Miso auf H-Pegel geht (oder bereits ist):
1
staticunsignedcharmmc_enable(){
2
3
MMC_CS_LOW;
4
if(!mmc_wait_ready()){
5
mmc_disable();
6
returnFALSE;
7
}
8
9
returnTRUE;
10
}
Das funktioniert bei mir leider nicht. Meine Karte(n) liefert vor
Absendung des CMD0 Kommandos immer L-Pegel. Aus diesem Grund kommt es
bei mir nicht zur CMD0 Absendung. Habe die mmc_wait_ready erstmal
auskommentiert, wäre für eine Erläuterung dankbar ...
Viele Grüße
recently
Hallo.
>getestet, ob Miso auf H-Pegel geht (oder bereits ist)
Miso sollte H sein, weil da ein PullUp dran sein sollte.
Ich muss das im Wiki unbedingt mal ändern.
Damit sollte das dann klappen.
Viele Grüße
Daniel
Hallo Daniel,
vielen Dank für die schnelle Antwort. Habe den Schaltplan von meinem
Pollin Net-IO mit SD-Karten-ADD-On untersucht und finde dort keinen
Pullup.
Bin ein wenig irritiert, die Hardware funktionierte ja mit der alten
Software, auf dem Oszilloskop sieht das Miso-Signal auch normal aus,
schön rechteckig und ungefähr zwischen 0 und 3V. Aber es ist 0V, wenn
die Karte herausgezogen oder gerade hereingesteckt wurde.
Was für ein Widerstand sollte da eingelötet werden ?
- recently -
Das kann auch ein Effekt der der Karte sein, dass die die Leitung
schwach auf low zieht wenn sie eingesteckt wird und direkt Saft bekommt
(evtl. noch mit Prelleffekten auf der Versorgung). Da ich die Versorgung
der Karte bei mir immer erst einschalte, wenn die Karte im Slot
detektiert wurde, konnte ich dieses Verhalten bei inzwischen ca. 15
getesteten Karten nicht feststellen.
@Daniel R: hast du den mmc_init mal testen können?
Gruß
Fabian
Leider nein, hab diese Woche noch 2 Klausuren und es war Karneval :)
Komme ich aber bald dazu, danke das Du da soviel Mühe mit rein
Investiert hast.
Viele Grüße
Daniel
Hallo Daniel,
habe den 10k Widerstand eingebaut ... Unterschied wie Tag und Nacht. Die
Initialisierung funktioniert jetzt sauber und reproduzierbar (ohne
Pullup hatte ich mehrere CMD0-Wiederholungen, jetzt immer genau 1x).
Sollte man Pollin mal mitteilen ... :-)
Vielen Dank für den Tipp !
Viele Grüße
recently
Haloo,
Ich bin nur Anfänger und ich möchte nur einfacher Programm machen.
Programm macht neue Datei – zum Beispiel „1.txt“ und schreibt jede 10
Sekunden Temperatur (es ist in string format). Jede Temperatur an neue
Zeile. Zuerst möchte ich nur library 0.6.2 testen.
Ich habe SD-Karte, ATMega 168 – es ist durch MISO, MOSI, SCK und CS
verbinden.
Jetzt teste ich Version 0.6.2. Ich habe AVR Studio 4.18, ich öffne
main_simple.c, dann gebe ich Project -> Configuration Options – ich
schreibe Frequency 16MHz (ich habe 16 MHz Krystal). Und dann
programmierte ich den Prozessor. Ich lasse den Programm etwa 10 sekunden
laufen. Aber es macht nichts. Die Karte ist leer. Mache ich etwas
schlecht ? Muss ich noch etwas machen ? Die Karte ist normal formatiert
in Windows – FAT.
Können Sei mir bitte helfen ? Vielen Dank.
Hallo,
läuft der ATMega 168 mit 3,3 Volt?
Läuft das Beispielprogramm ohne irgendwelche Änderungen?
Wie sieht die Schaltung aus?
Versuch immer in kleinen Schritten etwas auszuprobieren, bis es läuft
und erweitere es dann erst.
Viele Grüße
Daniel
Atmega hatte 5Volt, jetzt läufte mit 3,3V aber es geht auch nicht.
Ich mache keine Änderungen - nur frequency.
Die Schaltung ist wie hier
(http://www.mikrocontroller.net/articles/AVR_FAT32), aber keine HC4050
(ich habe 3,3 Volt).
Hallo,
dann mach doch mal noch einen PullUp an MISO vom Kontroller.
Beziehungsweise an DO der Karte.
Dann könntest Du noch mal versuchen in der mmc_config.h
1
#define MMC_MAX_SPEED FALSE
zu setzen.
Und eventuell die mmc_init() zu benutzen die in folgendem Link
angesprochen wird.
Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Falls das alles nichts hilft, müsstest Du mal ein Foto vom Aufbau machen
und hochladen, damit man sich eventuell ein bild von möglichen
Fehlerquellen machen kann.
Du solltest auch mehrere Karten ausprobieren ob vielleicht nur eine
bestimmte nicht funktioniert.
Viele Grüße
Daniel
Hallo zusammen
Ich habe ein Problem mit der AVR Fat32 Library
http://www.mikrocontroller.net/articles/AVR_FAT32
Zur Hardware:
Ich verwende einen Atmega16 mit 12MHz Quarz
Am Hardware SPI Hängt die SD Karte (micro SD)
Der Atmega wird mit 3,3V Betrieben.
Nun das Problem
Die Library funktioniert grundsätzlich sehr gut... Ich habe die Dateien
1:1 übernommen uns es klappte auf anhieb.
Doch ich habe das problem, das wenn ich z.B. die Datei bild.bmp öffnen
lassen will mit der Lib, dann verwende ich folgenden Code
1
while(FALSE==mmc_init()){//Karte Initialisieren
2
nop();
3
}
4
Out1_1;
5
if(TRUE==fat_loadFatData()){
6
unsignedcharfile_name[9]="bild.bmp";
7
8
if(MMC_FILE_EXISTS==ffopen(file_name)){
9
Out1_0;
10
// Setzen einer Variable und dann runterzaehlen geht am schnellsten !
11
seek=file.length;
12
// Lesen eines chars und Ausgabe des chars.
13
// Solange bis komplette Datei gelesen wurde.
14
while(ucBufferCounter!=56)//Daten auslesen
15
{
16
ucBuffer[ucBufferCounter]=ffread();
17
--seek;//Byte Zähler
18
ucBufferCounter++;
19
}//56Bytes Buffer auslesen
20
}
21
22
}
nicht von den 56Bytes irritieren lassen... das spielt derzeit keine
rolle!
Doch wenn ich diesen Code ausführen lasse, dann meldet der Code das Die
Datei existiert jedoch erstellt er selbige auf der Karte.
Wenn ich Die karte also in den PC einschiebe, befindet sich zweimal die
Datei bild.bmp im Root verzeichniss... Windows motzt nun also und ich
muss die Karte formatieren...
Wass jedoch prblemlos geht, ist eine von der Lib erstellte Datei lesen
oder zu erweitern... Auch mit dem Computer... Aber es kann ja nicht
sein, das ich immer mit dem AVR eine Datei erstellen muss und diese Dann
am Computer bearbeiten muss. Dies geht sowiso nur bei txt dateien.
Getestet habe ich den Code mit mehreren Karten. An dennen liegt es also
nicht! An der Lib config habe ich nichts verändert!
Was auch merkwürdig ist, das bei dem Beispielcode von hier
http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Code
steht beim Filename "man beachte die Grossbuchstaben" aber es hat im
beispiel nur kleinbuchstaben.
Hat jemand eine idee wo hier der wurm drinn sein könnte?
Hallo,
ich komme grad nicht dazu ne neue Version zusammen zu packen in der auch
die neue Initialisierungsfunktion ist und auch die neue
fat_loadFiledataFromCluster.
unsignedshortrow;// um durch zeilen zu gehen, eigentlich erstes byte einer reihe...
9
unsignedcharsectors;// um durch sektoren zu zaehlen, sectors+sec = tatsaechliche sektornummer (absoluter sektor)
10
unsignedchari;// um durch eine zeile/reihe zu laufen
11
unsignedcharj;// laufvariable fuer sfn
12
13
// diese variablen muessen statisch sein, weil ein lfn eintrag auf 2 cluter aufgeteilt sein kann !
14
staticunsignedcharchecksum=0;// die kurze dateinamen checksumme, die ausgelesene.
15
staticenumflags{wait=0,start,readout}lfn_state;
16
staticunsignedcharmatch=0;// treffer bei datei namen vergleich zaehlen
17
18
constunsignedcharmap[13]={1,3,5,7,9,14,16,18,20,22,24,28,30};// index von map ist index des zu pruefenden bytes und inhalt ist index des zu pruefenden bytes in der reihe
19
constunsignedcharname_length=strlen((char*)name)-1;// es wird die laenge des dateinamen zum vergleichen benoetigt!
20
21
sectors=0;
22
23
// 5 moegliche zustaende im inneren der beiden schleifen...
24
do{// sektoren des clusters pruefen
25
row=0;// neuer sektor, dann reihen von 0 an.
26
mmc_read_sector(sec+sectors,fat.sector);// laed den sektor sec auf den puffer fat.sector
27
fat.lastSector=file.currentSectorNr;// sichern der alten sektor nummer
28
file.currentSectorNr=sec+sectors;// setzen des aktuellen sektors
29
do{// reihen des sektors pruefen
30
// 1.) nach einem eintrag mit 0x00 kommt nix mehr => restlicher cluster leer!
31
if(fat.sector[row]==0x00){
32
returnFALSE;
33
}
34
// 2.1) ist eintrag ein lfn eintrag? siehe: http://en.wikipedia.org/wiki/File_Allocation_Table#Long_file_names
35
if((fat.sector[row]&0x40)==0x40&&fat.sector[row+11]==0x0F&&fat.sector[row]!=0xE5){// ist lfn eintrag, jetzt pruefen...
match=0;// vergleich index zurueck setzen, damit nicht wieder in diesen zustand gewechselt wird.
78
checksum=fat.sector[row+13];// checksumme sichern zum vergleich mit der errechneten anhand des kurzen dateinamens. in naechstem zustand vergleich.
79
}
80
}
81
// 4.) gesuchte reihe auf stuct file laden zum weiter verarbeiten. das ist der sfn eintrag, mit dem firstCluster, der laenge usw...
82
if(lfn_state==readout&&fat.sector[row+11]!=0x0F){
83
lfn_state=wait;
84
fat_loadRowOfSector(row);
85
file.row=row>>5;// reihe sichern, ist fuer ffrm wichtig
86
if(checksum==fat_lfn_checksum(&fat.sector[row])){// pruefen ob checksumme stimmt...wenn ja alles klar :)
87
file.entrySector=file.currentSectorNr;// sichern des sektors in dem der sfn dateieintrag steht.
88
returnTRUE;
89
}
90
}
91
92
}while((row+=32)<512);// mit row+32 springt man immer an die 1. stelle einer reihe (zeile) und das durch einen ganzen sektor
93
}while(++sectors<fat.secPerClust);// geht durch sektoren des clusters
94
95
returnFALSE;// datei nicht gefunden, zumindest in diesem cluster...
96
}
Diese Funktion solltes Du mal test weise in der fat.c austauschen.
>man beachte die Grossbuchstaben
Die Kommentare in den Sourcen sind nicht immer aktuell ^^
Sag mir mal ob in der mmc_config.h
Daniel R. schrieb:> Die Kommentare in den Sourcen sind nicht immer aktuell ^^
Kein Problem :)
Vielen Dank für die Antwort
Ich habe LFN Support auf True
und auch MMC File Exists auf True
Ich verwende übrigens die neuste Version aus dem SVN
habe besagten Code ersetzt jedoch kommen nun folgende Meldungen
../fat.c:195: error: 'struct Fat' has no member named 'lastSector'
../fat.c:195: error: 'struct File' has no member named 'currentSectorNr'
../fat.c:196: error: 'struct File' has no member named 'currentSectorNr'
../fat.c:255: error: 'struct File' has no member named 'currentSectorNr'
Anscheinend ist das Struct geändert worden von dir :)
Variable im Programm geben die in 10 ms Intervallen runtergezählt wird
bis 0. Wenn Du Dich an der main_simple.c orientierst sollte das kein
Problem werden.
Ich habe mit deiner Neusten Version ein sehr merkwürdiges aber
reproduzierbares verhalten entdeckt.
Ich möchte auf der Speicherkarte überprüfen ob die Datei logfile.txt
existiert...
Das mache ich wie folgt:
1
unsignedcharfile_name_2[]="logfile.txt";
2
3
if(ffileExsists(file_name_2))
4
{
5
text_neu("OK",90,90,1,0,0,255);
6
}
7
else
8
{
9
text_neu("ERROR",90,90,1,255,0,0);
10
}
Problem -> Die funktion liefert immer Error zurück obwohl die Datei auf
der Speicherkarte liegt (habe auch grossklein schreibung geachtet!) LFN
ist aktiviert.
Prüfe ich hingegen ob die Datei test.bmp existiert, klappt der test
einwandfrei. Beide Dateien beinhalten etwas. sind also nicht 0Byte
gross!
Nun das ganz spezielle...
Möchte ich nun also die Datei Lesen (logfile.txt) wass ja eigentlich
nicht gehen sollte, so wird diese angelegt und es befinden sich wieder
zweimal die selben dateien auf der Karte. Wichtig hier zu beachten ist,
das die Lib die neue Datei mit Grossbuchstaben erstellt egal ob ich der
Funktion kleibuchstaben übergeben habe.
Könnte dies ein hinweis darauf sein, das in dieser funktion nicht auf
LFN geachtet wird?
Vielleicht sagt dir meine Fehlerbeschreibung ja etwas...
Ansonsten keine Probleme :)
Hallo,
ja klingt irgendwie danach:
Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Ersetze die Funktion in der fat.c durch die Funktion aus dem Post.
Benutzt Du die Version 0.6.2 ? Da sollte wenn Du die Datei zum lesen
öffnest auf jeden Fall keine zweite Datei mit dem selben Namen angelegt
werden.
Viele Grüße
Daniel
Hallo Daniel
Ja ich habe die Funktion ersetzt... Ja ich verwende die Version 0.6.2
Ich habe das Problem gefunden...
Es scheint so, als ob die Funktion File Exists nur mit kurzen Dateinamen
klar kommt...
Dies stört mich nicht weiter, da ich ja darauf achten kann...
Aber wollte dir halt dennoch den hinweis geben :)
Dann ist es allerdings etwas merkwürdig das LFN nicht unterstützt wird
obwohl ich den Schalter auf True habe. Das selbe ist es mit SDHC karten
Ich habe den schalter auf True
Aber 8GB Karten werden nicht initialisiert.... (FAT)
Daniel R. schrieb:> Das kann nicht sein. In der 0.6.2 ist der Schalter für SDHC raus> geflogen.
Ohhh.... schande... Tut mir leid... ja du hast recht... ich habe auch
keinen.
Daniel R. schrieb:> Hast Du die hier gepostete mmc_init Version benutzt?> Beitrag "Re: MMC SD library FAT16 FAT32 read write">> Hast Du die hier gepostete fat_loadFileDataFromCluster Version benutzt?> Beitrag "Re: MMC SD library FAT16 FAT32 read write">> Damit geht das auf jeden Fall.>> Viele Grüße
Ich habe diese Version von der du mir den link gesendet hast.
Ok, Du brauchst die Version 0.6.2 hier aus dem Thread und dann musst Du
die beiden Funktionen austauschen. Die Beiden Funktionen aus den Links
die ich gepostet hab. Dann wird es klappen. Bin wie gesagt noch nicht
dazu gekommen die einzubauen und das ins SVN hochzuladen.
Viele Grüße
Daniel
Ok
Vielen Dank
Ich werde die Anpassungen vornehmen und eventuelle probleme wieder
fragen wenn ich darf :)
Ich denke das ich dann auch mit den Verzeichnissen arbeiten kann... Das
klappt mommentan auch noch nicht
Hallo,
die Tabelle ist so zu lesen:
Pin 1 der SD/MMC Karte soll an Pin 15 des ATmega168
Pin 2 der SD/MMC Karte soll an Pin 17 des ATmega168
...
...
Bei der DIP Version des ATmega168 sieht man im Datenblatt, dass Pin 15
des IC der Port B1 des Kontrollers ist.
>Und hast du in library behandelt Ergennung>der Karte und Schutz von Überschreibung ?
Du meinst ob eine Karte im Slot steckt und der Hardware Schreibschutz an
ist?
Ja da ist was in der Lib, weiß aber nicht genau ob das auf Anhieb
funktioniert.
Viele Grüße
Daniel
Kurt Bohnen schrieb:> Leider funktioniert trotz MISO PullUP nur eine der 3 Karten. Mit der> 0.5.9C hatten die alle funktioniert.> Schade dass ich keine Zeit zur Fehlersuche habe.
Heute hatte ich Zeit. Das Problem war wohl, das ich "alten" Code aus dem
SVN genommen hatte. Mit dem aktuellen Code und den Patches aus dem
Thread hier funktionieren jetzt alle Karten!
Ein Problem bleibt immer noch:
Ich schreibe 921600 Byte auf die Karte. Kontrolle mit Win XP: Dateigröße
und Inhalt OK. Dann nach checkdisk: Datei ist 4kB größer weil Datenmüll
am Ende angehängt wurde.
Das passiert aber nur bei FAT32 formatierten Karten. Bei FAT16 gibt es
keine Probleme. LFN hat keinen Einfluss.
Mfg,
Kurt
Moin! Ich verzweifel hier mal wieder an der Ansteuerung einer
MicroSD-Karte (habe schon zwei verschiedene probiert). MCU ist ein
AT90CAN128, Pegelwandler ein MAX3002. Die Verdrahtung habe ich schon
hundertmal geprüft. MISO-Pullup (10k) habe ich auch.
Ich schaffe nicht einmal die mmc_init(). spi_read_byte() gibt immer nur
0 zurück. Nach dem Timeout wird dann abgebrochen. Was kann ich noch
machen, bin völlich ratlos?
Ich habe die neueste Version im Einsatz inkl. den Modifikationen aus den
Posts hier.
Hm, mach doch mal ein Foto vom Aufbau.
>habe schon zwei verschiedene probiert
Wenn das nicht total außergewöhnliche Karten sind sollten die schon
gehen.
>Nach dem Timeout wird dann abgebrochen.
Also die Timer Einstellungen sind richtig? Ist vielleicht der Timer zu
schnell eingestellt? Überprüf mal ob die Zeiten des Timers stimmen.
Ich mache die Einstellungen um nicht nachdenken zu müssen mit
http://clsql.med-info.com/download.html>Ich schaffe nicht einmal die mmc_init()
Klingt für mich irgendwie nach Hardware Problem
Viele Grüße
Daniel
Daniel,
hast du eine Idee wo mein Problem liegt oder sonst jemand? Ich bin doch
wohl nicht der einzige, der seine Karten mal mit chkdsk geprüft hat?
Mfg,
Kurt
Hallo Kurt,
also ich würde mal vermuten, dass da die 2. Fat dran schuld ist.
Hast Du die Möglichkeit die Karte mal so zu formatieren, dass nur eine
Fat angelegt wird?
Sonst kann ich mir das eigentlich nicht erklären. Besonders, weil es nur
bei Fat32 auftritt. Bis auf die Fat Einträge selbst ist Fat16 und Fat32
nämlich identisch.
Unter Linux würde formatieren mit nur einer Fat so aussehen:
1
mkdosfs -v -F32 -f1 -s4 -I /dev/sdb
Der Befehl erstellt ein Fat32 Dateisystem mit nur einer Fat und 4
Sektoren pro Cluster auf dem Device sdb.
Viele Grüße
Daniel
So ich habe jetzt mal alle Signale vor (5V, high) und hinter (3V, low)
dem Pegelwandler aufgenommen. Herausgekommen ist der Anhang. Die kurzen
Puls bei MISO low sind etwa 10ns lang. Kann jemand bei der Deutung des
Bildes helfen?
So ich habe jetzt mal je einen SPI Interpreter auf die low und high side
gepackt. Auf der low side können auch Bytes entziffert werden -
natürlich nicht auf der high side. Machen die Bytes Sinn? Ist der
Pegelwandler defekt?
Jetzt fall ich gleich vom Glauben ab: Wenn der LogicAnalyser
angeschlossen ist, funktioniert scheinbar alles, d.h die Test-Datei wird
geschrieben (obwohl die aufgezeichneten Kurven anderes schließen
lassen), ziehe ich ihn ab, geht nix mehr. Wodurch lässt sich so ein
Verhalten erklären?
Ich habe spontan an das hier gedacht:
http://www.eevblog.com/2011/03/11/eevblog-155-itead-studio-pcb-prototype-goof/
Aber ein Massefehler kann ich eigentlich ausschließen. Irgendwelche
Ideen?
Vielen Dank im Vorraus und entschuldigung für die vielen Posts in Folge.
Gruß Sven
Wenn ich die Karte mit dem SD Formatter 3.0 formatiere tritt das Problem
nicht mehr auf. Aber gibt es nicht einen Workaround für die Firmware?
Mfg,
Kurt
Hallo.
@ Sven S. (schwerminator)
Hast du abblock Kondensatoren an allen IC's?
Was benutzt Du als Pegelwandler?
@ Kurt Bohnen (kurt)
Es wird dafür keinen Workaround geben. Das würde nämlich bedeuten, dass
alle Fat Operationen zwei mal gemacht werden müssten. Die zweite Fat ist
eigentlich gedacht um zu schauen ob es einen Unterschied gibt. Gibt es
den muss wohl ein Fehler vorliegen. Korrigieren kann man den dann aber
noch nicht.
Eventuell eine Alternative zu dem normalen check disk suchen.
Viele Grüße
Daniel
Abblockkondensatoren sind reichhaltig verbaut. Als Pegelwandler benutze
ich einen MAX3002. Einen solchen habe ich schonmal erfolgreich mit einer
SD-Karte betrieben, allerdings ohne MISO-Pullup, ich werde das Gefühl
nicht los, dass sich MAX3002 und der Pullup aus welchen Gründen auch
immer nicht vertragen. In meiner jetzigen Schaltung ist der Pullup mit
10k dimensioniert auf der 3V-Seite des Wandlers, was jedoch
grundsätzlich richtig sein müsste...
Gruß Sven
Daniel R. schrieb:> @ Kurt Bohnen (kurt)>> Es wird dafür keinen Workaround geben. Das würde nämlich bedeuten, dass> alle Fat Operationen zwei mal gemacht werden müssten. Die zweite Fat ist> eigentlich gedacht um zu schauen ob es einen Unterschied gibt. Gibt es> den muss wohl ein Fehler vorliegen. Korrigieren kann man den dann aber> noch nicht.>> Eventuell eine Alternative zu dem normalen check disk suchen.
OK. Dann muss ich diesmal zu Elm Chans lib wechseln. Die ist zwar
deutlich größer aber in dieser Hinsicht toleranter.
Trotzdem vielen Dank!
Mfg,
Kurt
In Chans Lib wird die zweite Fat auch nicht beschrieben, da hast Du das
gleiche Problem.
Das hat ja auch nix mit Tolerant zu tun. Sondern mit dem Unsinn zwei Fat
Tabellen führen zu müssen anstelle von ordentlichen Codes um Fehler zu
beheben. Die Idee einfach alles doppelt da hin zu schreiben ist ein
Repetition Code und ne ganz große Glanzleistung von MS...
Du hast ja geschrieben, dass die Daten korrekt sind und nach einem check
disk erst falsch. Vielleicht sind die ja schon vorher falsch? Poste doch
mal die Änderungen die du gemacht hast, vielleicht kann ich dann mehr
dazu sagen.
Viele Grüße
Daniel
Ich bin mir jetzt fast sicher dass das FAT32 Problem bei Chan nicht
auftritt, werde das aber nochmal prüfen.
Daniel R. schrieb:> ganz große Glanzleistung von MS...
Da gebe ich dir Recht!
Ich kann nicht ausschließen dass jemand mein Projekt benutzt der seine
SD-Card mit FAT32 und Windows formatiert. Wenn er dann aus welchem Grund
auch immer checkdisk laufen lässt und die neu angelegten Dateien mit
Müll volgestopft werden ist das weniger schön...
Daniel R. schrieb:> Poste doch> mal die Änderungen die du gemacht hast
Keine, nur die Portdefinitionen. Dann einfach eine neue Datei erstellen,
900kB reinschreiben und schließen.
Ich melde mich später nochmal mit mehr Details.
Mfg,
Kurt
Hallo.
@ JVogel (Gast)
Kannst auch an andere Pins hängen, musst dann aber software SPI benutzen
und einschalten in der config. Zudem musst Du dann natürlich auch die
richtigen Pins einstellen in der mmc.h
Hallo nochmals. Ich habe noch ein paar Tests gemacht:
- Auch ohne Pullup klappts nicht ohne LogicAnalyser
- Zusätzlicher 100n bringt ebenfalls nicht den gewünschten Erfolg
- Folgende Leitungen auf der High-Side des Pegelwandlers müssen an den
LA geklemmt sein, damit es funktioniert: CS, SCK und MOSI (+ GND) -
sprich alle Leitungen in Richtung der SD. Die Eingangsimpedanz des LA
ist wie folgt: 200K Ohms, paralleled by <5pF.
Welche Schlüsse kann ich aus der Information ziehen?
Bei mir hängt das programm bei mmc_enable(); nach dem SPI_INIT
mmc_send_cmd(CMD0, 0)
->if ( FALSE == mmc_enable() )
dort bleibt es hängen woran kann das liegen?
Hab einen Atmega32@16mhz
Timer :
1
TCCR0=(1<<CS02)|(1<<CS00)|(1<<WGM01);
2
TCNT0=START_TCNT;
3
OCR0=TOP_OCR;
4
5
ISR(TIMER0_COMP_vect)
6
{
7
TimingDelay=(TimingDelay==0)?0:TimingDelay-1;
8
9
}
mmc.h
1
#define MMC_Write PORTC //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
2
#define MMC_Read PINC
3
#define MMC_Direction_REG DDRC
4
5
#if defined (__AVR_ATmega32__)
6
#define SPI_MISO 3 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
7
#define SPI_MOSI 2 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
8
#define SPI_Clock 1 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
9
#define SPI_SS 0 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist (CS)
// schalter die den funktionsumfang aendern bzw, den funktionsumfang einiger funktionen :)
5
#define MMC_WRITE TRUE // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
6
#define MMC_OVER_WRITE FALSE // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien ueberschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
7
#define MMC_MULTI_BLOCK FALSE // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber moeglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
8
#define MMC_ENDIANNESS_LITTLE TRUE // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
9
#define MMC_LFN_SUPPORT FALSE // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
10
#define MMC_RM_FILES_ONLY TRUE // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
11
12
// schalter die explizit funktionen mit kompilieren oder nicht!
13
#define MMC_TIME_STAMP FALSE // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
14
#define MMC_RM FALSE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
15
#define MMC_SEEK TRUE // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
16
#define MMC_MKDIR FALSE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
17
#define MMC_GET_FREE_BYTES FALSE // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
18
#define MMC_LS FALSE // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
19
#define MMC_CD FALSE // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
20
#define MMC_FILE_EXSISTS FALSE // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
21
#define MMC_WRITE_STRING TRUE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.
22
#define MMC_WRITEN FALSE // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwriten mit kompiliert. mit dieser funktion koennen mehrere zeichen auf die karte geschrieben werden!
23
24
// vorsicht, da die variable die die sektoren zaehlt ein short ist (MMC_MAX_CLUSTERS_IN_ROW*fat.secPerClust) !!
25
#define MMC_MAX_CLUSTERS_IN_ROW 256 // gibt an wie viele cluster am stueck ohne fat-lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
Moin, bei irgend einem cmd an die Karte kann man als Parameter die
Spannung mit angeben. Die Karte antwortet dann positiv oder nicht. Weiß
aber grad nicht aus dem Kopf welches cmd das ist.
3,3 Volt wäre schon besser und erwarte nicht zu viel von den
Spannungsteilern.
@ Sven S. (schwerminator)
Probier mal 1k Widerstände längst den Leitungen, quasi als Terminator...
Was sagt denn das Datenblatt vom MAX3002 zu korrekten Beschaltung?
Viele Grüße
Daniel
Ok dan kram ich mal lieber in meiner kiste irgendwo hab ich noch ein
Spannungsregler au 3V, oder ich bau mir einen Spannungseiler der mit ca
3.3V gibt. Was denkt ihr ist die bessere Wahl?
Daniel R. schrieb:> In Chans Lib wird die zweite Fat auch nicht beschrieben, da hast Du das> gleiche Problem.
HELLO1.TXT wurde mit Chans Lib erstellt. TEST1.TXT mit deiner, Daniel.
Danach habe ich die Karte auf Fehler prüfen lassen. Wie man sieht ist
HELLO1.TXT unverändert, TEST1.TXT ist genau um 4kB gewachsen.
Daher würde ich vermuten das irgendeine Variable falsch initialisiert
wird oder falsch abgefragt, <,>,<=,>=...
Das Problem ist mir schon in früheren Versionen vor der 0.6.2
aufgefallen.
Mfg,
Kurt
Hallo ich habe das gleiche problem wie jvogel. Auch an einem atmega32
ich habe ihn auf 3.3v laufen und den timer von ihm kopiert ist der timer
falsch? Und oder geht nur. Soft spi nicht? Sry schreibe vom handy aus
dh vielleicht buchstaben drwher etc
Hallo.
@ Kurt Bohnen (kurt)
Tatsächlich, glaube es gibt da ein Problem in der Fat.
Es wird ein Cluster zu viel verkettet. Was erstmal an den Daten nichts
ändert, da die Dateilänge ja stimmt. Es wird aber Platz verschenkt.
Bin das gerade am ändern.
@ marvin (Gast)
Welche Werte nimmst Du denn?
Viele Grüße
Daniel
@ JVOGEL (Gast)
Ich würde sagen Dein SPI läuft nicht richtig.
Um den von Kurt Bohnen (kurt) angesprochenen Bug zu beheben, müssen
folgende Zeilen in der Datei file.c in der Funktion fflushFileData()
ausgetauscht werden:
1
// cluster chain verketten
2
fat_setClusterChain(fat_secToClust(chain.startSectors),fat_secToClust(file.currentSectorNr));// verketten der geschriebenen cluster
durch
1
// cluster chain verketten.
2
if(file.cntOfBytes==0){// gerade genau irgend einen sektor voll geschrieben.file.currentSectorNr zeigt jetzt auf den neu zu beschreibenden.
3
if(file.currentSectorNr-1>=chain.startSectors){
4
fat_setClusterChain(fat_secToClust(chain.startSectors),fat_secToClust(file.currentSectorNr-1));// verketten der geschriebenen cluster
Vielen Dank Daniel, jetzt läuft es perfekt! Allerdings hast du vergessen
das ACMD41 von (0x80+41) auf (41) zu ändern.
@JVOGEL,
hast du einen PullUP an MISO? Auch der /SS des µC braucht einen Pullup,
oder muss auf Ausgang geschaltet werden.
Mfg,
Kurt
Hi, danke schonmal für die Tipps. Hatte gestern keine Zeit mehr zu
testen und heute bin ich erst einmal auf der arbeit. Meinst du einen
Pullup in form des internen oder ein externen Pullup? Wenn er nicht
schon in der Programmierung eingebunden ist dann eher nicht, aber ich
kann auch mal ein Foto meiner Schaltung machen, heute Abend. Der halbe
Sonntag hab ich damit verbracht, leider bisher ohne Erfolg.
Habe ja einen spannungteiler mit 470ohm / 620 Ohm ist wirkt der nicht
wie ein Pullup?
Bin erstma ein Kaffee trinken ;)
Habe mir gestern in die Methode spi_write_command? oder so ähnlich ein
puts("test"); rein gemacht und das ergebnis war dann ungefähr:
Boot test test
also bleibt er beim 2. mal dort hängen bei
So, dann solltest Du zum testen auf jeden Fall erstmal hardware SPI
benutzen. Bei deinem Spannungsteiler komm ich nur auf 2,844 Volt. Das
ist bisschen wenig. Und eigentlich generell mist, dass mit dem
Spannungsteiler!
Betreibe die Schaltung am besten mit 3,3 Volt. Was genau spricht bei Dir
dagegen?
Zum berechnen der nötigen Timer Werte benutze ich immer folgendes Tool:
http://clsql.med-info.com/download.html
Wie sehen Deine Timer Werte aus?
Bild von der Schaltung wäre gut.
Ich bin mir sicher, dass wir das ans laufen bekommen :)
Viele Grüße
Daniel
Hatte zuletzt einen spannungsteiler mit 290 ohm / 620 Ohm.
Das problem, dass ich habe ist das mein MAX232 mit 3.3V nicht so richtig
funktionieren möchte, manchmal liest man, dass er mit 3.3V laufen würde
aber bei mir leider nicht. Mein LCD Display funktioniert leider auch nur
mit 5V.
Aber zum testen baue ich mir nachher eine LED auf mein Breadboard um den
Status anzeigen zu lassen, dann kann ich auch 3.3V verwenden.
Ich hoffe, dass ich heute abend Zeit finde, dann bauch ich mir die
Schaltung nochmal neu auf (Ohne Spannungsteiler)und mache dann ein Foto
falls es, dann immer noch nicht geht. Und meinen Sourcecode hänge ich
dann auch nochmal komplett an.
Vielen dank schonmal im vorraus.
Ok, dann mach lieber einen Spannungsteiler beim max232 um auf 3,3 Volt
zu kommen. LCD Displays brauchen nur an der Versorgungsspannung 5 Volt.
Zu mindest die die ich habe. Beim max232 würde dann sogar nur der RX
Pfad zum Kontroller als Spannungsteiler reichen. Da TX ja 3,3 Volt wäre
und das als Hi Pegel reicht...
>Breadboard
Damit hatte ich auch immer Probleme wenn es um SD Karten ging. Extrem
kurze Kabel und Kontroller 3,3 Volt und SD Karte 3,3 Volt helfen da
aber.
Mann muss da bedenken, dass die Karten mit 25 MHz spezifiziert sind, da
sind saubere Flanken ein muss!
Also zusammenfassend.
Kontroller 3,3 Volt
SD/MMC 3,3 Volt
LCD 5 Volt Versorgung und 3,3 Volt Datenleitungen
MAX232 <- TX Kontroller direkt
-> RX Kontroller Spannungsteiler auf 3 Volt
Viele Grüße
Daniel
Hm, ok mal doch mal nen kompletten Schaltplan, ich kann mir grad die
ganze Schaltung nur schwer vorstellen.
Zu MAX323 find ich nur "Precision, Single-Supply, SPST Analog Switches"
?
So hab mich doppelt vertan, hab den MAx232 der funktioniert aber leider
nicht bei 3.3v bei mir.
So hab jetzt bilder gemacht, und alles :(
vielleicht kann mir wer den helfenden schlag auf den hinterkopf geben.
Ok, das 2. Bild ist der Max232?
Ich sehe garkeine Pegelwandlung zwischen uC und SD Karte?
Läuft da alles mit 3,3 Volt?
Toll das Bild vom Multimeter :)
Wo geht das Kabel hin?!?
Ist das da ein ISP Programmier Adapter?
Den machst Du aber nach dem Programmieren immer ab oder?
Bei Deinen Test würde ich Dir empfehlen diese Einstellung in der
mmc_config.h noch zu machen.
Ja im 2. Bild ist der Max232,
Multimeter kabel gehen an das Breadboard aussen an jeweils ein stift in
+ und GND.
Der ISP Programmieradapter ist ein USB <--> ISR Programmier adapter der
gibt der schaltung den 5V Saft, oder bene 3,3V jenachdem was man dort
mit einem Schalter einstellt.
Der bleibt eigentlich immer dran, oder ist das schon das problem, dass
das SPI dadurch gestörrt wird? Bzw vom ISP Programmierer als Master
verwendet wird? :)
So hab nun zwei dräht in den ISP programmer gesteckt fuer VCC und GND
aber funtkioniert trozdem nicht und der MAX232 geht auch immer noch nit
mti 3.3v :(
manno
Ok, ich weiß nicht genau wo ich anfangen soll...
1. Nimm einen anständigen 3,3 Volt Regler der 1 A Strom liefert.
2. Nimm eine Anständige Quelle die den Regler speist!
3. Klemm nur die SD Karte an die SPI Schnittstelle.
4. Überprüfe alle Anschlüsse und Einstellungen im Code 3 mal!
Zu dem Max232 hatte ich Dir schonmal was geschrieben,
5 Volt Versorgung und dann an die RX TTL Seite einen Spannungsteiler!
Weißt Du was ich damit meine?
Du solltest Dir Methoden überlegen wie Du Hardware debuggst.
Mein Vorschlag: Modul weise Prüfen ob es geht und dann nach und nach
zusammenschalten...
@ Sven S. (schwerminator)
Bist Du weiter gekommen mit diesen seltsamen Spikes da?
Viele Grüße
Daniel
IN AVR Studio hab ich:
Device: atmega32
Frequency: 16000000
OPTIMIZATION:-O2
Ok dann muss ich warten bis ich eirder zum gelben C komme. Hab hier nur
noch einen 3v Regler und einen 5v. Ein Stabilisiertes Netzteil hab ich
noch und eine passende buchse dazu.
So kann ich dann auch die verschiedenen Komponente mit 5v oder 3,3v
gleichzeitig speisen.
Hm, 3 Volt sollte auch gehen. Hauptsache ein richtiger Regler.
So eine SD Karte zieht auch schon mal gerne 200 mA oder mehr kurzzeitig.
Ich hab gerade keine Lust die Pinbelegung vom Max232 nachzuschauen, aber
ja so meinte ich das. Zwischen Max232 RX und Kontroller RX den
Spanungsteiler
Mit Einstellungen im Code meinte ich die Pin Einstellungen falls Du sie
geändert hast, halt sonst noch alle Änderungen im Code. Dann alle Kabel
Verbindungen usw...
Viele Grüße
Daniel
Ich glaub ich hat nen kurzen und entweder der MAX232 oder der RS232 port
an meine PC hats durchgeknallt, naja ich lass es jetzt erstmal bis ich
mal wieder ruhige minuten habe die tage.
Also ergebnis bisher:
MAX232 kann nicht defekt sein, da ich einen neuen Ausgetauscht habe und
der funktioniert auch nicht.
Atmega32 ist auch nicht defekt, habe ich auch ausgetauscht.
Weiss einer wie ich schnell einfach testen kann ob der RS232 port am pc
nen knacks bekommen hat?
Momentan probiere ich die neuste LIB(0.6.3) aus.
Ich bin von der 0.6.1 umgestiegen
2 Sachen waren zu beachten:
- Im Dateinamen muss nun ein Punkt sein (8.3). LFN ist bei mir aus
- Das Chip_select Define ist rausgeflogen und die Pin-Belegung war
dadurch falsch.
Übersetzen mit
#define MMC_MULTI_BLOCK TRUE
ging nicht.
> 2 Sachen waren zu beachten:> - Im Dateinamen muss nun ein Punkt sein (8.3). LFN ist bei mir aus> - Das Chip_select Define ist rausgeflogen und die Pin-Belegung war> dadurch falsch.
Kannste dazu mal etwas mehr schreiben?
-> in der Vorlage "main_simple.c" ist doch im dateinamen ein "."
-> wie hast du das Problem mit dem MMC_CHIP_SELECT gelöst. Is mir eben
auch erst aufgefallen. Umgelötet oder einfach die Pinnummer geändert?
Grüße,
Matze
So, habs dann auch zum laufen bekommen und kann meine Fragen jetzt für
alle beantworten:
-> Beim Dateinamen nuss nichts geändert werden (zumindest beim
AVR-Studio 4 und 5beta)
-> Die SD-Karte wird kompett (und nich wie im Wiki angegeben) an den
SPI-Port angeschlossen. Falls aus einer älteren Version die Leitung vom
CS der Karte an einen anderen PIN als den SS geht, dann muss das
geändert werden...
Grüße,
Matze
Hi,
ich hab da nen Problem. Ich würde gerne Verzeichnisse anlegen und in
dieses Verzeichnis eine Datei.
Wenn ich die Datei ohne Verzeichnis anlegen lasse, dann funzt alles!
Wenn ich allerdings erst das Verzeichnis anlege und das öffne um darin
dann die Datei zu platieren, dann bekomme ich nur Datenmüll.
Hier der Code, mit dem ich das Verzeichnis anlege und hinein wechsel:
1
unsignedchardatum_verzeichnis[]="12345678";
2
ffmkdir(datum_verzeichnis);
3
ffcd(datum_verzeichnis);
4
_delay_ms(10);
(Die Pause an Ende nahm ich mit rein, da ich dachte, daß mein µC (ein
ATmega128) versucht die Datei anzulegen bevor das Anlegen des
Verzeichnisses abgeschlossen ist (-> Datendurcheinander).
Der Screenshot von dem, was mir WindowsXP SP3 anzeigt, wenn ich die SD-
Karte einlege, is im Anhang.
Kann sich das jemand erklären?!
Ohja: Wie erwähnt: PC: Win XP SP3, µC: ATmega128, 3,3V, SD ohne Zusatz
an SPI, Compiler AVR Studio
Grüße,
Matze
Hm, schau ich mir heute Abend mal an.
Möglicherweise ist da was durcheinander gekommen bei den
Versionsänderungen.
Mag ich jetzt mal nicht ausschließen.
Viele Grüße
Daniel
Hi,
Ich würde gerne das Einfügen von Daten in eine Datei in deine Funktion
implementieren.
Mit Einfügen meine ich:
z.B. aus einer TXT Datei mit dem Inhalt: "Hallo Welt!" Durch einfügen
von "schöne, neue " an die Stelle 6 "Hallo schöne, neue Welt°" zu
machen.
Ich habe mir gestern darüber gedanken gemacht und würde dir die gern
kurz vorstellen, damit du mir ein paar Tipps geben kannst, was ich
möglicherweise vergessen habe:
1) mit ffseek(x); zu der einzufügenen Stelle springen.
2) mit der Bedingung ("512 - file.cntOfBytes" aus z.B. ffseek() ) die
restlichen Bytes aus dem Sektor in einer Variablen zwischenparken damit
sie nich überschrieben werden
3) in einer Variablen die "Nummer" des Folgesektors merken
4) normales Schreiben der einzufügenen Daten (hier "schöne, neue ")
5) zurückschreiben der Daten aus 2)
6) in der Fat Tabelle die Folgesektornummer von 3) angeben, um das alles
auch wieder schön zu verknüpfen
Das klingt ja erstmal gar nicht schwer. Jedoch weiß ich noch nicht mit
welches Funktionen ich die aktuelle Sektornummer und die
Folgesektornummer auslesen kann.
Zudem weiß ich noch nicht, wie ich die Fat-Tabelle aktuallisieren soll:
macht es Sinn die gesamte Tabelle auch in einer Var. zu parken (vgl. 2)
) um dann normal schreiben zu können. Nebenbei merke ich mir, wieviele
Einträge ich in die Fat Tabelle mache und schreibe den Inhalt aus Fat-
Variablen dann einfach wieder an die richtige Stelle zurück? Aber wie
kann ich in der Fat-Tabelle schreiben?
Du siehst, noch ein paar Fragen, aber eigentlich müsste das doch möglich
sein, oder?!
Grüße,
Matze
Hm, diese Diskussion hatten wir da schon mal :
Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Ich bin zu dem Schluss gekommen,dass es nicht so ohne weiteres möglich
ist, weil man entweder immer ganze Cluster einfügen müsste. Oder man
muss die kompletten Daten nach den eingefügten "aufrücken".
Keine Ahnung wie ein Betriebssystem das macht. Wenn ich da in eine 2 GB
große Datei was einfüge, werden sicher nicht alle Daten umkopiert, oder
doch?!?
Viele Grüße
Daniel
Aber ein Sektor muss doch nicht zu 100% voll mit Daten besetzt sein. Von
daher müsste das doch gehen. Das einzige, was ein bißchen aufwendig
werden könnte, wäre das erneuern der FAT- Tabelle.
Ich werde das mal angehen, wenn ich etwas zeit habe. Aber kannst du mir
noch kurz sagen, wie ich die Fat- Tabelle auslese, Daten hineinschreibe,
usw.?
Grüße
Hallo,
ich hab da im Wiki ein wenig zu geschrieben.
Falls Du danach noch Fragen hast, stell sie :)
Nur der letzte Cluster einer Fat Kette muss nicht voll besetzt sein.
Alle anderen davor schon. Man kann also nicht einfach einen halb vollen
Cluster mitten in die Kette schummeln...
Daniel,
magst du bei Gelegenheit die aktuellen Versionen wieder per SVN
verfügbar machen?
Ansonsten kommt man per deinem zugehörigen Artikel und dem dort
gegebenen Link auf aktuelle Versionen nur bis zur Version 0.6.1. Auch
habe ich ein bisschen die Übersicht verloren, welche Verison mit welchen
händischen Ändeurngen nun aktuell sein könnte...
Danke, Michael
Hallo,
ich kann mich nicht mehr anmelden beim SVN.
Hab dem zuständigen schon mal ne Mail geschrieben, ist aber keine
Antwort gekommen...
Werde wohl wieder dazu über gehen die aktuellste Version im Wiki zu
verlinken.
Viele Grüße
Daniel
Hi,
ja da wo es im Wiki immer den SVN Link gab, gibt es jetzt immer einen
Link zur aktuellen Version ohne SVN.
http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status
Falls man da noch händisch etwas ändern muss schreibe ich es dann da
auch dazu.
Viele Grüße
Daniel
Hallo,
ich habe folgendes Problem mit der Bibliothek (SourceCodeV3.0).
Mit dem µC kann ich eine Datei auf der SD Karte erstellen und auslesen,
der Computer (WinXp ServicePack 3) kommt damit auch prima klar. Wenn ich
allerdings mit dem Computer z.B. eine Textdatei "hallo.txt" auf der SD
Karte erstelle erkennt der µC diese einfach nicht. Er legt die gleiche
Datei mit dem selben Namen nochmal an, sodass diese dann zweimal
vorhanden ist, jedoch ohne brauchbahren Inhalt. Ich habe die Karte unter
Windows mit FAT formatiert, könnt da das Problem liegen?
Zur bessern Fehlersuche habe ich mal die "config.h", "mmc.h" und
"SDCardTest.c" angehängt. Ich hoffe ihr könnt mir helfen.
Gruß
Hanno
Hi, ich glaube ich habe grad wieder nen Bug gefunden...
Er ist reproduzierbar mit der Version 0.6.3.1 auf einem ATmega128 und
beliebigen SD-Karten.
Er tritt immer auf, wenn man z.B. zwei Dateien immer abwechselnd
beschreibt. Wenn die erste Datei größer ist als 2 Sektoren (bei 4.096
Byte / Sektor) und sobald die zweite Datei größer wird als 2 Sektoren,
hängt sich das Programm auf. Das funktioniert auch mit einem geänderten
main_sample.c (nicht nur bei meinem "Mutter"- Programm)
Ich hoffe, daß das Problem kein großes ist!
Grüße und schöne Ostern noch!
Sorry, das Problem tritt aus, wenn 4 Dateien geschrieben werden und wenn
eine zweite größer als 2 Sektoren werden "will"
-> Sprich, wenn zwei Dateien die größe von zwei Sektoren haben und eine
davon drei Sektoren großer werden "will" / muss.
Grüße,
Matze
Hallo,
kann mir mal jemand sagen, wie ich die neue Bibliothek in mein Eclipse
Projekt integrieren kann? Hab noch nicht so viel Erfahrung damit.
Bei der letzten Version die ich hatte, habe ich einfach die Dateien in
mein Projekt kopiert und die Pfade zu den Header Dateien angepasst.
Jetzt habe ich mir die Version 0.6.3.1 runtergeladen und weiß eigentilch
garnicht was ich mit den Dateien anfangen soll?
Matze Niemand schrieb:> Sorry, das Problem tritt aus, wenn 4 Dateien geschrieben werden und wenn> eine zweite größer als 2 Sektoren werden "will"> -> Sprich, wenn zwei Dateien die größe von zwei Sektoren haben und eine> davon drei Sektoren großer werden "will" / muss.>> Grüße,> Matze
Sorry, war wohl ein Fehler des Programmieres hüstel
geht alles...
Grüße,
Matze
Hallo.
@ Matze Niemand (hupe123)
Schön das es jetzt geht :)
@ Hanno Winter (hannow)
Ich habe im Wiki ein paar Sätze dazu geschrieben wie man das einbindet.
Orientier Dich einfach an den mitgelieferten Beispielen. Oder an den
Beispielen früherer Versionen.
Viele Grüße
Daniel
Hi,
ich wollte grad die Version 0.6.3.1 in meine Anwendung einbauen und
bekomme, auch beim Compilieren der main_sample, haufenweise
Fehlermeldungen (siehe Anhang).
Wo kommen wie auf einmal her? Ich finde den "wahrscheinlich" einfach
Fehler nich...
Der Compiler is: AVR Studio 4 und 5beta (beide die gleichen
Fehlermeldungen, im Anhang sind die aus AVR Studio 5beta), WinXP SP3
Grüße, Matze
??? Hä? Ich habe die Datei eben nochmal von
http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status
heruntergeladen und aus dem Ordner "AVRStudio-SD.MMC_lib_0.6.2" die
Datei "mmc_project.aps" geöffnet und wollte die compilieren - das selbe
Problem. Und wenn ich AVR studio 4 frage, welcher µC benutzt werden
soll, steht da "ATmega168"...
Was mache ich falsch?
Hallo,
ich brauche mal wieder einen Tipp...seit dem ich nun die neue Bib auf
den Controller gespielt habe, funktioniert die Initialisierung einfach
nicht?
Ich denke, dass ich alles so wie vorher eingestellt habe, also liegt
Chip Select noch auf PB1,...normal wäre PB4, aber wenn ich das in der
mmc.h anpasse müsste es ja eigentlich gehn?
Ich weiß gerad gar nicht wo ich anfangen soll zu suchen...an der
Hardware kanns nicht liegen, denn mit der alten Version klappt die
initialisierung ohne Probleme.
Hallo,
hast Du einen Pullup an DO der Karte, bzw am MISO vom Kontroller?
Und ja, der Chip Select Pin hat sich geändert, also die Belegung. Wenn
Du das in der mmc.h anpasst sollte das gehen.
Viele Grüße
Daniel
Hallo!
Das ist eine echt geile Lib. Super Arbeit!
Auch für Einsteiger leicht verständlich.
Kann mir einer vielleicht sagen, wie ich mit dieser Lib z.B. MP3 Dateien
einfach nach der Reihe auslesen kann, ohne dass ich den Namen angeben
muss?
Das z.B. 10 mp3´s auf der sd karte sind und der µc die dann alle
nacheinander ausliest. Ist das möglich?
Danke!!!
hi
@ Matze Niemand
"Hmm,... ich wollte eben mal wieder weitermachen und AVRstudio4 schmeißt
mir mit der neuen mmc.c Datei immernoch ein Fehler raus:
../fat.c:213: warning: implicit declaration of function 'toupper'"
du musst die Datei ctype.h in fat.c einbinden dann geht`s
#include <ctype.h>
mfg Marcel
Hallo,
ich habe die neue Bibliothek bei mir immer noch nicht zum laufen
gebracht...hatte zwar keinen Pullup an DO, aber selbst mit klappt die
Initialisierung nicht.
Mein Problem mit der alten Bib ist ja nur, dass ich mit dem Computer
keine Dateien auf der SD-Karte erstellen kann, um diese dann mit dem
Mikrocontroller weiterzuverarbeiten. Kann mir jemand sagen, was der
Computer anders bei der Erstellung von Dateien macht als der
Mikrocontroller?
Doch, das hat man immer...mit ein wenig Kreativität :)
Mach eine LED mit Vorwiderstand an einen Pin.
Im Programm machst Du die LED dann an einer bestimmten Stelle an.
Entweder das Programm läuft bis da und die LED leuchtet, oder eben
nicht. So kann man sehen bis wo es läuft.
Du könntest Dir natürlich auch Debug Ausgaben auf dem uart machen oder
so...
Viele Grüße
Daniel
Hallo,
habe da mal ein paar Fragen zur lib:
Ist das Low-Level IO (also MMC/SD etc.) vom fat code getrennt?
Weil ich dies selber realisiert habe und das gerne so übernehmen würde.
unter welcher Lizenz läuft der Code? Weil ich derzeit an einem Projekt
sitze, was unter Umständen kommerziell eingesetzt werden soll.
mit freundlichen Grüßen
Flo
Hallo,
getrennt ist relativ :)
War mal so gedacht, ist aber dann doch relativ verzahnt.
Klar schreiben eines Blocks und Initialisierung sollte ohne weiteres
portierbar sein.
Lizenz ist mir egal.
Viele Grüße
Daniel
Hallo,
da das jetzt schon mehrer Leute gefragt haben,
was würde passieren wenn ich sage:" Nee gib mir mal 50 Euro dafür"?
Mir ist es aber egal was wer damit macht...
Viele Grüße
Daniel
Mach ne readme.txt mit dazu
wo du nen copyright mit deinem namen reinschreibst
und dadrunter dass es BSD is. Dann kann die jeder Frei verwenden
bearbeiten und sons was
ein zwei regeln gibt es da noch aber prinzipiel sollte die Linzenz für
das projekt hier ganz gut sein :P
>da das jetzt schon mehrer Leute gefragt haben,>was würde passieren wenn ich sage:" Nee gib mir mal 50 Euro dafür"?
wahrscheinlich wärst du dann Händler mit allem drum und dran. Steuer,
Gewährleistung, Support, irgendwelche Anmeldungen, ...
btw. tolle Bibliothek.
Hallo,
ich habe eine kleine, wahrscheinlich banale Frage. Habe eine SD Karte
mit einem Mega 16 verbunden und möchte Werte aus einer Text-Datei
auslesen und an einem Port ausgeben. Als nur komisches Zeug ausgegeben
wurde habe ich mal per uart ausgeben lassen, was genau der uC eigentlich
von der Karte einliest und musste feststellen dass da irgendein Murks
angezeigt wird. Also habe ich zunächst eine Text-Datei mit ffwrite vom
uC aus erstellt und diese dann anschließend wie vorher ausgegeben... das
funktionierte einwandfrei. Wenn ich jedoch nur ein einziges Zeichen mit
einem Text-Editor in der Datei am Rechner verändere und das ganze
speichere, dann steht wieder nur murks da. Woran liegt das? Ich habe die
Vermutung dass irgendwas mit der Codierung nicht stimmt, bzw der Editor
da irgendwie noch was reinmogelt. Wie kann man nun am PC eine Text-Datei
erstellen, die auch wirklich nur aus dem besteht was man im Editor
sieht?
Viele Grüße
PS.: die Library ist echt super!
Hallo,
eine ganz normale Textdatei muss die Lib lesen können. Hast Du die Lib
mit LFN Untersützung kompiliert? Vielleicht macht der PC da immer lange
Dateinamen aus den Dateien beim schließen. Wenn Du so eine Datei hier
hochladen würdest, schau ich mir die mal mit einem Hex-Editor an. Der
zeigt einem wirklich die Bytes an aus der so eine Datei besteht.
Viele Grüße
Daniel
Hallo Daniel,
hier hab ich mal ein paar Werte eingetragen, einmal mit dem Mac
Text-Edit in test.txt und dann nochmal mit Windows im Editor in
test1.txt. Die Codierung ist Standardmäßig bei Windows auf ANSI und Bei
test.txt hab ich ASCII eingestellt, weil dort anscheinend UTF-8 Standard
ist. Das wär echt super, wenn du dir das kurz mal anschauen könntest.
Achso, LFN ist natürlich mitkompiliert worden.
Viele Grüße und Danke für die Hilfe
PS.: Ich hätte noch eine andere Frage zur Funktion ffls(): Wie genau
funktioniert diese?
bzw. was beudeutet genau "// zeigt direktory inhalt an, muss zeiger auf
eine ausgabe funktion übergeben bekommen" ? Kann ich die Funktion nutzen
um in einen String sämtliche Dateinamen, die vorhanden sind,
reinzukopieren? Wenn ja, wie genau stelle ich das an?
Oh ich seh grad das sind in beiden Fällen tatsächlich genau 15 Bytes.
Sehr seltsam. Kann es sein dass etwas mit der Formatierung der Karte
nicht stimmt? Bzw wie kann ich diese am besten formatieren?
Hallo,
am besten formatierst Du die Karte mit FAT32, windows oder linux, das
ist egal.
ffls() ist eine Baustelle seit der Umstellung auf LFN. Das zeigt
momentan nämlich nur SFN an.
Ich schau mir das spätestens morgen mal genauer an..
Viele Grüße
Daniel
Hallo
ich habe noch keinerlei Erfahrung mit SD-Card Anwendungen. Ich möchte
angeregt durch diesen Thread mal damit anfangen. Ich habe einen
Atmega328P. Einige haben da ja schon die LIB angepasst, haben aber nicht
explizit geschrieben was. Wo muß man da überall anpassen?
-mmc.h
-uart.h
..oder sonst noch wo? Ich habe im Artikel nichts über Prozessoranpassung
gelesen. Gibt es ein "kleines" Testprogram, mit dem eine "schnelles"
erfolgserlebnis hat.
Vielen Dank
Achim
Hallo,
es liegt ein Beispielprogramm bei.
Für den ATmega328 musst Du nur, wie Du schon festgestellt hast, die
mmc.h und das Uart Zeug anpassen. Hast Du spezielle Fragen?
Viele Grüße
Daniel
Hallo
ich möchte die SD-Card an einen Atmega328P 3,3V System hängen. Meine
Frage ist nun muß man da Pullup Widerstände dranmachen?
Ich habe in der mmc.c nichts gefunden dass da die internen Pullups
aktiviert werden?
Es gibt ja da sehr viele Schaltungsvarianten. Kann mir jemand kurz sagen
welche Ankopplung bei dem 3,3V System am erfogversprechendsten ist?
Vielen Dank
Achim
Hallo,
ja Pullup an MISO wäre ganz gut. Ordentliche Stromversorgung und
Enstörkondensatoren Kondensatoren schaden auch nicht.
Ich hab aber auch schon Schaltungen gesehen, da hätte man gesagt, DAS
läuft NIEMALS, hat es dann aber doch...
Viele Grüße
Daniel
Hallo,
super Lib, ein großes Dankeschön an alle die da mitgewerkelt haben.
Ich habe nun ein kleines Problem,
wenn ich eine Datei erstelle und dort mit einer Schleife 100mal das
gleiche reinschreibe und anschließend wieder schließe, danach denn
wieder mit dem µC auslese und über uart ausgebe, funktioniert alles
wunderbar.
(Quelltext ist der aus dem Tutorial nur mit ner Schleife extra)
Wenn ich nun aber die SD Karte in den PC stecke findet er zwar die
Datei, sie hat auch ne variable Größe z.B. 5kB(jenachdem wie oft ich da
reinschreibe), nur kann ich sie nicht öffnen. Windows meint, die Datei
sei beschädigt. Woran liegt das?
Leider bin ich gerade erst mit der SD/FAT Materie angefangen und kenne
da noch nicht alle Vorgaben.
Viele Grüße
André
Hallo,
probier mal nur mit kurzen Dateinamen zu kompilieren und dann das mit
der Datei. Poste zur Sicherheit mal den Code den Du geändert hast,
vielleicht ist da ein Fehler.
Um zu verstehen was da passiert ist es gut sich die Daten mal mit einem
Hex-Editor wie WinHex anzuschauen. Da kann man dann genau sehen wie die
Daten auf der Karte strukturiert sind.
Viele Grüße
Daniel
Hey, habe das Porblem gefunden.
Scheinbar war das Format der Karte nicht auf FAT16/32, sondern FAT12.
Deine Lib hat das nicht erkannt und dachte es sei FAT16, so hat die denn
einfach drauf geschrieben, sodass die Daten zwar drauf waren aber das
Dateisystem kaputt war.
Mit ne größeren Karte die auf FAT32 formatiert wurde läuft es nun.
Ich hatte das gleiche Problem mit dem exacten Code von dir.
Linux ist es scheinbar völlig wurst was es bekommt, aber Windows ist da
dummerweise etwas zimperlich... ;)
Danke aber für deine Rückmeldung, vielleicht hilft dir der Fehler ja, um
die Lib. noch bissle robuster zu machen.
Hallo Zusammen,
ich versuche gerade ein Verzeichnis auf der SD Karte an zu legen.
Es wir auch erzeugt, nur lässt es sich am PC nicht öffnen. Es kommt eine
Fehlermeldung.
der Code sieht so aus.
uint8_t dada[] = "DAN";
ffmkdir(dada);
Mache ich etwas falsch?
Datei erzeugen funktioniert, öffnen schreiben, lesen alles gut.
Gruß
Max
Danke das war es.
Ist vielleicht an gedacht in der nächsten Version eine kleine Schleife
im ffmkdir zu integrieren die prüft wie lang der String ist und dann
entsprechen SPACE anhängst?
Gruß
Max
Hi Daniel !
Erstmal super Bibliothek.
Ich habe jetzt nicht sämtliche Antworten darauf gelesen und hoffe das
meine folgende Frage noch nicht gestellt wurde :).
Ich möchte mittels Microblaze und dem dazugehörigen SPI Core Daten auf
eine SD Karte schreiben und diese komfortabel via PC auslesen. Also z.B.
Prozessdaten abgespeichert in einer .txt file.
Eignet sich deine Bibliothek für solch eine Hardware Platform?
Ich habe noch nie mit FAT16/32 gearbeitet und hoffe, dass die Frage
nicht zu trivial ist :)
Gruss
Hallo,
das sollte kein Problem sein.
Habe auch die Lib auch schon auf einem Altera NIOS laufen gehabt.
Genauer gesagt mit dem DE2 Board von Altera. Du musst nur den ganzen SPI
Kram anpassen...
Viele Grüße
Daniel
Eine Frage hab ich noch,
ich war gerade drauf und dran das komplett selber zu schreiben. Also
zuerst die Karteninitialisierung realisieren, dann schreiben eines
Blockes und dann am "Ende" die Realisierung von FAT32.
Nun überleg ich gerade ob ich dein angebotenes Projekt verwenden, da ich
Neuling auf dem Gebiet bin. Jedoch hab ich absolut kein Überblick über
das, was angepasst werden muss.
Ist die Initilisierungsprozedur denn an den "initialization flow" von
der Spezifikation angepasst ?
http://elm-chan.org/docs/mmc/sdinit.png
Kann den obigen Beitrag nichtmehr editieren (leider). Sorry also für den
Spam.
Ich wollte Dich fragen ob es mit der TPU Probleme geben könnte.
Irgendwie verwendest du ja "TimingDelay" für die mmc_init Funktion. Ist
das eine über die TPU vom AVR (falls vorhanden) erzeugte Verzögerung?
Wie müsste man es verändern ? Reicht da eine einfache "Soft-Tpu" in Form
einer for-Schleife (bissle unsauber ich weiß :) ).
Gruss
Christian
Hallo,
erstmal großen Dank an diese gute Library. Ich benutze sie um auf einer
SD/SDHC eine TXTdatei anzulegen um dort meine AD gewandelten Werte
abzuspeichern. Das funktioniert bis jetzt auch ganz gut... Nun habe ich
Probleme bei einer anderen Sache. Ich möchte auf der SD Karte eine Datei
(unter Windows) anlegen. Die heißt dann z.B. config.txt. Von dort soll
sich der Controller später verschiedene Werte holen und die
entsprechenden Variablen (also die Controllervariablen wie z.B.
Abtastzeit) dannach setzen. Das Problem ist, dass die unter Windows
angelegte Datei von der FATlibrary nicht gefunden wird. Ich habe es mit
ffopen((unsigned char*)config.txt) und auch direkt mit
if(fat_loadFileDataFromDir((unsigned char*) "config.txt")==TRUE)...
probiert, doch leider kein Erfolg. Ich habe auch schon verschiedene
Schreibweisen versucht (CONFIG, CONFIG TXT, CONFIG.TXT). Hat auch nicht
geklappt.
Funktionieren tut es nur, wenn ich mit meinem Controller die config.txt
Datei anlege und später unter Windows editiere. Dann wird die Datei auch
immer gefunden und ich kann die nötigen Werte raus holen.
für Tipps wäre ich sehr dankbar.
Hi!
Ich habe ein Problem und zwar hab ich das fertige KEIL - Project von
Version 0.6.3.1 auf meinen STM32F107VB geworfen. Ich hab nur den CS-Pin
auf meine Hardware angepasst.
Aber leider funktioniert bei mir das mmc_init nicht.
bei CMD0 bekomm ich noch 0x01 zurück, aber bei ACMD41 oder CMD1 bekomm
ich immer 0xFF zurück.
Hat wer Erfahrung damit oder eine Idee was mein Problem sein könnte?
Vielen Dank schonmal...
lG
Mark
Hallo,
wollte mit folgenden Parametern die Lib übersetzen.
MMC_OVER_WRITE = FALSE
MMC_MULTI_BLOCK = TRUE
Fehlermeldung!
start_Sectors und currentSectorNr sind nicht in struct Fat_t vorhanden.
Und so wie es aussieht, hat der Compiler wohl auch noch recht.
Gruß
Uwe
Hallo,
ich habe Ihnen eine PM geschickt, leider ohne Hinweis, ob Sie die Info
erhalten haben. Deshalb schreibe ich zur Sicherheit hier im Thread.
Bitte kontaktieren Sie mich, sobald Sie die Nachricht erhalten.
Vielen Dank
Hi Leute,
Ich versuch schon seit einiger Zeit mit der ffwrite funktion die ADC
werte meines XMega128 abzuspeichert. Strings klappen einwandfrei jedoch
mit den int da hab ich probleme entweder er zeigt nur hieroglyphen (im
übertragenen Sinn) an oder gar nichts an.
Ich speichere es als *.txt file.
Wahrscheinlich ist es nur eine kleinigkeit die ich übersehen hab aber
ich weis nicht mehr weiter.
Ich hoffe Ihr wisst vielleicht was.
Übrigens danke für die tolle lib.
Super danke das funktioniert einwandfrei, jedoch hab ich jetzt ein
anderes kleines problem mit meinen dogl128 den ich verwende. Den
beschreib ich leider auch mit der printf funktion.
Jetzt schreibe ich zwar wenn ich ins Unterprogramm springe die funktion
um auf die sd-karte und wenn ich wieder rausspring schreib ichs wieder
um auf den lcd. Nun geht der Display so lange aus so lang ich im
Unterprogramm bin.
Gibt es irgendeine möglichkeit auch eine andere funktion als die printf
zu verwenden???
Hallo,
du legst im Prinzip zweimal das Selbe an und wechselst nur mit
stdout = &mystdout; // bindet ffwrite() ein
oder
stdout = &my_stdout; // bindet printf() unter DOGM128 ein
Das funktioniert sehr gut, ich mach genau das Selbe.
Ich schreibe Temperaturen auf die SD-Card
z.B
stdout = &my_stdout; // bindet ffwrite()() ein
printf("%02d; %02d; \r\n",ds18b20.cel[0],ds18b20.cel[1]);// SP anzeigen
stdout = &mystdout; // bindet printf() DOGM128 ein
Gruß xmega
Hi,
kann sein, dass ich was falsch mache, aber kann auch sein, dass ich
einen Fehler gefunden hab.
Ich habe zwei Dateien auf der Karte. Wenn ich eine dritte Datei anlege,
in die ich die Daten einer der beiden Datein kopiere und dann die
Quell-Datei loesche, dann wird die zweite Datei, die am Anfang da war
gleich mit geloescht.
Das Kopieren mach ich so, dass ich eine Zeile lese, die Datei schliesse
und die Daten dann in die Zieldatei schreibe, diese wieder schliesse und
so weiter. Also ist immer nur eine Datei offen. fflush verwende ich auch
nach jedem Zugriff und ich habe es bereits versucht mit Pausen zwischen
den Zugriffen.
Gruesse
Dusty
Der Fehler tritt in Delete_DB auf. Die Bilder zeigen, was ich meine. Die
Funktion ist noch nicht fertig, da ich den Fehler erst behoben haben
muss.
Spaeter wird das orginal File geloescht und das temporaere File noch mal
kopiert als orginal.
Was mich dann auch zum naechsten Punkt bringt. Eine Funktion zum
Umbennen von Dateien waere echt hilfreich.
Die Bilder zeigen Folgendes. Zuerst was auf der Karte ist am Anfang.
Dann dass das Kopieren funktioniert hat. Datensatz 3 ist geloescht in
temp.tmp. Dann dass nicht nur das geloescht File weg ist, sondern auch
noch eine weitere Datei fehlt.
rm im Terminal ruft nur ffrm("temp.tmp") auf.
Gruesse
Dusty
Hi again,
und noch ein Fehler. Ich habe eine Karte geloescht und eine Datei mit
2mb Groesse angelegt. Diese habe ich mit Leerzeichen vollgeschrieben.
Wenn ich die Datei jetzt lese, dann sind dort Frakmente alter Dateien
drin.
Gruesse
Dusty
Hallo,
erstmal:
Das ist doppelt in der Kombination! ffclose ruft fflushFileData eh auf.
Das erzeugt unnötige Schreiboperationen.
1
fflushFileData();
2
ffclose();
fflushFileData sollte nur verwendet werden wenn man ewig lange eine
Datei geöffnet hat und sicherheitshalber zwischendurch mal die Daten
sichern möchte. Sonst ist das nicht nötig. Im gegenteil, es werden so
Unmengen von Schreiboperationen verursacht.
>Der Fehler tritt in Delete_DB auf.
Aber erst bei rm verschwinden doch die Dateien oder? Sind vorher alle
Dateien da und so wie sie sein Sollten? Mit Pc überprüft?
Dann, was meinst Du mit gelöscht? Formatiert?
Wie legst Du denn eine Datei mit 2MB an schreibst erst dann?
Poste mal bitte noch die Dateien, dann schau ich mal, wann ich Zeit habe
das bei mir laufen zu lassen um den Fehler reproduzieren zu können.
Hilfreich wäre auch die mmc_config.h und welche Version der Lib Du
benutzt.
Viele Grüße
Daniel
Hi!
Wie schaut denn der Speicherverbrauch der Lib aus (mit gehts
hauptsächlich um RAM)? Wieviel belegt die Statisch im RAM und wieviel
Platz solle auf dem Stack noch verfügbar sein?
Hallo Daniel,
erst mal Kompliment für die gelungene Lib!
Banale Frage:
Ich habe die Lib in einen Datenlogger integriert, läuft so weit auch
super (Textdatei, ca. 40 Byte pro Zeile, minütliches, zeilenweises
Schreiben).
Das Problem ist, dass die Ansteuerung nach ca. 12h "abschmiert", die
Karte wird dauerhaft angewählt und die Datei zerschossen.
Meine Vermutung ist, dass zwischendurch ein fat-lookup stattfinden
sollte.
Kann das sein? Karte ist dauerhaft unter Spannung.
Und wie kann ich einen fat-lookup bei initialisierter Karte durchführen?
Um meine Frage selbst zu beantworten:
ich habe testweise die MMC_MAX_CLUSTERS_IN_ROW in der mmc_config.h auf
2048 hochgesetzt. Seit 10 Tagen Dauerbetrieb keine Probleme, alles
bestens.
Nochmal: super Lib! ;-)
Oh Sorry hab ich wohl einen Fehler gemacht...
Hab nur kurz den Quellcode überflogen und das kam mir komisch vor, aber
jetzt da ich sehe das TimingDelay ja gar nicht in der Funktion
initialisiert wird wird mir klar das ich ein wenig weiter in den
Quellcode hätte schauen müssen...
Gruß
Philipp
Hi. Die Library läuft bei mir inzwischen recht gut. Wenn ich allerdings
in der 0.6.4 sowohl MMC_MULTI_BLOCK auf TRUE als auch MMC_OVER_WRITE auf
FALSE stelle, kommt es zu folgenden Fehlern in file.c:
Error 1 'struct Fat_t' has no member named 'currentSectorNr'
Error 2 'struct Fat_t' has no member named 'startSectors'
Error 3 'struct Fat_t' has no member named 'startSectors'
Error 4 'struct Fat_t' has no member named 'currentSectorNr'
Error 5 'struct Fat_t' has no member named 'startSectors'
Error 6 'struct Fat_t' has no member named 'currentSectorNr'
Error 7 'struct Fat_t' has no member named 'currentSectorNr'
Und Tatsache: Beschriebene Felder befinden sich in anderen Strukturen.
Ein einfaches Umändern hat bei mir keinen Erfolg gebracht => weitere
Fehler. Kann es sein, dass da ein paar Dateien/Funktionen aus
unterschiedlichen Versionen durcheinander geraten sind?
Gruß Sven
Ich habe momentan auch noch Probleme,
ich schreibe minütlich Datensätze mit je 182 Byte in eine Textdatei.
Nach 4h25min (263 Datensätzen) + 574 Byte Spaltenüberschrift (insgesamt
49152 Byte, also exakt 48kB) wird die Karte zwar noch angesprochen, aber
nicht mehr beschrieben.
Bin momentan ratlos, an was das liegen könnte.
Nachtrag:
die verwendete Karte ist eine etwas ältere Kingston 256MB-Karte.
Mit einer MAX 60x 1GB sind die Leuchtzeiten der LED am CS deutlich
kürzer.
Ich vermute diese alte Kingston-Karte ist zu langsam.
Hallo,
ich versuche nun auch schon seit ein paar Tagen eine SD Karte (1Gb mit )
deiner Lib anzusteuern. Ich komme aber nicht über mmc_init hinaus. Auf
dem Terminal wird mir nur Boot angezeigt. Hab bereits den 10k Pullup an
MISO und auch schon alle Verbindungen geprüft. Mein µC ist ein Atmega
168 und er läuft mit 10Mhz. Zum testen verwende ich deinen Beispielcode.
Ich habe auch schon #define MMC_MAX_SPEED FALSE versucht, aber das hat
auch nichts gebracht. Was kann ich noch versuchen?
Gruß Michael
Hallo,
Hab mir die Signale noch mal mit dem Oszi angesehen. MOSI und SCK sehen
wie auf dem Bild aus. Dort ist die Ansteigs- und Abfallszeit zu langsam
für die SD Karte, oder nicht? Wenn ja woran kann das liegen?
Gruß Michael
Hast du die Möglichkeit deine ganze Schaltung auf 3.3V laufen zu lassen?
Dann könntest du den Spannungsteiler zur Karte weglassen -> eine
mögliche Fehlerquelle weniger.
Gruß
Fabian
Ja, miss mal mit deinem Skop den Spannungseinbruch beim Einschalten der
Karte. Manche Karten sind da sehr zickig und geben schon bei
Schwankungen <200mV auf. Und die Stromaufnahme der Dinger ist nicht
unerheblich.
Gruß
Fabian
Danke erst mal für eure Tipps. Ich habe jetzt noch mal 22µF für die 3,3
V Versorgung eingebaut. Jetzt bricht die Versorgungsspannung nicht mehr
ein, davor schon. Aber auch das hat nichts geholfen.
Gruß Michael
>Aber auch das hat nichts geholfen
Spannungsteiler als Pegelkonverter für SD Karten
sind kompletter Schwachsinn. Das wurde hier schon oft
genug durchgekaut.
Wie gesagt, versuch mal die ganze Schaltung wenn möglich mit 3V3 zu
versorgen... dann keine Pegelkonverter... sonst such ich dir auch
nochmal ne Schaltung mit aktivem Konverter (getestet) raus.
Gruß
Fabian
Ich hab jetzt die Schaltung mal mit 3V3 getestet und die 1k8
"kurzgeschlossen". Die 3k3 gegen Masse sollten ja nicht Sören oder?
Aber es geht trotzdem nicht.
Gruß Michael
Michael Mayer schrieb:> Die 3k3 gegen Masse sollten ja nicht Sören oder?
Darauf würde ich mich erstmal nicht verlassen...
Wie debuggst Du denn aktuell? Kannst Du sehen, ob die Karte gar nicht
antwortet oder bei welchem CMD es zum Problem kommt?
Gruß
Fabian
Hallo
echt gute lib. Bin relativ schnell damit zurecht gekommen und jetzt
läuft sie auf dem ATXMEGA128A1. Ich habe allerdings ein Problem.
Wie kann ich eine Datei immer wieder lesen ohne die Datei wieder mit
ffopen zu initialisieren?
Also ich hab jetzt noch mal genauer getestet.
Das Programm bleibt bereits bei
1
if(mmc_send_cmd(CMD0,0)==1){// Enter Idle state
Hängen danach bekomme ich keine Ausgabe über UART mehr.
Wenn ihr weiter Informationen bracht kann ich die nachliefern.
Ich hoffe jetzt kann mir jemand helfen.
Gruß Michael
Ich habe ein Problem beim Lesen meiner microSD-Karte. Wenn ich mir die
Daten anzeige die gelesen wurden, entdecke ich immer vier Bytes die
zusätzlich zu den Daten auf der SD-Karte hinzugefügt wurden und zwar
immer genau nach 512 Bytes folgen 0xB9 0x33 0xFF 0xFE
Woher kommen die?
Ah jetzt weiss ich es. Das müsste die CRC sein (0xB9, 0x33) und 0xFE das
Startbyte für den nächsten Block. 0xFF weiss ich noch nicht.
Gibts es auch ein Kommando wo die CRC nicht mit ausgegeben wird?
Hallo,
Ich habe mir gerade aus dem Wiki die Datei AVR-mmc-0.6.4.zip
heruntergeladen und versuche die gerade zu kompilieren, allerdings
bekomme ich folgende Fehlermeldungen:
Error 1 'TCCR0A' undeclared (first use in this function)
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c 80 2 sdtest0
Error 2 each undeclared identifier is reported only once for each
function it appears in D:\AVR-Studio\sdtest0\sdtest0\main_simple.c 80
2 sdtest0
Error 3 'TIMSK0' undeclared (first use in this function)
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c 81 2 sdtest0
Error 4 'OCIE0A' undeclared (first use in this function)
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c 81 14 sdtest0
Error 5 'OCR0A' undeclared (first use in this function)
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c 84 2 sdtest0
Error 6 'TCCR0B' undeclared (first use in this function)
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c 86 2 sdtest0
Ich benutze einen ATmega16.
Und noch eine Frage: Ich habe eine "SD-Platine", bei der folgende
Pinbelegung gegeben ist:
Dat2 - unrouted
CS - PIN 3 (über 1,8k/3,3k Spannungsteiler)
DI - PIN 5 (über 1,8k/3,3k Spannungsteiler)
GND - GND
VCC - VCC über LF33CV
CLK - PIN 7 (über 1,8k/3,3k Spannungsteiler)
GND - GND
DO - PIN 6 (mit einer 3,3V Zenerdiode von dieser Leitung zu GND)
DAT1 - unrouted
Kann ich diese Platine überhaupt verwenden? Und wenn ja an welchen Port
soll ich sie am Besten anschließen?
Und welche Anpassungen muss ich dann in den Dateien vornehmen?
Viele Grüße,
Manuelito
@ Manuel Vossel.
Die Register haben beim Atmega 16 andere Bezeichnungen. Musst du mal im
Datenblatt nachschauen.
Kann mir keiner bei meinem Problem helfen?
Das Programm bleibt bereits bei
Dann stimmt etwas mit deinem Programm aber nicht, weil hängen bleiben
dürfte er da doch gar nicht.
Ich hatte damals viel an dieser Funktion rumgepätscht (siehe auch meine
Posts zur Init weiter oben) damit sie mit allen meinen Karten lief, aber
wenn du den "aktuellen" Patchstand hast gibt es auch hier ein Timeout.
Wenn du Interesse hast kann ich dir meine init nochmal posten zum
Vergleich.
Gruß
Fabian
TimingDelay=100;// Initialization timeout of 1000 msec
17
18
if(mmc_send_cmd(CMD8,0x1AA)==1){// SDv2?
19
for(n=0;n<4;n++){
20
ocr[n]=spi_read_byte();// Get trailing return value of R7 resp
21
}
22
if(ocr[2]==0x01&&ocr[3]==0xAA){// The card can work at vdd range of 2.7-3.6V
23
24
// while (TimingDelay && mmc_send_cmd(ACMD41, 1UL << 30)); // Wait for leaving idle state (ACMD41 with HCS bit)
25
while(TimingDelay){// Wait for leaving idle state (ACMD41 with HCS bit)
26
mmc_send_cmd(CMD55,0);
27
if(!mmc_send_cmd(ACMD41,1UL<<30))
28
break;
29
}
30
31
while(TimingDelay){
32
if(mmc_send_cmd(CMD58,0)==0x00){// Check CCS bit in the OCR
33
for(n=0;n<4;n++){
34
ocr[n]=spi_read_byte();
35
}
36
ty=(ocr[0]&0x40)?CT_SD2|CT_BLOCK:CT_SD2;// SDv2
37
/*
38
if(ocr[0] & 0x40) {
39
ty = CT_SD2 | CT_BLOCK;
40
} else {
41
ty = CT_SD2; // SDv2
42
}
43
*/
44
break;
45
}
46
}
47
//ty = CT_SD2 | CT_BLOCK;
48
49
50
51
}
52
}else{// SDv1 or MMCv3
53
if(mmc_send_cmd(ACMD41,0)<=1){
54
ty=CT_SD1;
55
cmd=ACMD41;// SDv1
56
}else{
57
ty=CT_MMC;
58
cmd=CMD1;// MMCv3
59
}
60
while(TimingDelay&&mmc_send_cmd(cmd,0));// Wait for leaving idle state
61
}
62
// if (!TimingDelay || mmc_send_cmd(CMD16, 512) != 0) // Set R/W block length to 512
63
// ty = 0;
64
if(ty!=(CT_SD2|CT_BLOCK)){
65
while(TimingDelay&&(mmc_send_cmd(CMD16,512)!=0));
66
}
67
if(!TimingDelay)ty=0;
68
}else{j--;}
69
}while(j>0);
70
fat.card_type=ty;
71
mmc_disable();
72
73
if(fat.card_type==0){
74
returnFALSE;
75
}
76
#if (MMC_MAX_SPEED==TRUE)
77
spi_maxSpeed();
78
#endif
79
80
returnTRUE;
81
}
ich hatte (siehe auch oben bei meinem Patchvorschlag schon angemerkt,
dass meiner Meinung nach der ACMD41 falsch definiert ist. Bei mir gings
jedenfalls top nach Änderung:
Also mein Problem hat sich mittlerweile erledigt, ich hatte irgendwie
ein Hardwareproblem auf meiner Platine.
Ich habe zwar alles mit dem Multimeter durchgepiepst, aber irgendwas
schien wohl doch kaputt zu sein - mit einer anderen Platine funktioniert
es nämlich jetzt :-)
Eine Frage habe ich aber noch: Bei ffread() werden ja immer 512 Byte
gelesen und der Rest zwischengepuffert.
In meinem speziellen Fall wird es allerdings so sein, dass ich alle 40ms
eine bestimmte Anzahl Byte benötige (wahrscheinlich 432, steht aber noch
nicht fest), die sich auch nicht ändern wird. Das ganze ist für eine
LED-Animation, dort will ich einen digitalen RGB-Strip im 25Hz-Takt mit
Daten füttern. Wäre es dann sinnvoll, diesen Puffer auf 432 Byte (oder
wieviele es nachher werden) zu verkleinern? Bzw. falls ich mehr brauche
auf soviel erhöhen?
Da ich mittlerweile einen ATmega644 habe ist RAM nicht mehr so ein
großes Problem.
Ich blicke den Quellcode leider nicht ganz, daher kann ich nicht
wirklich sagen, wie dieser Puffer einen Geschwindigkeitsvorteil bringt -
daher hier die Frage.
Viele Grüße,
Manuelito
Manuel Vossel schrieb:> Also mein Problem hat sich mittlerweile erledigt, ich hatte irgendwie> ein Hardwareproblem auf meiner Platine.
Da kann ich auch nur drauf hinweisen, das Problem hatte ich auch!
Es kommt wirklich auf eine sehr ordentliche Hardware mit sauberer,
stabiler Versorgung an.
Ich hatte das Erweiterungsboard für AVR-NET-IO von Pollin und kann nur
sagen: Finger weg, das Ding ist Schrott! Falsche Dimensionierung,
falsche Bauteilwahl, Layout muss angepasst werden (Kratzen und Drähte
einflicken), SD-Kartenhalter hakt.
Kurz und Gut, wenn man schon Elkos für digitale Technik verwendet, dann
bitte low-ESR. Der Müll, der von Pollin geliefert wird (step-up-Regler
statt linear-Spannungsregler für 3.3V), lässt die Karte immer mal wieder
abschmieren (hängt sich auf). Nachdem ich ordentliche Bauteile
draufgebaut hatte, lief alles wunderbar.
Mein Problem besteht leider immer noch:
- minutenweises Schreiben, ca. 200 Byte pro Datensatz
- täglich wird ein neues File angelegt
- MMC_MAX_CLUSTERS_IN_ROW auf 16383
Nach zwei Tagen wird ein neues File angelegt und ein Stück weit
beschrieben, danach bleibt das Chipselect auf low und die Karte hängt
sich auf (bleibt in der Schreib- oder Lesefunktion hängen). Das neu
angelegte File ist dann defekt.
Hat irgend jemand eine Lösung für dieses Problem?
Ich bin da irgendwie ratlos.
Nach langem Suchen hab ich die SD-Karte endlich zum laufen bekommen.
Jetzt hab ich noch zwei Fragen:
1. Kann ich, und wenn ja wie kann ich den verbleibenden Speicherplatz
bestimme?
2. Wie gehe ich beim trennen der SD-Karte vom AVR ab besten vor? Ich hab
einen Taster den ich drücken will bevor ich die Karte abziehe. Aber wie
beende ich die Kommunikation ordnungsgemäß?
Gruß Michael
Hallo Michael,
woran lag's denn schlussendlich?
Zu 1) Gute Frage ;-)
Zu 2) ein fflushFileData() und danach ein ffclose() sollten alles nötige
erledigen.
Gruß
Fabian
Fabian B. schrieb:> Hallo Michael,> woran lag's denn schlussendlich?
Das weiß ich auch nicht genau. Nachdem ich den Spannungsregler
ausgetauscht habe ging es. Der hat zwar zuvor auch 3,3 V rausgegeben
aber vielleicht ist er kurz Eingebrochen ( Auf dem Oszi war aber nichts
zu sehen).
Gruß Michael
Hallo,
erst mal Danke für die tolle Vorarbeit hier. Damit habe sogar ich es
hinbekommen Daten auf SD-Karten zu schreiben.
Doch jetzt bin ich auf ein Problem gestoßen:
Ich bekomme jede 10 Sekunden einen Datenstring den ich auf die Karte
schreiben möchte (Datei öffnen -> schreiben -> Datei schließen)
Nun habe ich das Problem, dass genau 512 Datensätze geschrieben werden
und alle weiteren im Nirwana verschwinden.
An der Dateigröße kann es kaum liegen, zu Testzwecken habe ich schon
viel größere Datenmengen schreiben können. Da habe ich die Datei aber
nicht ständig auf- und wieder zugemacht. Liegt das evtl. daran?
Ich möchte aber nicht die Datei die ganze Zeit offen lassen, damit die
Daten nicht verloren gehen, wenn man die Karte aus dem Leser zieht, ohne
sie vorher sauber zu beenden.
Danke schon mal.
Gruß
Peter
Dann antworte ich mir mal selber :)
Problem hab ich umgangen, indem ich alle x Durchläufe ein
fflushfiledata() mache und nur ganz am Ende, wenn ich regulär das
Programm verlasse. Wenn die Karte nicht ordnungsgemäß entfernt wird,
gehen nur ein paar Daten verloren und nicht alle.
Hi zusammen,
so wie ich das sehe, ist es mit den Funktionen nur möglich immer nur
eine Datei zur Zeit zu öffen. Richtig?
Ich bräuchte eine Lib mit der ich zwei (verschiedene) Dateien zeitgleich
öffnen kann. Theoretisch würde es reichen das nur eine Datei geschrieben
und die andere nur gelesen wird.
Wie schwierig / groß wäre die Änderung der Lib?
Danke!
Hi Fabian,
ich habe einen Navtex und DWD (Wetter) Empfänger gebaut, der die
Textmeldungen auf einer SD Karte speichert (FAT16/32).
Der User kann über ein GLCD die Meldungen auswählen und sich anzeigen
lassen.
Funktioniert super, da ich bisher nur alle 3 Stunden für ca. 10 Minuten
Meldungen empfange (Navtex). Die DWD Meldungen hatte ich bisher auch
stark eingegrenzt. So störte es nicht wenn der User mal für 10 - 20
Minuten keine Meldungen lesen konnte. (Die Datenübertragung läuft mit 50
Baud :o)
Jetzt will ich evtl. ständig alle DWD Meldungen aufzeichnen (der Sender
läuft 24/7) und daher ist fast immer eine Datei geöffnet. Der User hat
nur noch zwischen den einzelnen Meldungen die Gelegenheit zu lesen. Das
geht gar nicht :-/
Viele Grüße,
Dirk
Servus alle miteinander!
Super Paket, gefällt mir super und funktioniert noch viel besser!
Da ich eine energieoptimierte Schaltung entwickle, hatte mich der
laufende Timer und vor allem der Aufruf der ISR gestört, die permanent
aufgerufen wurde.
Das habe ich behoben, indem beim setzen der Werte in die Variable
TimingDelay durch den Aufruf der Funktion TimingDelay_set(uint_8t time)
erledigt wird.
Die Funktion schaltet anschließend den Timer und dessen Interrupts ein (
eine Initialisierung des Timers muss vorher dennoch erfolgen).
Die Variable selber kann weiterhin wie gewohnt verwendet werden.
Die ISR wurde dahingehend verändert, dass sie den Timer und dessen
Interrupts deaktiviert, sofern die Variable den Wert 0 erreicht hat.
TimingDelay=0;// initialisierung der zaehl variable
16
cli();
17
TCCR3A=1<<WGM01;// timer0 im ctc mode
18
TIFR3&=~(1<<OCF3A);//clearing interrupt flag
19
TIMSK3|=1<<OCIE3A;// compare interrupt an
20
21
TCNT3=START_TCNT;// ab wo hochgezaehlt wird,
22
OCR3A=TOP_OCR;// maximum bis wo gezaehlt wird bevor compare match
23
24
//TCCR3B = PRESCALER; // wenn prescaler gesetzt wird, lauft timer los
25
sei();// interrupts anschalten, wegen compare match
26
}
27
28
staticvoidTimingDelay_set(uint8_ttime)
29
{
30
TimingDelay=time;
31
cli();
32
TIFR3&=~(1<<OCF3A);//clearing interrupt flag
33
TIMSK3|=(1<<OCIE3A);
34
TCCR3B=PRESCALER;
35
sei();
36
}
Die entsprechenden Änderungen in der mmc.c habe ich bereits vorgenommen
und den Timer und dessen dazugehörigen Parts mit eingebunden...
Da ich den AT90CAN128 verwende, ist der Timer 1 ein 8Bit Timer, weswegen
ich die entsprechenden Register auf Timer 3 geändert habe.
Die mmc.c befindet sich im Anhang. Es wurde die aktuelle Version 0.6.4
verwendet.
Viele Grüße und frohes Fest!
Georg
Hast du keinen Basistimer der eh immer läuft? Der kann das ja mit
machen...
Aber solange die CPU mit Takt X läuft isses für den Stromverbrauch
zumindest gleich, ob der Timer 1000 oder 1 Mal pro Sekunde aufgerufen
wird.
Gruß
Fabian
Hallo!
Ich versuche grad meine SD Karte mit Soft SPI anzusteuern (PORTA), weil
bei mir schon ein VS1011 am SPI Port hängt und die beiden mögen sich
anscheinend nicht. Deswegen hab ich mir gedacht, dass ich die SD Karte
einfach per Soft Spi auf einem anderen Port ansteuere.
Aber es funktioniert gar nicht mit PORTA.
ich hab in der config.h
#define MMC_SOFT_SPI TRUE
geändert und mmc.h meine Pins
#if defined (_AVR_ATmega644_)
#define SPI_MISO 2
#define SPI_MOSI 4
#define SPI_Clock 3
#define SPI_SS 5
#endif
Programm Compiliert, es läuft nicht.
dann hab ich die SPI Pins vom PortB wieder zusätzlich angelötet.
und nochmal kompiliert und es lief.
Aber der Grund ist: in der mmc.c spi_init() warum es auf PORTB läuft und
auf PORTA nicht.
diese Zeile SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);
eigentlich braucht man diese Zeile für Soft SPI nicht. oder?
Weil wenn ich diese Zeile wegkommentiere dann läuft es auch auf PORTB
nicht mehr.
Hab ich vielleich was übersehen?
Hallo!
Tolle Lib! - die ich nur zum Lesen von Daten von der SD-Karte verwende.
Bisher hatte ich Daten immer nur vom Stammverzeichnis der Karte gelesen,
ging mit der Version 0.6.1 auch bestens. Nun möchte ich aber meine Daten
von Dateien aus 2 Verzeichnisebenen lesen, und dazu munter zwischen den
Verzeichnissen hin und her wechseln. Mittels ffcd() war es nicht
möglich, überhaupt in ein Verzeichnis hinein zu wechseln. Daher habe ich
die jetzt aktuelle Vers. 0.6.4 heruntergeladen. Hier funktioniert ffcd()
bestens, nacheinander ffcd(Verzeichnis_Ebene_1) ,
ffcd(Verzeichnis_Ebene_2) wechselt auch in die Verzeichnisse, ich kann
die dortigen Dateien problemlos lesen.
LEIDER komme ich aber aus dem Verzeichnis nicht zurück, d.h. ffcdLower()
funktioniert nicht. Muss ich evtl. bei den Verzeichnisnamen und
Dateinamen irgendwas beachten, damit ich auch mal wieder aus einem
direktory zurück komme? Habe den gesamten Thread durchgelesen - bin aber
mit dem Problem scheinbar allein?
Gruß Volker
Hallo,
Volkers Nachricht kann ich bestätigen.
cdlower tut nicht richtig.
In meinem Fall bin ich ein Verzeichnis tiefer gegangen.
Das erste cdlower tat garnichts. Nach dem 2. cdlower war ich wieder auf
dem Root.
Verzeichnis löschen geht auch nicht.
Info:
Zum Test habe ich die FAT-Sourcen in ein PC-Projekt (VC6.0) eingebunden.
Jedoch wird nur Fat.c und File.c verwendet.
Von einer SD-Karte habe Disk-Image gemacht.
Mmc.c greift nun auf das Image zu, statt auf SPI.
For all my lovely friends
True ist ein boolscher Ausdruck etc und blabla...
#ifndef TRUE
# define TRUE (1==1)
#endif
#ifndef FALSE
# define FALSE (0==1)
#endif
macht weniger Probs im Zusammenhang mit anderen Bibliotheken.
Ferner habe ich die entsprechenden Stellen geändert in den Dateien im
Anhang (Variablen unt Rückgabewerte direkt durch 1 und 0 ersetzte und
sonst den Status mit if (status) oder if (!Status) ersetzt).
Jetzt schmiert der Kompiler bei mir bei Verwendung der CAN lib von Atmel
auch nicht mehr ab :)
(war der Fall, doppelte Definierung und so.... )
Viel Spaß damit!
MfG
Ps.: Weiterhin sind die Änderungen bezüglich des Timers enthalten (siehe
weiter oben im Thread...)
Edit: Wäre super, wenn 'der Herr der Dateien' das mit in die nächste
Revision rein packt.
damit kann man strings aus dem Flash auf die SD-Karte schreiben.
Ferner gehören die Strukturdeklarationen
File_t in die file.h
und Fat_t und Chain_t in die fat.h
Sonst kommt es verinzelt zu Problemen mit der Umgebung (AVR STudio 5)(in
unschönen Fällen kompiliert er dann nicht mehr).
in die mmc.h muss
1. Datei öffnen
2. Daten lesen.
Ein Zeilenende wird durch 0x0d 0x0a gekennzeichnet.
Wenn du diese beiden Bytes in der Reihenfolge gelesen hast, weisst du,
dass danach eine neue Zeile beginnt.
Schau dir einfach mal eine text Datei auf dem PC mit einem Hex Editor
wie 'Hex Editor MX' an.
MfG
Hallo,
ja so habe ich es probiert,es kommt nur mühl aus.
unsigned char test54;
if( MMC_FILE_OPENED == ffopen(file_name,'r') ){
seek = file.length;
do{
strcpy(test54, ffread());
}while(--seek);
ffclose();
}
hier ausgabe.
Was mache ich falsch??
Gruss
Milan
Du hast die Datei rückwärts, angefangen beim Ende ausgelesen.
Jetzt beginnst du beim Anfang.
Sollte so funktionieren.
Arbeite mit Breakpoints, dann kommst du auch alleine auf die Lösung ;)
Hallo zusammen,
ich habe es so jetzt abgeendert:
unsigned char test54;
char test56[200];
if( MMC_FILE_OPENED == ffopen(file_name,'r') ){
seek = file.length;
uint8_t temp=0;
uint8_t last_character;
do{
strcpy(test54, ffread());
if ( test54 == 0x0a && last_character== 0x0d)
{
break;
}
else
{
last_character=test54 ;
test56[temp] = last_character;
}
}while(temp++<=seek);
ffclose();
}
DisplayText(0,10,test56); // heir brauche ich eine Char Array zur
ausgabe oder einen String;
es kommt nichts raus weil die funktion nie aufhürt du laufen. obwohl
eine break beim zeilen umbruch ist!
Gruss
Milan
Hallo zusammen,
es ist ein neuer Problem aufgetaucht!
1
if(MMC_FILE_OPENED==ffopen("spot.txt",'r'))
2
{
3
4
unsignedlongintseek=file.length;
5
6
unsignedlongintcount=0,count2=0;
7
unsignedlongintcount1=0;
8
intzeichen;
9
charausgabe[12][50];
10
11
while(seek>=count1)
12
{
13
chartest56[260];
14
count=0;
15
zeichen=ffread();
16
while((zeichen!='\n')&&(seek>=count1))
17
{
18
test56[count]=zeichen;
19
zeichen=ffread();
20
count++;
21
count1++;
22
23
24
25
//_delay_ms(50);
26
}
27
//count--;
28
test56[count]='\0';
29
DisplayText(0,10*count2,test56);
30
count2++;
31
32
intj;
33
chard;
34
intnr2=0,pos2=0;
35
36
for(j=0;j<strlen(test56)-1;j++)
37
{
38
d=test56[j];
39
if(d==0)break;
40
41
if(d==',')
42
{
43
// wenn Trennungszeichen
44
ausgabe[nr2][pos2]=0;// endekennung
45
nr2++;
46
pos2=0;
47
48
}
49
else
50
{
51
// wenn normales zeichen
52
ausgabe[nr2][pos2]=d;// zeichen speichern
53
pos2++;
54
}
55
56
}
57
58
59
60
}
61
ffclose();
62
}
wenn ich mit der funktion auslese, schreibt mir immer ein paar
lehrzeichen auf ende. jedes mahl ein paar. obwohl nur lesen ist.
Weiss jemand zufälig warum??
oder was ich da falsch mache??
Danke im Voraus
Milan
Hallo und erst mal danke für diese tolle Lib.
Habe so weit alles zum laufen bekommen,
nur bekomme ich beim auslesen der karte nur murx raus.
Eigentlich sollte -> Inhalt der Testdatei 0123456789 <- ausgelesen
werden.
Statdessen bekomme ich das hier:
----------------------------------------------------------------
Boot...Ok
Datei wird geoeffnet:
gelesen:
``
ÿ
``
ÿ
`
ÿ
```
``
`
``
---------------------------------------------------------------------
Woran kann das liegen ?
Es wird genau die richtige Anzahl an Chars ausgelesen aber eben falsch
übermittelt oder so.
Hardware SPI, SANDISK 4GB SDHC, AT90USB1287 @ 8MHz
Liebe Grüße Chris
Meine Bautrate scheint OK zu sein, da ich ja folgenden Text angezeigt
bekomme... nur eben der inhalt der Karte wird falsch gelesen denke ich
Chris schrieb:> Boot...Ok>> Datei wird geoeffnet:>> gelesen:______________________________________________________________________
_
Hier mal mein C-Code.
1
#include<stdlib.h>
2
#include<avr/io.h>
3
// In config.h werden alle nötigen Konfigurationen vorgenommen
4
#include<config.h>
5
#include<file.h>
6
#include<fat.h>
7
8
// Hardwareabhängig
9
#include<mmc.h>
10
11
// Hardwareabhängig, es kann auch eine eigene eingebunden werden !
Das ist aber nicht der Code zu deiner Ausgabe. Das "gelesen:" wird in
dem Code ja nirgends geschickt.
Aber kann es sein, dass dein rs232_text() einen Zeiger erwartet,
ffread() aber einen char zurückgibt? Was ist denn die Deklaration von
rs232_text()?
Gruß
Fabian
Hallo Fabian...
Fabian B. schrieb:> Aber kann es sein, dass dein rs232_text() einen Zeiger erwartet,
genau das war auch der Fehler. Hab ich gar nicht dran gedacht.
Jetzt klappt es wunderbar.
Vielen dank für die Hilfe
LG Chris
Hey,
ich habe eine Frage. Ich habe das Problem, dass ich geschriebene Strings
nicht mehr lesen kann.
Das File wird richtig geschrieben und ich kann mit Windows auch drauf
zurgreifen. Auch werden Strings korrekt angehängt.
Ich bekomme beim Auslesen mit den µC aber immer nur
0xFA,0x07,0xFA,0x07,...,0xFA,0x07. An der RS232-Kommunikation liegt das
nicht.
Woran kann das liegen? Ich würde mich freuen, wenn jemand helfen kann :)
// Der Code:
@Andre Iwers:
Du hast auch einen 9.3 Dateinamen verwendet, vieleicht zerstört das die
fat. Laut Doku -http://www.mikrocontroller.net/articles/AVR_FAT32-
dürfen nur 8.3 Dateinamen verwendet werden.
@Milan:
Deine Frage ist etwas undeutlich. Daten auf der Disk sind physikalisch.
Aber es gibt 2 Möglichkeiten:
1. Die Datei kopieren und dabei die Textzeile überspringen, die alte
Datei löschen und die neue Datei umbenennen.
2. Wenns nur um's löschen geht kann man die Daten nach der zu löschenden
Zeile "auf" die zu löschende Zeile "drüberkopieren". -siehe "ffseek"-
sorry, bischen blöd ausgedrückt
Gruß, Christoph
Hallo,
ich hatte Probleme beim Lesen von Dateien deren Name die Form
<1234567.123> hat, bzw. eine Dateinamenlänge von 10 (ohne den Punkt) bei
MMC_LFN_SUPPORT = TRUE.
Ich denke der Fehler liegt hier:
hi mich würde interessieren wie man auf einfachen weg, unter benutzung
dieser lib, ab einer bestimmten stelle aus der datei lesen kann. ist
soetwas möglich? vielleicht habe ichs auch in diesem sehr langen thread
überlesen.
mfg,
surtur
wie in etwa würde ein beispielcode aussehen um bis zu einer gewissen
position durch zu iterieren, und dann ab position n immer x zeichen zu
lesen. dann wieder ab position x+n+1 und so weiter. :-) oder muss ich
jedesmal die position merken und dann wieder von vorn bis zur zu
lesenden position gehen. und von dort aus lesen? wäre nämlich ein
ziemlicher overhead.
gruß,
surtur
wenn ichs mir genau überlege:
natürlich wäre vom dateiende nach vorn lesen auch eine option.
dann bräuchte ich die gelesenen bytes nur umzudrehen.
und nicht erst von vorn bis zu nem index durchzugehen.
sofern soetwas möglich ist.
gruß,
surtur
Gibt es trotz "Baustelle" ein Möglichkeit die ffls Funktion zu nutzen?
Ziel ist es, das Dateien über ein Lcd ausgewählt werden können. Ich habe
die Funktion bereits so abgewandelt, dass ich nur die Dateinamen
erhalte. Allerdings sind diese im 8.3 Format und ffopen akzeptiert dies
anscheinend nicht.
ffopen funktioniert super mit 8.3.
Was genau bekommst du denn als Dateinamen zurück? Hast du mal ein
Beispiel, auch wie du's dann an ffopen weitergibst?
Gruß
Fabian
Das Öffnen funktioniert übrigens, wenn ich einen Dateinamen, der alle 8
Zeichen belegt, übergebe (also wenn keine Leerzeichen im Dateinamen
sind).
Fabian B. schrieb:> Hast du mal ein> Beispiel, auch wie du's dann an ffopen weitergibst?
Kannst du mal das ganze Codesegment posten, bitte? Also von einlesen per
ffls bis öffnen per ffopen. Inkl. Definition relevanter Variablen.
Gruß
Fabian
Die Dateien, die volle 8.3 Zeichen haben, können übrigens nur dank
dieser vorgeschlagenen Änderung gelesen werden:
Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Ich vermute, in der fat_loadFileDataFromCluster ist noch ein weiterer
Fehler drin, der seit Umstellung auf LFN, diese nicht mehr funktionieren
lässt?
Hallo Daniel R.
iste die Aussage noch aktuell, dass die Library nich mehrere Dateien
gleichzeitig öffnen kann?
SDHC Support ist inzwischen drin, habe ich das richt verstanden?
Hallo Daniel,
es ist mir gelungen, die Library erfolgreich in mein web basiertes I/O
Modul einzubinden. Ich habe zwar noch keinen Anwendungsfall für den neu
gewonnenen Speicherplatz, aber das kommt sicher noch.
Ich musste lediglich die SPI Schnittstelle an den ATxmega128D3 anpassen,
aber das war überhaupt kein Problem. Schwieriger fiel mir die Einbindung
in uIP (den Webserver), weil der Multi-Threading fähig ist, die avrfat32
library aber nicht. Aber ich denke, ich habe das nun mit akzeptablen
Beschränkungen hinbekommen:
- Der Webserver listet nur die ersten 1300 Bytes des
Inhaltsverzeichnisses auf. Mehr Dateien will ich sowieso nicht ablegen.
- Beim Datei-Download müssen alle anderen konkurrierenden Web-Anfragen
warten, bis der Download beendet ist oder abgebrochen wurde.
Vielen Dank für die Veröffentlichung der SD/MMC Karten Library. Sie war
mir eine sehr große Hilfe.
Mein Projekt ist hier: http://stefanfrings.de/avr_io/
Hallo Thilo,
hast Du inzwischen eine Lösung des Problems gefunden? Bir mir tritt der
gleiche Fehler auf. Nach Reparatur der Datei bleiben exakt 48k
verfügbar. Setze ich per PC/Editor noch Zeichen an das Ende der Datei -
abspeichern - schreibt mein Gerät die nächsten Datensätze einwandfrei.
Wenn nicht, geht die Datei bei weiterem Beschreiben kaputt.
Offensichtlich passiert das, wenn die Datenbytes genau bis Sektorende
reichen. Ist es nur 1 Byte mehr, wird ordentlich weiter geschrieben.
Thilo M. schrieb:> Mein Problem besteht leider immer noch:>> - minutenweises Schreiben, ca. 200 Byte pro Datensatz> - täglich wird ein neues File angelegt> - MMC_MAX_CLUSTERS_IN_ROW auf 16383>> Nach zwei Tagen wird ein neues File angelegt und ein Stück weit> beschrieben, danach bleibt das Chipselect auf low und die Karte hängt> sich auf (bleibt in der Schreib- oder Lesefunktion hängen). Das neu> angelegte File ist dann defekt.>> Hat irgend jemand eine Lösung für dieses Problem?> Ich bin da irgendwie ratlos.
Ich habe noch keine Lösung dafür gefunden, aber falls Daniel das mal
testen will hänge ich eine Datei an, bei der dieser Fehler auftritt.
Zusätzlich die mmc_config.
Thilo M. schrieb:> Ich habe noch keine Lösung dafür gefunden, aber falls Daniel das mal> testen will hänge ich eine Datei an, bei der dieser Fehler auftritt.>> Zusätzlich die mmc_config.
Fehler beim zyklischen Zufügen von Messdaten zu einer bestehenden Datei.
Heute habe ich einen entscheidenden Hinweis gefunden. Offensichtlich hat
das etwas mit dem Hersteller und dem Kartentyp zu tun. Eines meiner
Geräte (hatte ich ganz vergessen) läuft seit 35 Tagen mit zyklischem
Abspeichern 15s/je ca.60 Byte unter Verwendung einer billigen SD-Card.
Bei teuren ATP-Industrial-Grade - Karten - 512MB steigt die Geschichte
bei einer Dateigröße von 48 oder 54KB aus - und zwar immer genau bei
einem Sektorwechsel zwischen zwei Speichervorgängen.
Dabei werden Daten in den schon benutzten Datenbereich an falscher
Stelle abgelegt. Es entstehen u.a. neue Dateinamen, die einen Teil der
ASCII-Zeichen aus den abgespeicherten Daten enthalten.
Ich werde mich mal mit den Unterschieden zwischen industriellen und
nichtindustriellen SD-Karten beschäftigen und melde mich wieder.
Wolfgang Sch. schrieb:> Offensichtlich hat> das etwas mit dem Hersteller und dem Kartentyp zu tun.
Das habe ich nun auch festgestellt.
Eine uralte 256MB Kingston Karte zeigt diesen Fehler nicht. Sie schreibt
(bis jetzt) fehlerfrei, hat aber deutlich längere Zugriffszeiten.
Die Motorola Micro-SD (2GB) mit Adapter brach nach 38kB ab (siehe oben
verlinktes File).
Das Zerstören des Files kann man vehindern, indem man bei 10 erfolglosen
Initialisierungs- Lese- oder Schreibversuchen den Versuch abbricht. Dann
sind wenigstens die Daten bis dahin nicht verloren.
Thilo M. schrieb:> Wolfgang Sch. schrieb:>> Offensichtlich hat>> das etwas mit dem Hersteller und dem Kartentyp zu tun.>> Das habe ich nun auch festgestellt.
Hallo Thilo,
ich glaube, ich habe das Problem beseitigen können.
Probiere mal am Ende der Funktion "fat_writeSector"
einige Dummy-Bytes von der SPI zu lesen. Ebenso in "fat_loadSector"
so etwa:
#if (MMC_WRITE==TRUE)
if( fat.bufferDirty == TRUE )
{
fat.bufferDirty = FALSE; // buffer kann nicht dirty sein weil
wird geschrieben
mmc_write_sector( file.currentSectorNr,fat.sector ); //
schreiben von sektor puffer
Takte(); //einige Bytes dummy-Lesen
}
#endif
Offensichtlich brauchen manche Karten an der Stelle noch ein paar Takte.
Das ist erst mal ein vorläufiges Ergebnis, ich teste mal über ein paar
Tage.
Jetzt bin ich bei 200KB geloggte Daten, soweit bin ich bisher noch nie
gekommen.
Hi Wolfgang,
habe getan, was du geraten hast, drei Byte zusaätzlich gelesen, und
siehe da: die Motorola-Karte schreibt auch weiter (alte Datei von oben
im Anhang verwendet)!
Werde die auch mal ein paar Tage laufen lassen.
;-)
Kleine Änderung:
Um ganz korrekt zu sein habe ich das dummy-read jetzt nur noch an einer
Position in "mmc_write_sector" eingefügt. Funktioniert.
..............
if ( retrys == 0)return FALSE; // If not accepted, return with
error
mmc_disable();
spi_read_byte();
spi_read_byte();
spi_read_byte();
spi_read_byte();
spi_read_byte();
spi_read_byte();
return TRUE;
}
.............
In den FALSE - Fällen werden sowieso jede Menge Bytes gelesen - ohne
Schreiben.
Wolfgang Sch. schrieb:> Kleine Änderung:> Um ganz korrekt zu sein habe ich das dummy-read jetzt nur noch an einer> Position in "mmc_write_sector" eingefügt. Funktioniert.> ..............
Kommando zurück! Mit dieser Änderung treten dann doch wieder Fehler auf.
Ich bleibe jetzt bei der Version vom 13.05.
Ich habe seit Jahresanfang eine Sandisk 1GB Micro-SD am Laufen, alle
paar Wochen taucht ein Fehler auf: Schreiben des Files wird abgebrochen,
ab 00:00 Uhr wird ein neues File angelegt (so gewollt) und bei jedem
Schreibvorgang wird ein neues File mit demselben Filenamen angelegt.
Habe auch dort die Änderung eingefügt, weil zufällig heute dieser Fehler
auftrat. Der Logger hat sofort korrekt weitergeschrieben, mal sehen
wie's weitergeht.
Hi Wolfgang,
mit 6 zusätzlich gelesenen Byte (wie du oben beschrieben hast) war bei
einer Motorola 128MB Micro-SD nach 6144 Byte Schluss. Funktioniert also
auch nicht immer.
Thilo M. schrieb:> Hi Wolfgang,>> mit 6 zusätzlich gelesenen Byte (wie du oben beschrieben hast) war bei> einer Motorola 128MB Micro-SD nach 6144 Byte Schluss. Funktioniert also> auch nicht immer.
Bin auf der Suche nach der Ursache. Auf jeden Fall tritt aber kein
Dateisalat mehr auf - oder? Wie äußert sich bei Dir das Problem? Ich
vermute, dass früher geschriebene Sektoren nicht mehr vorhanden sind?
Wolfgang Sch. schrieb:> Auf jeden Fall tritt aber kein> Dateisalat mehr auf - oder?
Nein, das hatte ich vorher schon ausgeschlossen, indem ich 10 Versuche
beim Lesen und Schreiben gemacht habe, bei Fehler bricht er einfach ab.
Ich habe die zusätzlichen Byte (Lesen und Schreiben) wieder entfernt und
habe die Taktrate (clk) auf 500kHz heruntergestellt. Seit vier Tagen
schreibt er jetzt auf der "Problemkarte" fehlerfrei (minütlich ein
Datensatz).
Manche Karten scheinen an gewissen Stellen ein kleines Päuschen zu
benötigen, ist der Takt zu schnell, reicht die Zeit nicht. Wenn ich Zeit
habe, suche ich die Stelle(n), brauche den Logger aber gerade an einer
Solaranlage.
Hallo,
wie provoziert Ihr den Fehler? ich schreibe Teilweise meherere 100 MB
Files auf die Karte und habe bis jetzt noch keine Fehler gehabt.
Schreibe entweder in einem Stück oder mit mehrmaligem öffnen der Datei.
Viele Grüße.
Hi Andre,
die Fehler tauchen bei mir nach mehreren Tagen bis Wochen auf.
Provoziert habe ich die nicht. Beim einen Logger schreibt er auch
mehrere Wochen ohne Fehler (tägliche Textfiles mit ca. 220kB), dann
taucht ein Fehler auf.
Es ist ein Fehler in der ffcdLower() Funktion,
fat_loadRowOfSector(1); ist falsch!!
richtig ist:
fat_loadRowOfSector(0x20);
dann funktioniert auch das cd..
uint8_t ffcdLower(void){
if( fat.dir == 0 )return FALSE; // im root dir, man kann nicht
hoeher !
fat_loadSector(fat_clustToSec(fat.dir)); // laed 1. sektor des
aktuellen direktory.
fat_loadRowOfSector(0x20); // ".." eintrag (parent dir) ist 0
wenn parent == root
fat.dir=file.firstCluster; // dir setzen
return TRUE;
}
Gruß Dietmar
Thilo M. schrieb:
Hallo Thilo,
Du hast recht, der Fehler tritt bei langsamen Takt nicht mehr auf. Ich
habe jetzt probeweise mal Abspeichern von je 512 Byte programmiert,
Abtastzeit 10s.
Nach spätestens 3 Minuten tritt der Fehler auf, wenn Takt > 500KHz.
Ursache ist wohl die interne Speicherplatzverwaltung der SD-Karten, die
sehr viele Speicherzyklen vertragen --> bis zu 10Mio. Praktisch ist der
Flash auch nur einige 1000mal beschreibbar, die interne Organisation der
Karte sorgt aber dafür, dass der Speicher möglichst gleichmäßig
abgenutzt wird.
Diese Umspeicher-Arbeitsschritte macht die Karte allein, ohne äußeres
Zutun.
Wenn man nun wüsste, wann das passiert, hätten wir das Problem gelöst.
Bin weiter am Testen...
Thilo M. schrieb:> Hm...>> der Fehler ist immer noch da, trotz 500kHz Takt.> In angehängter Datei wird einfach nicht weitergeschrieben.
Hallo Thilo,
mir ist nach längerem Test jetzt absolut klar, worin das Problem
besteht.
Immer, wenn genau bis zum Ende eines Sektors oder Clusters geschrieben
wird und die Datei dann geschlossen wird, gehen Daten verloren und/oder
die FAT wird fehlerhaft.
Das kann man simulieren, indem man nicht seine Orginaldaten schreibt,
sondern immer 16 oder 32 oder 64.... Byte. Dann tritt der Fehler exakt
an der gleichen Stelle auf. Kartenart und Hersteller sind egal. Was
weiter oben angenommen wurde, basierte auf Zufall.
Ich habe jetzt erst mal um den Fehler herumprogrammiert:
ffwrites(Messwerteintrag);
if((file_.cntOfBytes &1) ==0) ffwrite(0x20);
- soll heißen, dass vor dem Schreiben von 0dh 0ah geprüft wird, ob die
Dateilänge ungerade oder gerade ist. Im letzteren Fall hänge ich noch
ein Leerzeichen dran.
Seit einigen Tagen läuft es nun ohne Fehler, egal wie schnell, egal
welcher Kartentyp.
Die Funktion
void fflushFileData(void)
enthält noch einen Fehler, wahrscheinlich ist es irgendwie an dieser
Stelle falsch:
// wenn fat.cntOfBytes == 0 ist der sektor gerade vorher schon
geschrieben worden oder es ist noch nichts hinein geschrieben worden.
dann wert so setzten, dass die schleife uebersprungen wird
count = (file_.cntOfBytes==0) ? 512:file_.cntOfBytes;
Eine Abhilfe habe ich noch nicht gefunden, dazu muss man sich tiefer
einarbeiten. Vielleicht kann uns Daniel helfen?
Wolfgang Sch. schrieb:> count = (file_.cntOfBytes==0) ? 512:file_.cntOfBytes;
Man hätte auch schreiben können:
count = (file_.cntOfBytes==0) ? 512:0;
dürfte aber kein Unterschied bei der Funktion sein.
Welcher Fehler taucht denn da auf?
Ist bei dir der Unterstrich nach file (als file_.) überall dran?
Den gibt's bei mir nicht. Evtl. ist das 'ne andere Version?
Ich werde es auch mal testen, gerade Zählerstände zu vermeiden.
Hallo zusammen,
hab leider sehr viel um die Ohren momentan.
Lese aber schon noch mit hier.
Muss mal sehen das ich meine Entwicklungsumgebung für den FAT kram
wieder zusammenbaue. Sollte sich das mit den geraden und speziell mit
den 2er Potenzen bestätigen gehe ich dem auf den Grund.
Viele Grüße
Daniel
Thilo M. schrieb:> Wolfgang Sch. schrieb:>> count = (file_.cntOfBytes==0) ? 512:file_.cntOfBytes;>> Man hätte auch schreiben können:>> count = (file_.cntOfBytes==0) ? 512:0;>> dürfte aber kein Unterschied bei der Funktion sein.> Welcher Fehler taucht denn da auf?>> Ist bei dir der Unterstrich nach file (als file_.) überall dran?> Den gibt's bei mir nicht. Evtl. ist das 'ne andere Version?>> Ich werde es auch mal testen, gerade Zählerstände zu vermeiden.
Hallo Thilo,
das mit den ungeraden Sektorenlängen habe ich vereinfachend gemacht, um
gerade komplett gefüllte Sektoren (512 Byte) zu vermeiden. Alle anderen,
mit einer geraden Anzahl Bytes gefüllter Sektoren werden auch auf
"ungerade" gebracht, das wäre aber eigentlich nicht nötig.
file_ - Unterstrich:
Die Software wurde auf einem Luminary - Prozessor (ARM-CORTEX) zum
Laufen gebracht. Compiler: Keil µVision4.
Bei der Implementierung gab es ein Problem mit der Bezeichnung "file",
daher der Unterstrich.
Zum Problem:
Ich vermute, dass das Problem darin besteht, dass
fat.bufferDirty = TRUE;
gesetzt wird, wenn
count < 512 (while - Schleife)
aber nicht, wenn
count == 512
Ich werde mal noch ein wenig probieren.
Hat eigentlich mal jemand Lust mit den neuen Erkenntnissen ein Paket zu
bauen?
Das letzte Paket zu nehmen und dann alle hier gefundenen Fixes
einzubauen wäre etwas aufwendig.
Vielleicht wäre einer der "Vielverwender" hier dazu bereit?
Gruß
Fabian
Hi Fabian,
ich denke, wenn der Fehler mit den "eben vollen" Sektoren gefunden ist,
wäre es an der Zeit, da hast du Recht.
Mittlerweile ist es, bis auf diesen Fehler, ziemlich wasserdicht.
Lassen wir Daniel noch Zeit, er kennt seinen Code am besten und dürfte
wissen, wo er suchen muss. ;-)
Stimmt.
Bisher habe ich die Lib nur für's lesen genutzt, daher habe ich oben
nach meinem init-Patch nix mehr geupdated. Gerade auch weil's ja
scheinbar immer wieder Schreibprobleme gab.
Wenn das jetzt wirklich eine Lösung ist, wäre alles zusammen in einem
"0.7"-release ne tolle Sache.
Gruß
Fabian
Daniel R. schrieb:> Hallo zusammen,> hab leider sehr viel um die Ohren momentan.> Lese aber schon noch mit hier.>> Muss mal sehen das ich meine Entwicklungsumgebung für den FAT kram> wieder zusammenbaue. Sollte sich das mit den geraden und speziell mit> den 2er Potenzen bestätigen gehe ich dem auf den Grund.>> Viele Grüße>> Daniel
Hallo Daniel,
bin hocherfreut, dass Du noch mal einen Blick darauf wirfst.
Ich konnte aus Platzgründen nicht 512 Byte auf einmal schreiben, deshalb
16 oder 32 ... Byte. Kann man auch anders machen, z.B. 2x250 Byte, dann
12 Byte, ev. auch 1x512 Byte -- habe ich aber nicht probiert.
Fehler auslösen:
Wichtig ist nur, dass der Sektor zum Schluss genau bis Ende gefüllt
wurde.
Bitte für jeden Schreibvorgang
1. Datei öffnen (bzw. neu anlegen)
2. Bytes schreiben
3. Datei schließen
so kann ich bei meinem Gerät den Fehler auslösen.
Viele Grüße,
Wolfgang
Scheinbar liegt das Problem nicht nur an den "eben vollen" Sektoren.
Vor zwei Stunden hat er trotz ugerade gehaltener Filegröße einfach
wieder aufgehört weiterzuschreiben.
Falls es zur Analyse hilft hänge ich da geloggte File mal dran.
Edit:
nachdem ich versucht habe, ein Byte anzuhängen, hat Windows das File als
schreibgeschützt erkannt und es ließ sich nicht mehr abspeichern.
Scheinbar liegt das Problem in der FAT, nicht an der Datei an sich.
Irgendwo macht die Software falsche Einträge, warum auch immer.
Ich hatte auch schon den Fall, das der selbe Dateiname 25x vorkam, sich
aber nur auf eine Datei bezog.
Edit 2:
Karte ist defekt. Lässt sich weder formatieren, noch beschreiben.
Windows erkennt den Datenträger als schreibgeschützt, egal wie der
Schiebeschalter steht.
Wäre natürlich ein dummer Zufall, wenn das Stück ausgerechnet jetzt
gestorben wäre.
Thilo M. schrieb:> Edit 2:>> Karte ist defekt. Lässt sich weder formatieren, noch beschreiben.> Windows erkennt den Datenträger als schreibgeschützt, egal wie der> Schiebeschalter steht.>> Wäre natürlich ein dummer Zufall, wenn das Stück ausgerechnet jetzt> gestorben wäre.
Hallo Thilo,
bei mir laufen 2 Datenlogger seit 2 Wochen mit 10s Speicherabstand im
"ungerade" - Modus fehlerfrei. Jedes Mal werden ca. 60 Byte abgelegt.
Gruß, Wolfgang
Hallo,
wie macht sich das bei Euch bemerkbar. Hängt er sich bei Euch auf? Wenn
ja, in welcher Funktion genau? Ich habe zurzeit das Problem, dass er
sich kurz nach Start des Logvorgangs aufhängt.
Gruß
André
Wolfgang Sch. schrieb:> bei mir laufen 2 Datenlogger seit 2 Wochen mit 10s Speicherabstand im> "ungerade" - Modus fehlerfrei.
Bei mir jetzt auch.
Ich hatte den Takt des SPI versehenlich auf 8MBit gelassen, was für das
DOGm Display kein Problem ist. Nur die alte SD-Karte konnte das nicht
und hat sich verabschiedet. Die neue PLATINUM 1GB ist für max. 5MBit
Schreiben spezifiziert und hat mit gelegentlichen Schreibfehlern
reagiert (Resekt!).
Nun läuft das Ganze mit 1MBit seit Tagen fehlerfrei.
Ich denke, wenn der "Eben-Voll-Fehler" gefunden ist, dann ist das Ganze
ziemlich wasserdicht.
> Nun läuft das Ganze mit 1MBit seit Tagen fehlerfrei.> Ich denke, wenn der "Eben-Voll-Fehler" gefunden ist, dann ist das Ganze> ziemlich wasserdicht.
Gratuliere.
Beitrag "MMC/SD-Karte mit FAT16 an AVR"
läuft bei mir ~5 Jahren 24/7. Steuert nebenbei ne FB und hat nen
Webserver. Fehlerfrei.
SCNR
Torsten S. schrieb:> läuft bei mir ~5 Jahren 24/7. Steuert nebenbei ne FB und hat nen> Webserver. Fehlerfrei.
Ja, bei mir läuft der Heizungsregler seit 2008 auch prima (8x PT1000,
DCF77/RTC, 6 Ausgänge, Dreipunkt-Schrittregler, State-Machine, VBus
(RESOL) einbindung, DOGm-Display), die SD-Karte kam dazu und dürfte
jetzt serienreif sein.
Webserver habe ich auch zwei am Laufen, machen keine Probleme mit
SD-Karte seit 1.1.12.
Hallo Daniel,
mich würde mal interessieren ob es hier schon irgendwelche Fortschritte
in Bezug auf den Bug mit der Clusterlänge gibt, ich würde die lib gern
auf einem atmega128 einsetzen welche Version ist denn da angebracht ? Im
SVN gibt es die 0.6.1 die hatte ich mir jetzt erstmal runtergeladen und
damit mal ein paar erste Tests gemacht, das funktionierte soweit. Sollte
ich besser die 0.6.4 verwenden ? Ich habe mal den Thead quergelesen - so
ganz schlau werde ich daraus eigentlich nicht welche Version nun noch
bekannte Bugs enthält.
@Wolfgang Sch.: Was genau hast Du denn geändert ?
A.H. schrieb:> Hallo Daniel,>> mich würde mal interessieren ob es hier schon irgendwelche Fortschritte> in Bezug auf den Bug mit der Clusterlänge gibt, ich würde die lib gern> auf einem atmega128 einsetzen welche Version ist denn da angebracht ? Im> SVN gibt es die 0.6.1 die hatte ich mir jetzt erstmal runtergeladen und> damit mal ein paar erste Tests gemacht, das funktionierte soweit. Sollte> ich besser die 0.6.4 verwenden ? Ich habe mal den Thead quergelesen - so> ganz schlau werde ich daraus eigentlich nicht welche Version nun noch> bekannte Bugs enthält.>> @Wolfgang Sch.: Was genau hast Du denn geändert ?
Hallo A.H.
das funktioniert, weil zusätzliche Leerzeichen in der Ausgabedatei nicht
stören:
ffwrites(Messwerteintrag); //aus Puffer "Messwerteintrag"
Dateilaenge=file_.cntOfBytes;
if((Dateilaenge &1) ==0) ffwrite(0x20);
ffwrite(0xd);
ffwrite(0xa);
In einem Projekt, bei dem eine SD-Karte als Datenspeicher (FAT16 mit
SFN) werwendet wird, ist mir unangenehm aufgefallen, dass beim Löschen
einer Datei immer eine weitere Datei mitgelöscht wird. Mit einem
Diskeditor habe ich festgestellt, dass zwar der erste Buchstabe beider
Dateinamen durch 0xE5 ersetzt wird, die zur zusätzlich gelöschen Datei
gehörenden Cluster werden in der FAT aber nicht als "frei" markiert und
bleiben belegt.
Auf der Suche nach dem Grund habe ich folgende Codestelle in "file.c" ab
Zeile 484 entdeckt:
1
//////// ob ordner oder datei, der sfn und lfn muss geloescht werden!
2
fat.bufferDirty=TRUE;// damit beim laden der geaenderte puffer geschrieben wird
3
do{
4
fat.sector[row]=0xE5;
5
if(row==0){// eintraege gehen im vorherigen sektor weiter
6
fat_loadSector(fat.lastSector);// der davor ist noch bekannt. selbst wenn der aus dem cluster davor stammt.
7
fat.bufferDirty=TRUE;
8
row=512;// da nochmal row-=32 gemacht wird, kommt man so auf den anfang der letzten zeile
9
}
10
row-=32;
11
}while(fat.sector[row+11]==0x0f&&(fat.sector[row]&0x40)!=0x40);// geht durch alle reihen bis neuer eintrag erkannt wird...
12
13
fat.sector[row]=0xE5;
Die do..while-Schleife ist doch eigentlich nur für LFN gedacht, oder?
Wäre es nicht richtiger, die Schleife "andersherum" zu schreiben, also
so:
1
//////// ob ordner oder datei, der sfn und lfn muss geloescht werden!
2
fat.bufferDirty=TRUE;// damit beim laden der geaenderte puffer geschrieben wird
3
while(fat.sector[row+11]==0x0f&&(fat.sector[row]&0x40)!=0x40)// geht durch alle reihen bis neuer eintrag erkannt wird...
4
{
5
fat.sector[row]=0xE5;
6
if(row==0){// eintraege gehen im vorherigen sektor weiter
7
fat_loadSector(fat.lastSector);// der davor ist noch bekannt. selbst wenn der aus dem cluster davor stammt.
8
fat.bufferDirty=TRUE;
9
row=512;// da nochmal row-=32 gemacht wird, kommt man so auf den anfang der letzten zeile
10
}
11
row-=32;
12
}
13
14
fat.sector[row]=0xE5;
Dann kommt man überhaupt nicht in die Schleife, falls man keinen LFN
hat. Ist meine Überlegung richtig?
@Wolfgang Sch. Danke ich habe das bei mir als bugfix erstmal auch so
eingebaut.
Mir ist beim testen ein Fehler aufgefallen der in die gleiche Richtung
zu gehen scheint. Wenn ich am PC eine Datei auf die Speicherkarte
kopiere z.B. NAME.TXT und der µC soll dann auf die gleiche Speicherkarte
in die gleiche Datei schreiben gibt es die Daten anschließend zwei mal
mit identischem Namen und Inhalt aber unterschiedlicher Größe auf der
Karte.
Wenn ich mit der Datenträgerüberprüfung von XP auf die Karte gehe wird
putzigerweise kein Fehler gefunden, Windows gibt beim löschen der beiden
Dateien einen Fehler aus (Datei nicht gefunden) anschließend sind beide
Dateien weg.
Eine mit Windows auf die Karte kopierte Datei kann ich mir ffrm nicht
löschen.
Ist das zwischen 0.6.1 und 0.6.4 schon gefixt worden ?
Hallo alle zusammen.
Ich hab grade die library runtergeladen und an meiner Hard getestet.
Scheit so weit alles zu funktionieren (riesen dank an Daniel!!!!!) ABER:
ich hab da noch n Nokia 6100 LCD, dass ueber das selbe SPI geht. Wenn
man nun zuerst die SD-karte initialisiert usw. und ne Datei liest, bevor
man etwas mit dem LCD macht, dann klappt's. Wenn man nun nach dem start
der LCD was macht, dann kommt das Programm einfach nicht weiter. Also
wie
if( MMC_FILE_OPENED != ffopen("TXT1.TXT",'r') )
{ mach etwas
}
else mach etwas anderes
macht weder etwas noch was anderes. Scheint so, als ob der CS-pin nicht
richtig tickt....
'Ne Idee was man da macht?
ja sicher doch!
momentan hab ich noch ein Software-SPI hinzugefügt, so dass der LCD da
drüber läuft. Wenn man solche unabhängige ports benutzt, ist alles OK.
man kann dateien öffnen, lesen usw. ich hab ne ATMega 64, also viele
pins, und es wäre nicht weiter kritisch, wenn ich den Software-spi
lasse, wäre aber trotz dem nicht schlecht rauszufinden, was da los ist.
leider bleiben die daten auf der karte drauf. warum auch immer. In der
Datei sind die weg, aber ich bekomme fehler wenn ich zeile 2 und 4
auslese.
Gruss
Milan
Ich tippe mal darauf, wie man es beim PC programmieren auch macht:
Man legt sich eine temporäre datei an. Schreibt da alle Zeilen rein, die
man behalten will und löscht das die orginal Datei und benennt die
temporäre Datei um, so dass sie so heißt wie die orginal Datei.
Probier das doch mal.
Grüße
Hallo Matze,
danke für den Tipp, daran habe ich auch gedacht.
Problem ist, dass die Datei bis 50MB oder mehr gross sein kann. Also 1
zu 1 kopieren geht nicht. Und so viel ich weiss kann ich nur eine Datei
aufmachen und bearbeiten.
Gruss
Milan
Jo, das stimmt. Du müsstest auslesen, bis dein Speicher voll ist und
dann dein Speicherinhalt in die temporäre Datei schreiben. Anderes ist
leider nicht möglich - so weit ich weiß.
Einfach löschen einer Zeile ist aber auch aus Gründen der Datenstruktur
nicht möglich. Beschäftige dich doch mal damit, wie eine Datei
eigentlich auf dem Datenträger aussieht. Als Ansatz: leg dir eine Datei
mit einem kurzen, definierten Inhalt an und öffne die SD- Karte dann mit
einem HEX- Editor. Suche dann mit dem HEX- Editor nach deiner
Zeichenfolge als HEX- Werte. Das kannst du auch an deinem PC machen,
musst nicht extra den µC verwenden.
Wenn du verstanden hast, wie Dateien auf der SD- Karte aussehen, weißt
du auch, daß ein anderer Weg als mit der temp. Datei echt umständlich zu
realisieren ist (bis hin zur völligen Unumsetzbarkeit)
Klar, überschreiben geht. Du musst bloß die Textstelle haben (ffseek ist
dein Freund)
Aber zu dieser Bibliothek: geplant war das mal als Datenlogger... ;)
Was hast du eigentlich genau vor und wielange brauchst du um 50MB Daten
zu schreiben?
Hallo,
wäre sehr nett, wenn mir jemand helfen könnte. Versuche nun seit ein
paar Wochen schon die Bibliothek zum laufen zu bekommen.
Verwendet einen Atmega644P und dieses Modul von Conrad als Pegelwandler
http://www.conrad.de/ce/de/product/197220/ um Hardwarefehler zu
vermeiden.
Für den 10ms Timer (TimingDelay) verwende ich Timer 1.
Dieser zählt bis 16000 bei einem 16MHz Takt und löst somit jede ms ein
Interrupt aus. Wurde im Interrupt bis 10 gezählt, so werden 10 ms
abgezogen. Das ganze funktioniert und wurde bereits getestet.
1
volatileuint8_tTimingDelay;// fuer mmc.c
2
volatileuint8_tMillisekunden_SD=0;
3
4
ISR(TIMER1_COMPA_vect)//Taktgeber 1ms
5
{
6
Millisekunden_SD++;
7
if(Millisekunden_SD==10)
8
{
9
TimingDelay=(TimingDelay==0)?0:TimingDelay-1;
10
//TimingDelay wird so lange heruntergezählt, bis TimingDelay == 0 ist.
11
Millisekunden_SD=0;
12
}
13
}
In mmc_config.h wurden folgende Änderungen vorgenommen:
1
#define MMC_MAX_SPEED FALSE
In mmc.h wurde folgende Änderung gemacht:
1
#define __AVR_ATmega644__
Verwendet wird das Hardware SPI
In der Hauptdatei wird folgender code ausgeführt:
1
if(TRUE==mmc_init())
2
{
3
Display_write_OK();
4
}
5
else
6
{
7
Display_write_Fehler();
8
}
9
10
11
if(TRUE==fat_loadFatData())
12
{
13
Display_write_OK();
14
}
15
else
16
{
17
Display_write_Fehler();
18
}
Die Initiallisierung funktioniert. Die Funktion fat_loadFatData()
liefert hingegeben ein FALSE zurück. Konkret liefert die Funktion
mmc_read_sector() in der Funktion fat_loadFatData() ein FALSE zurück.
1
TimingDelay=20;
2
do{// Wait for data packet in timeout of 200ms
3
token=spi_read_byte();
4
}while((token==0xFF)&&TimingDelay);
5
6
if(token!=0xFE){
7
returnFALSE;// If not valid data token, retutn with error
8
}
9
//token ist ungleich 0xFE
Jemand eine Idee, woran das liegen könnte?
Die Karte ist FAT32 Formatiert mit einer Blockgröße von 512 Byte. Es
handelt sich um eine 1 GB PLATINUM SD Karte.
Hallo,
ich versuche auch die Sachen zum Laufen zu bekommen.
Ich verwende folgenden Code:
while (mmc_init() !=0) // rückgabewert 0 dann ist karte
initialisiert
{
LCD_displayStringLn(Line1,20, "Initializing card faild!");
while(1)
{
nop();
}
}
if(0==fat_loadFatData()) // rückgabewert 0 dann sind die fat
daten bekannt
{
LCD_displayStringLn(Line1,20, "Karte ready...");
// rückgabewert 2 bedeutet, datei ist nicht vorhanden und wurde
grade angelegt.
//bereit zum schreiben !
if(2==ffopen(file_name))
{
LCD_displayStringLn(Line2,20, "Datei wurde angelegt!");
ffwrites((unsigned char*)"Hallo Welt");
ffclose();
}
// hier ist rückgabewerte eigentlich 1, datei ist vorhanden und
wurde geöffnet.
//bereit zum lesen !
else
{
unsigned long int seek = 0;
unsigned int temp = 0;
LCD_displayStringLn(Line2,20, "Datei bereits vorhanden!");
seek=file.length;
ffseek(2);
temp = ffread();
LCD_drawUint16(Line7,100,temp);
LCD_drawUint16(Line8,100,seek);
ffclose();
}
}
Datei anlegen funktioniert suoer. Ich will aus der Datei genau das "a"
auslesen. Aber ich komme nicht so richtig klar mit dem ffseek(). Wie
kann ich in der Datei an diese Stelle springen und genau den Buchstaben
auslesen?
Grüße, Jens
durch das file.cntOfBytes=0 fängt es immer vom 0 an. zu lesen.
Es passiert weil ich funktion in funktion gemacht habe. Und dann fängt
es da wo es bei der erster funktion aufgehört hat!
Gruss
Milan
Michael P. schrieb:> Moin,>> die meiste Arbeit haben die Routinen für das Lesen und Schreiben der> SD-Karte gemacht (wegen neu schreiben und so). Bei den FAT- und> Dateifunktionen habe ich erstmal nur die Void-Pointer (die ICC430> Version die ich nutze kann damit nicht um), die ganzen Zählvariablen> angepasst und natürlich die Funktionsaufrufe der Low-Level-Routinen> geändert. Eben um zu sehen ob es funktioniert. Und es funtkioniert.>> Weitere Anpassungen sind sicherlich noch möglich, mach ich irgendwann> auch noch.>> Michael
Ich hänge gerade auch noch daran, die Lib für MSP430 zu portieren. Magst
du vlt. schreiben, was genau du jetzt angepasst hast? Bisher habe ich
sämtliche SPI-Routinen angepasst sowie die zugehörigen Makros wie
MMC_CS_LOW, MMC_READ etc.
Wo ich Probleme mit dem Compiler bekomme, sind die Arithmetiken auf
void-Pointer wie bei "void *vsector;". Das kommt zum Glück nur zweimal
vor. Generell ist das dekr/inkr von void Pointern auch nicht
standardkonform (weder C, noch C++). Siehe dazu mein Thema hier:
http://www.c-plusplus.de/forum/p2249560#2249560
Frage an Michael P.: Wie hast du das angepasst? Frage allgemein: Sollte
man das in der Bibliothek nicht generell korrigieren?
Falls es die Hilfsbereitschaft vergrößert:
------------------------------------------
Ich bin bereit, den Quelltext meiner Portierung wenn sie läuft zur
Verfügung zu stellen. Generell wäre ich dann dafür, dass man z.B.
sämtliche SPI-Funktionen aus der mmc.h auslagert und eine spi.h o.ä. als
wirkliche Schnittstelle einführt. Entsprechend der Plattform müssten
dann nur Makros in der spi.h angepasst und die Methoden in einer
spi.c(pp) ausgeprägt werden.
hallo,
die lib vom daniel funktioniert sehr gut.
schade das ich wohl zu dumm bin einen string ins unit8_t file_name[]; zu
bekommen um den Datei Namen in der laufzeit zu generieren.
mit char file_name[10] ginge es, aber die ffopen funktion erwartet ein
uint8_t. wie macht man das wenn man nicht so en dummkopp is?
1
uint8_tfile_name[10];
2
charzahl_str[3];
3
4
// Dateinamen z.B. "Jan12.csv" aus aktuellem Datum zusammensetzen
beides war falsch.
jetz geht es aber endlich mit itoa und strcat;
das habe ich geändert:
ffopen((uint8_t*)file_name,'r')
ffwrites((uint8_t*)log_daten)
so setze ich den string file_name zusammen;
Hallo Leute,
ich möchte gerne diese Bibliothek, welche bisher einen sehr guten
Eindruck macht, für eine Art Datenlogger benutzen. D.h. es müssen
lediglich Daten an das Ende einer Datei geschrieben werden können.
Jedoch habe ich dafür nur einen Atmega16 zur Verfügung und das Hex-File
ist bei mir jedoch 17,8 KB groß. Es passt als nicht auf den Atmega16.
Dabei habe ich schon die Compiler-Optimierung auf möglichst geringe
Speichergröße gestellt und in den Config-Files nur das nötigste an
Funktionalität aktiviert. Den bisherigen Code zum Testen findet ihr im
Anhang.
Hat jemand von euch vielleicht noch eine Idee wie sich der Code
verkleinern lässt, denn eigentlich fehlt ja auch noch der Teil der die
Daten "erzeugt", welche dann auf der SD-Karte gespeichert werden sollen.
Oder ist es überhaupt möglich diese Bibliothek auf einem Atmega16 zu
verwenden?
Vielen Dank für eure Hilfe.
hm.. ohne mir deinen Quelltext angeschaut zu haben: warum nimmst du nich
einen größeren ATmega? Der ATmega32 und 64 sind doch pin-gleich, wenn
ich mich richtig entsinne...
Dann haste auch auf jeden Fall genug Platz für deine Anwendung.
Grüße,
Matze
Hi,
ich habe ein sehr seltsames Phänomen mit der lib.
Bei meinem Projekt funktioniert das Schreiben auf die Karte oft so wie
es soll. Also vom Prinzip her geht es (Das Grundgerüst von dem Projekt
besteht aus einem Vorgänger Projekt, dass seit einem Jahr nun schon
einwandfrei funktioniert). Wenn ich aber meinen Code verändere schreibt
die lib offensichtlich nicht mehr auf die Karte. Es entsteht einfach
eine leere Datei. Wenn man sich die Karte mit einem Hex Editor anschaut,
sieht man, dass der letzte geschrieben String sich auf der Karte
befindet, sonst nichts. Er überschreibt also die Daten auf der Karte
ständig.
Die lib setzt also nach dem schreiben des Strings aus irgend einem Grund
die Position innerhalb der Datei wieder auf den Ursprungswert. So werden
vorhandene Dateien nicht vergrößert und neue sind leer.
Wenn ich dann aber wieder die Änderung im Code beseitige, geht es
wieder.
Das komische ist aber, dass diese Änderungen nicht mit der lib zu tun
haben, sprich z.b. wenn ich eine bestimmte if-Abfrage entferne oder
sowas in der Art. Auf alle Fälle sind die Änderungen eindeutig und haben
definitif nichts mit der lib zu tun. Ich hatte ja auch schon meine
memcpy in Verdacht, aber selbst wenn ich die rausnehme geht es nicht
immer. Also ich gehe davon aus, dass ich nicht ausversehen eine Variable
der lib mit 0 überschreibe. Aber ich finde nun auch schon seit Tagen
nicht die Lösung von meinem Problem.
Hatte jemand von Euch so was auch schon mal?
Woran könnte es liegen?
Ich weiß nicht, ob mein Fehler wirklich weg ist, aber ich habe auf alle
Fälle doch noch einen Fehler gefunden: Der Timer war nicht auf 10 ms,
sondern auf 20 ms eingestellt (die Rache des übernommenen Grundgerüsts,
das lauft nämlich mit 16, statt jetzt mit 8 Mhz). Auf alle Fälle läuft
die Software im Moment so wie sie soll.
Kann es wirklich am Timer gelegen haben?
Hallo wie kann ich mehrere Dateien auf der SD Karte anlegen und
beschreiben?
In eine kann ich erfolgreich schreiben, diese wird anschließend
geschlossen. Auch öffnen, anhängen und schließen lässt sich
reproduzieren. Sowie ich jedoch in eine zweite Datei anlegen/beschreiben
möchte, wird diese angelegt, aber nichts wird hineingeschrieben? Was
kann ich da tun? Sie sind in keinem Fall beide gleichzeitig geöffnet.
Gruß,
Ralf
rs232_text("\nDatei konnte nicht gefunden werden");
81
WDH3224_TEXT(150,1,"Datei konnte nicht gefunden werden",1,0);
82
}
nun, das ganze hatte ich auf meinem Testboard (AT90USB1287)ausprobiert
und es lief. Jetzt habe ich es auf das Aktuelle Projekt übertragen
ATMega1284, das SD-Card Modul ist das gleiche geblieben. Nun lauft das
programm allerdings nur noch bis zu dem Punkt, wo ich "Boot...OK" lesen
kann. Danach passiert leider nichts mehr. Das einzige was noch anders
ist, ist die SD-Card und als ich das mal durchgemessen habe, das CS low
ist.
LG Chris
Hallo Leute,
es läuft jetzt fast alles.
Habe jetzt das Problem, das ich die zu lesende datei nicht komplett auf
ein Array im Controller packen kann, da dazu der Speicher fehlt.
Kann ich irgendwie mit ffseek() an eine Bestimmte Stelle in der Datei
Springen in abhängigkeit der gefundenen Absätze in der Datei am ende ist
ja immer ein 0x0D für </r>. Habe daas mit ffseek bisher so verstanden,
das man die Speicherstelle expliziet vorgeben muss...
Bsp. was ich meine.
Ich will aus Zeile 5 ETWAS LESEN, ALSO MÜSSTE 4X 0X0D ERKANNT WERDEN UND
AB DER NÄCHSTEN STELLE MÜSSTEN ALLE CHARS GELESEN WERDEN BIS WIEDER 0x0D
kommt!? Geht das ?
LG Chris
Hallo,
SurtuR schrieb:> hat keiner ne idee oder antwort für mich auf meine frage weiter oben:
Ich habe es mit zwei verschiedenen Versionen getestet. Beide
funktionieren nach dem beigelegten Code einwandfrei. Also- zwei
geöffnete Dateien einmal beschreiben und beim Zweiten öffnen etwas
anhängen.
Einmal auf Atxmega Ebene und einmal auf LPCXpresso-LPC1769 Ebene.
Code stammt aus LPC1769 Version. Ist aber kompatible mit dem Original
(AVR).
Gruß G.G.
vielen dank g.g. für die antwort.
hmm vielleicht sollte ich es noch einmal mit der neusten version der lib
probieren. ich benutzte bisher immer eine version vor der 0.6.4 (ich
glaub es war die mmc-0.6.zip. vielleicht liegt da der fehler. vielleicht
liegts auch am gering dimensionierten ram des atmega168. mal schauen.
gruß,
ralf
leider hat das ummodeln auf version 0.6.4 nichts gebracht.
ich stehe immer noch vor dem problem, das in die zweite datei nichts
geschrieben wird nachdem sie angelegt wurde.
// entsprechender Bereich mit version < 0.6.4
// Auszug Begin
else if (puffer[3]='U')
{
if ((puffer[4]=='S') && (puffer[5]=='1'))
{
sram_ledred=puffer[7];
sram_ledyello=puffer[9];
sram_ledgreen=puffer[11];
sram_var1=puffer[13];
eeprom_write_byte(&cntlogsd,sram_cntlogsd+1);
eeprom_write_byte(&ledred,sram_ledred);
eeprom_write_byte(&ledyello,sram_ledyello);
eeprom_write_byte(&ledgreen,sram_ledgreen);
eeprom_write_byte(&var1,sram_var1);
sum=0;
for (i=0;i<sizeof(puffer);i++){puffer[i]=0;}
pufflauf=0;
updateleds();
uputc(0x06);
}
else if (puffer[4]=='F')
{
// wenn ESC U F data -> speichere data auf
SD-Karte
if(MMC_FILE_EXISTS == ffopen(uptdatei))
{
ffseek(file.length);
uint8_t z;
for (z=5;z<13;z++)
{
ffwrite(puffer[z]);
}
ffclose();
for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} pufflauf=0;
sum=0;
}
uputc(0x06);
}
}
// Auszug Ende
// Entsprechender Bereich mit Version 0.6.4
// Auszug Begin
else if (puffer[3]='U')
{
if ((puffer[4]=='S') && (puffer[5]=='1'))
{
sram_ledred=puffer[7];
sram_ledyello=puffer[9];
sram_ledgreen=puffer[11];
sram_var1=puffer[13];
eeprom_write_byte(&cntlogsd,sram_cntlogsd+1);
eeprom_write_byte(&ledred,sram_ledred);
eeprom_write_byte(&ledyello,sram_ledyello);
eeprom_write_byte(&ledgreen,sram_ledgreen);
eeprom_write_byte(&var1,sram_var1);
sum=0;
for (i=0;i<sizeof(puffer);i++){puffer[i]=0;}
pufflauf=0;
updateleds();
uputc(0x06);
}
else if (puffer[4]=='F')
{
// wenn ESC U F data -> speichere data auf
SD-Karte
if(MMC_FILE_ERROR == ffopen(uptdatei,'r'))
{
ffopen(uptdatei,'c');
ffclose();
}
if(MMC_FILE_OPENED== ffopen(uptdatei,'r'))
{
ffseek(file.length);
uint8_t z;
for (z=5;z<13;z++)
{
ffwrite(puffer[z]);
}
ffclose();
for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} pufflauf=0;
sum=0;
}
uputc(0x06);
}
}
// Auszug Ende
also irgendwie is da doch noch n bug drin vermute ich.
ich zeichne werte auf, schon ne ganze weile -alle paar minuten. für
jeden monat wird ne extra datei angelgegt.
sobald die aktuelle zu beschreibende datei aber 76kB gross ist, lässt
sich die karte nicht mehr beschreiben. sie lässt sich zwar
initialisieren, aber sobald ein schreibvorgang gestartet wurde, wechselt
die meldung von "init-ok" auf "init-felher".
es läuft lange gut, aber warum ist nach 76kB schluß?
kann das jemand bestätigen?
am code sollte es nicht liegen, so ein seltsamer fehler...
blödkopp schrieb:> sobald die aktuelle zu beschreibende datei aber 76kB gross ist, lässt> sich die karte nicht mehr beschreiben.
Was für ein Nickname! :-)
Du hast vermutlich das Problem mit den "eben vollen" Sektoren.
Lies mal die Dateigröße aus und teile sie durch 512. Wenn's ohne
Nachkommaanteil aufgeht, dann siehe
Beitrag "MMC SD library FAT16 FAT32 read write"
dort wurde gezeigt, wie das Thema umgangen werden kann.
Und achte auf die max. Schreibgeschwindigkeit die deine Karte kann!
Ich bin da auch schon 'reingefallen.
Hallo Leute,
habe gerade das Problem, dass meine Datei nicht mehr gefunden wird.
1
if(MMC_FILE_EXISTS==ffopen("TEST000.TXT"))
2
{
3
WDH3224_CLEAR();
4
WDH3224_TEXT(3,0,"Datei wird geoeffnet",2,0);
5
6
rs232_text("\nDatei wird geoeffnet:\n");
7
8
9
// Phase 1
10
for(i=0;i<ZeilenNr-1;i++)
11
{
12
while(ffread()!='\n');
13
}
14
15
// Phase 2
16
n=0;
17
while((get_c=ffread())!='\n')
18
sd_card_string[n++]=get_c;
19
sd_card_string[n]='\0';
20
21
WDH3224_TEXT(20,0,sd_card_string,1,0);
22
rs232_text(sd_card_string);
23
rs232_text("\n");
24
rs232_text("\nEOF\n");
25
ffclose();
26
27
28
}
29
30
else
31
{
32
rs232_text("\nDatei konnte nicht gefunden werden");
33
WDH3224_TEXT(150,2," Datei konnte nicht gefunden werden ",1,1);
34
}
das init der Karte wird mit OK bestätigt und beim öffnen, springt er
gleich in die ELSE Anweisung. Habe jetzt schon zich mal den Dateinamen
gewechselt immer auf das Format 8.3 geachtet, die Karte Formatiert und
acuh mal mehrere Dateien gleichzeitig drauf gepackt zum testen, aber er
will nie eine davon öffnen. Hatte das schon jemand? oder kann mir vlt.
sagen was da falsch laufen könnte?
Thilo M. schrieb:> blödkopp schrieb:>> sobald die aktuelle zu beschreibende datei aber 76kB gross ist, lässt>> sich die karte nicht mehr beschreiben.>> Du hast vermutlich das Problem mit den "eben vollen" Sektoren.> Lies mal die Dateigröße aus und teile sie durch 512. Wenn's ohne> Nachkommaanteil aufgeht, dann siehe> Beitrag "Re: MMC SD library FAT16 FAT32 read write"> dort wurde gezeigt, wie das Thema umgangen werden kann.>> Und achte auf die max. Schreibgeschwindigkeit die deine Karte kann!> Ich bin da auch schon 'reingefallen.
also rechne ich
Ich meinte, wenn du das Eigenschaften-Fenster der Datei aufmachst, der
Wert hinter "Größe" (nicht Größe auf Datenträger, die lässt sich immer
durch 512 teilen).
Hallo,
vielen Dank zunächst mal für diesen tollen Thread.
Ich versuche gerade, die Bibliothek für ein Projekt mit einem ATMEGA128
zu verwenden. Klappt eigentlich beinahe alles auf Anhieb, ABER....
Beim Erzeugen eines Directories wird dieses auch angelegt, was jedoch
verdächtig lange dauert. Ca. 1-2 Sekunden @8MHz. Das muss eigentlich in
einigen ms erledigt sein. Wenn dann in dieses Verzeichnis gewechselt
werden soll, klappt dies nicht. Das Erzeugen einer neuen Datei findet
trotzdem im Hauptverzeichnis statt.
Wird die SD-Karte dann unter Windows gelesen, kann nicht in das
Verzeichnis gewechselt werden, obwohl es angezeigt wird. Es sei
angeblich nicht verfügbar.
Das Berechnen mit fat_getfree dauert ebenfalls sehr, sehr lang. Da
kommen schon einige Sekunden zusammen. Der errechnete freie
Speicherplatz scheint aber zu stimmen.
Ich verwende die die Version 0.6.4, AVR Studio 4.18, WinAVR-20100110.
Getestet habe ich mit einer 32MB, einer 2 GB und einer 16 GB Karte.
Verhalten ist bei allen identisch. MAX_SPEED wurde auch schon getestet.
Hat jemand noch eine Idee, woran es liegen könnte?
Das Schreiben klappt mit voller Geschwindigkeit ohne jedes Problem.
Einen Hardwarefehler kann ich eigentlich ausschliessen.
Vielen
Dank
Da ich die Bibliothek fix brauchte und ich keine Lust auf lange
Diskussionen hier hatte, hab ich die mal debuggt. (allerdings nur für
sfn und FAT 16) - ich hoffe, dass ich den Rest nicht allzu sehr kaputt
gemacht habe.
"wichtigste Bugs":
- bei cdLower wurden die zeilen nicht richtig übergeben
- beim Löschen gabs auch ernsthafte Probleme
- bei mkdir muss der Verzeichnisname exakt 11 Zeichen lang sein (auch
Leerzeichen)
Ich hänge den code mal an, vielleicht interressiert sich jemand dafür
(ich übernehme aber keinen Support und keine Haftung)
Chris schrieb:> Hallo Leute,> habe gerade das Problem, dass meine Datei nicht mehr gefunden wird.> das init der Karte wird mit OK bestätigt und beim öffnen, springt er> gleich in die ELSE Anweisung. Habe jetzt schon zich mal den Dateinamen> gewechselt immer auf das Format 8.3 geachtet, die Karte Formatiert und> acuh mal mehrere Dateien gleichzeitig drauf gepackt zum testen, aber er> will nie eine davon öffnen. Hatte das schon jemand? oder kann mir vlt.> sagen was da falsch laufen könnte?
Hallo zusammen ich habe das gleiche Problem.
kann jemand bitte helfen. ich komme nicht weiter.
Gruss
Milan
Daniel R. schrieb:> Hallo zusammen,> hab leider sehr viel um die Ohren momentan.> Lese aber schon noch mit hier.>> Muss mal sehen das ich meine Entwicklungsumgebung für den FAT kram> wieder zusammenbaue. Sollte sich das mit den geraden und speziell mit> den 2er Potenzen bestätigen gehe ich dem auf den Grund.>> Viele Grüße>> Daniel
hallo,
nach tagen oder wochen geht aufeinmal nix mehr obwohl bis dahin sauber
messdaten auf MMC gespeichert wurden. das ist echt ärgerlich, hatte ich
das thema mmc doch schon abgehackt.
hab jetzt mittlerweile mehrere mmc teiber durchprobiert und finde es
echt schade das gerade dieser anfängerfreundliche leicht zu
integrierende treiber hier noch bugs drin hat denn der is eigentlich der
beste.
gruß
fauli schrieb:> nach tagen oder wochen geht aufeinmal nix mehr obwohl bis dahin sauber> messdaten auf MMC gespeichert wurden
Hi fauli,
das Problem habe ich auch, nach vielen Monaten einwandfreiem Betrieb
schreibt der Logger auf einmal nix mehr.
Ich habe den Eindruck, dass es an meinem Kartenadapter liegt
(Kontaktproblem zur Micro-SD-Karte).
Hatte auch am PC schon Probleme mit den ausgeleierten Adaptern. Evtl.
hat da jemand Erfahrungen?
...tuts eigentlich ffrm mittlerweile ?
Habe einige Tests gemacht und es scheint keine Verzeichnisse zu löschen.
ffrm("ABCDE ");
oder
ffrm("ABCDE");
steigen beide in
file.c
// datei/ordner nicht vorhanden, dann nicht loschen...
if(FALSE==fat_loadFileDataFromDir(name)){
return FALSE;
}
aus.
Das Verzeichnis ist aber vorhanden. Es macht auch keinen Unterschied, ob
man das Verzeichnis mit dem Controller oder mit Windows anlegt...
GRuß
Tom
Hallo,
Ich benutze bibliotekido Unterstützung MMC / SD:
AVR-mmc-0.6.4.zip
Autor: Daniel R. (zerrome)
Datum: 24.07.2011 08:49
Es funktioniert gut mit MMC, hat SD-Karte nicht unterstützt. Warum?
Radek
Wie kann ich bei geöffneter Datei die FAT updaten / zur SD schreiben? Da
ich noch unkalkulierbare Zustände habe, sind alle gesammelten Daten nach
einem Reset verloren...
Schade, dass es niemanden mehr gibt, der sich wirklich aktiv um dieses
brauchbare Projekt kümmert. Daniel R. (zerrome) ist wohl ausgestiegen
:-(
Aber zur Frage: Du kannst die Änderungen mit fflushFileData() auf die
SD-Karte schreiben. Damit steigt allerdings die Schreiblast, d. h. es
gibt mehr Schreibzugriffe.
Guten Abend,
ich habe mal ne Frage. Habt ihr auch hin und wieder das Problem, dass
die SD sich nicht initialisieren lässt? Ich habe auch das Gefühl, wenn
ich voher die freien Bytes auslese hängt sie sich noch öfters auf.
Jemand Erfahrung damit, bzw. kann das jemand bestätigen?
Wie schließt ihr die SD an? Irgendwo noch extra Pullups/downs?
Viele Grüße
André
Schade, dass es niemanden mehr gibt, der sich wirklich aktiv um dieses
brauchbare Projekt kümmert. :-(
Ich schaue auch nur sporadisch hier rein, deshalb kommt die Antwort erst
mit großer Verspätung.
Ich habe Pull-Ups (75 kOhm) an CS (Chip Select) sowie an den unbenutzten
Datenleitungen DAT1 und DAT2. Beim Initialisieren, also vor dem
Umschalten auf SPI, müssen diese Leitungen die richtigen Pegel haben.
Außerdem lege ich über die Versorgungsleitungen einen keramischen
Stützkondensator mit 100 nF, und zwar möglichst nahe an der SD-Karte.
Bei mir hängt sich die SD-Karte nie auf, aber das Abfragen der freien
Bytes dauert ziemlich lange. Vielleicht interpretierst Du das nur als
"Aufhängen". Warte einfach mal länger ab, das kann durchaus Minuten
dauern.
Hallo!
Huch, hier ist ja nicht mehr so viel los. Naja, vielleicht hat ja
trotzdem jemand Lust zu Helfen:
Okay, ich hatte mal wieder ein wenig Zeit an meiner Terrariensteuerung
weiter zu basteln. Ziel war es den Temperaturverlauf auf einer SD-Karte
zu speichern.
Grundprinzip des bisherigen Programms:
4 MHz ATMega162, Interrupt über Timer1 jede Millisekunde, die ISR zählt
dann gegebenenfalls die Uhr weiter und soll sich um die
Wellenpaketsteuerung der Heizung kümmern.
Die Lichtsteuerung passiert dann im Hauptprogramm. Code-Schnipsel dazu
finden sich bei Bedarf am Ende des Posts.
Jetzt habe ich aus einem USB-Dongle mit SD-Karten-Leser die Halterung
ausgelötet und mit einem 74HC4050 an den Hardware-SPI des ATMegas
gehangen.
Ich habe versucht den Interrupt auf 10 ms zu setzen:
1
// Configure Timer 1
2
// TCCR1A = 0x00;
3
TCCR1B|=(1<<CS10);
4
OCR1AL=0x9C40;
5
TIMSK|=(1<<OCIE1A);//Allow Compare Interrupt
Als Hauptprogramm habe ich erstmal einfach das Beispielprogramm genommen
und die UART-Ausgabe durch eine Ausgabe auf das angeschlossene
LCD-Display ersetzt.
Nach etwas Rumwackeln an der Karte fing er dann auch an auf die Karte zu
schreiben. Das Ergebnis:
1
ls -l
2
total 0
3
-rw-r--r-- 1 user users 0 1. Jan 1980 TEST.TXT
4
-rw-r--r-- 1 user users 0 1. Jan 1980 TEST.TXT
5
-rw-r--r-- 1 user users 0 1. Jan 1980 TEST.TXT
6
-rw-r--r-- 1 user users 0 1. Jan 1980 TEST.TXT
7
-rw-r--r-- 1 user users 0 1. Jan 1980 TEST.TXT
8
-rw-r--r-- 1 user users 0 1. Jan 1980 TEST.TXT
9
-rw-r--r-- 1 user users 0 1. Jan 1980 TEST.TXT
Die Datei sollte nicht nochmal neu erstellt werden wenn es sie schon
gibt und eigentlich sollten die Dateien auch einen Inhalt haben. So ganz
scheint es also noch nicht funktioniert zu haben.
Ausserdem:
Was kann/muss ich tun um dieses Programm auf meinen 1 ms-Timer
anzupassen?
Wenn es ein Problem mit der Karte gibt bleibt das Programm in
irgendwelchen Schleifen hängen, was bei der Steuerung der Temperatur
oder des Lichts störend sein dürfte.
Gibt es dafür bekannte Lösungen die einfach zu implementieren sind und
zuverlässig funktionieren?
Ich möchte dieses Projekt eigentlich gerne mit einem µC weitermachen,
auch wenn es mit einem Raspberry wohl einfacher wäre ;)
Hier die versprochenen Code-Schnipsel (ich hoffe sie sind nicht zu lang
fürs Forum):
Bitte immer daran denken, dass das Problem mit dem "Sektor gerade voll"
immer noch besteht (siehe viel weiter oben). Also: Immer schön nur eine
ungerade Datenanzahl auf die Karte schreiben. Dann treten diese
komischen FAT-Geschichten (Daten weg, plötzlich mehrere Dateien mit
gleichem Namen usw.) nicht auf.
Bin grade mal durch den Thread "durchgeflogen" - wenn ich das richtig
verstehe hat der Autor die Weiterentwicklung aufgegeben? Sehr schade
falls wahr, weil das wirklich ein gutes und nützliches Projekt ist.
Selber experimentier ich grade mit 'ner etwas schrägen Anwendung:
Dateien auf einem FAT Datenträger, die Container für CP/M Disk-Images
sind. Wobei ich dann typischerweise Datenblöcke von 512 Byte Größe in
der Gegend rumschiebe.
Bei der Gelegenheit hab ich (neben allen positiven Aspekten) eine Sache
an dem Projekt-Code entdeckt der mir nicht optimal erscheint: die
Funktion ffseek lädt gleich einen 512 Byte Sektor, wenn sie die passende
absolute Adresse gefunden hat. Fühlt sich aus meiner Sicht irgendwie
nicht "richtig" an - ffseek sollte diese Adresse nur zurückliefern und
es dann anderen Funktionen überlassen, ob der Sektor gelesen oder
geschrieben werden soll.
Just my 2 cents.
Ansonsten: Klasse Projekt!
Hab gestern und heute ein wenig mit der Bibliothek experimentiert, und
dabei folgenden Fehler gefunden:
In der *main_simple.c* Beispieldatei werden für eine Reihe von
Systemtakten die Konstanten für den Timer definiert, die Definition für
20MHz Systemtakt ist fehlerhaft. Dort steht (Version 0.6.4):
Habe diese Lib auch im Einsatz und bisher mit dem Ungerade-Modus das
Problem mit den vollen Sektoren umgangen.
Wollte der Sache aber auf den Grund gehen, damit das lästige
Prüfen-und-Leerzeichen-anhängen entfällt.
Deshalb habe ich die Bibliothek mal genauer untersucht.
Zu Testzwecken habe ich immer 512 Byte auf einmal geschrieben. Wie
erwartet blieb die Datei jedes Mal bei 32kB "hängen" (Zuordnungseinheit
32768 Bytes). Beim Schreiben von ungeraden Datenblöcken waren auch
größere Dateien möglich.
Vor dem Schreiben wird ja immer zuerst ffseek() ausgeführt, um an die
akutelle Position in der Datei zu gelangen. Dabei bin ich in ffseek()
auf folgendes gestoßen:
Wenn aber der Sektor genau vollgeschrieben ist (Bytes % 512 == 0) und
keine weiteren Sektoren mehr anstehen, gab das einen Überlauf bei
chain.cntSecs -= 1;
Habe also folgendes ausprobiert:
Hallo Martin,
ich habe ja vor langer Zeit den Fehler entdeckt, aber nie Zeit gehabt,
nach der Ursache zu suchen. Mit der Beseitigung dieses Fehlers dürfte
das Projekt perfekt sein. Einige Geräte laufen bei mir seit Jahren im
ungerade-Modus fehlerfrei (LUMINARY-CPU's). Ich teste morgen und teile
das Ergebnis mit.
Danke für Deine Bemühungen!
Hallo Wolfgang,
leider scheint das auch noch nicht ganz des Rätsels Lösung zu sein.
Habe zwei Datenlogger mit der Modifikation laufen.
Einer läuft tadellos, beim anderen habe ich Sprünge in der Aufzeichnung,
wenn ein Sektor vollgeschrieben wurde. Da sind dann plötzlich ein paar
Zeilen vertauscht...
Die Sprünge laufen nach diesem Prinzip (Jede Zeile steht für einen
Eintrag)
111111
22 555555
666666
777777
22222
333333
444444
Muss auch mit dem ffseek() zusammenhängen, womit er mit dem Schreiben
wieder einsteigt...
Hast du schon was herausgefunden?
Hallo Martin,
tatsächlich ist da immer noch der Wurm drin. Ab 15.Mai habe ich etwas
mehr Zeit, da werde ich das Problem lösen. Das Hauptproblem ist, dass
man die komplette Funktionsweise der Software erst mal verstehen muss.
Ich schätze, dass ich etwa 3-4 Tage Einarbeitung benötige.
Ich melde mich wieder!
Hi,
echt cooles Projekt, hat soweit erst mal auch gut geklappt. Leider bin
ich mit der Dauer für solch einen Schreibvorgang noch nicht wirklich
zufrieden. Dauert schon ne weile, bis man seine Daten auf die SD kriegt.
Hat da jemand Tipps, wie das vielleicht schneller gehen könnte?
Hallo,
ich versuche einen Datenlogger mit einem ATmega 8A aufzubauen. Ich habe
mir den Beitrag durchgelesen und den Source-Code angeschaut. Sehr
hilfreich, danke!
Das Beispiel ist mit einem ATmega 8
http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status
Schaltung aufgebaut wie im Beispiel. Ich habe allerdings einige Probleme
mit dem Code:
Zunächst hatte ich Probleme mit den Timer-Registern, die haben im Code
andere Bezeichnungen als im Datenblatt des ATmega 8 und des 8A. Die habe
ich entsprechend des AVR-Datenblattes angepasst.
Original:
static void timer0_init(){
TimingDelay = 0; // initialisierung der zaehl variable
TCCR0A = 1<<WGM01; // timer0 im ctc mode
TIMSK0 = 1<<OCIE0A; // compare interrupt an
TCNT0 = START_TCNT; // ab wo hochgezaehlt wird,
OCR0A = TOP_OCR; // maximum bis wo gezaehlt wird bevor compare match
TCCR0B = PRESCALER;// wenn prescaler gesetzt wird, lauft timer los
sei(); // interrupts anschalten, wegen compare match
}
Angepasst:
static void timer0_init(){
TimingDelay = 0; // initialisierung der zaehl variable
TCCR1A = (1<<WGM12); // timer0 im ctc mode
TIMSK = (1<<OCIE1A); // compare interrupt an
TCNT0 = START_TCNT; // ab wo hochgezaehlt wird,
OCR1A = TOP_OCR;// maximum bis wo gezaehlt wird bevor compare match
TCCR1B = PRESCALER;// wenn prescaler gesetzt wird, lauft timer los
sei(); // interrupts anschalten, wegen compare match
}
Dann bin ich noch total erstaunt, dass der uC mir nur über eine Baudrate
von 600 antwortet, im Quelltext steht doch 9600 ?!? hatte jmd das selbe
Problem?
"// Wenn auf dem terminal "Boot... OK" zu lesen ist, ist Init OK."
Und ich bekomme immer nur "\nBoot" als Antwort, das aber in regelmäßigen
Abständen. Woran kann das liegen, bei euch funktionierts doch überall,
ich habe ja am Quelltext quasi nichts verändert. Hatte es mit drei
verschiedenen SD-Karten probiert, alle standartformatiert, immer mit dem
gleichen Ergebnis.
Hat jmd von euch Erfahrungen mit dem Source-Code "AVR Version 0.6.4" vom
oben Beschriebenen Link?
Ich danke euch im Voraus für eure Antworten.
Grüße
Johannes
Hallo ich nochmal mit einem Update,
heute habe ich das Ganze nochmal mit einem ATmega 169A probiert.
Habe 1:1 den Quelltext von
http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code-Beispiel
Aktuellste Version 0.6.4 genommen. Gleiche Problematik mit der Bautrate
600 statt 9600 und dass ich nur "\nBoot" empfange.
Ich habe nichts am Quelltext verändert und benutze die
Beispeilschaltung.
Komisch ...
Bei wem geht die Software denn und was verwendet ihr für eine Hardware?
Grüße
Johannes
Hallöchen..
Benutze die Version 6.4. Auf meinem Xmega128A1 funktioniert Lesen und
Schreiben über SPI mit 8MHz problemlos. Mit 16Mhz SPI Clock laufen
leider nicht alle SD Karten (Class4). Gibt Fehler bei der
Initialisierung, könnte vlt. aber am Timer im Xmega liegen. Werde das
mal überprüfen. Ferner funktioniert der MultiBlock Modus nicht. Habe
einige Unverständlichkeiten in der Datei "mmc.c" für den MultiBlock
Zugriff gefunden wzB:
response=mmc_write_command(cmd);// cmd13, alles ok?
14
15
mmc_wait_ready();
16
17
mmc_disable();
18
returnresponse;
19
}
Compiler Error: "response=mmc_write_command (cmd);"
Hab diese Zeile ersetzt durch:
spi_write_byte(cmd);
response = spi_read_byte;
Es scheint aber noch mehr Fehler in den Routinen für den MultiBlock
Zugriff zu geben. Bin auf der Suche..
Gruß Rolf
Hallöchen..
Da bin ich nochmal schnell. Der Initialisierungsfehler mit 16MHz SPI
Clock lag an dem verwendeten Breakout Board für die SD Karte. Da sitzen
5 Volt Pegelwandler zwischen den Steuerleitungen zur SD Karte um den
Pegel von 5 Volt auf 3.3 Volt abzusenken. Auf dem Board sitzt ein
Umschalter für 5 Volt oder 3 Volt Betrieb. Dieser steht bei mir auf 3
Volt, da ich einen Xmega mit 3.3 Volt Betriebspannung verwende. Diese
Pegelwandler scheinen bei 16MHz die Signalflanken der Steuerleitungen zu
sehr abzuflachen, so dass eine sichere und gute Datenübertragung zur
oder von der SD Karte nicht mehr gewährleistet ist.
Habe jetzt die Pegelwandler überbrückt, so das die Steuerleitungen
direkt mit dem Xmega verbunden sind.
Bild: SD Karte Breakout Board
Gruß Rolf
Hallöli..
Hab leider immer noch das Problem das bei MultiBlock Read kein Byte von
der SD Karte gelesen wird. Das Programm verweilt leider dauerhaft in der
while Schleife und wartet auf ein zu empfangenes FE Byte. Hab
verschiedene SDHC Karten (Class4) ausprobiert. Woran könnte es liegen ?
Wenn man die Berichte nur mal überfliegt ist es besser sich nach einer
Alternative umzusehen die auch das tut was sie soll.
FatFs von ElmChan ist z.B. so eine.
Dem Autor war nicht mal klar was der Unterschied zwischen einer .h und
.c Datei ist wenn man sich die ersten Posts in diesem Thread anguckt.
Das spricht Bände.
Hallo Torsten
Danke für den Tip. Die Software von ElmChan habe ich mir bereits
angesehen. Macht einen sehr guten Eindruck. Allerdings müsste ich dafür
die ganzen Routine in meinem Synth Projekt ändern
(http://www.cczwei-forum.de/cc2/thread.php?postid=86316#post86316).
Dafür habe ich aber im Moment keine Zeit. Ferner weis ich nicht, wieviel
Ram für die Zwischenspeicherung der Daten im Prozessor notwenig ist.
Muss mit dem Ram sehr sparsam umgehen, da andere Funktionen in meinem
Synthesizer auch Speicherplatz beanspruchen.
Mir ist aufgefallen, dass in den Funktionsroutinen
"mmc_multi_block_start_read" und "mmc_multi_block_read_sector" beim
Warten auf das Startbyte nur 0x00 empfangen wird. Wenn ich diese
Routinen umgehe findet eine Datenübertragung statt. Allerdings sind die
ersten Bytes nur Müll. Mir scheint es so, das die SD Karte die
MultiBlock Befehle nicht versteht. Bin aber kein Experte in Bezug auf
das FAT32 System. Verschiedene aktuelle SD Karten (Class4) habe ich auch
getestet.
Mir ist auch nicht ganz klar, ob sich der MultiBlock Zugriff in meinem
Projekt lohnt. Fürs Laden eines Sound Presets von der SD Karte wird
immer auf eine 32KByte große Binär Datei zugeriffen. Diese Datei
beinhaltet die Parameter und WAV-Dateinamen für insgesammt 128 Presets
in einer Sound-Bank. Beim Laden von Sound Samples siehts ein wenig
anders aus. Ein Wav-File kann die Größe von 1KByte bis 1MByte haben.
Bild 1: Datei und Ordner-System im Synthesizer
Bild 2. Preset Menü
Gruß Rolf
Guten Tag,
ich scheitere am versuch die Version 3.1 zu kompelieren, leider bekomme
ich fünf fehler (alle Fehler sind in der Datei fat-0.3.c):
-conflicting types for 'fat_writeSector'
-conflicting types for 'fat_getNextCluster'
-conflicting types for 'fat_getFreeCluster'
-conflicting types for 'fat_setCluster'
-'superfloppy' undeclared (first use in this function)
ich verwende Atmel Studio 6.2.
Wie könnte ich diese Fehler beheben ?
Grüße
Moritz
Hallo Moritz
Ich habe mit der Version 0.6.4 auch Probleme beim kompilieren und bin
aus diesem Grund wieder zurück auf eine 5er Version glaube ich. Kanns
leider nicht genau sagen. Im Anhang die kompilierten Dateien. Einfach
die Dateien in AVR Studio 6.2 im Solution Explorer als Existen Item
"adden" bzw laden und kompilieren. Wichtig ist die initialisierung eines
Timers mit 10ms Interrupt, da sonst zeitkritische Sachen in der SD
Routine nicht funktionieren. In dem Timer wird die Variable TimingDelay"
decrementiert.
Hab dir mal den Source Code drangehangen. die zwei Dateien sd_card.c und
sd_card.h sind meine Funktionsroutinen im Programm und als Beispiel
gedacht. Ist aber alles noch etwas konfus. Ich hoffe das hilft dir
weiter :)
LG Rolf
>ich scheitere am versuch die Version 3.1 zu kompelieren,
Was willst du mit diesem uralten Kram? Alle bereits
gefundenen Fehler noch mal suchen? Nimm ne neuere Version
und klopp den Dreck in die Tonne.
In einem Datenlogger-Projekt habe ich bisher FatFs von ElmChan
verwendet, der hat aber in der aktuellen Version einige radikale
Veränderungen bei einigen Funktionsaufrufen vorgenommen und die
Konfiguration ist dank der vielen Module auch schon immer sehr chaotisch
gewesen - es ist wohl schwer, eine eierlegende Wollmilchsau auf Dauer am
Leben zu erhalten.
Hier dagegen läuft die Konfiguration dank einer zentralen .h-Datei sehr
einfach und problemfrei und ich konnte den Kode direkt und ohne Probleme
zum Laufen bringen - Version 0.6.1 vom SVN-Server ist zwar 4 Jahre alt,
ließ sich aber problemlos mit AVR-Studio 6.1 und aktueller Toolchain
kompilieren.
Testsystem: 3,3V ATmega328P und microSD SDHC von 4GByte und 8GByte.
Der Quellkode selbst ist etwas gewöhnungsbedürftig - bin dabei, den Kode
etwas aufzuräumen und zu anglifizieren.
Aber : Bei der Verwendung langer Dateinamen scheint es ein Problem zu
geben, wenn der lange Dateiname kürzer ist, als ein kurzer Dateiname -
eine auf diese Weise erstellte Datei hat plötzlich zwei Punkte im
Dateinamen und läßt sich unter Windows nicht öffnen - da sich das
vermeiden läßt, habe ich noch nicht nach dem Fehler gesucht...
Und erst jetzt sehe ich ein, daß die "aktuelle" Version auf dem SVN
eine uralte Version ist, und man sich wie immer hier im Forum durch
Gigazeilen von Kommentaren und inkrementellen Änderungen Lesen muß.
Schade eigentlich. Ich will ja nicht wirklich etwas umsonst und ohne
Arbeit haben, hatte mich ja schon daran gemacht, die Version 0.6.1
aufzuräumen, aber das macht dann ja wohl keinen Sinn mehr... Mal sehen,
och ich Version 0.6.4 ebenfalls direkt und unproblematisch zum Laufen
bekomme, auch wenn mir der eingeführte 10ms-Timer doch einiges
Kopfzerbrechen bereitet - abgesehen von Aktivitäten soll mein Logger nur
einmal pro Sekunde aufwachen, aber das läßt sich sicher irgendwie
anpassen...
Ich hoffe, ich habe jetzt schließlich die aktuelle Version gefunden...
Hat jemand von Euch erfahrungen mit dieser implementierung gemacht:
https://github.com/BizzaBoy/RFAT
Besonderes Interesse wäre wie "robust" diese Implementierung wirklich
ist. Der Autor behauptet ja es sei: "100% power fail safe."
Hallöchen..
Ich benutze die aktuelle Version der FAT32 Library.
Ich hab nun folgendes Problem. In einem Ordner befinden sich insgesamt 9
Dateien. Mit der 'ffrm()' Funktion möchte ich eine Datei aus dieser
Liste löschen. Leider werden aus der Liste immer 2 Dateien gelöscht.
Z.B. Datei-Liste mit Bezeichnung 1-9. Wenn ich die Datei '3' lösche,
dann wird die Datei '2' mit gelöscht. Wenn ich Datei '9' lösche, wird
Datei '8' auch gelöscht. Wenn ich die 1.Datei '1' lösche, wird Datei '2'
auch gelöscht. Ist nur eine Datei vorhanden und wird diese gelöschr,
bekomme ich wieder andere Dateien mit 0Byte angezeigt ????
Mein Code:
1
// set folder
2
ffcd("");ffcd("SAMPLE");
3
4
// file available ?
5
if(fat_loadFileDataFromDir(sample_name)==TRUE)
6
{
7
// delete file
8
ffrm(sample_name);
9
ffclose();
10
}
Hardware: SDHC Card 4GB SanDisk Fat32 Format
Software: Aktuelle Version FAT32
Schreib- und Lesefunktionen funktionieren problemlos. Nur das löschen
der Dateien nicht. Kann mir vielleicht jemand helfen. Danke im Voraus.
Gruß Rolf
Hallo..
Hier im Forum gabs einen Beitrag von Lukas
Beitrag "Re: MMC SD library FAT16 FAT32 read write" indem
er auf einige Fehler in der FAT32 Library hingewiesen hat.
Das Löschen von Dateien funktioniert mit der neuen 'ffrm()' Routine von
Lukas problemlos.
Im Anhang nochmal die FAT32 Library von Lukas.
Gruß Rolf
Hey,
ich hab eine Frage zur "TimeDelay" variable...die wird doch nur
benötigt, damit man in einem Fehlerfall nicht in einer Endlosschleife
steckt, oder? D.h. man braucht diese nicht unbedingt im ISR
dekrementieren. Oder liege ich da falsch?
Frage2: mmc_init()und fat_loadFatData() wird ohne Probleme(return ==
TRUE) ausgeführt. Wenn ich dann eine Datei anlege
1
if (ffopen(fname, 'c') == MMC_FILE_CREATED)
2
{
3
ffwrites((uint8_t*) "test");
4
ffwrite(0x0D);
5
}
6
ffclose;
und diese schließe, findet die Funktion ffopen(fname, 'r') die Datei
nicht.(Fehlercode: MMC_FILE_ERROR)
Hatte jemand evtl. noch dieses Problem?
Hallo Andy,
in der 'mmc_init' wird TimingDelay auch benutzt. Könnte sein, dass deine
Karten dann nicht mehr richtig initialisiert bzw erkannt werden, wenn du
es weglässt. Da ich mehrere Timer-Interrupts in meinem Synthesizer
benutze, habe ich TimingDelay mit integriert.
Ich benutze die letze Version 6.4 Datei Anlegen und Öffnen geht bei mir
ohne Probleme.
Beispiel:
(die Delays sind nur für die Textmeldungn auf meinem Display notwendig)
1
// save Preset Data ---------------------------------------------------
2
set_preset_folder();
3
4
// Data.bin file available ?
5
if(fat_loadFileDataFromDir("Data.bin")==FALSE)
6
{
7
fillrectangle(30,38,280,145,color_blue1);
8
rectangle(33,42,99,243,color_white);
9
fillrectangle(139,42,180,65,color_blue1);
10
draw_string("File 'Data.bin' not found!",42,75,6,color_white);
11
_delay_ms(1000);
12
if(MMC_FILE_CREATED==ffopen("Data.bin",'c'))
13
{
14
draw_string("create new File...",42,90,6,color_white);
15
_delay_ms(500);
16
ffwriten(0,0x8000);
17
}
18
ffclose();
19
}
20
21
22
voidset_preset_folder(void)
23
{
24
// set Preset Folder --------------------------------------------------
25
ffcd("");
26
ffcd("PRESET");
27
28
// set PRBANK Folder --------------------------------------------------
29
charfolder_temp[9];
30
strcpy(folder_temp,"PRBANK");
31
32
charxx[3];
33
sound_bank=sel_sound_bank;
34
35
itoa(sound_bank,xx,10);
36
if(sound_bank>9)
37
{
38
strcat(folder_temp,xx);
39
}
40
else
41
{
42
strcat(folder_temp,"0");
43
strcat(folder_temp,xx);
44
}
45
ffcd(folder_temp);
46
47
// Set SOUND Folder --------------------------------------------------
Bezogen auf meinen Beitrag #3769720 vom 19.08.2014 10:27 (etwas weiter
oben):
Ich habe das Datei System auf der 4GB SD Karte meines Synthesizers
geändert. Dazu gehört das abspeichern oder löschen von Samples und
Presets.
Das hört sich jetzt nicht gerade kompliziert an, aber die Arbeit steckt
mal wieder in den Details. Die Abbildung zeigt die Ordner Stuktur auf
der SD Karte.
Auf der SD Karte gibt es drei Ordner mit der Bezeichnung PRESET, SAMPLE
und SYSTEM. Im Ordner 'Preset' sind die gesamten Sound Parameter,
UserWave-Table und ggf das Sample-File für den Sound abgespeichert. Der
Ordner 'SAMPLE' beinhaltet die gesamte Sample Library. Hier kann man
Samples laden, speichern oder löschen, ohne eine Beeinflussung auf die
Preset Sounds. Dadurch kann man z.B. die komplette Sample Library auf
der SD Karte ändern oder austauschen, ohne Gefahr zu gehen, dass sich
die Preset Sounds verändern. Falls ein Preset ein Sample-File besitzt,
wird dieses immer im Preset Ordner mit abgespeichert.
Im Ordner 'SYSTEM' befinden sich System relevante Daten wzB Bilder,
Sequenzer-Daten, USERWAVE-Table und die aktuelle Midi CC Tabelle. Die
USERWAVE-Table besteht aus 128 festen Wellenformen mit 256 Byte Größe
und kann beliebig ausgetauscht werden. Damit stehen dem Benutzer
unendlich viele Möglichkeiten der Soundgestaltung zur Verfügung.
Gruß Rolf
andy schrieb:> Hey,>> ich hab eine Frage zur "TimeDelay" variable...die wird doch nur> benötigt, damit man in einem Fehlerfall nicht in einer Endlosschleife> steckt, oder? D.h. man braucht diese nicht unbedingt im ISR> dekrementieren. Oder liege ich da falsch?>> Frage2: mmc_init()und fat_loadFatData() wird ohne Probleme(return ==> TRUE) ausgeführt. Wenn ich dann eine Datei anlege>
1
if (ffopen(fname, 'c') == MMC_FILE_CREATED)
2
> {
3
> ffwrites((uint8_t*) "test");
4
> ffwrite(0x0D);
5
> }
6
> ffclose;
7
>
> und diese schließe, findet die Funktion ffopen(fname, 'r') die Datei> nicht.(Fehlercode: MMC_FILE_ERROR)> Hatte jemand evtl. noch dieses Problem?
Hi Andy
Ich glaube ich hatte mal ein ähnliches Problem.
Es könnte noch daran liegen, dass du zuerst einen Ordner anlegen musst
und dann eine neue Datei in dem Ordner erstellen kannst.
Gruß Rolf
Hey Rolf,
danke für deine Antwort. Leider hat es daran nicht gelegen. Habe jetzt
auch Timingdelay mit eingebaut, hilft auch nichts. Bin immer noch am
suchen der Lösung. Wenn ich den Fehler finde, melde ich mich ;)
Hallo Rolf,
Obwohl diese lib nicht als eine der zuverlässigsten gilt hast Du Dich
dran gemacht diese benutzbar zu machen - mutig. Und scheinbar tuts die
auch.
Beim überfliegen des obigen Quelltextes bin ich beeindruckt. Ohne von
dieser Materie allzuviel zu verstehen kann ich nur ahnen wieviel Arbeit
da drin steckt. Respekt!
Das einzige was mir nicht gefällt sind die vielen einzelnen
read_par_value() und write_par_value() Aufrufe. Vielleicht könnte man
das in ein struct packen und mit einem einfachen memcpy initialisieren
oder von der Karte lesen.
Einen guten Rutsch,
Torsten
Hallo Leute,
erstmal vielen Dank für die Library. Ich wollte einen Datenlogger bauen,
und wenn die mmc_init durchläuft funktioniert alles hervorragend. Nur
manchmal kommt er nicht durch die prozedur
1
while(FALSE==mmc_init()){
2
_delay_ms(100);
3
4
}
Egal wie lange ich warte, die init läuft nicht durch. Hingegen andere
male funktioniert es... es scheint ziemlich zufällig zu sein. Außerdem
habe ich herrausgefunden, dass wenn ich mit meinem Finger den Miso pin
berühre, dann funktieniert das meistens, kann aber ebenfalls zufall
sein. Ein Hardreset des controllers hilft auch nicht immer. Wenn Die
Spannungsversorgung an bleibt und die sd karte einmal initialisiert
worden ist und man dann den controller resettet, dann geht es fast
immer. Aber wenn diese wieder ausgeschaltet wurde, dann funktionier das
weniger oft.
Hatte jemand von euch schonmal solche probleme? Ich bin mittlerweile
wirklich ratlos.
Grüße
Nicolai
PS: ATMEGA32 16MHZ Quartz SDHC 8GB
Hallo,
Der letzte Beitrag ist ja schon etwas her...
ich habe die hardware so aufgebaut wie beschrieben und benutze auch den
Beispielcode. Leider kommt der Controller fast nie druch die MMC_Init
funktion.
Ich habe jetzt alle Einträge hier gelesen und auch weitere die man so im
Internet findet. Leider konnte mir keiner so wirklich helfen. Wenn die
karte erstmal initialisiert ist funktionier das Schreiben auch
zuverlässig mehrere Tage lang. Interessanter Weise hängt sich die
Funtkion wirklich auf...
hat jemand damit schon Erfahrung?
Viele Grüße
Nicolai
Hallo,
ich hoffe hier liest manchmal noch jemand mit. Habe die lib erfolgreich
zum laufen gebracht. Nur mit neuen SD-karten gibt es auf einmal
Probleme. Lesen und schreiben klappt nur einmal. Dann kann man zwar die
geschrieben machen auf dem PC anschauen jedoch nicht auf der MCU.
Unterscheid zu alten karten ist der "First Physical Sector". Bei den
altern Karten ist diese immer 1 bei den neuen 8192. Was hat das zu
bedeuten und kann das mein Problem sein? Wie kann man das lösen?
Grüße Peter
Das Problem hatte ich vor Jahren gefunden, aber noch keine Lösung. Ich
verwende die Software bisher in vielen Projekten völlig ohne Probleme.
Das war nur möglich, weil ich immer nur Klartext an PC zu übertragen
hatte, da störte es nicht, ein zusätzliches Leerzeichen vor dem 0d0a
einzufügen, wenn die übertragene Zeichenzahl für diese Zeile ungerade
war.
Seit der Findung des Problems liegt ein Link zu meiner E-Mail auf diesem
Beitrag. In den neuen Einträgen war bisher noch kein Lösung des Problems
dabei.
Hallo,
Seit einiger Zeit versuche ich es diese Bibliotheken einzubinden und zu
nutzen.
Im konkreten Fall geht es hier um einen Atmega48 der auf eine SD-Karte
schreiben soll.
Nun bin ich relativ ungeübt, was Bibliotheken einbinden usw angeht,
sodass ich wahrscheinlich eine deutlich detailliertere Anleitung
benötige.
Nun zum Eigentlichen Problem:
Ich arbeite derzeit mit Atmel Studio 7. Beim Erstellen eines neuen
Projektes, füge ich:
fat.c, fat.h
file.c, file.h
mmc.c, mmc.h
mmc_config.h
uart.c, uart.h
hinzu.
Danach bekomme ich diese Fehlermeldungen angezeigt(Im Anhang
fehlermeldung_anfang_sd)
Dabei ist mir aufgefallen, dass in der mmc.h kein AT_Mega48 enthalten
ist, weshalb ich den Mega8(der Pingleich ist) kopiert habe und umbenannt
habe. (Zu sehen in Aenderung1_mmc.h_)
Danach sind mehr Fehlermeldungen aufgetaucht, die so wie es ausschaut,
viel mit dem UART zu tun haben. (Zu sehen in
fehlermeldung_nachAenderung1_sd)
Da stellt sich mir die Frage, warum benötige ich diese uart.h überhaupt?
Nun bin ich mir unsicher, ob ich total auf dem Holzweg bin oder mich
langsam der Lösung des Problems nähere.
Ich würde mich über Antworten sehr freuen.
Mit freundlichem Gruß
Marius
Im Tutorial gibt es das Setting
> #define MMC_SDHC_SUPPORT TRUE
Aber in den Quelltexten von Version 0.6.4
(http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip)
konnte ich dieses Setting nicht finden.
Ist das Setting überflüssig geworden oder ist der Link zum Download
nicht mehr aktuell?
Wer Fehlermeldungen des Kompilers bekommt , wie
DECLARATION_AC_POWER_ON_IRGENDWAS undeclared ,
dem fehlen additionelle Header-Files , oder aber hat diese Deklarationen
in weiteren System-Headern der Compillier-Umgebung schon vorhanden .
Insbesondere wenn die Kompillierumgebung Linux ist , dann werden mit den
GCC-Bibliotheken und besonders mit dem Linux-Kernel in
/usr/include/*/linux ständig Deklarationen verändert , ausgelagert in
andere Header , oder gar vollständig entfernt , oder umbenannt .
Dieser Strang ist schon ca. 10 Jahre alt , und viele Systemheader des
GNU-Compilers , der C-Bibliotheken und des Linux-Kernels werden sehr
andersartig aussehen .
Die Kompillierumgebung hat sich sehr verändert , und man müsste sich
Linux - Betriebssystem e aus alten Zeiten besorgen , um an die Header
und Fertigkompillierten Bibliotheken zu kommen , die zum Kompillieren
und Finalem Verlinken bzw. Statischem Einbau nötig sind .