Cette librairie permet de lire des fichiers présents sur un volume (testé avec carte micro SD).
Afin de fonctionner correctement, la librairie se base sur deux fonctions permettant de lire un secteur, ou d’écrire dans un secteur.
bit SD_ReadBlock(unsigned char token, unsigned char *buf, unsigned int nbBytes, unsigned long sectorAddr)
bit SD_WriteBlock(unsigned char token, unsigned char *buf, unsigned int nbBytes, unsigned long blkAddr);- token
-
Valeur à envoyer avant une opération de lecture.
- buf
-
Tableau pour stocker les valeurs lues.
- nbBytes
-
Le nombre de bytes à lire (nombre de bytes dans un secteur).
NoteAvant que le Boot Sector ne soit lu, la taille d’un secteur est définie dans le fichier fat32.h - sectorAddr
-
Adresse du secteur à lire
- return
-
Retourne 1 si la lecture à réussi, autrement 0
La librairie contient 3 structures :
- BootSector
-
Contient les informations nécessaires pour le fonctionnement de base du FAT32
Nom Taile (byte) Description BytsPerSec
2
Le nombre de byte par secteur
SecPerClus
1
Le nombre de secteur par cluster
RsvdSecCnt
2
Le nombre de secteur dans la région réservée
NumFATs
1
Le nombre de Table FAT
FATSz32
4
La taille d’une Table FAT
RootClus
4
Le numéro de cluster de la racine
RootDirSector
2
Le premier secteur de la racine (pas réellement dans le Boot Sector)
- FileEntry
-
Contient les informations minimum pour trouver et lire un fichier (plus peuvent être rejoutée si besoin)
Nom Taile (byte) Description Name
11
Nom du fichier (8 Bytes de nom + 3 Bytes d’extension)
FstClustHi
2
MSBytes du numéro de cluster
FstClustLO
2
LSBytes du numéro de cluster
fileSize
4
Taille du fichier
- FileInfo
-
Sert de curseur au fichier ouvert. Il permet de savoir ou nous en sommes dans la lecture. Il peut également être déplacé manuellement.
Nom Taile (byte) Description baseCluster
4
Numéro du cluster de depart
currentCluster
4
Numéro du cluster actuel
Offset
4
Offset en byte depuis le début du fichier
fileSize
4
Taille du fichier
currentSector
2
Numéro du secteur actuel dans le cluster
void SwapEndianINT(unsigned int *val);
void SwapEndianLONG(unsigned long *val);Ces deux fonctions permettent de changer l’endianness d’une valeur. Elles sont nécessaires car les valeurs sur la carte SD sont en Little Endian alors que le microcontrôleur traite les valeurs en tant que Big Endian. La valeur passée en entrée sera directement changée.
| val |
Adresse de la valeur à convertir |
unsigned int a = 0x0002;
SwapEndianINT(&a);
// a == 0x0200 = 512Cette fonction permet de lire les informations utiles du Boot Sector et de les stocker dans une structure de type BootSector.
BootSector ParseBootSector(unsigned char *buf);| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| return |
Structure BootSector qui contient les informations lues |
unsigned char buffer[512];
BootSector bs;
bs = ParseBootSector(buffer);ReadFileEntry permet de lire une entrée de fichier et de stocker les informations lues dans une structure de type FileEntry. Elle est utilisée dans la fonction OpenFile .
FileEntry ReadFileEntry(unsigned char *buf, unsigned int offset);| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| offset |
Position de l’entrée de fichier dans le secteur (doit être un multiple de 32) |
| return |
Structure FileEntry qui contient les informations lues |
unsigned char buffer[512];
FileEntry fe;
// buffer doit contenir le secteur ou se trouve
// l'entrée du fichier
fe = ReadFileEntry(buffer, 160);Cette fonction permet de transformer le nom du fichier lu sur la carte qui possède un format avec une taille fixe (ex : FILE____TXT) à un format plus lisible (ex : file.txt). Cette conversion facilite la comparaison lors de la recherche de fichier sur le disque.
unsigned char CleanFilename(char *filename);| filename |
Nom du fichier (qui peut être trouvé dans la structure FileEntry) |
| return |
La Taille du nom du fichier après conversion |
// Exemple 1
CleanFilename(fs.Name);
// Exemple 2
CleanFilename("FILE TXT");Cette fonction permet de lire la table FAT et retourne la valeur du prochain Cluster
unsigned long GetNextClusterValue(BootSector *bs, unsigned char *buf, unsigned long clusterNumber);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| clusterNumber |
Numéro de cluster actuel |
| return |
Numéro de cluster suivant |
unsigned long clusterValue;
clusterValue = GetNextClusterValue(&bs, buffer, 8);Cette fonction permet de modifier les tables FAT afin de faire pointer le secteur actuel au prochain secteur, puis indiquer la fin du fichier avec le secteur suivant
void SetNextClusterValue(BootSector *bs, unsigned char *buf, unsigned long clusterNumber, unsigned long nextClusterNumber);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| clusterNumber |
Numéro de cluster actuel |
| nextClusterNumber |
Numéro de cluster suivant |
SetNextClusterValue(&bs, buffer, 8, 10);Calcule et retourne la valeur du premier secteur du numéro de cluster passé en paramètre
unsigned long GetSectorFromCluster(BootSector *bs, unsigned long cluster);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
| clusterNumber |
Numéro de cluster actuel |
| return |
Adresse du premier secteur du cluster |
unsigned long sector;
sector = GetSectorFromCluster(&bs, 8);Cette fonction cherche dans la table FAT un cluster vide
unsigned long FindFreeCluster(BootSector *bs, unsigned char *buf);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| return |
Le numéro de cluster vide |
cluster = FindFreeCluster(&bs, buf);Cette fonction cherche dans le cluster du secteurDepart une entrée de fichier et retourne l’offset depuis le secteurDepart en byte
unsigned int FindFileEntry(BootSector *bs, char *buf, unsigned long secteurDepart, char *filename);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| secteurDepart |
Numéro de secteur ou commencer la recherche (doit être le premier secteur du cluster) |
| filename |
Nom du fichier à chercher |
| return |
Position (offset) en byte depuis le secteurDepart |
|
Note
|
Si l’entrée du fichier se trouve à l’offset 192 du deuxième secteur, la fonction retourne 512 + 192 |
unsigned long offset;
offset = FindFileEntry(&bs, buffer, 8192, "file.txt");Liste tous les fichiers présents dans un cluster
void ListFilesDirectory(BootSector *bs, unsigned char *buf, unsigned char *texte, unsigned long secteurDepart);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| texte |
Tableau ou seront stocké les noms de fichiers |
| secteurDepart |
Numéro de secteur ou commencer la recherche (doit être le premier secteur du cluster) |
ListFilesDirectory(&bs, buf, texte, 8192);Cette fonction permet "d’ouvrir" un fichier. Elle retourne une structure qui contient la position du curseur dans le fichier.
FileInfo OpenFile(BootSector *bs, unsigned char *buf, unsigned long secteurDepart, FileEntry *fe, char *filename);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| secteurDepart |
Premier secteur du cluster dans lequel se trouve le fichier (Racine, Premier secteur d’un dossier, …) |
| fe |
Adresse de la structure (FileEntry) qui contiendra les informations de base sur le fichier |
| return |
Structure FileInfo qui contient la position du curseur |
FileInfo fi;
fi = FileOpen(&bs, buffer, 8192, &fe, "file.txt");Cette fonction permet de lire un nombre précis de byte dans un fichier depuis la position du curseur
unsigned int ReadFile(BootSector *bs, unsigned char *buf, unsigned char *output, FileInfo *fi, unsigned int length);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| output |
Adresse d’un tableau ou écrire les valeur lues |
| fi |
Structure FileInfo qui contient la position du curseur |
| length |
Nombre de byte à lire |
| return |
Nombre de bytes lus (retourne une valeur plus petite que length si la fin du fichier a été atteinte) |
// Lis 25 bytes depuis la position du curseur
FileRead(&bs, buffer, output, &fi, 25);Cette fonction permet d’écrire un nombre précis de byte dans un fichier, en ajoutant le contenu à la fin du fichier (mode append)
void WriteFile(BootSector *bs, unsigned char *buf, FileInfo *fi, FileEntry *fe, unsigned char *texte, unsigned int length);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
| buf |
tableau de 512 bytes pour stocker les valeurs lues |
| fi |
Structure FileInfo qui contient la position du curseur |
| fe |
Structure FileEntry qui contient l’entrée du fichier |
| texte |
Buffer contenant les informations à écrire |
| length |
Nombre de byte à écrire |
// Lis 25 bytes depuis la position du curseur
FileRead(&bs, buffer, output, &fi, 25);Cette fonction permet de déplacer le curseur du fichier actuellement ouvert
bit FileSeek(BootSector *bs, unsigned char *buf, FileInfo *fi, unsigned long offset, bit mode);| bs |
Adresse de la structure (BootSector) qui contient les informations du BootSector |
||||
| buf |
tableau de 512 bytes pour stocker les valeurs lues |
||||
| fi |
Structure FileInfo qui contient la position du curseur |
||||
| offset |
Nombre de byte à avancer |
||||
| mode |
Mode de déplacement
|
||||
| return |
SUCCESS (1) ou FAILED (0) |
// Avance le curseur de 500 bytes depuis le
// début du fichier
FileSeek(&bs, buffer, &fi, 500, SEEK_SET);
// Avance le curseur de 500 bytes depuis la
// position du curseur
FileSeek(&bs, buffer, &fi, 500, SEEK_CUR);BootSector bs;
FileEntry fe;
FileInfo fi;
unsigned char buffer[512];
// Parse le boot sector et ouvre le fichier
bs = ParseBootSector(buffer);
fi = OpenFile(&bs, buffer, bs.RootDirSector, &fe, "test.txt");
// Lis le fichier puis affiche le contenu sur le LCD_DOG
ReadFile(&bs, buffer, texte, &fi, 20);
SelectPosCaractLiCo(2, 0);
AfficherChaineAZT(texte);
// Lis 20 nouveaux bytes qui seront également affichés sur le LCD_DOG
ReadFile(&bs, buffer, texte, &fi, 20);
SelectPosCaractLiCo(3, 0);
AfficherChaineAZT(texte);BootSector bs;
FileEntry fe;
FileInfo fi;
unsigned char buffer[512];
unsigned char texte[15];
unsigned char nbBytes = 0;
// Parse le boot sector et ouvre le fichier
bs = ParseBootSector(buffer);
fi = OpenFile(&bs, buffer, bs.RootDirSector, &fe, "test.txt");
nbBytes = sprintf(texte, "Hello World!");
WriteFile(&bs, buffer, &fi, &fe, texte, nbBytes);