Programm für PIC-Microcontroller und MMC-Speicherkarte mit FAT16
Finden und Lesen einer Datei
(auch wenn die zerstückelt abgespeichert wurde)

Hier stelle ich vor eine Beispielprogramm, die eine Datei findet und ausliest von einer mit FAT16 formatierter 64 MB MMC - Carte.

Unsere vorherige Programm könnte MMC Speicher an beliebiger Stelle auslesen.
Um eine Datei vom formatierten Datenträger auslesen zu können, braucht man:
Position von Dateianfang und falls Datei zerstückelt, abgespeichert ist,
Anfangposition jedes Clusters der Datei zu bestimmen.
Um das zu erreichen, muss Programm in der Lage sein
Anfangsektoren der FAT-Strukturen zu finden, sowie
bestimmte Bytes auslesen.

Folgende Unterprogramme ermöglichen es:

Funktion-Name Input Output Beschreibung der Funktion
void Byte_lesen (void) AH, AL, BytN ByteLes Liest 2 Byte an bestimmter Position in einem Sektor aus und speichert in Variable "ByteLes". High und Low Adresse des Sektors sollen in "AH, AL" abgespeichert sein. Position soll in Variable BytN abgelegt sein(0...512).
void Suche(const char *wort) String, Verz ByteLes Sucht ein 11 Byte String, Dateiname + Erweiterung. Liefert in Variable "ByteLes" Nummer des ersten Cluster der Datei. Bevor diese Funktion aufgerufen wird, soll in Variable "Verz" Anfangadresse des Verzeichnisbereiches abgespeichert sein.
void Lesen(char H,uns16 L) H, L - Liest ein Sektor aus und sendet Daten seriell zum PC, als Parameter benötigt Sektoradresse.


Programmablauf:

