STM32F407ZGT6使用SDIO方式驱动SD卡之FATFS文件系统移植

tech2024-10-29  11

STM32F407ZGT6使用SDIO方式驱动SD卡之FATFS文件系统移植

下载源码将源码添加到工程修改源文件

下载源码

官网地址:http://elm-chan.org/fsw/ff/00index_e.html

将源码添加到工程

修改源文件

主要修改diskio.c和ffconf.h这两个底层文件

ffconf.h的修改如下: #define FF_USE_MKFS 1 #define FF_USE_STRFUNC 1 #define FF_CODE_PAGE 936 #define FF_USE_LFN 2 #define FF_MAX_LFN 255 #define FF_VOLUMES 2 根据自己需求进行修改

diskio.c的修改如下: 首先是:底层驱动函数接口的编写 也是我的踩坑之旅,之前移植不成功也是因为底层驱动的接口函数没有写好造成的

disk_status disk_initialize disk_read disk_write disk_ioctl get_fattime

1、disk_status状态函数,返回OK就可以了

DSTATUS disk_status ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { DSTATUS status = STA_NOINIT; switch (pdrv) { case SD: /* SD CARD */ status &= ~STA_NOINIT; break; case SPI_FLASH: /* SPI Flash */ break; default: status = STA_NOINIT; } return status; }

2、Inidialize a Drive //初始化一个设备

DSTATUS disk_initialize ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { DSTATUS status = STA_NOINIT; switch (pdrv) { case SD: /* SD CARD */ if(SD_Init()==SD_OK) { status &= ~STA_NOINIT; } else { status = STA_NOINIT; } break; case SPI_FLASH: /* SPI Flash */ break; default: status = STA_NOINIT; } return status; }

3、在读和写的过程,一定要注意字节对齐,字节不对齐,挂载不成功,这个是大坑

DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ BYTE *buff, /* Data buffer to store read data */ LBA_t sector, /* Start sector in LBA */ UINT count /* Number of sectors to read */ ) { DRESULT status = RES_PARERR; SD_Error SD_state = SD_OK; switch (pdrv) { case SD: /* SD CARD */ if((DWORD)buff&3) { DRESULT res = RES_OK; DWORD scratch[SD_BLOCKSIZE / 4]; while (count--) { res = disk_read(SD,(void *)scratch, sector++, 1); if (res != RES_OK) { break; } memcpy(buff, scratch, SD_BLOCKSIZE); buff += SD_BLOCKSIZE; } return res; } SD_state=SD_ReadMultiBlocks(buff,sector*SD_BLOCKSIZE,SD_BLOCKSIZE,count); if(SD_state==SD_OK) { /* Check if the Transfer is finished */ SD_state=SD_WaitReadOperation(); while(SD_GetStatus() != SD_TRANSFER_OK); } if(SD_state!=SD_OK) status = RES_PARERR; else status = RES_OK; break; case SPI_FLASH: break; default: status = RES_PARERR; } return status; } DRESULT disk_write ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ const BYTE *buff, /* Data to be written */ LBA_t sector, /* Start sector in LBA */ UINT count /* Number of sectors to write */ ) { DRESULT status = RES_PARERR; SD_Error SD_state = SD_OK; if (!count) { return RES_PARERR; /* Check parameter */ } switch (pdrv) { case SD: /* SD CARD */ if((DWORD)buff&3) { DRESULT res = RES_OK; DWORD scratch[SD_BLOCKSIZE / 4]; while (count--) { memcpy( scratch,buff,SD_BLOCKSIZE); res = disk_write(SD,(void *)scratch, sector++, 1); if (res != RES_OK) { break; } buff += SD_BLOCKSIZE; } return res; } SD_state=SD_WriteMultiBlocks((uint8_t *)buff,sector*SD_BLOCKSIZE,SD_BLOCKSIZE,count); if(SD_state==SD_OK) { /* Check if the Transfer is finished */ SD_state=SD_WaitWriteOperation(); /* Wait until end of DMA transfer */ while(SD_GetStatus() != SD_TRANSFER_OK); } if(SD_state!=SD_OK) status = RES_PARERR; else status = RES_OK; break; case SPI_FLASH: break; default: status = RES_PARERR; } return status; }

