►Final Code
Using these functions, along with Chan’s tff.c module creates all the tools you need to read and write to a FAT16 SD card. An example program to display the root directory of the SD card would look like this:
#include "integer.h" #include "tff.h" #include "diskio.h" FATFS SDCard; void ShowDirectory( char *path ); char *ShowFatTime( WORD ThisTime ); char *ShowFatDate( WORD ThisDate ); DWORD get_fattime(); void main() { /* 1) mount drive... */ if( f_mount( 0, &SDCard ) ) { printf("Couldn't mount drive...\r\n"); while( 1 ); } /* 2) initialize card... */ if( disk_initialize( 0 ) & STA_NOINIT ) { switch( CardType ) { case 0 : printf("Couldn't find SD card\r\n"); break; case 1 : printf("Card type is MMC - Can't use this type\r\n"); break; case 2 : printf("Couldn't initialize SD Card drive...\r\n"); break; default : printf("Unknown Card Type error...\r\n"); break; } while( 1 ); } /* 3) show directory... */ ShowDirectory(""); while( 1 ); } void ShowDirectory( char *path ) { FILINFO finfo; DIR dirs; FATFS *fs; DWORD clust; ULONG TotalSpace, FreeSpace; FRESULT res; char VolumeLabel[12]; if(disk_read(0, SDCard.win, SDCard.dirbase, 1) != RES_OK) { printf("\r\nCouldn't read directory sector...\r\n"); return; } strncpy( VolumeLabel, &SDCard.win, 11 ); VolumeLabel[ 11 ] = 0x00; if( f_opendir(&dirs, path) == FR_OK ) { if( VolumeLabel[0] == ' ' ) printf("\r\n Volume in Drive C has no label.\r\n"); else printf("\r\n Volume in Drive C %s\r\n", VolumeLabel ); printf(" Directory of C:\%s\r\n\n", path ); while( (f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0] ) { putchar('['); putchar(( finfo.fattrib & AM_RDO ) ? 'r' : '.'); putchar(( finfo.fattrib & AM_HID ) ? 'h' : '.'); putchar(( finfo.fattrib & AM_SYS ) ? 's' : '.'); putchar(( finfo.fattrib & AM_VOL ) ? 'v' : '.'); putchar(( finfo.fattrib & AM_LFN ) ? 'l' : '.'); putchar(( finfo.fattrib & AM_DIR ) ? 'd' : '.'); putchar(( finfo.fattrib & AM_ARC ) ? 'a' : '.'); putchar(']'); printf(" %s %s ", ShowFatDate(finfo.fdate), ShowFatTime( finfo.ftime )); printf("%s %6ld %s\r\n", (finfo.fattrib & AM_DIR)?"<DIR> ":" ", finfo.fsize, finfo.fname ); } } else { printf("The system cannot find the path specified.\r\n"); return; } printf("%cCalculating disk space...\r", 0x09 ); // Get free clusters res = f_getfree("", &clust, &fs); if( res ) { printf(" f_getfree() failed...\r\n"); return; } TotalSpace = (DWORD)(fs-> max_clust - 2) * fs-> csize / 2; FreeSpace = clust * fs-> csize / 2; printf("%c%lu KB total disk space.\r\n", 0x09, TotalSpace ); printf("%c%lu KB available on the disk.\r\n", 0x09, FreeSpace ); } char *ShowFatTime( WORD ThisTime ) { char msg[12]; BYTE AM = 1; int Hour, Minute, Second; Hour = ThisTime > > 11; // bits 15 through 11 hold Hour... Minute = ThisTime & 0x07E0; // bits 10 through 5 hold Minute... 0000 0111 1110 0000 Minute = Minute > > 5; Second = ThisTime & 0x001F; //bits 4 through 0 hold Second... 0000 0000 0001 1111 if( Hour > 11 ) { AM = 0; if( Hour > 12 ) Hour -= 12; } sprintf( msg, "%02d:%02d:%02d %s", Hour, Minute, Second*2, (AM)?"AM":"PM"); return( msg ); } char *ShowFatDate( WORD ThisDate ) { char msg[10]; int Year, Month, Day; Year = ThisDate > > 9; // bits 15 through 9 hold year... Month = ThisDate & 0x01E0; // bits 8 through 5 hold month... 0000 0001 1110 0000 Month = Month > > 5; Day = ThisDate & 0x001F; //bits 4 through 0 hold day... 0000 0000 0001 1111 sprintf( msg, "%02d/%02d/%02d", Month, Day, Year-20); return( msg ); } DWORD get_fattime() { RTC_CURRENT rtc; RTC_read( &rtc ); return ((DWORD)((WORD)(rtc.Year) + 20) << 25) | ((DWORD)rtc.Month << 21) | ((DWORD)rtc.Date << 16) | ((DWORD)rtc.Hours << 11) | ((DWORD)rtc.Minutes << 5) | ((DWORD)rtc.Seconds > > 1); }