1. 程式人生 > 其它 >STM32F103-FATFS 檔案系統移植

STM32F103-FATFS 檔案系統移植

技術標籤:STM32STM32FATFS檔案系統SD卡驅動

首先準備一個例程,這裡準備一個原子的串列埠實驗

修改資料夾名稱為FATFS,防止中文出錯,編譯下載,測試工程是否正確

前往FATFS官網下載原始碼 http://elm-chan.org/fsw/ff/00index_e.html 點選下載最新版

工程目錄下新建FATFS 資料夾,用於存放原始碼

將所有檔案複製大工程的FATFS資料夾下,最上面兩個可以刪除

開啟工程新建檔案加新增檔案並新增路徑

修改 diskio.c

增加標頭檔案和巨集定義
#include "usart.h"
#include "sdio_sdcard.h"

#define SD_CARD	  0  //SD卡,卷標為0
#define SPI_FLASH 1	 //SPI Flash,卷標為1

修改 disk_status 函式

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	return RES_OK;
}

修改 disk_initialize 函式

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat=0;
	    
	switch(pdrv)
	{
		case SD_CARD:
			stat=SD_Init();//SD卡初始化 
  	break;
		
		case SPI_FLASH:
			/*未使用 SPIFLASH 預設為無*/
 		break;
		
		default:
			stat=1; 
	}		 
	if(stat) {return  STA_NOINIT;}
	else     {return 0;          } //初始化成功 
}

修改 disk_read 函式

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 */
)
{
	u8 res;
	if (!count)return RES_PARERR;  //count不能等於0,否則返回引數錯誤
	
	switch(pdrv)
	{
		case SD_CARD:
			res=SD_ReadDisk(buff,sector,count);	 
			while(res)//讀出錯
			{
				SD_Init();	//重新初始化SD卡
				res=SD_ReadDisk(buff,sector,count);	
				//printf("sd rd error:%d\r\n",res);
			}
		break;
			
		case SPI_FLASH:
			/*未使用 SPIFLASH 預設為無*/
			res=0;
		break;
		
		default:
			res=1; 
	}
	//處理返回值,將SPI_SD_driver.c的返回值轉成ff.c的返回值
	if(res==0x00) {return RES_OK;   }	 
	else          {return RES_ERROR;}
}

修改 disk_write 函式

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 */
)
{
	u8 res;
	if (!count)return RES_PARERR;  //count不能等於0,否則返回引數錯誤

	switch(pdrv)
	{
		case SD_CARD:
			res=SD_WriteDisk((u8*)buff,sector,count);
			while(res)//寫出錯
			{
				SD_Init();	//重新初始化SD卡
				res=SD_WriteDisk((u8*)buff,sector,count);	
				//printf("sd wr error:%d\r\n",res);
			}
		break;
			
		case SPI_FLASH:
			/*未使用 SPIFLASH 預設為無*/
			res=0;
		break;
		
		default:
			res=1; 
	}
	//處理返回值,將SPI_SD_driver.c的返回值轉成ff.c的返回值
	if(res == 0x00) {return RES_OK;   }	 
	else            {return RES_ERROR;}
}

修改 disk_ioctl 函式 ,如果沒有移植此函式,大部分情況可以正常使用,但是偶爾會有提示磁碟存在防寫,類似問題大概率是因為此函式移植問題!!!

DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res;						  			     
	if(pdrv==SD_CARD)//SD卡
	{
		switch(cmd)
		{
			case CTRL_SYNC:
				res = RES_OK; 
			break;
			
			case GET_SECTOR_SIZE:
				*(DWORD*)buff = 512; 
				res = RES_OK;
			break;
			
			case GET_BLOCK_SIZE:
				*(WORD*)buff = SDCardInfo.CardBlockSize;
				res = RES_OK;
			break;
			
			case GET_SECTOR_COUNT:
				*(DWORD*)buff = SDCardInfo.CardCapacity/512;
				res = RES_OK;
			break;
			
			default:
				res = RES_PARERR;
			break;
		}
	}
	else if(pdrv==SPI_FLASH)	//外部FLASH  
	{
		/*未使用 SPIFLASH 預設為無*/
	}
	else 
	{
		res=RES_ERROR;//其他的不支援
	}
	
  return res;
}

增加 get_fattime 函式

DWORD get_fattime(void)
{
	return 0;
}

修改ffconf.h

