移植步骤
A、获取FATFS源代码
说明
可到官网下载:http://elm-chan.org/fsw/ff/00index_e.html
B、解压FATFS源代码包
说明
解压会得到两个文件夹:doc(文档)和src(源码)
C、建立STM32工程,在工程项目中添加两个目录:sd和fatfs
说明
sd存放sd卡底层驱动代码
fatfs存放源码包解压得到的src目录中所有.c和.h文件
提示
建议重定义printf函数至串口,方便调试
D、对diskio.c文件中以下六个函数进行编辑(移植)
函数定义
DSTATUS disk_initialize (BYTE);//SD卡的初始化
DSTATUS disk_status (BYTE);//获取SD卡的状态,这里可以不用管
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);//从SD卡读取数据
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);//将数据写入SD卡,若该文件系统为只读文件系统则不用实现该函数
DRESULT disk_ioctl (BYTE, BYTE, void*);//获取SD卡文件系统相关信息
DWORD get_fattime(void); // 获取时间???
提示
函数编辑的参考代码在文档最末列出
E、总结:按照以上步骤前期的移植过程就完成,后续根据实际情况进行综合调试
F、参考代码
----------------------------------------------------------------------------------------------------------------------------
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv){
case 0 :
stat = sd_init();
// sd_init函数就是sd初始化函数,由sd底层驱动提供
// disk_initialize函数就是接口,保证FATFS的可移植性
if(stat==0)
return RES_OK;
else
return STA_NOINIT;
case 1 :
return RES_OK;
case 2 :
return RES_OK;
case 3 :
return RES_OK;
default:
return STA_NOINIT;
}
return STA_NOINIT;
}
----------------------------------------------------------------------------------------------------------------------------
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
int status;
if( !count ){ // arguments validate
return RES_PARERR;
}
switch (pdrv){
case 0:
status = SD_ReadDisk(buff,sector,count);
// SD_ReadDisk函数是sd卡底层驱动函数
if(status == 0)
return RES_OK;
else
return RES_ERROR;
case 1:
if(count==1)
return RES_OK;
else
return RES_OK;
default:
return RES_ERROR;
}
return RES_PARERR;
}
----------------------------------------------------------------------------------------------------------------------------
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
int status;
if( !count ){ // ´«²ÎÑéÖ¤
return RES_PARERR;
}
switch(pdrv){
case 0:
status = SD_WriteDisk((u8 *)buff,sector,count);
if(status == 0)
return RES_OK;
else
return RES_ERROR;
case 1:
if(count==1)
return RES_OK;
else
return RES_OK;
default:
return RES_ERROR;
}
return RES_PARERR;
}
----------------------------------------------------------------------------------------------------------------------------
// 改函数是一个杂类函数,常规性功能都可通过该函数进行实现(要移植)
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
if (drv==0)
{
MSD0_GetCardInfo(&SD0_CardInfo);
switch (ctrl)
{
case CTRL_SYNC :
return RES_OK;
case GET_SECTOR_COUNT :
*(DWORD*)buff = SD0_CardInfo.Capacity/SD0_CardInfo.BlockSize;
return RES_OK;
case GET_BLOCK_SIZE :
*(WORD*)buff = SD0_CardInfo.BlockSize;
return RES_OK;
case CTRL_POWER :
break;
case CTRL_LOCK :
break;
case CTRL_EJECT :
break;
/* MMC/SDC command */
case MMC_GET_TYPE :
break;
case MMC_GET_CSD :
break;
case MMC_GET_CID :
break;
case MMC_GET_OCR :
break;
case MMC_GET_SDSTAT :
break;
}
}else if(drv==1){
switch (ctrl)
{
case CTRL_SYNC :
return RES_OK;
case GET_SECTOR_COUNT :
return RES_OK;
case GET_SECTOR_SIZE :
return RES_OK;
case GET_BLOCK_SIZE :
return RES_OK;
case CTRL_POWER :
break;
case CTRL_LOCK :
break;
case CTRL_EJECT :
break;
/* MMC/SDC command */
case MMC_GET_TYPE :
break;
case MMC_GET_CSD :
break;
case MMC_GET_CID :
break;
case MMC_GET_OCR :
break;
case MMC_GET_SDSTAT :
break;
}
}
else{
return RES_PARERR;
}
return RES_PARERR;
}
----------------------------------------------------------------------------------------------------------------------------
// 空函数,没有改空函数会报错,调试有必要实现时,再做详细了解
DWORD get_fattime(void){
return 0;
}
----------------------------------------------------------------------------------------------------------------------------
// 获取SD卡状态,该函数这里参考代码未实现,实现方式参考上面的代码
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
// result = RAM_disk_status();
// translate the reslut code here
return stat;
case DEV_MMC :
// result = MMC_disk_status();
// translate the reslut code here
return stat;
case DEV_USB :
// result = USB_disk_status();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
----------------------------------------------------------------------------------------------------------------------------
常用函数
FATFS fs ;
DIR dirs ;
FILINFO finfo ;
FIL fil ;
FRESULT res ;
unsigned char rbuffer[512] ;
unsigned char wbuffer[]="xxxxx" ;
unsigned int br ;
unsigned int bw ;
disk_initialize(0);
// 初始化磁盘,调用Fatfs文件系统内 diskio.c 文件 ;
f_mount(0,&fs);
// 为设备创建一个挂载点,0为本地设备号(Logical drive number),&fs为本地设备的挂载点(Pointer to the work area);
f_mount(0,NULL);
// 卸载已经创建的挂载点,在操作完成后一定要卸载相应的挂载点;
f_mkdir("/xxx");
// 在根目录上创建一个名为‘xxx’的文件夹,'/'代表根目录,该操作的输入函数是字符串或者字符串数组;
f_opendir(&dirs,"/xxx");
// 打开在根目录上的‘xxx’文件夹,并将信息保存在dirs指向的地方;
f_readdir(&dirs,&finfo);
// 读取dirs指向的文件夹的信息,将相应的信息保存在finfo指向结构体;
f_open(&fil,"/xxx/xx.txt", --------------);
FA_READ // 读文件预指令,用f_read(); 函数读取;
FA_WRITE // 写文件预指令,用f_write();函数写入;
FA_OPEN_EXISTING // 打开文件条件属性,如果该文件不存在则打开失败(此属性为默认属性);
FA_OPEN_ALWAYS // 打开文件条件属性,如果该文件不存在则创建同名文件;
FA_CREATE_NEW // 创建文件属性,创建对应文件名的新文件;
FA_CREATE_ALWAYS // 创建文件属性,创建对应文件名的新文件,如相同文件名的文件存在则覆盖原文件;
// 常用方式 FA_CREATE_NEW , FA_OPEN_EXISTING | FA_WRITE , FA_OPEN_EXISTING | FA_READ
f_write(&fil,wbuffer,sizeof(wbuffer),&bw); // 在mdk测试下有一些问题,在博客里可以看到
f_read (&fil,rbuffer,sizeof(rbuffer),&br); //
f_close(&fil); // 关闭文件,每次打开都必须关闭文件