本帖最后由 qjp1988113 于 2020-11-26 08:56 编辑
拿到开发板已经快一周了,一直想做点什么,可是感觉V103的库做的和F103的太兼容了,就连函数的结构都差不多。前面先试了下几个外设,库函数好评,特别是IIC的库,我很喜欢这种把IIC协议分段写的模式,对于其他IIC芯片,自己就可以灵活运用了。经过昨天和今天的一点时间,我移植了下FATFS,并读写了TXT和,列出目录。下面谈一谈FATFS的移植,在这里,我一开始用最新版本的,可是总是碰到内存不足的,各种莫名其妙的问题,搞的不胜其烦。不是默认分配的内存大了,就是各种溢出的问题。后来想了下,以前在用M0时也用过FATFS,但FATFS不是最新版本的(M0的FLASH和RAM也不大).找到旧版的FATFS文件,主要就是:"diskio.c"、"diskio.h"、"ff.c"、"ff.h"、"ffconfig.h"。其中用户操作"diskio.c"和"ffconfig.h"即可。我仅做了SD的挂载,SPI FLASH未做。
diskio.c:
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
/*-----------------------------------------------------------------------*/
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/
#include "diskio.h"
#include "spi_sd.h" //添加自己的SD驱动头文件
#define BLOCK_SIZE 512 /* 块大小 */
/****************************************
*函数名称:disk_initialize
*输 入:drv -指定要初始化的逻辑驱动器号,即盘符
应当取值0~9
*输 出:函数返回一个磁盘状态作为结果
*功 能:初始化磁盘驱动器
******************************************/
DSTATUS disk_initialize (
BYTE drv
)
{
UINT8 status;
/* SD卡初始化 */
status = SD_Initialize();
if(status != 0){
return STA_NOINIT;
}
else
{
return RES_OK;
}
}
/****************************************
*函数名称:disk_status
*输 入:drv -指定要初始化的逻辑驱动器号,即盘符
应当取值0~9
*输 出:函数返回一个磁盘状态作为结果
*功 能:返回磁盘驱动器状态
******************************************/
DSTATUS disk_status (
BYTE drv
)
{
return RES_OK;
}
/****************************************
*函数名称:disk_read
*输 入:drv -指定要初始化的逻辑驱动器号,即盘符
应当取值0~9
buff -数据读取缓冲区
sector -读扇区地址
count -连续读多少个扇区
*输 出:函数返回一个磁盘状态作为结果
*功 能:在磁盘驱动器上读取扇区
******************************************/
DRESULT disk_read (
BYTE drv,
BYTE *buff,
DWORD sector,
BYTE count
)
{
UINT8 res;
if (count==1){
res = SD_ReadDisk(buff,sector,count);
}
else{
}
if(res==0){
return RES_OK;
}
else{
return RES_ERROR;
}
}
/****************************************
*函数名称:disk_write
*输 入:drv -指定要初始化的逻辑驱动器号,即盘符
应当取值0~9
buff -数据写入缓冲区
sector -写扇区地址
count -连续写多少个扇区
*输 出:函数返回一个磁盘状态作为结果
*功 能:在磁盘驱动器上写入扇区
******************************************/
#if _READONLY == 0
DRESULT disk_write (
BYTE drv,
const BYTE *buff,
DWORD sector,
BYTE count
)
{
UINT8 res;
if (count==1){
res = SD_WriteDisk((UINT8 *)buff,sector,count);
}
else{
}
if(res==0){
return RES_OK;
}
else{
return RES_ERROR;
}
}
#endif /* _READONLY */
/****************************************
*函数名称:disk_write
*输 入:drv -指定要初始化的逻辑驱动器号,即盘符
应当取值0~9
ctrl -指定命令代码
buff -指向参数缓冲区的指针,取决于命令代码
count
*输 出:函数返回一个磁盘状态作为结果
*功 能:控制设备指定特性和除了读/写外的杂项功能
******************************************/
DRESULT disk_ioctl (
BYTE drv,
BYTE ctrl,
void *buff
)
{
return RES_OK;
}
/****************************************
*函数名称:get_fattime
*输 入:无
*输 出:当前时间以双字值封装返回,位域如下:
bit31:25 年(0~127)(从1980开始)
bit24:21 月(1~12)
bit20:16 日(1~31)
bit15:11 时(0~23)
bit10:5 分(0~59)
bit4:0 秒(0~59)
*功 能:获取当前时间
******************************************/
DWORD get_fattime(void)
{
return 0;
}
ffconfig.h (进行配置)
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.09 (C)ChaN, 2011
/----------------------------------------------------------------------------/
/
/ CAUTION! Do not forget to make clean the project after any changes to
/ the configuration options.
/
/----------------------------------------------------------------------------*/
#ifndef _FFCONF
#define _FFCONF 6502 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Functions and Buffer Configurations
/----------------------------------------------------------------------------*/
#define _FS_TINY 1 /* 0:Normal or 1:Tiny */
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
/ object instead of the sector buffer in the individual file object for file
/ data transfer. This reduces memory consumption 512 bytes each file object. */
#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
/ f_truncate and useless f_getfree. */
#define _FS_MINIMIZE 0 /* 0 to 3 */
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/
/ 0: Full function.
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
/ are removed.
/ 2: f_opendir and f_readdir are removed in addition to 1.
/ 3: f_lseek is removed in addition to 2. */
#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
#define _USE_MKFS 0 /* 0:Disable or 1:Enable */
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/----------------------------------------------------------------------------*/
#define _CODE_PAGE 1
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
/ 949 - Korean (DBCS, OEM, Windows)
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
/ 1250 - Central Europe (Windows)
/ 1251 - Cyrillic (Windows)
/ 1252 - Latin 1 (Windows)
/ 1253 - Greek (Windows)
/ 1254 - Turkish (Windows)
/ 1255 - Hebrew (Windows)
/ 1256 - Arabic (Windows)
/ 1257 - Baltic (Windows)
/ 1258 - Vietnam (OEM, Windows)
/ 437 - U.S. (OEM)
/ 720 - Arabic (OEM)
/ 737 - Greek (OEM)
/ 775 - Baltic (OEM)
/ 850 - Multilingual Latin 1 (OEM)
/ 858 - Multilingual Latin 1 + Euro (OEM)
/ 852 - Latin 2 (OEM)
/ 855 - Cyrillic (OEM)
/ 866 - Russian (OEM)
/ 857 - Turkish (OEM)
/ 862 - Hebrew (OEM)
/ 874 - Thai (OEM, Windows)
/ 1 - ASCII only (Valid for non LFN cfg.)
*/
//#define _USE_LFN 0 /* 0 to 3 */
#define _USE_LFN 0 /* 0 to 3 */
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN option switches the LFN support.
/
/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
/ Unicode handling functions ff_convert() and ff_wtoupper() must be added
/ to the project. When enable to use heap, memory control functions
/ ff_memalloc() and ff_memfree() must be added to the project. */
#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
/* To switch the character code set on FatFs API to Unicode,
/ enable LFN feature and set _LFN_UNICODE to 1. */
#define _FS_RPATH 0 /* 0 to 2 */
/* The _FS_RPATH option configures relative path feature.
/
/ 0: Disable relative path feature and remove related functions.
/ 1: Enable relative path. f_chdrive() and f_chdir() are available.
/ 2: f_getcwd() is available in addition to 1.
/
/ Note that output of the f_readdir fnction is affected by this option. */
/*---------------------------------------------------------------------------/
/ Physical Drive Configurations
/----------------------------------------------------------------------------*/
#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
/* Maximum sector size to be handled.
/ Always set 512 for memory card and hard disk but a larger value may be
/ required for on-board flash memory, floppy disk and optical disk.
/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size
/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */
#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */
/* When set to 0, each volume is bound to the same physical drive number and
/ it can mount only first primaly partition. When it is set to 1, each volume
/ is tied to the partitions listed in VolToPart[]. */
#define _USE_ERASE 0 /* 0:Disable or 1:Enable */
/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command
/ should be added to the disk_ioctl functio. */
/*---------------------------------------------------------------------------/
/ System Configurations
/----------------------------------------------------------------------------*/
#define _WORD_ACCESS 0 /* 0 or 1 */
/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS
/ option defines which access method is used to the word data on the FAT volume.
/
/ 0: Byte-by-byte access.
/ 1: Word access. Do not choose this unless following condition is met.
/
/ When the byte order on the memory is big-endian or address miss-aligned word
/ access results incorrect behavior, the _WORD_ACCESS must be set to 0.
/ If it is not the case, the value can also be set to 1 to improve the
/ performance and code size.
*/
/* A header file that defines sync object types on the O/S, such as
/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */
#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module.
/
/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
/ 1: Enable reentrancy. Also user provided synchronization handlers,
/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
/ function must be added to the project. */
#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */
/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
defines how many files can be opened simultaneously. */
#endif /* _FFCONFIG */
对于创建读写TXT的程序(混合了SD底层的直接读写):
//SD TEST
mem_init(); //初始化内部内存池
Delay_Ms(300);
while(SD_Initialize())//检测不到SD卡
{
printf("SD Card Error!\r\n");
printf("Please Check! \r\n");
LED2_TOG();
Delay_Ms(300);
}
//检测SD卡成功
LED2_OFF();
printf("SD Card OK!\r\n");
sd_size=SD_GetSectorCount();
printf("SD Card Size: %d MB\r\n",sd_size>>11);
SD_Read_Sectorx(0);
printf("\r\n");
//通过FATFS系统函数
f_mount(0,&fs);
/* 得到SD卡的总容量和剩余容量 */
while(fat_getfree("0",&total,&free))
{
printf("@:FAT ERROR!\r\n");
LED2_TOG();
Delay_Ms(300);
}
LED2_OFF();
printf("SD total is:%dMB!\r\n",total>>10);
printf("SD Free is:%dMB!\r\n",free>>10);
/////////////////////////
printf("FatFS write read test!\r\n");
/* 创建文件并可对其写入 */
rt = f_open(&fdst,"0:/Write.txt",FA_CREATE_ALWAYS | FA_WRITE);
if ( rt == FR_OK )
{
printf(">Create Write.txt successful!\r\n");
/* 将缓冲区的数据写到文件中 */
rt = f_write(&fdst,g_szTextBuf, sizeof(g_szTextBuf), &bw);
/*关闭文件 */
f_close(&fdst);
printf(">Write Write.txt successful!\r\n");
}
else
{
printf("[url=home.php?mod=space&uid=322316]@create[/url] Write.txt failed!\r\n");
}
Delay_Ms(1000);
rt=f_open(&fdst,"0:/Write.txt",FA_READ);//打开文件
if(rt == FR_OK)
{
printf(">Open Write.txt successful!\r\n");
f_read(&fdst,buf,512,(UINT32*)&br);
if(br)
{
printf(">The read data is: %s \r\n",buf);
}
else
{
printf("[url=home.php?mod=space&uid=1100831]@read[/url] data failed!\r\n");
}
}
f_close(&fdst);
/////////////////////////
printf("FatFS read test!\r\n");
//打开SD卡test.txt文本
rt=f_open(&fdst,"0:/Book/test.txt",FA_READ);
if(rt==0)
{
f_read(&fdst,buf,512,(UINT32*)&len);
if(len)
{
printf("the read data is :%s\r\n",buf);
}
else
{
printf("[url=home.php?mod=space&uid=1100831]@read[/url] data failed!\r\n");
}
}
else
{
printf("No such files,please check!\r\n");
}
f_close(&fdst);
遍历目录函数:
void ScanFileWithLevel(u8 * path)
{
//现采用目录深度可控的非递归方法如下:
#define LEVEL <font color="#ff0000">3 </font> //LEVEL设置大小代表遍历的深度,8就代表8层,内存足够的话可以设置更大些
u8 j,m;
u8 l[LEVEL]; //l[]保存每层文件夹长度,返回上级目录时用
DIR dir_a[LEVEL]; //FATFS使用的目录结构,只有这个比较占内存需要LEVEL*36字节
char tbuf[64]; //注意tbuf的大小要能放得下最深的文件名绝对路径
char *fn;
m = 0;
j = 1;
strcpy(tbuf,path);
printf("the root path:%s\r\n", tbuf);
while(1)
{
if ( j > m )
{ //只有搜索子目录时才执行
f_opendir(&dir_a[j-1], (TCHAR*)tbuf);
l[j-1] = strlen((char *)tbuf);
}
m = j;
f_readdir(&dir_a[j-1], &fileinfo); //读取当前目录下的一个文件
if (fileinfo.fname[0] == 0)
{ //到末尾了,退出
if (j>1) j--; //下个循环进入父目录
else break;
tbuf[l[j-1]] = '\0'; //存储的路径返回上级目录
}
else
{
#if _USE_LFN
fn = *fileinfo.lfname ? fileinfo.lfname : fileinfo.fname;
#else
fn = fileinfo.fname;
#endif
sprintf((char *)tbuf,"%s/%s",tbuf,fn);//搜索到的文件或文件名连接成完整的路径
//strcat(tbuf,"/");
//strcat(tbuf,fn);//字符串连接
if (fileinfo.fattrib & AM_DIR)
{ //是目录
printf("%s [%dD]\r\n", tbuf,j); //打印目录
if (j<LEVEL) j++; //下个循环进入子目录
}
else
{
printf("%s [%dF]\r\n", tbuf,j); //打印文件
tbuf[l[j-1]] = '\0'; //存储的路径返回目录
}
}
}
}
执行结果如图(当前深度设置为3):
程序结构目录(整合了板上的一些外设,板子引脚设计的有些合理):
移植过程中发现把变量赋值给其本身也会报错:
这时蛋疼,修改IDE的代码分析功能:
右击工程名--->属性:
程序比较乱,请高手勿喷:
FATFS.rar
(939.08 KB)
|
|
good