4、最后就是IO控制函数

DRESULT disk_ioctl ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { DRESULT status = RES_PARERR; switch (pdrv) { case SD: /* SD CARD */ switch (cmd) { // Get R/W sector size (WORD) case GET_SECTOR_SIZE : *(WORD * )buff = SD_BLOCKSIZE; break; // Get erase block size in unit of sector (DWORD) case GET_BLOCK_SIZE : *(DWORD * )buff = 1;//SDCardInfo.CardBlockSize; break; case GET_SECTOR_COUNT: *(DWORD * )buff = SDCardInfo.CardCapacity/SDCardInfo.CardBlockSize; break; case CTRL_SYNC : break; } status = RES_OK; break; case SPI_FLASH: break; default: status = RES_PARERR; } return status; }

5、时间戳函数

__weak DWORD get_fattime(void) { /* 返回当前时间戳 */ return 0 } //时间戳可以加载RTC实时时钟进行时间的获取

6、最后进行测试:

FATFS fs; /* FatFs文件系统对象 */ FIL fnew; /* 文件对象 */ FRESULT res_sd; /* 文件操作结果 */ UINT fnum; /* 文件成功读写数量 */ BYTE ReadBuffer[1024]={0}; /* 读缓冲区 */ BYTE WriteBuffer[] = /* 写缓冲区*/ "256.23256:88989,565256:568952.5689\r\n"; void FATFS_Test(void) { printf("\r\n****** 这是一个SD卡 文件系统实验 ******\r\n"); //在外部SPI Flash挂载文件系统,文件系统挂载时会对SPI设备初始化 res_sd = f_mount(&fs,"0:",1); /*----------------------- 格式化测试 ---------------------------*/ /* 如果没有文件系统就格式化创建创建文件系统 */ if(res_sd == FR_NO_FILESYSTEM) { printf("》SD卡还没有文件系统,即将进行格式化...\r\n"); /* 格式化 */ res_sd=f_mkfs("0:",0,0); if(res_sd == FR_OK) { printf("》SD卡已成功格式化文件系统。\r\n"); /* 格式化后,先取消挂载 */ res_sd = f_mount(NULL,"0:",1); /* 重新挂载 */ res_sd = f_mount(&fs,"0:",1); } else { printf("《《格式化失败。》》\r\n"); while(1); } } else if(res_sd!=FR_OK) { printf("!!SD卡挂载文件系统失败。(%d)\r\n",res_sd); printf("!!可能原因:SD卡初始化不成功。\r\n"); while(1); } else { printf("》文件系统挂载成功,可以进行读写测试\r\n"); } /*----------------------- 文件系统测试:写测试 -----------------------------*/ /* 打开文件,如果文件不存在则创建它 */ printf("\r\n****** 即将进行文件写入测试... ******\r\n"); res_sd = f_open(&fnew, "0:FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE ); if ( res_sd == FR_OK ) { printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。\r\n"); /* 将指定存储区内容写入到文件内 */ res_sd=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum); if(res_sd==FR_OK) { printf("》文件写入成功,写入字节数据:%d\n",fnum); printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer); } else { printf("!!文件写入失败:(%d)\n",res_sd); } /* 不再读写,关闭文件 */ f_close(&fnew); } else { printf("!!打开/创建文件失败。\r\n"); } /*------------------- 文件系统测试:读测试 ------------------------------------*/ printf("****** 即将进行文件读取测试... ******\r\n"); res_sd = f_open(&fnew, "0:FatFs读写测试文件.txt", FA_OPEN_EXISTING | FA_READ); if(res_sd == FR_OK) { printf("》打开文件成功。\r\n"); res_sd = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum); if(res_sd==FR_OK) { printf("》文件读取成功,读到字节数据:%d\r\n",fnum); printf("》读取得的文件数据为:\r\n%s \r\n", ReadBuffer); } else { printf("!!文件读取失败:(%d)\n",res_sd); } } else { printf("!!打开文件失败。\r\n"); } /* 不再读写,关闭文件 */ f_close(&fnew); // /* 不再使用文件系统,取消挂载文件系统 */ // f_mount(NULL,"0:",1); }

最新回复(0)