<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zerrome</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zerrome"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Zerrome"/>
	<updated>2026-04-11T03:55:17Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59566</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59566"/>
		<updated>2011-08-16T05:50:25Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Sourcen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip AVR Version 0.6.4] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme. Bei der Aktuellen Version ist Multi-block ungetestet.&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Achtung. Gefahr!&amp;lt;/u&amp;gt; Die Anschlussart mit einem normalen Pegelwandler wie im Bild rechts birgt jedoch die Gefahr der Zerstörung der SD Karte. Nämlich genau dann, wenn einmal (z.B. falsche Portdeklaration) versehentlich die MISO Leitung an 5V liegt oder wenn noch ein weiterer 5V-Teilnehmer am SPI Bus hängt und 5V Signale einspeist. Dann liegen am Datenausgang der SD Karte nämlich plötzlich 5V an, und das ist fatal. Besser und professioneller sind sog. birektionale Pegelwandler, die alle Datensignale in beide Richtungen von 5V &amp;lt;&amp;gt; 3,3V transferieren. Eine Bezugsquelle für ein fertiges Kartenmodul inkl. birektionalem Pegelwandler ist z.B. [http://www.shop.display3000.com/elektronikmodule/sd-kartenmodul/index.html Display3000]. Tipp: ganz an das Ende scrollen, dort gibt es ein paar anschauliche Informationen. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
* Hier immer die Aktuellste Version mit Informationen dazu [http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status FAT16/32].&lt;br /&gt;
&lt;br /&gt;
* Achtung! Nur noch alte Version im SVN.&lt;br /&gt;
&lt;br /&gt;
Sourcecode mit Linux Makefile und als AvrStudio-Projekt auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 Alte Versionen SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Man weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnisbaum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59565</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59565"/>
		<updated>2011-08-16T05:49:56Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Sourcen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip AVR Version 0.6.4] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme. Bei der Aktuellen Version ist Multi-block ungetestet.&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Achtung. Gefahr!&amp;lt;/u&amp;gt; Die Anschlussart mit einem normalen Pegelwandler wie im Bild rechts birgt jedoch die Gefahr der Zerstörung der SD Karte. Nämlich genau dann, wenn einmal (z.B. falsche Portdeklaration) versehentlich die MISO Leitung an 5V liegt oder wenn noch ein weiterer 5V-Teilnehmer am SPI Bus hängt und 5V Signale einspeist. Dann liegen am Datenausgang der SD Karte nämlich plötzlich 5V an, und das ist fatal. Besser und professioneller sind sog. birektionale Pegelwandler, die alle Datensignale in beide Richtungen von 5V &amp;lt;&amp;gt; 3,3V transferieren. Eine Bezugsquelle für ein fertiges Kartenmodul inkl. birektionalem Pegelwandler ist z.B. [http://www.shop.display3000.com/elektronikmodule/sd-kartenmodul/index.html Display3000]. Tipp: ganz an das Ende scrollen, dort gibt es ein paar anschauliche Informationen. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
* Hier immer die Aktuellste Version mit Informationen dazu [http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status FAT16/32].&lt;br /&gt;
&lt;br /&gt;
* Achtung! Nur noch alte Version im SVN.&lt;br /&gt;
&lt;br /&gt;
Sourcecode mit Linux Makefile und als AvrStudio-Projekt auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Man weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnisbaum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59564</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59564"/>
		<updated>2011-08-16T05:49:44Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Sourcen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip AVR Version 0.6.4] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme. Bei der Aktuellen Version ist Multi-block ungetestet.&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Achtung. Gefahr!&amp;lt;/u&amp;gt; Die Anschlussart mit einem normalen Pegelwandler wie im Bild rechts birgt jedoch die Gefahr der Zerstörung der SD Karte. Nämlich genau dann, wenn einmal (z.B. falsche Portdeklaration) versehentlich die MISO Leitung an 5V liegt oder wenn noch ein weiterer 5V-Teilnehmer am SPI Bus hängt und 5V Signale einspeist. Dann liegen am Datenausgang der SD Karte nämlich plötzlich 5V an, und das ist fatal. Besser und professioneller sind sog. birektionale Pegelwandler, die alle Datensignale in beide Richtungen von 5V &amp;lt;&amp;gt; 3,3V transferieren. Eine Bezugsquelle für ein fertiges Kartenmodul inkl. birektionalem Pegelwandler ist z.B. [http://www.shop.display3000.com/elektronikmodule/sd-kartenmodul/index.html Display3000]. Tipp: ganz an das Ende scrollen, dort gibt es ein paar anschauliche Informationen. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
* Hier immer die Aktuellste Version mit Informationen dazu &lt;br /&gt;
[http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status FAT16/32].&lt;br /&gt;
&lt;br /&gt;
* Achtung! Nur noch alte Version im SVN.&lt;br /&gt;
&lt;br /&gt;
Sourcecode mit Linux Makefile und als AvrStudio-Projekt auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Man weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnisbaum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59563</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59563"/>
		<updated>2011-08-16T05:49:08Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Sourcen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip AVR Version 0.6.4] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme. Bei der Aktuellen Version ist Multi-block ungetestet.&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Achtung. Gefahr!&amp;lt;/u&amp;gt; Die Anschlussart mit einem normalen Pegelwandler wie im Bild rechts birgt jedoch die Gefahr der Zerstörung der SD Karte. Nämlich genau dann, wenn einmal (z.B. falsche Portdeklaration) versehentlich die MISO Leitung an 5V liegt oder wenn noch ein weiterer 5V-Teilnehmer am SPI Bus hängt und 5V Signale einspeist. Dann liegen am Datenausgang der SD Karte nämlich plötzlich 5V an, und das ist fatal. Besser und professioneller sind sog. birektionale Pegelwandler, die alle Datensignale in beide Richtungen von 5V &amp;lt;&amp;gt; 3,3V transferieren. Eine Bezugsquelle für ein fertiges Kartenmodul inkl. birektionalem Pegelwandler ist z.B. [http://www.shop.display3000.com/elektronikmodule/sd-kartenmodul/index.html Display3000]. Tipp: ganz an das Ende scrollen, dort gibt es ein paar anschauliche Informationen. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Achtung! Nur noch alte Version im SVN.&lt;br /&gt;
* Hier immer die Aktuelle mit Informationen dazu [http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status FAT16/32].&lt;br /&gt;
Sourcecode mit Linux Makefile und als AvrStudio-Projekt auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Man weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnisbaum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59562</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=59562"/>
		<updated>2011-08-16T05:48:44Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Sourcen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip AVR Version 0.6.4] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme. Bei der Aktuellen Version ist Multi-block ungetestet.&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Achtung. Gefahr!&amp;lt;/u&amp;gt; Die Anschlussart mit einem normalen Pegelwandler wie im Bild rechts birgt jedoch die Gefahr der Zerstörung der SD Karte. Nämlich genau dann, wenn einmal (z.B. falsche Portdeklaration) versehentlich die MISO Leitung an 5V liegt oder wenn noch ein weiterer 5V-Teilnehmer am SPI Bus hängt und 5V Signale einspeist. Dann liegen am Datenausgang der SD Karte nämlich plötzlich 5V an, und das ist fatal. Besser und professioneller sind sog. birektionale Pegelwandler, die alle Datensignale in beide Richtungen von 5V &amp;lt;&amp;gt; 3,3V transferieren. Eine Bezugsquelle für ein fertiges Kartenmodul inkl. birektionalem Pegelwandler ist z.B. [http://www.shop.display3000.com/elektronikmodule/sd-kartenmodul/index.html Display3000]. Tipp: ganz an das Ende scrollen, dort gibt es ein paar anschauliche Informationen. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Achtung! Nur noch alte Version im SVN.&lt;br /&gt;
* Hier immer die Aktuelle mit Informationen dazu [http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status FAT16/32].&lt;br /&gt;
Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Man weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnisbaum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=58851</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=58851"/>
		<updated>2011-07-24T07:12:19Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* FAT 16/32 , die Bibliothek */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip AVR Version 0.6.4] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme. Bei der Aktuellen Version ist Multi-block ungetestet.&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Achtung. Gefahr!&amp;lt;/u&amp;gt; Die Anschlussart mit einem normalen Pegelwandler wie im Bild rechts birgt jedoch die Gefahr der Zerstörung der SD Karte. Nämlich genau dann, wenn einmal (z.B. falsche Portdeklaration) versehentlich die MISO Leitung an 5V liegt oder wenn noch ein weiterer 5V-Teilnehmer am SPI Bus hängt und 5V Signale einspeist. Dann liegen am Datenausgang der SD Karte nämlich plötzlich 5V an, und das ist fatal. Besser und professioneller sind sog. birektionale Pegelwandler, die alle Datensignale in beide Richtungen von 5V &amp;lt;&amp;gt; 3,3V transferieren. Eine Bezugsquelle für ein fertiges Kartenmodul inkl. birektionalem Pegelwandler ist z.B. [http://www.shop.display3000.com/elektronikmodule/sd-kartenmodul/index.html Display3000]. Tipp: ganz an das Ende scrollen, dort gibt es ein paar anschauliche Informationen. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Achtung! Nur noch alte Version im SVN.&lt;br /&gt;
Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Man weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnisbaum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=58850</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=58850"/>
		<updated>2011-07-24T06:50:07Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Der Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip AVR Version 0.6.4] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme. Bei der Aktuellen Version ist Multi-block ungetestet.&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen, oder um an eine Datei etwas anzuhängen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Achtung. Gefahr!&amp;lt;/u&amp;gt; Die Anschlussart mit einem normalen Pegelwandler wie im Bild rechts birgt jedoch die Gefahr der Zerstörung der SD Karte. Nämlich genau dann, wenn einmal (z.B. falsche Portdeklaration) versehentlich die MISO Leitung an 5V liegt oder wenn noch ein weiterer 5V-Teilnehmer am SPI Bus hängt und 5V Signale einspeist. Dann liegen am Datenausgang der SD Karte nämlich plötzlich 5V an, und das ist fatal. Besser und professioneller sind sog. birektionale Pegelwandler, die alle Datensignale in beide Richtungen von 5V &amp;lt;&amp;gt; 3,3V transferieren. Eine Bezugsquelle für ein fertiges Kartenmodul inkl. birektionalem Pegelwandler ist z.B. [http://www.shop.display3000.com/elektronikmodule/sd-kartenmodul/index.html Display3000]. Tipp: ganz an das Ende scrollen, dort gibt es ein paar anschauliche Informationen. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Achtung! Nur noch alte Version im SVN.&lt;br /&gt;
Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Man weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnisbaum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=56621</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=56621"/>
		<updated>2011-04-17T15:17:10Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Der Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/attachment/107226/mmc-0.6.3.1.zip Version 0.6.3.1] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme. Bei der Aktuellen Version ist Multi-block ungetestet.&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen, oder um an eine Datei etwas anzuhängen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Achtung. Gefahr!&amp;lt;/u&amp;gt; Die Anschlussart mit einem normalen Pegelwandler wie im Bild rechts birgt jedoch die Gefahr der Zerstörung der SD Karte. Nämlich genau dann, wenn einmal (z.B. falsche Portdeklaration) versehentlich die MISO Leitung an 5V liegt oder wenn noch ein weiterer 5V-Teilnehmer am SPI Bus hängt und 5V Signale einspeist. Dann liegen am Datenausgang der SD Karte nämlich plötzlich 5V an, und das ist fatal. Besser und professioneller sind sog. birektionale Pegelwandler, die alle Datensignale in beide Richtungen von 5V &amp;lt;&amp;gt; 3,3V transferieren. Eine Bezugsquelle für ein fertiges Kartenmodul inkl. birektionalem Pegelwandler ist z.B. [http://www.shop.display3000.com/elektronikmodule/sd-kartenmodul/index.html Display3000]. Tipp: ganz an das Ende scrollen, dort gibt es ein paar anschauliche Informationen. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Man weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnisbaum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=56620</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=56620"/>
		<updated>2011-04-17T15:13:48Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Der Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/attachment/107226/mmc-0.6.3.1.zip Version 0.6.3.1] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen, oder um an eine Datei etwas anzuhängen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Achtung. Gefahr!&amp;lt;/u&amp;gt; Die Anschlussart mit einem normalen Pegelwandler wie im Bild rechts birgt jedoch die Gefahr der Zerstörung der SD Karte. Nämlich genau dann, wenn einmal (z.B. falsche Portdeklaration) versehentlich die MISO Leitung an 5V liegt oder wenn noch ein weiterer 5V-Teilnehmer am SPI Bus hängt und 5V Signale einspeist. Dann liegen am Datenausgang der SD Karte nämlich plötzlich 5V an, und das ist fatal. Besser und professioneller sind sog. birektionale Pegelwandler, die alle Datensignale in beide Richtungen von 5V &amp;lt;&amp;gt; 3,3V transferieren. Eine Bezugsquelle für ein fertiges Kartenmodul inkl. birektionalem Pegelwandler ist z.B. [http://www.shop.display3000.com/elektronikmodule/sd-kartenmodul/index.html Display3000]. Tipp: ganz an das Ende scrollen, dort gibt es ein paar anschauliche Informationen. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Man weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnisbaum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Datenbereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektornummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordnernamen ist das gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Datenbereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei-Eintrag und in die Nutzdaten der Datei (alles im Datenbereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1. Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=50938</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=50938"/>
		<updated>2010-09-27T11:14:40Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* FAT 16/32 , die Bibliothek */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei software SPI läuft die Initialisierung nicht mit 400 KHz, das gibt bei einigen Karten Probleme&amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen/schließen, oder um an eine Datei etwas anzuhängen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=MMC-_und_SD-Karten&amp;diff=50762</id>
		<title>MMC- und SD-Karten</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=MMC-_und_SD-Karten&amp;diff=50762"/>
		<updated>2010-09-19T09:28:28Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Bibliotheken zur Ansteuerung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MMC- und SD-Speicherkarten lassen sich im [[SPI]]-Modus relativ einfach mit einem Mikrocontroller ansteuern. Prinzipiell git es zwischen SD-Card und MMC nicht viele Unterschiede, allerdings sind SD-Karten weiter verbreitet, in der Regel schneller als MMCs, und haben eine besser implementiertes SPI-Interface. Es existieren diverse Varianten (miniSD, microSD) die zur normalen SD-Card kompatibel sind.&lt;br /&gt;
&lt;br /&gt;
Die Karte liest das anliegende Datenbit mit der steigenden Taktflanke ein, als SPI-Modi eignen sich somit Mode 0 (CPOL=0, CPHA=0) und Mode 3 (CPOL=1, CPHA=1) (siehe auch [[Serial Peripheral Interface]]). Bei MMCs ist der SPI-Modus nicht genau spezifiziert, somit kommt es durchaus mal vor dass der SPI-Modus je nach Karte unterschiedlich gewählt werden muss, oder dass die Karte überhaupt nicht zuverlässig funktioniert (siehe [http://www.mikrocontroller.net/forum/read-1-343528.html Beitrag im Forum]).&lt;br /&gt;
&lt;br /&gt;
== DOs und DON&#039;Ts bei der Ansteuerung ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Lasst euch nicht verrückt machen&#039;&#039;&#039; wenn es einfach nicht funktioniert, sondern probiert zu allererst mal eine SD-Karte eines anderen Herstellers aus. Die MMC-Implementierung für AVR von Elm Chan z.&amp;amp;nbsp;B. funktioniert mit SanDisk problemlos hat aber mit Platinum Karten ein Problem.&lt;br /&gt;
* Taktfrequenz bei der Initialisierung nicht höher als 400kHz&lt;br /&gt;
* Ein Pullup-Widerstand am Ausgang der MMC/SD Karte (DO) ist für eine saubere Initialisierung per SPI notwendig! [http://www.mikrocontroller.net/topic/112421#1001693 (Thread mit Erklärung dazu)]&lt;br /&gt;
* Saubere Versorgung: Kein Dioden-Pfusch, mit dem eine vorhandene 5V Versorgung mittels in Reihe geschalteter Dioden auf irgendwas im Bereich 3V &amp;quot;geregelt&amp;quot; wird. Stattdessen einen guten 3,3V-Regler verwenden. Die Karte mag es nicht, wenn mehr als 60mV Ripple auf Vcc ist. LM317 oder LM1117-ADC/-3.3 mit entspechenden Kondensatoren reicht zumindest bei Basteleien allemal.&lt;br /&gt;
* Sauberer Anschluss der Digitalschnittstelle: Spannungsteiler &amp;quot;verschleifen&amp;quot; die Signale bei hohen Frequenzen und die Übertragungsrate muss dann begrenzt werden. Also entweder ein [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler] oder gleich an ein 3,3V I/O anschließen.&lt;br /&gt;
* Ein Pullup-Widerstand an der Select-Leitung (/CS) schadet nicht und stellt sicher, dass die Karte erst mit Absicht selektiert wird.&lt;br /&gt;
* 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).&lt;br /&gt;
* Die Karten verfügen weder über einen Reset- noch einen Sleep-Anschluss. Moderne Karten reduzieren bei Nichtbenutzung ihren Stromverbrauch, einen vollständigen Reset kann man jedoch nicht per Software auslösen. Daher sollten die Karten per P-Channel-FET oder Spannungsregler/-wandler mit Enable-Funktion so angeschlossen werden, dass über Versorgung an/aus ein (Power-On-)Reset ausgelöst werden kann. Dabei darauf achten, dass vorhandene Pull-Up-Widerstände bei abgeschalteter Versorgung ebenfalls deaktiviert werden (vgl. z.&amp;amp;nbsp;B. Schaltplan für den Anschluss von SD-Card/MMC per SPI an AVR in Chans Beispielen. Link unten).&lt;br /&gt;
* Guter Kontakt im Steckplatz, sehr gut eignen sich mit der Zange verbogene Stiftleisten, oft sieht es aus als ob es &amp;quot;passt&amp;quot;, aber es gibt doch keinen Kontakt, daher bei Fehlern: Immer Durchmessen! Auch zu erwähnen wären da alte ISA-Bus Buchsen, die auf jedem alten PC Mainboard drauf sind. Um sicher zu gehen, dass der Kontakt wirklich gut ist, sollte man aber trotzdem SD-Slots benutzen. Diese bekommt man u.a. bei CSD (günstig), Reichelt (teuer) oder aus alten Kartenlesern.&lt;br /&gt;
* Guter Kontakt #2: Was sich im übrigen auch sehr gut eignet sind Adapter von MiniSD auf normales SD-Format, um dann MiniSD zu benutzen. Wenn man eine Stiftleiste im 2.54mm-Format oder Lötnägel im selben Format auf der Platine hat, kann man daran wunderbar den SD-Kartenadapter anlöten. Das ist mechanisch recht stabil. Ein kleines Manko ist allerdings, daß dann eine Gold-Lötzinn-Legierung durch die vergoldeten Kontakte entsteht und das soll ja dem Lötzinn langfristig nicht sehr zuträglich sein. Aber für&#039;s Hobby funktioniert das wunderbar.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
||[[Bild:SD Steck Stift.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;sup&amp;gt;(Liefere Bild in besserer Qualität nach!)&amp;lt;/sup&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bibliotheken zur Ansteuerung ==&lt;br /&gt;
&lt;br /&gt;
* [http://elm-chan.org/fsw/ff/00index_e.html ELM ChaN FatFs]  FAT(12,16,32)-Dateisystem. Klein und übersichtlich, hochoptimiert, frei auch für kommerzielle Anwendung. Beispiele für AVR, H8, LPC2k mit MCI u.a. enthalten (&amp;quot;samples&amp;quot;), neuere Versionen mit LFN-Unterstützung. Beispiel für AT91SAM7 inkl. DMA im Projekt [[ARM MP3/AAC Player]].&lt;br /&gt;
&lt;br /&gt;
* [http://elm-chan.org/fsw/ff/00index_e.html ELM ChaN Petit FatFS] FAT(12,16,32)-Dateisystem. Sehr klein. Beispiele für AVR.&lt;br /&gt;
&lt;br /&gt;
* [http://sourceforge.net/projects/efsl EFSL] FAT16/32-Dateisystem, unterstützt Partitionen und Superfloppys, Beispielcode für AVR, LPC2000 und AT91SAM7 enthalten (siehe auch [http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/efsl_arm/ M. Thomas&#039; ARM+SD/MMC Seite])&lt;br /&gt;
&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#cf Holger Klabundes FAT16/32] mit Beispielen für AVR MMC/SD und CF, LPC2k mit SPI&lt;br /&gt;
&lt;br /&gt;
* libfat aus dem [http://sourceforge.net/projects/devkitpro devkitpro-Projekt] u.a. LFN-Unterstützung.&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikro-control.de/Joomla/index.php?option=com_content&amp;amp;task=view&amp;amp;id=18&amp;amp;Itemid=30 SD-Logger] - FAT 16, für den privaten Einsatz kostenfrei&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-4-125350.html MMC-Ansteuerung mit FAT16 von Ulrich Radig]&lt;br /&gt;
&lt;br /&gt;
* [http://www.zws.com/products/dosfs/index.html DOSFS Free FAT12/FAT16/FAT32 Filesystem] &amp;quot;DOSFS is a free FAT-compatible filesystem intended for fairly low-end embedded applications. Intended target systems would be in the ballpark of 1K RAM, 4K ROM or more&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/48481 MMC/SD-Karte mit FAT16 an AVR] von Roland Riegel&lt;br /&gt;
&lt;br /&gt;
* [ftp://ftp.circuitcellar.com/pub/Circuit_Cellar/2005/176/Sham176.zip Circuit Cellar FAT16 MMC/SD] mit MMC/SD Hardwaretreiber für MSP430&lt;br /&gt;
&lt;br /&gt;
* [http://www.analog.com &amp;quot;Implementing FAT32 File Systems on ADSP-BF533 Blackfin Processors&amp;quot;] Application Note und Code von ADI&lt;br /&gt;
&lt;br /&gt;
* [http://www.atmel.com/dyn/products/tools.asp?family_id=682 FAT-Code in Atmel&#039;s AVR32 UC3 Software-Library]&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/FAT32 AVR FAT16/32] Bibliothek mit Wiki. Unterstützt LFN und Ordner Rekursiv löschen. SVN für neuste Version.&lt;br /&gt;
&lt;br /&gt;
* [http://www.embedded-os.de/index.html?pcfat_port.htm pC/FAT driver] &amp;quot;using SPI for sector read/write to MMC/MMCplus/HD-MMC/M-Bridge/SD/SDHC-cards on different platforms&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* [http://www.dharmanitech.com/2009/01/sd-card-interfacing-with-atmega8-fat32.html SD Card Interfacing with ATmega8] (FAT32 implementation) by CC Dharmani&lt;br /&gt;
* [[AVR FAT32]]&lt;br /&gt;
&lt;br /&gt;
== Allgemeine Informationen ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.digitalspirit.org/file/index.php/obj/docs/sd/ Datenblätter] ( [http://www.digitalspirit.org/file/index.php/obj-download/docs/sd/ProductManualSDCardv2.2final.pdf SD Card Product Manual 2.2] )&lt;br /&gt;
&lt;br /&gt;
* [http://elm-chan.org/docs/mmc/mmc_e.html ELM ChaN - How to Use an MMC]&lt;br /&gt;
&lt;br /&gt;
* [http://elm-chan.org/fsw/ff/00index_e.html ELM ChaN - MMC/SD Benchmarks]&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/list-1-1.html?filter=MMC*+SD Beiträge zum Thema MMC/SD im Forum (ca. 200 Threads)]&lt;br /&gt;
&lt;br /&gt;
* [http://www.shop.display3000.com/pi8/pi14/pd102.html Weiter unten im Text (runterscrollen) gibt es interessante Oszi-Bilder zu den oft genannten Spannungsteilern oder Transistorlösungen als Pegelwandler]&lt;br /&gt;
&lt;br /&gt;
* [http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;amp;nodeId=2680&amp;amp;dDocName=en547784 Microchip Memory Disk Drive System mit FAT32 und SDHC Unterstützung]&lt;br /&gt;
&lt;br /&gt;
* [http://www.ifas.htwk-leipzig.de/easytoweb/download/D&amp;amp;E_11_2006_Anbindung_von_SD-Karten.pdf Gute Beschreibung der SDIO-Architektur und wie man eine SD-Karte mit ARM bzw. AVR benutzt]&lt;br /&gt;
&lt;br /&gt;
== Bauteile ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.instructables.com/id/EZD6Q18LYGES1762SJ/ DIY SD-Card Fassung aus einem alten Floppy Kabel]&lt;br /&gt;
&lt;br /&gt;
* [http://www.watterott.com/index.php?page=search&amp;amp;page_action=query&amp;amp;desc=on&amp;amp;sdesc=on&amp;amp;keywords=multicomp&amp;amp;x=0&amp;amp;y=0 Halter für SD-Karten] (Shop www.watterott.com)&lt;br /&gt;
&lt;br /&gt;
== Projekte ==&lt;br /&gt;
&lt;br /&gt;
* [http://retromaster.wordpress.com/ufe/ Ultimate Floppy Emulator] von Retromaster (PIC32 @ 80 Mhz, 16 Mb SDRAM)&lt;br /&gt;
&lt;br /&gt;
[[Category:Bauteile]]&lt;br /&gt;
[[Category:Datenübertragung]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=49684</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=49684"/>
		<updated>2010-08-04T12:41:12Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Einfaches Code Beispiel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
* Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
* Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
* Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
*[http://www.mikrocontroller.net/wikifiles/0/0c/Wiki.pdf Diese Seite als PDF.]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* Das File-Modul, bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das FAT16/32-Modul, bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Das MMC/SD-Modul, ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SDHC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [[AVR_-_Die_genaue_Sekunde_/_RTC|RTC]] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [[Serial_Peripheral_Interface|SPI]] oder Hardware SPI&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [[AVR_FAT32#Interne_Technik|Interne Technik]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [[AVR_FAT32#Sourcen|Sourcen]]. Ein einfaches Beispiel auch unter [[AVR_FAT32#Einfaches_Code_Beispiel|Code Beispiel]].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [[MMC- und SD-Karten]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [[Pegelwandler]].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [[Serial_Peripheral_Interface|SPI]]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [[AVR_FAT32#Die_Funktionalit.C3.A4t|Link]]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig.&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten.&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen.&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[9]=&amp;quot;test.txt&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[13]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String.&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei.&lt;br /&gt;
             // Schreibt Zeilenumbruch in die Text Datei.&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei.&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([[AVR_FAT32#Die_FAT|Bild 2]]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintrag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [[AVR_FAT32#Die_FAT|Bild 2]]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [[AVR_FAT32#Sektor_0_oder_LBA|Bild 1]]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [[AVR_FAT32#Daten|Bild 3]]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47280</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47280"/>
		<updated>2010-05-07T11:59:54Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Der Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread.]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.mikrocontroller.net/wikifiles/0/0c/Wiki.pdf Diese Seite als PDF.]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47279</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47279"/>
		<updated>2010-05-07T11:58:38Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Der Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.mikrocontroller.net/wikifiles/0/0c/Wiki.pdf Diese Seite als PDF]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Wiki.pdf&amp;diff=47278</id>
		<title>Datei:Wiki.pdf</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Wiki.pdf&amp;diff=47278"/>
		<updated>2010-05-07T11:57:00Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47277</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47277"/>
		<updated>2010-05-07T11:56:24Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Der Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Seite als PDF [[Datei:wiki.pdf]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47276</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47276"/>
		<updated>2010-05-07T11:55:50Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Der Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&amp;lt;br&amp;gt;&lt;br /&gt;
[Datei:wiki.pdf Diese Seite als PDF]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47275</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47275"/>
		<updated>2010-05-07T11:54:47Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Der Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
[wiki.pdf Diese Seite als PDF]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47270</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47270"/>
		<updated>2010-05-07T11:39:11Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* FAT 16/32 , die Bibliothek */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47269</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47269"/>
		<updated>2010-05-07T11:38:06Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Der Status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47267</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47267"/>
		<updated>2010-05-07T10:16:56Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Funktionsübersichts Diagramm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel, ältere Version der Lib. Viele der Funktionen enden in Schreiboperationen, weil das Diagramm mit der Option &amp;quot;MMC_OVER_WRITE TRUE&amp;quot; erstellt wurde.&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47266</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47266"/>
		<updated>2010-05-07T10:12:37Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Bedeutung der Schalter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben/gelesen wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B.&lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47265</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47265"/>
		<updated>2010-05-07T10:10:25Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Einfaches Code Beispiel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst endet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47264</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47264"/>
		<updated>2010-05-07T10:06:10Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Root Dir */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über Sektor 0 bekannt und ab dem Root-Dir spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47263</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47263"/>
		<updated>2010-05-07T10:03:57Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Daten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32 Bytes = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47262</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47262"/>
		<updated>2010-05-07T09:59:12Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* FAT 16/32 , die Bibliothek */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Der größte Teil der des FAT Protokolls ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet high-level Datei Operationen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über #defines in der config.h den Umfang der Lib zu bestimmen, dies wirkt sich auch extrem auf die Codegröße aus.&lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47261</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47261"/>
		<updated>2010-05-07T09:55:22Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Einfaches Code Beispiel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47260</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47260"/>
		<updated>2010-05-07T09:50:24Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Schreiben */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47259</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47259"/>
		<updated>2010-05-07T09:50:06Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Lesen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47258</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47258"/>
		<updated>2010-05-07T09:49:03Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Interne Technik */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47257</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47257"/>
		<updated>2010-05-07T09:48:11Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Interne Technik */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47256</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47256"/>
		<updated>2010-05-07T09:46:13Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Die Funktionalität */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Vor- und Rückspulen in Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47255</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47255"/>
		<updated>2010-05-07T09:32:02Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Die Funktionalität */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47254</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47254"/>
		<updated>2010-05-07T09:31:28Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Die Funktionalität */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47253</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47253"/>
		<updated>2010-05-07T09:26:18Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Schaltplan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah an ICs). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47252</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47252"/>
		<updated>2010-05-07T09:25:31Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD/SDHC */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png SD/SDHC/MMC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/SDHC/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47250</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47250"/>
		<updated>2010-05-07T09:24:21Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD/SDHC ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47249</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47249"/>
		<updated>2010-05-07T09:23:32Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|500px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47248</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47248"/>
		<updated>2010-05-07T09:23:00Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|550px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|550px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47247</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47247"/>
		<updated>2010-05-07T09:22:35Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/5/50/Mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47246</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47246"/>
		<updated>2010-05-07T09:21:35Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:mmc_sd.png|450px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/archive/c/ca/20100507023809!Pinout_mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Mmc_sd.png&amp;diff=47245</id>
		<title>Datei:Mmc sd.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Mmc_sd.png&amp;diff=47245"/>
		<updated>2010-05-07T09:19:50Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:Pinout_mmc_sd.png&amp;diff=47244</id>
		<title>Datei:Pinout mmc sd.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:Pinout_mmc_sd.png&amp;diff=47244"/>
		<updated>2010-05-07T09:16:30Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: hat eine neue Version von „Datei:Pinout mmc sd.png“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47243</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47243"/>
		<updated>2010-05-07T09:15:53Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:pinout_mmc_sd.png|thumb|right|250px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/archive/c/ca/20100507023809!Pinout_mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47237</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47237"/>
		<updated>2010-05-07T02:43:05Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:Pinout_mmc_sd.png|thumb|right|250px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/archive/c/ca/20100507023809!Pinout_mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47236</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47236"/>
		<updated>2010-05-07T02:42:53Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:Pinout_mmc_sd.png|thumb|right|250px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/archive/c/ca/20100507023809!Pinout_mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47235</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47235"/>
		<updated>2010-05-07T02:42:39Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:Pinout_mmc_sd.png|thumb|right|250px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/archive/c/ca/20100507023809!Pinout_mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47234</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47234"/>
		<updated>2010-05-07T02:42:21Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:Pinout_mmc_sd.png|thumb|right|250px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/archive/c/ca/20100507023809!Pinout_mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47233</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47233"/>
		<updated>2010-05-07T02:41:48Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
[[Bild:Pinout_mmc_sd.png|thumb|right|250px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/archive/c/ca/20100507023809!Pinout_mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]] &lt;br /&gt;
&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47232</id>
		<title>AVR FAT32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_FAT32&amp;diff=47232"/>
		<updated>2010-05-07T02:41:27Z</updated>

		<summary type="html">&lt;p&gt;Zerrome: /* Pinbelegung MMC/SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Der Status ==&lt;br /&gt;
&lt;br /&gt;
Aktuelle Version: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN-Repository] &amp;lt;br&amp;gt;&lt;br /&gt;
Bekannte Probleme: Bei [http://de.wikipedia.org/wiki/Byte-Reihenfolge Big Endian] Controllern müssen größere Anpassungen gemacht werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Problem melden, oder sonstige Anfrage: [http://www.mikrocontroller.net/user/show/zerrome Persönliche Nachricht], oder auch hier [http://www.mikrocontroller.net/topic/105869#new Thread]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 16/32 , die Bibliothek ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Mod.jpeg|thumb|right|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schichtmodell] der Lib&#039;&#039;&#039;]]&lt;br /&gt;
Dies ist eine freie FAT 16 / 32 Bibliothek.&lt;br /&gt;
&lt;br /&gt;
Die Bibliothek ist modular und besteht aus folgenden Modulen:&lt;br /&gt;
&lt;br /&gt;
* File&lt;br /&gt;
* FAT16/32  &lt;br /&gt;
* MMC/SD    (hardwareabhängig)&lt;br /&gt;
&lt;br /&gt;
Das MMC/SD-Modul ist dafür zuständig, die Kommunikation mit [[MMC- und SD-Karten]] zu managen. Wie z.&amp;amp;nbsp;B. Initialisierung der Karte oder low-level Routinen zum schreiben auf die Karte. Es ist das einzige Hardware abhängige Modul.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das FAT16/32-Modul bietet die grundlegenden Funktionen für den FAT-Zugriff und die Initialisierung der FAT. Es dient als Middleware zwischen low-level Karten Zugriff und high-level Datei Operationen. Das ganze FAT Protokoll ist dort implementiert.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das File-Modul bietet Funktionen wie man sie von Dateizugriffen kennt, wie z.&amp;amp;nbsp;B. ffopen/ffclose um eine Datei zu öffnen oder um an eine Datei etwas anzuhängen und diese wieder zu schließen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt die Möglichkeit über defines in der config.h den Umfang der Lib zu bestimmen. &lt;br /&gt;
&lt;br /&gt;
Die Module sind [http://en.wikipedia.org/wiki/C_(programming_language)#C99 c99] C-Standard Konform .&lt;br /&gt;
&lt;br /&gt;
=== Code einbinden ===&lt;br /&gt;
&lt;br /&gt;
Die Module werden über die *.h Dateien bekannt gemacht. Zudem müssen noch die dazugehörigen *.c Dateien eingebunden werden. Es gibt mehrere Möglichkeiten dies zu tun. Einmal im Makefile im Bereich der &amp;quot;c source files&amp;quot; oder bei &lt;br /&gt;
[http://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung IDEs] &lt;br /&gt;
über einen Dialog der das Gleiche macht.&lt;br /&gt;
&lt;br /&gt;
=== Die Funktionalität ===&lt;br /&gt;
&lt;br /&gt;
In der Datei config.h gibt es Möglichkeiten die Bibliothek zu konfigurieren.&amp;lt;br&amp;gt; &lt;br /&gt;
Folgende Funktionen werden unterstützt (FAT16/32):&amp;lt;br&amp;gt;&lt;br /&gt;
* Lesen, Schreiben und Überschreiben von Dateien.&amp;lt;br&amp;gt;&lt;br /&gt;
* Löschen von Dateien und Ordnern, bei Ordnern Rekursiv.&amp;lt;br&amp;gt;&lt;br /&gt;
* Schnelleres Schreiben und Lesen durch Multi-Block Operationen.&amp;lt;br&amp;gt;&lt;br /&gt;
* Kartenunterstützung für MMC/SD/[http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SHDC].&amp;lt;br&amp;gt;&lt;br /&gt;
* Falls eine [http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC RTC] vorhanden ist, kann bei den Dateioperationen die Zeitstempel Funktionalität genutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
* Anbindung der Karte über Software [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI] oder Hardware [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]&amp;lt;br&amp;gt;&lt;br /&gt;
* Ermitteln der freien Bytes auf der Karte &amp;lt;br&amp;gt;&lt;br /&gt;
* Anlegen von Ordnern &amp;lt;br&amp;gt;&lt;br /&gt;
* Wechseln von Verzeichnissen &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Die Schalter ====&lt;br /&gt;
Hier ein Auszug aus der config.h mit den wichtigsten Parametern: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define MMC_SMALL_FILE_SYSTEM 	TRUE&lt;br /&gt;
#define MMC_WRITE		TRUE	&lt;br /&gt;
#define MMC_OVER_WRITE 		FALSE&lt;br /&gt;
#define MMC_MULTI_BLOCK 	FALSE&lt;br /&gt;
#define MMC_SDHC_SUPPORT	TRUE&lt;br /&gt;
#define MMC_TIME_STAMP 		FALSE&lt;br /&gt;
 &lt;br /&gt;
#define MMC_MAX_SPEED 		TRUE&lt;br /&gt;
&lt;br /&gt;
#define MMC_SOFT_SPI 		FALSE&lt;br /&gt;
&lt;br /&gt;
#define MMC_MAX_CLUSTERS_IN_ROW 256&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bedeutung der Schalter ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SMALL_FILE_SYSTEM TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt den Funktionsumfang der Lib. Es Fallen Folgende Funktionalitäten raus: ffcd(), fat_str(), ffls(), ffcdLower(), ffmkdir() und ffrm() der Teil mit Ordnern rekursiv löschen. (&#039;&#039;&#039;FALSE&#039;&#039;&#039; = Komplette Unterstützung)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob schreib Unterstützung einkompiliert wird oder nicht. (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Write an)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_OVER_WRITE TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; bestimmt ob ffwrite() mit Überschreiben Funktionalität Kompiliert wird oder nicht. Überschreiben von Dateien ist nicht so performant. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik] (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = Dateien überschreiben)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MULTI_BLOCK TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest ob mit MultiBlock Read/Write Unterstützung Kompiliert wird oder nicht. Geht nur wenn &#039;&#039;&#039;OVER_WRITE FALSE&#039;&#039;&#039; ist! (&#039;&#039;&#039;TRUE&#039;&#039;&#039; = MultiBlock Operation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_SPEED TRUE&#039;&#039;&#039;,  oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob nach der Initialisierung der MMC/SD Karte mit maximalem Speed geschrieben wird oder nicht. Zum testen wenn man nicht sicher ist ob die Hardware die maximale Geschwindigkeit mit macht empfiehlt sich &#039;&#039;&#039;FALSE&#039;&#039;&#039; als Wert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_MAX_CLUSTERS_IN_ROW&#039;&#039;&#039; 1-500, gibt an, wie viele Cluster, leer oder Verkettet die zusammenhängen, gesucht werden sollen. Hier muss man den Overhead des Suchens abwägen, gegen die Zeit, die z.&amp;amp;nbsp;B. benötigt wird 500 Cluster in der Fat zu verketten. Siehe auch: [http://www.mikrocontroller.net/articles/AVR_FAT32#Interne_Technik Interne Technik]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SDHC_SUPPORT TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit SDHC Unterstützung Kompiliert wird oder ohne. Der [http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29 SD Standard 2.0] wird damit unterstützt, also Karten bis 32 GB Größe.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_TIME_STAMP TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob die Zeitstempel Unterstützung mit kompiliert wird oder nicht. Wenn TRUE, dann wird das Erstelldatum und die Erstellzeit eingetragen. Bei weiteren Schreibzugriffen auf die Datei wird dann auch das Zugriffsdatum und die Zugriffszeit eingetragen. Es müssen dafür auch 2 Funktionen in der fat.c mit Code gefüllt werden, damit diese das Datum und die Zeit liefern.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MMC_SOFT_SPI TRUE&#039;&#039;&#039;, oder &#039;&#039;&#039;FALSE&#039;&#039;&#039; legt fest, ob mit Software SPI Unterstützung kompiliert wird, oder nicht. Wenn &#039;&#039;&#039;TRUE&#039;&#039;&#039;, muss in der mmc.h noch eingetragen werden welche Pins als SPI Interface benutzt werden sollen. Es werden nur Pins des selben Ports unterstützt. Also z.&amp;amp;nbsp;B. nur Pins von Port B. &lt;br /&gt;
&lt;br /&gt;
==== Die C Funktionen ====&lt;br /&gt;
&lt;br /&gt;
Das Modul FILE bietet in der Standard-Konfiguration folgende für den Nutzer interessante Funktionen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char ffread(void)&lt;br /&gt;
void          ffwrite(unsigned char c)&lt;br /&gt;
void          ffwrites(unsigned char *s )&lt;br /&gt;
unsigned char ffopen(unsigned char name[])&lt;br /&gt;
unsigned char ffclose(void)&lt;br /&gt;
void          ffseek(unsigned long int offset)&lt;br /&gt;
unsigned char ffcd(unsigned char name[])&lt;br /&gt;
void          ffls(fptr uputs_ptr)&lt;br /&gt;
unsigned char ffcdLower(void)&lt;br /&gt;
unsigned char ffrm(unsigned char name[])&lt;br /&gt;
unsigned char ffmkdir(unsigned char name[])&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul MMC/SD bietet für den Nutzer direkt nur eine interessante Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char mmc_init(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Modul FAT bietet für den Nutzer direkt nur zwei interessante Funktionen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
unsigned char fat_loadFatData(void)&lt;br /&gt;
unsigned long long int fat_getFreeBytes(void)&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Anwendungen der Funktionen gibt es Beispiele, Kommentare und Dokumentation in den [http://www.mikrocontroller.net/articles/AVR_FAT32#Sourcen Sourcen]. Ein einfaches Beispiel auch unter [http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel Code Beispiel].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle Funktionen, die mit FAT-Namen in Zusammenhang stehen (Datei- und Ordner-Namen), müssen folgende Konvention erfüllen: &amp;lt;br&amp;gt;&lt;br /&gt;
Die FAT-Namenskonvention ist immer 8.3, das heißt, ein Datei-Name mit maximal 8 Zeichen und eine Datei-Endung mit maximal 3 Zeichen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ein Dateiname &amp;quot;test.txt&amp;quot; MUSS in &amp;quot;TEST&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;TXT&amp;quot; gewandelt werden! Noch ein Beispiel: &amp;quot;MAIN&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;C&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot; = &amp;quot;main.c&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Nur vFAT erfüllt lange Datei-Namen !&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interne Technik ===&lt;br /&gt;
&lt;br /&gt;
In der Regel wird das [http://www.mikrocontroller.net/wikifiles/e/e9/Mod.jpeg Schicht-Modell] eingehalten. Das heißt, jedes Modul nutzt nur die Funktionen aus der Schicht darunter, es gibt allerdings Ausnahmen, aus Gründen der Code-Größe. Beispiel : ffwrite nutzt direkt die Funktion mmc_write_sector(sector); aus dem Modul mmc.c. Aufgrund der Namens-Konvention ist aber leicht zu erkennen, woher die Funktion kommt.&lt;br /&gt;
&lt;br /&gt;
 mmc → mmc.c&lt;br /&gt;
 fat → fat.c&lt;br /&gt;
 ff  → file.c&lt;br /&gt;
&lt;br /&gt;
Es gibt in dem Modul fat, &amp;quot;Daten-Ketten&amp;quot;. Die Aufgaben sind atomar aufgeteilt. Zum lesen von Daten sind beispielsweise die Funktionalitäten, lesen eines Sektors, auswerten der Information und weitere Entscheidung (nächsten Sektor laden usw.) nötig. Die Idee dabei ist gewesen, die Funktionen der atomaren Aufgabe nach zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Beispielkette:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
fat_loadSector -&amp;gt; fat_loadRowOfSector -&amp;gt; fat_loadFileDataFromCluster -&amp;gt; fat_loadFileDataFromDir [-&amp;gt; fat_cd]&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Diese Kette wird beispielsweise beim Öffnen einer Datei durchlaufen. Um die Datei zu öffnen, muss man wissen ob es die Datei im aktuellen Verzeichnis gibt. Um das herauszufinden, muss man den ersten Sektor des Verzeichnisses laden. Dann muss man die Reihen (immer 32 Byte am Stück), also Datei/Ordner-Einträge des Sektors prüfen. Da ein Cluster aus verschiedenen Sektoren bestehen kann, müssen diese auch geprüft werden. Als letzte logische Einheit müssen jetzt noch die verketteten Cluster geprüft werden, also das ganze Verzeichnis. Ist diese Kette so durchlaufen, weiß man, ob die Datei da ist oder nicht.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen ====&lt;br /&gt;
Beim lesen, einer Datei wird in der FAT nach verketteten Clustern gesucht. Bei einer unfragmentierten FAT liegen im Idealfall alle Cluster in einer Reihe. Dies wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
Es wird der erste Cluster der Datei gesucht und solange gesucht, bis MAX_CLUSTERS_IN_ROW am Stück gefunden wurden, oder ein Abbruch der Kette erkannt wird. Wird ein Abbruch erkannt, wird erstmal das bekannte Teilstück der kompletten Kette gelesen, danach wird das nächste Teilstück gesucht. Bis die ganze Kette durchlaufen wurde. &amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer unfragmentierten Fat kann man oft die ganze Datei lesen ohne einen weiteren Fat lookup, das ist extrem effizient!&lt;br /&gt;
&lt;br /&gt;
==== Schreiben ====&lt;br /&gt;
Beim schreiben, einer Datei wird in der FAT nach leeren Clustern gesucht. Bei einer unfragmentierten FAT liegen diese im Idealfall alle nebeneinander. Das wird ausgenutzt:&lt;br /&gt;
&lt;br /&gt;
# Es werden ab Cluster Nr. 2, MAX_CLUSTERS_IN_ROW am Stück gesucht, oder so viele, wie es freie am Stück gibt.&lt;br /&gt;
# Diese werden beschrieben (also die Sektoren die mit diesen Clusternummern in Zusammenhang stehen). Sind genügend freie für die Datei Daten bekannt, werden die Cluster verkettet und man ist fertig.&lt;br /&gt;
# Sind nicht genügend freie bekannt, wird die erste Teil Kette verkettet und die letzte Cluster Nummer dieser Kette gesichert (file.lastCluster). Jetzt werden wieder neue gesucht.&lt;br /&gt;
# Sind jetzt immer noch nicht genügend freie Cluster bekannt, werden die beiden Teilketten verkettet (wo die alte aufhört weiß man durch file.lastCluster). Weiter bei 2.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Bei beiden Methoden&#039;&#039; kann es zu größerem [http://de.wikipedia.org/wiki/Overhead_(EDV) Overhead] kommen, wenn die FAT fragmentiert ist. Im Extremfall ist immer nur ein Cluster am Stück frei bzw. verkettet.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsübersichts Diagramm ===&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/49287/FunktionsUebersichtsDiagramm.jpeg (Link)]    Größe: 2412 x&lt;br /&gt;
7946 Pixel (ältere Version der Lib)&lt;br /&gt;
&lt;br /&gt;
=== Die Richtlinien ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allgemein:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es ist immer darauf zu achten, dass es sich bei MMC/SD-Karten um Flash-Speicher handelt, dieser ist NICHT unendlich oft beschreibbar. Die Schreiben/Anhängen- und Löschen- Funktionalitäten sollten so selten wie möglich benutzt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Eine SD Karte besitzt einen eigenen Controller in der Karte, der auf den eigentlichen Flash-Speicher schreibt. So können die logischen von den physikalischen Sektoren getrennt werden (Wear Leveling). Also gibt es nicht so viele Schreib Vorgänge auf dem gleichen Sektor, weil der Karten Controller den logischen Sektor auf einen anderen physikalischen schreibt. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Auch: [http://de.wikipedia.org/wiki/SD_Memory_Card Wikipedia SD Karten] , und [http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten MMC- und SD-Karten].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Richtlinien stable-mmc-0.5.x:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wenn eine Datei zum schreiben geöffnet ist, aber gerade keine Daten zum schreiben vorliegen, bringt es keinen Vorteil (Strom oder Geschwindigkeit) die Datei zu schießen, wenn später noch Daten geschrieben werden sollen. Bei jedem ffclose, wird der Datei Eintrag geupdatet, also dieser Sektor geschrieben (möglicherweise zusätzlich sogar ein FAT Sektor).&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oftmaliges anlegen und löschen einer Datei schreibt immer die selben (logischen) Sektoren. Besser nicht löschen und einfach neu anlegen, mit anderem Namen, oder überschreiben, da dabei die schon verketteten FAT Sektoren nicht nochmals beschrieben werden, sondern nur die Daten Sektoren überschrieben werden. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Beispiel Beschaltung==&lt;br /&gt;
&lt;br /&gt;
=== Schaltplan ===&lt;br /&gt;
[[Bild:Schaltplan.jpeg|thumb|right|260px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/9/93/Schaltplan.jpeg Schaltplan]&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
MMC/SD-Karten brauchen 3,3 Volt. Wenn der Controller mit 5 Volt arbeitet, muss man die Spannungspegel anpassen. Arbeitet der Controller auch mit 3,3 Volt kann man alle Leitungen direkt mit der Karte verbinden. &amp;lt;br&amp;gt;&lt;br /&gt;
Als Beispiel für die mögliche Frequenz des hier verwendeten HC4050 zur Pegelwandlung: bei +125 °C und VCC von 2 V wird das Propagationdelay mit Max 130 ns angegeben. Das macht ungefähr 7,6 Mhz Maximal mögliche Frequenz. Bis +85 °C und VCC von 2 V geht es bis 9,5 Mhz. Da aber hier 3,3 Volt anliegen wird er in allen Bereichen etwas schneller sein.&amp;lt;br&amp;gt;&lt;br /&gt;
Siehe Datenblatt für mehr Infos oder [http://www.mikrocontroller.net/articles/Pegelwandler Pegelwandler].&lt;br /&gt;
&lt;br /&gt;
Benutzt wird der [http://www.mikrocontroller.net/articles/Serial_Peripheral_Interface SPI]-Port des Controllers (bis auf Slave Select, hier PB1). Es wäre aber auch Software basiertes SPI möglich, siehe hierfür auch [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_Funktionalit.C3.A4t Link]&amp;lt;br&amp;gt;&lt;br /&gt;
Die Kondensatoren C1 und C2 (100nF) dienen nur zum Entstören (möglichst nah am IC). Sollten an jedes digitale IC in einer Schaltung. &amp;lt;br&amp;gt;&lt;br /&gt;
Die MMC/SD-Leiste kann eine richtige Halterung sein oder was auch sehr gut passt ist ein Stück alte ISA-Bus Buchse eines alten Mainboards (nur MMC Karten). Die Abstände da passen gut. Einfach vom Board Flexen und dann kleine Kabel an den Stecker löten (da wo man unten jetzt das Metall sieht)&amp;lt;br&amp;gt;&lt;br /&gt;
Das HC4050 IC ist ein &amp;quot;high to low&amp;quot; level shifter. Es sorgt dafür, dass die 3 abgehenden Signale des MC auf 3.3 Volt gebracht werden. Das abgehende Signal der Karte zum Controller wird auch so als logisch high erkannt.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung MMC/SD ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout.png|thumb|left|440px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/1/15/Pinout.png MMC/SD/SDHC Karte - Atmega8/168/328]&#039;&#039;&#039;]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:Pinout_mmc_sd.png|thumb|right|250px|&#039;&#039;&#039;[http://www.mikrocontroller.net/wikifiles/archive/c/ca/20100507023809!Pinout_mmc_sd.png Pins SD/MMC Karte]&#039;&#039;&#039;]] &lt;br /&gt;
&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Der Code ==&lt;br /&gt;
&lt;br /&gt;
=== Sourcen ===&lt;br /&gt;
&lt;br /&gt;
* Sourcecode mit Linux Makefile und als AvrStudio-Projekt jetzt immer auf: [http://www.mikrocontroller.net/svnbrowser/avr-fat32 SVN AVR-Fat32]&lt;br /&gt;
&lt;br /&gt;
=== Einfaches Code Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel um in eine Datei zu schreiben/anhängen und wieder zu lesen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;config.h&amp;quot; 	// Hier werden alle nötigen Konfigurationen vorgenommen !&lt;br /&gt;
#include &amp;quot;file.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;mmc.h&amp;quot;		// Hardware abhängig&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;		// Hardware abhängig, es kann auch eine eigene eingebunden werden !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//*****************************************************************************************************************&lt;br /&gt;
void main(void){&lt;br /&gt;
&lt;br /&gt;
	// Uart initialisierung zu Ausgabe von Daten&lt;br /&gt;
	uinit();&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;\nBoot&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// Versuch Karte zu Initialisieren, bis es klappt.&lt;br /&gt;
	// Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.&lt;br /&gt;
	while (FALSE==mmc_init()){&lt;br /&gt;
		nop();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	uputs((unsigned char*)&amp;quot;...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !&lt;br /&gt;
	if(TRUE == fat_loadFatData()){&lt;br /&gt;
&lt;br /&gt;
	  // Wenn auf dem terminal &amp;quot;Boot... OK&amp;quot; zu lesen ist, ist Init OK.&lt;br /&gt;
	  // Jetzt kann man schreiben/anhaengen/lesen&lt;br /&gt;
	  uputs((unsigned char*)&amp;quot;Ok\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Dateinamen muessen in diesem Format sein !&lt;br /&gt;
	  // Man beachte die Größe des Arrays und die Großbuchstaben!&lt;br /&gt;
	  unsigned char file_name[13]=&amp;quot;TEST    TXT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	  // String zum in die Datei schreiben.&lt;br /&gt;
	  unsigned char str[14]=&amp;quot;Hallo Datei!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert nicht, also anlegen !&lt;br /&gt;
	  if(MMC_FILE_NEW == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String auf Karte !&lt;br /&gt;
	     // Nur richtige Strings koennen mit ffwrites geschrieben werden !&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	  // Datei existiert, also anhaengen !&lt;br /&gt;
	  if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	     // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !&lt;br /&gt;
	     ffseek(file.length);&lt;br /&gt;
&lt;br /&gt;
	     // Schreibt String&lt;br /&gt;
	     ffwrites(str);&lt;br /&gt;
&lt;br /&gt;
	     // Neue Zeile in der Datei&lt;br /&gt;
	     ffwrite(0x0D);&lt;br /&gt;
	     ffwrite(0x0A);&lt;br /&gt;
&lt;br /&gt;
	     // Schließt Datei&lt;br /&gt;
	     ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	   // Datei existiert also lesen.&lt;br /&gt;
	   // Gerade angelegt und beschrieben, oder war schon vorhanden und es wurde was angehaengt.&lt;br /&gt;
	   if(MMC_FILE_EXISTS == ffopen(file_name)){&lt;br /&gt;
&lt;br /&gt;
	      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !&lt;br /&gt;
	      unsigned long int seek=file.length;&lt;br /&gt;
&lt;br /&gt;
	      // Lesen eines chars und Ausgabe des chars.&lt;br /&gt;
	      // Solange bis komplette Datei gelesen wurde.&lt;br /&gt;
	      do{&lt;br /&gt;
	         uputc(ffread());&lt;br /&gt;
	      }while(--seek);&lt;br /&gt;
&lt;br /&gt;
	      ffclose();&lt;br /&gt;
	   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== FAT 32 Grundlegendes ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:fat32.png|thumb|right|250px|&#039;&#039;&#039;Bild 0:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/8/82/Fat32.png Grundlegende FAT32 Struktur]]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateisystem des Typs FAT besteht aus mehreren Bereichen.&lt;br /&gt;
FAT ist immer [http://de.wikipedia.org/wiki/Byte-Reihenfolge little Endian].&lt;br /&gt;
Ein Dateisystem wie FAT32 ist ein Verwaltungsinstrument. Der FAT16/32 Standard beschreibt die Art und Weise wie die Daten Verwaltet werden. &amp;lt;br&amp;gt;&lt;br /&gt;
Im Folgenden werden die Schritte die nötig sind um Daten aus dem System zu lesen und in das System zu schreiben erläutert. Die Zahlenbeispiele und Bilder sollen ein praktisches Beispiel geben. Zum Verständnis empfiehlt es sich, das ganze Kapitel FAT32 Durchzulesen !&lt;br /&gt;
 &lt;br /&gt;
* Der erste Teil, ist der Sektor 0 oder LBA. In dem Sektor stehen die nötigen Informationen um mit dem Auslesen beginnen zu können.&lt;br /&gt;
* Dann die FAT selber, also die Dateizuordnungstabelle.&lt;br /&gt;
* Der dritte Teil ist der &amp;quot;Daten&amp;quot; Bereich, in dem beispielsweise Dateieinträge/Ordnereinträge oder Daten stehen.&lt;br /&gt;
&lt;br /&gt;
FAT bedeutet File Allocation Table ( Dateizuordnungstabelle ). Dateizuordnungstabelle beschreibt schon das Prinzip der FAT. &lt;br /&gt;
Kern des Dateisystems ist eine einfach verkettete Liste, in der festgehalten wird wo sich die Daten befinden, die Dateizuordnungstabelle !&amp;lt;br&amp;gt;&lt;br /&gt;
In dieser Tabelle werden Cluster verkettet, diese verketteten Cluster können Dateien oder Ordner bilden, dazu später mehr.&amp;lt;br&amp;gt;&lt;br /&gt;
Der Unterschied zwischen FAT32 und FAT16 besteht darin, dass ein FAT16 Dateisystem noch einen speziellen Teil hat. Das Root-Dir ist nicht einfach ein weiterer Ordner wie bei FAT32 sondern ein festgelegter Teil, der Platz für 512 Einträge bietet. FAT einträge bei FAT16 sind nur 2 Byte groß. Der Rest ist gleich.&lt;br /&gt;
&lt;br /&gt;
=== Sektor 0 oder LBA ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:sektor0.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 1:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/c/c6/Sektor0.jpeg Sektor 0] (512 Byte) bei einer unpartitionierten Karte]]&lt;br /&gt;
Um das Dateisystem lesen zu können muss man wissen wo was steht. Die nötigsten Informationen sind: &lt;br /&gt;
&lt;br /&gt;
* Sektoren pro Cluster (rot)&lt;br /&gt;
* Reservierte Sektoren nach Sektor 0 (orange)&lt;br /&gt;
* Anzahl der FATs (gelb)&lt;br /&gt;
* Wieviele Sektoren von einer FAT belegt werden (grün)&lt;br /&gt;
* Der Root-Dir Cluster (blau)&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten ergibt sich demnach:&lt;br /&gt;
&lt;br /&gt;
* 1. Sektor der 1. FAT ist Sektor 32 ([http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]), also der erste Sektor nach der Anzahl der Reservierten (orange).&lt;br /&gt;
* Der erste Daten Cluster ist 1003, weil die Anzahl der FATs 1 ist, also einmal die Sektoren, die von einer FAT belegt werden (grün) (00003cb=971) 971 + 32 (orange) = 1003.&lt;br /&gt;
* Das Root-Dir ist Cluster 2, also Sektor 1003.&lt;br /&gt;
* Die Anzahl der Sektoren pro Cluster ist 4 (2048 Bytes/Cluster).&lt;br /&gt;
&lt;br /&gt;
Damit sind alle nötigen Daten vorhanden ! &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Mann weiß jetzt wo das Root-Dir beginnt, ab da spannt sich der Verzeichnis Baum auf. So kann man jetzt alle Dateieinträge lesen. Es sind also alle Informationen mit der man das Lesen einer Datei beginnen kann bekannt, bzw. man weiß wo man einen Dateieintrag machen muss beim schreiben. Um eine Datei aber vollständig lesen zu können, muss man alle Cluster kennen, die zu der Datei gehören, da kommt die FAT-Tabelle ins Spiel von der man ja jetzt auch die 1. Sektornummer kennt. Dort stehen ab dem 1. Cluster der Datei, verkettet alle Folgecluster.&lt;br /&gt;
&lt;br /&gt;
Bei FAT Dateisystemen können mehrere Sektoren (512 Bytes) logisch zu Clustern zusammengeschlossen werden. Ein Cluster ist für eine Datei die kleinste Speichereinheit. Das hat zur Folge, dass eine 100 Byte große Datei eventuell 2048 Bytes im Dateisystem belegt. Die rote Zahl gibt an wieviele Sektoren ein Cluster bilden. Der Daten Bereich wird immer in Clustern angegeben, das macht die Umrechnung von Sektoren zu Clustern nötig. In diesem Fall ist Cluster 2 der absolute Sektor 1003.&lt;br /&gt;
&lt;br /&gt;
=== Die FAT ===&lt;br /&gt;
 &lt;br /&gt;
Folgendes Bild zeigt den ersten FAT Sektor (512 Bytes) eines FAT32 Dateisystems (nicht den ersten Sektor der Karte!). Eingetragen sind: Root-Dir und zwei darin enthaltene Ordner sowie eine Datei mit 60.000 Bytes Größe.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Fat32.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 2:&#039;&#039;&#039; [http://www.mikrocontroller.net/wikifiles/b/b3/Fat32.jpeg 1. FAT Sektor] (hier Sektor 32)]]&lt;br /&gt;
Die Einträge 0-7 sind immer reserviert (Quasi Cluster 0 und 1)! Also beginnt die FAT ab 8 (rot, Cluster Nummer 2). Der erste Eintrag (rot) ist 4 Byte groß und zu lesen von Stelle 8 zu Stelle 11 weil little Endian, also umgedrehte Wertigkeit. 8 niedrigste Wertigkeit, dann 9 eins höher, 10 noch eine höher und 11 höchste (dazu später noch ein Beispiel).&amp;lt;br&amp;gt;&lt;br /&gt;
Wie von Microsoft empfohlen ist der erste mögliche Cluster das Root-Dir (rot). Welches hier nur einen Cluster lang ist.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An den gelben Einträgen wird die einfach verkettete Liste der FAT deutlich. Der erste gelbe Eintag steht an der Stelle des Clusters Nummer 5 und hat als Inhalt eine 6. Das bedeutet: Cluster 5 und 6 gehören zusammen. Würde an der Stelle des Clusters Nummer 5 ein FFFFFF0F stehen (little Endian) ist nur der Cluster 5 mit Daten belegt (wie bei rot, blau und grün).&amp;lt;br&amp;gt;&lt;br /&gt;
So tastet man sich vom ersten Cluster einer Datei bis zum Letzten Cluster einer Datei vor. Das ist der einzige Zweck der FAT (mit FAT ist hier die eigentliche Tabelle gemeint).&amp;lt;br&amp;gt;&lt;br /&gt;
Woher bekommt man aber den 1. Cluster einer Datei?&lt;br /&gt;
&lt;br /&gt;
=== Daten ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Data.jpeg|right|thumb|250px|&#039;&#039;&#039;Bild 3:&#039;&#039;&#039; Inhalt eines Ordners/Dirs (hier [http://www.mikrocontroller.net/wikifiles/f/fb/Data.jpeg Cluster 4])]]&lt;br /&gt;
&lt;br /&gt;
Ein Dateieintrag besteht aus 32 Bytes und liegt in einem Ordner/Dir im Datenbereich des Dateisystems ( 32Byte = eine Zeile).&lt;br /&gt;
&lt;br /&gt;
Dies ist der 1. Cluster eines Ordners. Hier sieht man den &amp;quot;.&amp;quot; bzw &amp;quot;..&amp;quot; Eintrag in Zeile 1 bzw. 2. Diese beiden Einträge sind in jedem ersten Cluster eines Ordners vorhanden. Außer im Root-Dir, von dort spannt sich der Verzeichnis Baum ja erst auf. Der &amp;quot;.&amp;quot; Eintrag hat als 1. Cluster Eintrag den eigenen Cluster, hier 4. Der &amp;quot;..&amp;quot; Eintrag ist interessanter, weil er den 1. Cluster des Übergeordneten Ordners enthält, hier 3. Ist der Übergeordnete Ordner das Root-Dir, ist der 1. Cluster Eintrag 0. Diese beiden Einträge werden in der Lib genutzt um rekursiv zu löschen.&lt;br /&gt;
&lt;br /&gt;
Die dritte Zeile des Bilds zeigt eine Datei namens TEST3.TXT (grün) mit 60.000 Bytes Größe (blau) und dem 1. Cluster 5,damit ist immer der 1. Daten Cluster gemeint (rot, Folgecluster siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Die_FAT Bild 2]). Speziell ist hier, dass die 4 Bytes des ersten Clusters aufgeteilt sind auf 2 unterschiedliche &amp;quot;Orte&amp;quot; im 32 Byte Eintrag (Wertigkeit: 26:27:20:21).&lt;br /&gt;
&lt;br /&gt;
Um nun die Daten der Datei lesen zu können, muss man die Daten Cluster kennen. Der erste Daten Cluster steht im Datei Eintrag, hier Cluster 5. Für die Folgenden sieht man in der FAT nach. Dort stehen die Folgecluster der Datei. An der Stelle des ersten Clusters der Datei Cluster 5 steht eine 6, d.h. der nächste Cluster ist 6. In dieser Form ist die FAT verkettet. Wenn in der FAT der letzte Cluster erreicht ist, inhalt des Clusters ist FFFFFFF0, liest man den letzten Sektor bis man insgesammt die Größe der Datei (blau) gelesen hat und ist fertig.&lt;br /&gt;
&lt;br /&gt;
=== Root Dir ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Dir.jpeg|thumb|right|250px|&#039;&#039;&#039;Bild 4:&#039;&#039;&#039; Root des Dateisystems (hier [http://www.mikrocontroller.net/wikifiles/2/26/Dir.jpeg Cluster 2])]]&lt;br /&gt;
Die Sektor Nummer des Root-Dirs, bei FAT32, wird aus Sektor 0 oder dem LBA ausgelesen (siehe [http://www.mikrocontroller.net/articles/AVR_FAT32#Sektor_0_oder_LBA Bild 1]). Zu Sehen ist hier in der ersten Zeile ein 32 Byte Eintrag eines Ordners. Zu erkennen ist dieser am Datei Attribut 0x10 an Stelle 11 (rot). Für den Ordner Namen ist das Gleiche Feld da wie für einen Dateinamen (grün). Der 1. Cluster des Ordners ist 3 (blau, Inhalt des Ordners ist [http://www.mikrocontroller.net/articles/AVR_FAT32#Daten Bild 3]). Bei Ordnern werden die Felder für die Größe genullt (orange). Das Root-Dir hat keinen &amp;quot;.&amp;quot; bzw. &amp;quot;..&amp;quot; Eintrag. Der erste Cluster des Dirs ist ja über die FAT bekannt und ab hier spannt sich der Verzeichnisbaum erst auf. Das Root-Dir bei FAT32 kann beliebig groß werden.&lt;br /&gt;
&lt;br /&gt;
=== Zusammenfassung ===&lt;br /&gt;
&lt;br /&gt;
Für Dateien und Ordner sind nur zwei Bereiche eines FAT32 Dateisystems wichtig, nämlich die FAT selbst und der Daten Bereich. &lt;br /&gt;
Eine Datei wird aufgesplittet, in einen Datei Eintrag und in die Nutzdaten der Datei (alles im Daten Bereich). Ein Ordner ist vom Eintrag im Dateisystem einer Datei sehr ähnlich. Wo bei einer Datei über den 1.Cluster eine Cluster-Chain für die eigentlichen Daten der Datei beginnt, wird bei einem Ordner so eine Cluster-Chain für weitere Datei/Ordner Einträge verkettet. Ein Ordner bietet pro Sektor maximal 16 Einträge (16*32=512).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Thread:  http://www.mikrocontroller.net/topic/105869&lt;br /&gt;
* Infos (englisch):  https://www.pjrc.com/tech/8051/ide/fat32.html&lt;br /&gt;
* Fatgen103 von Microsoft (einfach mal nach Fatgen103.pdf suchen..)&lt;br /&gt;
* [[MMC- und SD-Karten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&#039;&#039;&#039;Weitere Projekte mit FAT MMC/SD Karten:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [http://www.roland-riegel.de/sd-reader/index.html MMC/SD FAT16 card reader example application (Roland Riegel)]&lt;br /&gt;
* [http://www.ulrichradig.de/home/index.php/avr/mmc-sd MMC/SD FAT16 (Ulrich Radig)]&lt;br /&gt;
* [http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT MMC/SD FAT16/32 auch multi File (Holger Klabunde)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Speicher und Dateisysteme]]&lt;/div&gt;</summary>
		<author><name>Zerrome</name></author>
	</entry>
</feed>