1
Initialisieren serieller Schnittstelle
2
Initialisieren SPI-Übertragung und MMC
3
2 Byte-Wert lesen von Sektor 0, Position 1C6h, das ist Master Boot Record 1. Partitionseintrag (1BEh)
1C6h-1BEh=8 an dieser Stelle in dem Partitionseintrag ist ein Wert abgespeichert, der der Abstand zwischen MBR-Sektor und dem ersten Sektor der Partition in Sektoren angibt.
4
Diese 2 Byte-Wert in AL übertragen, AL enthält jetzt Anfangadresse des Volume Boot Records.
5
2 Byte-Wert lesen von Sektor =Anfangadresse des Volume Boot Records, Position Eh. Das ist Anzahl der reservierten Sektoren.
6
Anfangadresse des Volume Boot Records addieren mit Anzahl der reservierten Sektoren und Ergebnis in Variable "FAT" speichern. Das ist nämlich Anfangsadresse der FAT- Tabelle.
7
2 Byte-Wert lesen von Sektor =Anfangadresse des Volume Boot Records, Position 16h. Das ist Anzahl Sectors Per FAT. Da wir 2 FAT- Tabellen haben (FAT und seine Kopie), erhaltene Wert mit 2 multiplizieren, damit wir auf gesamte Anzahl der Sectors die für FAT belegt sind kommen.
8
Berechnen des Anfangadresse der Verzeichniseinträgen: Anfangsadresse der FAT- Tabelle addieren mit Anzahl Sectors, die für FAT belegt sind. Das Ergebnis wird in Variable "Verz" abgelegt.
9
Als Nächstes wird Anzahl der Sektoren berechnet, die für Verzeichniseinträgen (Hauptverzeichnis) reserviert sind.
Dafür gibt es Formel: (Anzahl Verzeichniseinträgen)*32/512. Aus mehreren Quellen habe ich erfahren, dass Anzahl Verzeichniseinträgen immer für 512 Einträge reserviert ist. Also Anzahl der Sektoren, die für Verzeichniseinträgen (Hauptverzeichnis) reserviert sind: 512*32/512= 32.
10
Adresse des ersten Sektors des Datenbereichs (Cluster0) berechnen. Addieren des Anfangadresse der Verzeichniseinträgen mit Anzahl der Verzeichniseinträgen-Sektoren (32). Das Ergebnis wird in Variable "Dat" abgespeichert. Damit sind alle Anfangsektoren der FAT-Strukturen gefunden und in Variablen "FAT", "Verz", "Dat" abgespeichert.
11
Es wird Unterprogramm Suche("TEST TXT"); gestartet. Die sucht erste Cluster der Datei Test.txt . Name der Datei ist immer 8 Zeichen lang. Wenn es kürzer ist, wird es mit Leerzeichen ausgefühlt. Der Punkt zwischen Dateiname und Erweiterung ist nicht in Verzeichniseintrag abgebildet. Zu suchende String soll 11 Zeichen in GROSSBUCHSTABEN erhalten. Nummer der erstes Clusters ist dann in "ByteLes".
12
Hier fängt eine Schleife an, die wird verlassen, wenn Cluster -Nummer den Wert 0xFFFF hat. Das bedeutet, dass Datei keine weiteren Clustern hat (Ende der Datei).In der Schleife:
13
Beim ersten Durchlauf Variable "Cluster" erhält Nummer des ersten Clusters der Datei.
Beim anderen Durchläufen erhält Variable "Cluster" aus "ByteLes" Nummer des nächsten Clusters, welche am Ende der Schleife ermittelt wird.
14
Cluster -Nummer wird korrigiert, weil erste 2 Stellen in FAT reserviert sind, aber in Datenbereich fangen Daten mit Cluster 0 an. Also echte Cluster -Nummer= Clusternummer-2.
15
Echte Cluster -Nummer wird in Variable "AL" übertragen.
16
Absolute physikalische Sektoradresse wird berechnet :
Dafür soll Cluster -Nummer mit 2 multipliziert werden. Weil 1 Cluster =2 Sektoren. Das geschieht durch Rotieren um eine Stelle nach links und zwar über Carry -Flag. Falls "AL" dabei überlüft (das passiert, wenn Datei auf MMC in Bereich >32MB sich befindet ) kommt Übertrag ins "AH".
17
Erhaltene Sektornummer addieren mit Adresse des ersten Sektors des Datenbereichs (Cluster0). Das Addieren passiert im Assemblermodus, weil Ergebnis eine 24Bitige Zahl ist und cc5x nur mit 16Bitigen Zahlen arbeiten kann.
Damit erhalten wir absolute physikalische Sektoradresse in "AH", "AL". AH - 8 Bit Variable High Teil der Sektoradresse, AL - 16 Bit Variable Low Teil der Sektoradresse.
18
Mit Funktion Lesen(AH,AL); lesen wir aus erstem Sektor des Clusters der Datei.
19
Physikalische Sektoradresse um eins erhöhen, mit Beachtung des Übertrags in "AH"
20
Mit Funktion Lesen(AH,AL); lesen wir aus zweitem Sektor des Clusters der Datei.
21
Nächste Cluster -Nummer aus FAT -Tabelle auslesen:
Es wird Sektor berechnet, in dem FAT -Eintrag sich befindet. Dafür wird Cluster- Nummer durch 100h geteilt, weil in einem Sektor 200h Bytes sind und FAT -Eintrag 2 Byte groß ist(In ein Sektor passen 100h Einträge ). Ergebnis wird in temp-Variable gespeichert.
22
AL erhält tatsächliche Sektoradresse den gesuchten FAT -Eintrags, in dem FAT -Anfangadresse zu errechnetem Wert in temp-Variable addiert wird.
23
Um FAT -Eintragnummer in ausgerechnetem Sektor zu erhalten, müssen wir von Cluster- Nummer, Anzahl der FAT -Eintrage in vorherigen Sektoren abziehen. Weil FAT -Eintrag 2 Byte groß ist, ist Byteposition gleich (FAT -Eintragnummer in ausgerechnetem Sektor) * 2.
24
Jetzt da wir Sektoradresse und Position in dem Sektor haben, können wir mit Funktion Byte_lesen FAT -Eintrag
auslesen. Und drin steht Nummer des nächsten Clusters der Datei.
25
"ByteLes" enthält jetzt Nummer des nächsten Clusters der Datei. Programm läuft an Stelle 12 weiter.