基于stm32f103c8t6的Fatfs文件系统移植,基于R0.15版本

1、固件地址

在这里插入图片描述

2、需要修改部分:

diskio.h\diskio.c (必须,底层驱动,与SD卡等相关)
ffconf.h(必须,可选功能配置)
integer.h(数据类型修改,或无)
ffunicode.c(修改字库,若使用中文FF_CODE_PAGE=936,C文件里的数组过大,中小容量单片机容量不足,采用外部FLASH存字库的办法)
ffsystem.c  (FF_USE_LFN =3时,采用堆处理长文件名,修改对应的内存管理函数)

3、ffconf.h配置

4、diskio.c中的关键函数


//定义设备号//两个设备//ke加到10个卷
#define SD_CARD	 0  //SD卡,卷标为0
#define EX_FLASH 1	//外部flash,卷标为1

#define FLASH_SECTOR_SIZE 	512		//512字节一个扇区	  		 			    
u16	    FLASH_SECTOR_COUNT= 1024;	//W25Q16q32共4M,前0.5用于fafts,后3.5用于存放字库(不用放字库的话最大为8192)
                                    //此变量用于定义FLASH用作fatfs的范围
#define FLASH_BLOCK_SIZE   	8      	//每个BLOCK有16个扇区

/* Get Drive Status */
DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
   //未写
	return 0;
}




//初始化设备
DSTATUS disk_initialize 
(
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat;
	int result;
	switch (pdrv) 
	{
	              case SD_CARD :
		                            result = SD_Initialize();  //初始化成功则返回0
									if(result)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
									{
										SD_SPI_SpeedLow();
										SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
										SD_SPI_SpeedHigh();
									}
		                            break;               
	              case EX_FLASH :
		                            result = SPI_Flash_Init();
                                     break;
	}
	if(result)
	{ return STA_NOINIT; } //初始化失败
	else 
	{ return 0; }
	
}

//读扇区
//pdrv:卷标 buff:读缓冲首地址 sector:开始扇区地址 count:扇区数
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);
                      if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
											{
												SD_SPI_SpeedLow();
												SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
												SD_SPI_SpeedHigh();
												return RES_NOTRDY; //未准备
											}
	                  	return RES_OK;

	    case EX_FLASH :
											for(;count>0;count--) //
											{
												SPI_Flash_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
												sector++;
												buff+=FLASH_SECTOR_SIZE;
											}
		                  return RES_OK;

	}
	return RES_PARERR;  //无效参数
}

//写一个扇区
#if FF_FS_READONLY == 0  //ffconf.h中开启
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 res;
	int result;
	
    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误	
	switch (pdrv) 
		{
	      case SD_CARD:     res=SD_WriteDisk((u8*)buff,sector,count); //写入成功返回0
		                    if(res){ break;}
			                return RES_OK;
			
	      case EX_FLASH:			
					              for(;count>0;count--)
												{										    
													SPI_Flash_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
													sector++;
													buff+=FLASH_SECTOR_SIZE;
												}
												res=0;
		                    return RES_OK;
	  }
	return RES_PARERR;
}
#endif


//其他磁盘控制
DRESULT disk_ioctl
(
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,	  	/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res;
	int result;

	switch (pdrv) 
		{
	       case SD_CARD : 
					              switch(cmd)
												{
													case CTRL_SYNC:         
														            SD_CS=0;													
																	if(SD_WaitReady()==0)res = RES_OK; 
																    else res = RES_ERROR;	  
																	SD_CS=1;
																	break;	 
													case GET_SECTOR_SIZE:
																		*(WORD*)buff = 512;
																			res = RES_OK;
																			break;	 
													case GET_BLOCK_SIZE:
																		*(WORD*)buff = 8;
																			res = RES_OK;
																			break;	 
													case GET_SECTOR_COUNT:
																			*(DWORD*)buff = SD_GetSectorCount();
																			res = RES_OK;
																			break;
												     default:
														                    res = RES_PARERR;
														                    break;
												}
												return res;
	       case EX_FLASH :
													switch(cmd)
														{
															case CTRL_SYNC:
																				res = RES_OK; 
																				break;	 
															case GET_SECTOR_SIZE:
																				*(WORD*)buff = FLASH_SECTOR_SIZE;
																			    res = RES_OK;
																				break;	 
															case GET_BLOCK_SIZE:
																				*(WORD*)buff = FLASH_BLOCK_SIZE;
																				res = RES_OK;
																				break;	 
															case GET_SECTOR_COUNT:
																				*(DWORD*)buff = FLASH_SECTOR_COUNT;
																				res = RES_OK;
																				break;
															default:
																				res = RES_PARERR;
																				break;
														}
														return res;		                

	 }
	return RES_PARERR;
}