#define FF_FS_READONLY	0
#define FF_FS_MINIMIZE	0
#define FF_USE_STRFUNC	1
#define FF_USE_FIND		0
#define FF_USE_MKFS		1
#define FF_USE_FASTSEEK	1
#define FF_USE_EXPAND	0
#define FF_USE_CHMOD	0
#define FF_USE_LABEL	1
#define FF_USE_FORWARD	0
#define FF_CODE_PAGE	936
#define FF_USE_LFN		2
#define FF_MAX_LFN		255
#define FF_LFN_UNICODE	0
#define FF_LFN_BUF		255
#define FF_SFN_BUF		12
#define FF_STRF_ENCODE	3
#define FF_FS_RPATH		0
#define FF_VOLUMES		2
#define FF_STR_VOLUME_ID	0
#define FF_VOLUME_STRS		"RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
#define FF_MULTI_PARTITION	0
#define FF_MIN_SS		512
#define FF_MAX_SS		512
#define FF_LBA64		0
#define FF_MIN_GPT		0x10000000
#define FF_USE_TRIM		0
#define FF_FS_TINY		0
#define FF_FS_EXFAT		0
#define FF_FS_NORTC		0
#define FF_NORTC_MON	1
#define FF_NORTC_MDAY	1
#define FF_NORTC_YEAR	2020
#define FF_FS_NOFSINFO	0
#define FF_FS_LOCK		0
#define FF_FS_REENTRANT	0
#define FF_FS_TIMEOUT	1000
#define FF_SYNC_t		HANDLE

修改main.c

#include "sys.h"
#include "delay.h"
#include "usart.h" 
#include "led.h" 		 	 
#include "lcd.h"  
#include "key.h"
#include "stdio.h"
#include "string.h"
 
#include "ff.h"
#include "sdio_sdcard.h"
 
  
//檔案系統定義使用
FATFS    ff_disk;                               /* FatFs檔案系統物件          */
FIL      ff_file;                               /* 檔案物件                   */
FRESULT  ff_rec;                                /* 檔案操作結果               */
UINT     ff_num;                                /* 檔案成功讀寫數量           */
DIR      ff_dir;                                /* 資料夾名稱                 */
FILINFO  ff_info;                               /* 檔案資訊讀取儲存           */
BYTE     ff_buff[99]={0};                       /* SD卡操作緩衝區             */

uint8_t Test_Buff[33] = {"檔案系統測試資料 FATFS TEST DATA"};


int main(void)
{
	delay_init();	    	 //延時函式初始化	  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設定中斷優先順序分組為組2:2位搶佔優先順序,2位響應優先順序
	uart_init(115200);	 	//串列埠初始化為115200
 	LED_Init();		  			//初始化與LED連線的硬體介面
	
	while(SD_Init())  //檢測是否存在SD卡
	{
		LED0 =! LED0;
		printf("SD Card Test..... \r\n");
		delay_ms(300);
	};
	LED0 = 1;
	
	ff_rec = f_mount(&ff_disk,"0:",0);                                           //掛載SD卡
	ff_rec = f_mkdir("0:/data");                                                 //建立資料夾
	ff_rec = f_open(&ff_file,"0:/test.txt",FA_CREATE_ALWAYS | FA_WRITE);         //開啟一個檔案,如果沒有則建立一個,有則覆蓋掉之前,並開啟寫入屬性
	printf("ERROR:%d\r\n",ff_rec);                                              //列印錯誤
	ff_rec = f_write(&ff_file,Test_Buff,32,&ff_num);                             //寫資料
	ff_rec = f_close(&ff_file);                                                  //關閉檔案
	
	memset(Test_Buff,0,32);                                                      //清零Test_Buff
	ff_rec = f_open(&ff_file,"0:/test.txt",FA_READ);                             //開啟檔案
	ff_rec = f_read(&ff_file,Test_Buff,32,&ff_num);                              //讀檔案內容
	ff_rec = f_close(&ff_file);                                                  //關閉檔案
	
	Test_Buff[32] = '\0';                                                        //新增結束符,不新增結束符,會導致末尾多出亂
	printf("ERROR:%d\r\nDATA:%s\r\n",ff_rec,Test_Buff);                        //列印錯誤
		
	while(1)
	{
		LED1 =! LED1;
		delay_ms(500);
	};
}

編譯下載,下載,串列埠列印無錯誤

檢視SD卡內容,資料正確

成功移植FATFS

個人見解,感謝閱讀。