5、ffsystem.c修改

#if FF_USE_LFN == 3	/* Use dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate/Free a Memory Block                                           */
/*------------------------------------------------------------------------*/
#include <stdlib.h>		/* with POSIX API */
#include "malloc.h"	   //内存管理函数
void *ff_memalloc 
(	            /* Returns pointer to the allocated memory block (null if not enough core) */
	UINT msize	/* Number of bytes to allocate */
)
{
	return (UINT*)mymalloc(sizeof(UINT));	/* Allocate a new memory block *///调用mymalloc();
}
void ff_memfree 
(
	void* mblock	/* Pointer to the memory block to free (no effect if null) */
)
{
	myfree(mblock);	/* Free the memory block *///调用myfree();
}
#endif

6、ffunicode.c修改

  修改ffuincode.c以通过SPI使用FLASH中的字库,避免占用stm32内部flash。
  首先ffconf.h中修改:
  #define FF_CODE_PAGE	936  //中文 支持中文
  //是否支持长文件名
  #define FF_USE_LFN		3  //在HEAP中,要修改ffsystem.c中的内存申请与释放函数
  #define FF_MAX_LFN		20 //长度
 在ffuincode.c中修改:先注释掉相应的FF_CODE_PAGE=936的数据 
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode Conversions for Static Code Page Configuration with   */
/* DBCS Fixed Code Page                                                   */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE >= 900

//返回特定编码
WCHAR ff_uni2oem 
(	                /* Returns OEM code character, zero on error */
	DWORD	uni,	/* UTF-16 encoded character to be converted */ //要被转换的//u32
	WORD	cp		/* Code page for the conversion */             //转换目标
)
{
	
	WCHAR t[2];
	WCHAR c;
	u32 i, li, hi;
	u16 n;			 
	u32 gbk2uni_offset=0;		  
						  
	if (uni < 0x80) //ASCII,直接不用转换.
	{c =(WCHAR)uni;}
	else //UNICODE 2 GBK  
	{ 
		if (uni < 0x10000 && cp == FF_CODE_PAGE) 	/* Is it in BMP and valid code page? */
		{
				gbk2uni_offset=0;	
				/* Unicode to OEMCP */
				hi=ftinfo.ugbksize/2;//对半开.
				hi =hi / 4 - 1;
				li = 0;
				for (n = 16; n; n--)
				{
					i = li + (hi - li) / 2;	
					SPI_Flash_Read((u8*)&t,ftinfo.ugbkaddr+i*4+gbk2uni_offset,4);//读出4个字节  
					if (uni == t[0]) break;
					if (uni > t[0])  li = i;  
					else hi = i;    
				}
				c = n ? t[1] : 0;  	  
		}				
	}
	return c;
}


WCHAR ff_oem2uni 
(	                /* Returns Unicode character in UTF-16, zero on error */
	WCHAR	oem,	/* OEM code to be converted */
	WORD	cp		/* Code page for the conversion */
)
{
	
	WCHAR t[2];
	WCHAR c;
	u32 i, li, hi;
	u16 n;			 
	u32 gbk2uni_offset=0;		  
						  
	if (oem < 0x80)  //ASCII,直接不用转换.
	{c = oem;}       
	else 
	{
		if (cp == FF_CODE_PAGE) /* Is it valid code page? */
		{	
			  gbk2uni_offset=ftinfo.ugbksize/2;	 //GBK 2 UNICODE
				/* Unicode to OEMCP */
				hi=ftinfo.ugbksize/2;//对半开.
				hi =hi / 4 - 1;
				li = 0;
				for (n = 16; n; n--)
				{
					i = li + (hi - li) / 2;	
					SPI_Flash_Read((u8*)&t,ftinfo.ugbkaddr+i*4+gbk2uni_offset,4);//读出4个字节  
					if (oem == t[0]) break;
					if (oem > t[0])  li = i;  
					else hi = i;    
				}
				c = n ? t[1] : 0;  	 
  	   }		
  }
  return c;
}
#endif

7、实例

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值