f_mount(0, &fs); //将文件系统设置到0区
if (f_opendir(&dirs, (const TCHAR*)”0:/Song”) == FR_OK) //读取该磁盘的根目录
{
while (f_readdir(&dirs, &finfo) == FR_OK) //循环依次读取文件名
{
if(!finfo.fname[0]) break; //如果是文件名为空表示到目录的末尾。退出
USART_OUT(USART1,"
文件名是:
%s
",finfo.lfname); //输出文件名---这里读出文件名是正常的
fn = finfo.lfname;
strcpy(ShuZu1,"0:/MUSIC/"); //复制路径(目录)
strcat(ShuZu1,(const char*)fn); //将文件名接在后面
res = f_open(&fsrc, ShuZu1, FA_OPEN_EXISTING | FA_READ); //长文件名
while(1)
{
res = f_read(&fsrc, buffer, sizeof(buffer), &br);//在这里无法读取数据 读出的res是9 说文件/目录对象是无效 原因?
......
if (res || br == 0) break; // 是否到文件尾
}
}
}
问题是读取Song文件夹中的文件名是正确的,无法读取文件的数据,请问问题出在哪里
自己恢复一下,问题找到了
打开的文件是Song文件不是Music文件,都是移植别人的东西没有细心看造成的
void Play_Music(void)
{
FILINFO finfo;//文件结构
DIR dirs;//目录对象结构
unsigned int count=0;
char * ShuZu1;
f_mount(0, &fs); //将文件系统设置到0区
if (f_opendir(&dirs, (const TCHAR*)”0:/Song”) == FR_OK)
{
while (f_readdir(&dirs, &finfo) == FR_OK) //循环依次读取文件名
{
ShuZu1=mymalloc(SRAMIN,finfo.lfsize); //为带路径的文件名分配内存
strcpy(ShuZu1,”0:/Song/”); //复制路径(目录)
strcat(ShuZu1,(const char*)finfo.lfname); //将文件名接在后面
res = f_open(&fsrc, ShuZu1, FA_OPEN_EXISTING | FA_READ);
br=1;
for (;;) {
res = f_read(&fsrc, buffer, sizeof(buffer), &br);
...
if (res || br == 0) break; // 是否到文件尾
}
f_close(&fsrc);
}
}
}
if (f_opendir(&dirs, (const TCHAR*)”0:/Song”) == FR_OK)这里只有一个/一定要注意哦 还有不是
strcpy(ShuZu1,”0:/Song/”);)这里只有两个/一定要注意哦 还有不是
FATFS fs; // 逻辑驱动器的标志
FIL fsrc, fdst; // 文件标志
unsigned char buffer[512]; // 文件内容缓冲区
FRESULT res; // FatFs 功能函数返回结果变量
unsigned int br, bw; // 文件读/写计数器
char str[100][100]; //存放文件名称
void Play_Music(void)
{
FILINFO finfo;
DIR dirs;
unsigned int count=0;
char path[50]={""},j=0;
char *result1;
char EXT1[4]=".mp3";
unsigned short i;
/*开启长文件名功能时, 要预先初始化文件名缓冲区的长度 */
#if _USE_LFN
static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1];
finfo.lfname = lfn;
finfo.lfsize = sizeof(lfn);
#endif
USART_OUT(USART1,"
文件系统(Tini-FatFS0.08b)启动成功!
");
disk_initialize(0); //fatfs可以管理多个介质的分区, 所以把物理存储介质SST25VF016B标示为0区,相当于磁盘编号
VS1003_start();
f_mount(0, &fs); //将文件系统设置到0区
if (f_opendir(&dirs, path) == FR_OK) //读取该磁盘的根目录
{
while (f_readdir(&dirs, &finfo) == FR_OK) //循环依次读取文件名
{
if (finfo.fattrib & AM_ARC) //判断文件属性是否为存档型 TXT文件一般都为存档型
{
if(!finfo.fname[0]) break; //如果是文件名为空表示到目录的末尾。退出
if(finfo.lfname[0])//长文件名
{
USART_OUT(USART1,"
文件名是:
%s
",finfo.lfname); //输出长文件名
result1=strstr(finfo.lfname,EXT1); //判断是否是mp3后缀的文件名
}
else//8.3格式文件名
{
USART_OUT(USART1,"
文件名是:
%s
",finfo.fname); //输出8.3格式文件名
result1=strstr(finfo.fname,EXT1); //判断是否是mp3后缀的文件名
}
if(result1!=NULL)
{
if(finfo.lfname[0])
{ //长文件名
// strcpy(str[i],(const char *)finfo.lfname); //将文件名暂存到数组里,以备LISTBOX调用
// i++;
}
else
{ //8.3格式文件名
// strcpy(str[i],(const char *)finfo.fname); //将文件名暂存到数组里,以备LISTBOX调用
// i++;
} //文件建立及增加内容。
}
}
}
}
}
为什么添加上strcpy(str[i],(const char *)finfo.fname);这个函数读取就不正常了呢 求解
FATFS fs; // 逻辑驱动器的标志
FIL fsrc, fdst; // 文件标志
unsigned char buffer[512]; // 文件内容缓冲区
FRESULT res; // FatFs 功能函数返回结果变量
unsigned int br, bw; // 文件读/写计数器
char str[100][100]; //存放文件名称
void Play_Music(void)
{
FILINFO finfo;
DIR dirs;
unsigned int count=0;
char path[50]={""},j=0;
char *result1;
char *ShuZu1;
char EXT1[4]=".mp3";
unsigned short i;
//开启长文件名功能时, 要预先初始化文件名缓冲区的长度
#if _USE_LFN
static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1];
finfo.lfname = lfn;
finfo.lfsize = sizeof(lfn);
#endif
USART_OUT(USART1,"
文件系统(Tini-FatFS0.08b)启动成功!
");
disk_initialize(0); //fatfs可以管理多个介质的分区, 所以把物理存储介质SST25VF016B标示为0区,相当于磁盘编号
VS1003_start();
f_mount(0, &fs); //将文件系统设置到0区
if (f_opendir(&dirs, path) == FR_OK) //读取该磁盘的根目录
{
while (f_readdir(&dirs, &finfo) == FR_OK) //循环依次读取文件名
{
if (finfo.fattrib & AM_ARC) //判断文件属性是否为存档型 TXT文件一般都为存档型
{
if(!finfo.fname[0]) break; //如果是文件名为空表示到目录的末尾。退出
if(finfo.lfname[0])//长文件名
{
USART_OUT(USART1,"
文件名是:
%s
",finfo.lfname); //输出长文件名
result1=strstr(finfo.lfname,EXT1); //判断是否是mp3后缀的文件名
}
else//8.3格式文件名
{
USART_OUT(USART1,"
文件名是:
%s
",finfo.fname); //输出8.3格式文件名
// result1=strstr(finfo.fname,EXT1); //判断是否是mp3后缀的文件名
}
// if(result1!=NULL)
{
if(finfo.lfname[0])
{ //长文件名
ShuZu1=mymalloc(SRAMIN,finfo.lfsize);
strcat(ShuZu1,(const char*)finfo.lfname);
// strcpy(str[i],(const char *)finfo.lfname); //将文件名暂存到数组里,以备LISTBOX调用
USART_OUT(USART1,"
文件名是:
%s
",ShuZu1);
i++;
}
else
{ //8.3格式文件名
// strcpy(str[i],(const char *)finfo.fname); //将文件名暂存到数组里,以备LISTBOX调用
// i++;
} //文件建立及增加内容。
}
}
}
}
}
这样是正常的 请问为什么
----------
那么如何读取文件的大小呢
采用ff.h中的#define f_size(fp) ((fp)->fsize)
----------
如何在已有文件后面继续写数据呢?
1种方法是利用读写方法 这对于不大的文件可以
2种方法是先读出文件的大小,然后偏移到文件的最后,再进行写数据
`
----------
/*-----------例程所用到的文件系统函数原型------------------------
---------------在文件系统中注册/注销 工作区(0-9)-----------------------------------------------------------------
FRESULT f_mount (
BYTE Drive, //Logical drive number
FATFS* FileSystemObject // Pointer to the work area
);
参数:
Drive:用逻辑驱动器号(0-9) 去注册/注销 工作区
FileSystemObject:文件系统工作区的标识。
--------------------------------------------------------------------------------
---------------打开目录------------------------------------------------------------------
FRESULT f_opendir (
DIR* DirObject, //空目录结构指针
const TCHAR* DirName //目录名指针
)
返回值:
FR_OK (0) 打开目录成功
--------------------------------------------------------------------------------
---------------读取目录下的文件名 --------------------------------------------------------
FRESULT f_readdir (
DIR* DirObject, // 目录结构指针
FILINFO* FileInfo // 文件信息指针
);
返回值:
FR_OK (0) 读取文件名成功
-------------------------------------------------------------------------------------------
----------------为了存取数据,打开文件目标----------------------------------------------------------
FRESULT f_open (
FIL* FileObject, // 文件结构型指针
const TCHAR* FileName, // 文件名指针
BYTE ModeFlags // 模式标志
);
ModeFlags:
FA_OPEN_EXISTING: 指定为文件不存在的话,返回错误
FA_READ: 指定为文件读
FA_CREATE_ALWAYS: 文件不存在的话,直接建立
FA_WRITE: 指定为文件写
--------------------------------------------------------------------------
-----------------读文件数据--------------------------------------------------------------
FRESULT f_read (
FIL* FileObject, // 文件结构型指针
void* Buffer, // 读数据缓冲区指针
UINT ByteToRead, // 要读取的字节数
UINT* ByteRead // 返回的所读取的可变字节数的指针
);
----------------------------------------------------------------------------------
-----------------写文件数据-------------------------------------------------------
FRESULT f_write (
FIL* FileObject, // 文件结构型指针
const void* Buffer, // 写数据缓冲区指针
UINT ByteToWrite, // 要写入的字节数
UINT* ByteWritten // 返回的所写入的可变字节数的指针
);
----------------------------------------------------------------------------------
-----------------关闭打开的文件---------------------------------------------------
FRESULT f_close (
FIL* FileObject // 文件结构型指针
);
-------------------------------------------------------------------------------
*/
``
----------
/*
说明:
* 下面测试的是在根目录下建立一个RECORDER文件夹,然后在RECORDER文件夹下建立一个”测试.txt”文件,如果”测试.txt”文件存在就打开这个文件
* 在”测试.txt”文件下写入512个8
* f_lseek(&fdst,0);这里函数的意思是假设文件中有1000个数据,把指针移动到第一个位置上,500就是把指针移动到文件中的第500位置处
* 作者:Flame
* 测试时间:20130710
*/
/*
void OutPutFile(void)
{
unsigned int a;
FILINFO finfo;
DIR dirs;
//开启长文件名功能时, 要预先初始化文件名缓冲区的长度 //
if _USE_LFN
static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1];
finfo.lfname = lfn;
finfo.lfsize = sizeof(lfn);
endif
USART_OUT(USART1,"
STM32开发板文件系统(Tini-FatFS0.08b)启动成功!
");
disk_initialize(0); //fatfs可以管理多个介质的分区, 所以把物理存储介质SST25VF016B标示为0区,相当于磁盘编号
f_mount(0, &fs); //将文件系统设置到0区
while(f_opendir(&dirs,"0:/RECORDER"))//打开录音文件夹
{
USART_OUT(USART1,"
打开RECORDER目录失败,正在建立RECORDER文件夹
%s
",finfo.lfname);
f_mkdir("0:/RECORDER"); //创建该目录
}
res = f_open(&fdst, "0:/RECORDER/测试.txt", FA_CREATE_ALWAYS | FA_WRITE); //以写的方式打开文件,如果不存在,就直接建立,如果存在就覆盖掉
br=512;
for(a=0; a<512; a++) buffer[a]=0x38; //因为可以一次读出512字节,先清空数据缓冲区
f_lseek(&fdst,0); //偏移到文件头.
res = f_write(&fdst, buffer, br, &bw); //将缓冲区的内容写入到目标文件 也就是a2.txt
//if (res || bw < br) break; // error or disk full //如果写入时异常,或者磁盘满,退出 如果是循环写入可以调用这一句来判断写的状态
f_close(&fdst); //关闭源文件
}*/
/*
说明:
* 下面的函数是测试把跟目录中的txt文件读出,并把内容拷贝到在根目录下新建立的a2.txt中
* 下面测试的条件是TF卡中必须有一个.txt的文件,并且.txt文件里面有内容,.txt文件必须在跟目录下
* 通过调用f_read(&fsrc, buffer, sizeof(buffer), &br),然后读取br可以得到读取数据的大小
* 要注意的是f_close(&fsrc);和f_close(&fdst);千万不要搞混
* 作者:Flame
* 测试时间:20130710
*/
/*void OutPutFile(void)
{
unsigned int a;
FILINFO finfo;
DIR dirs;
char path[50]={""}; //目录名为空,表示是根目录
//开启长文件名功能时, 要预先初始化文件名缓冲区的长度
#if _USE_LFN
static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1];
finfo.lfname = lfn;
finfo.lfsize = sizeof(lfn);
#endif
USART_OUT(USART1,"
稴TM32开发板文件系统(Tini-FatFS0.08b)启动成功!
");
disk_initialize(0); //fatfs可以管理多个介质的分区, 所以把物理存储介质SST25VF016B标示为0区,相当于磁盘编号
f_mount(0, &fs); //将文件系统设置到0区
if (f_opendir(&dirs, path) == FR_OK) //读取该磁盘的根目录
{
while (f_readdir(&dirs, &finfo) == FR_OK) //循环依次读取文件名
{
if (finfo.fattrib & AM_ARC) //判断文件属性是否为存档型 TXT文件一般都为存档型
{
if(!finfo.fname[0]) break; //如果是文件名为空表示到目录的末尾。退出
if(finfo.lfname[0]){USART_OUT(USART1,"
文件名是:
%s
",finfo.lfname);} //输出长文件名
else{USART_OUT(USART1,"
文件名是:
%s
",finfo.fname);} //输出8.3格式文件名
//if(result1!=NULL||result2!=NULL)//是的话就输出文件的内容
{
if(finfo.lfname[0]){res = f_open(&fsrc, finfo.lfname, FA_OPEN_EXISTING | FA_READ);}//以读的方式打开文件
else{res = f_open(&fsrc, finfo.fname, FA_OPEN_EXISTING | FA_READ); }//8.3格式文件名 以读的方式打开文件
res1 = f_open(&fdst, "a2.txt", FA_CREATE_ALWAYS | FA_WRITE); //以写的方式打开文件,如果不存在,就直接建立,如果存在就覆盖掉
br=1;
for (;;)
{ //循环读出被打开文件的扇区
for(a=0; a<512; a++) buffer[a]=0; //因为可以一次读出512字节,先清空数据缓冲区
res = f_read(&fsrc, buffer, sizeof(buffer), &br); //将文件内容读出到数据缓冲区 br存储此次读出数据的数量,最大512
USART_OUT(USART1,"%s
",buffer); //将缓冲区的内容输出到串口1
if (res || br == 0) break; // error or eof //判断是否到文件结束
res1 = f_write(&fdst, buffer, br, &bw); //将缓冲区的内容写入到目标文件 也就是a2.txt br是在读的时候设置了写入的大小,通过查看br可以确定写入数据的多少
if (res1 || bw < br) break; // error or disk full //如果写入时异常,或者磁盘满,退出
}
f_close(&fsrc); //关闭源文件
//res1 = f_write(&fdst, buffer, br, &bw);在这里可以添加f_write,以便添加其他数据
}
f_close(&fdst);//关闭目标文件 本条函数即时保存写入的数据,又是关闭目标文件,如有很多数据要写入,但不需要现在关闭可以调用f_sync函数,但是调用 f_sync前必蠪S_READONLY == 0可用
}
}
}
}*/
----------
如何在已有文件后面继续写数据呢?
1种方法是利用读写方法 这对于不大的文件可以
2种方法是先读出文件的大 ...
第二种操作步骤如下
1.f_mount(0, &fs); //将文件系统设置到0区
2.f_opendir(&dirs, path) //读取该磁盘的根目录
3.f_readdir(&dirs, &finfo) //循环依次读取文件名
4.if(finfo.lfname[0]){res = f_open(&fsrc, finfo.lfname, FA_OPEN_EXISTING | FA_READ);}//以读的方式打开文件
else{res = f_open(&fsrc, finfo.fname, FA_OPEN_EXISTING | FA_READ); }//8.3格式文件名 以读的方式打开文件
5.numSize1 = f_size(&fsrc); //读取文件大小
6.偏移到文件内容的尾部
以上说的有不对的地方希望高人多多指点,这样愚人自己总结的
“/*
说明:
* 下面的函数是测试在已有的”大海.txt”文件下继续添加数据
* 测试条件在TF卡中建立”大海.txt”文件,并在文件中添加内容,测试过程中可以分别添加<512数据,=512数据,>512数据进行分别测试
* 作者:Flame
* 测试时间:20130711
*/
unsigned int FATFSNumSize;//文件大小存储变量,为了查看方便放到函数外部
void OutPutFile(void)
{
unsigned int a;
FILINFO finfo;
DIR dirs;
char path[50]={“”}; //目录名为空,表示是根目录
//开启长文件名功能时, 要预先初始化文件名缓冲区的长度
if _USE_LFN
static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1];
finfo.lfname = lfn;
finfo.lfsize = sizeof(lfn);
endif
USART_OUT(USART1,"
STM32开发板文件系统(Tini-FatFS0.08b)启动成功!
");
disk_initialize(0); //fatfs可以管理多个介质的分区, 所以把物理存储介质SST25VF016B标示为0区,相当于磁盘编号
f_mount(0, &fs); //将文件系统设置到0区
if (f_opendir(&dirs, path) == FR_OK) //读取该磁盘的根目录
{
while (f_readdir(&dirs, &finfo) == FR_OK) //循环依次读取文件名
{
if (finfo.fattrib & AM_ARC) //判断文件属性是否为存档型 TXT文件一般都为存档型
{
if(!finfo.fname[0]) break; //如果是文件名为空表示到目录的末尾。退出
if(finfo.lfname[0]){USART_OUT(USART1,"
文件名是:
%s
",finfo.lfname);} //输出长文件名
else{USART_OUT(USART1,"
文件名是:
%s
",finfo.fname);} //输出8.3格式文件名
if(finfo.lfname[0]){res = f_open(&fsrc, finfo.lfname, FA_OPEN_EXISTING | FA_READ);}//以读的方式打开文件
else{res = f_open(&fsrc, finfo.fname, FA_OPEN_EXISTING | FA_READ); } //8.3格式文件名 以读的方式打开文件
FATFSNumSize = f_size(&fsrc); //读出文件的大小,说明读取文件大小必须在打开文件后才能读出
br=1;
for (;;)
{ //循环读出被打开文件的扇区
for(a=0; a<512; a++) buffer[a]=0; //因为可以一次读出512字节,先清空数据缓冲区
res = f_read(&fsrc, buffer, sizeof(buffer), &br); //将文件内容读出到数据缓冲区 br存储此次读出数据的数量,最大512
USART_OUT(USART1,"%s
",buffer); //将缓冲区的内容输出到串口1
if (res || br == 0) break; // error or eof //判断是否到文件结束
}
f_close(&fsrc); //关闭源文件
res1 = f_open(&fdst, "大海.txt", FA_CREATE_ALWAYS | FA_WRITE); //以写的方式打开"大海.txt"文件
if(finfo.lfname[0]) {res = f_open(&fsrc, finfo.lfname, FA_CREATE_ALWAYS | FA_WRITE);} //以写的方式打开文件
else {res = f_open(&fsrc, finfo.fname, FA_CREATE_ALWAYS | FA_WRITE); } //8.3格式文件名 以写的方式打开文件
for(a=0; a<512; a++) buffer[a]=0x36; //往buffer中写入512个6
f_lseek(&fsrc,FATFSNumSize); //偏移到打开文件内容的后面
//在这里要重点说明的是如果numSize<512将会把数据覆盖,如果numSize>512切numSize%512得到的余数将会覆盖,所有如果numSize不是512的整倍数,要单独做处理
//我的方法是读取这不到1个扇区的数据,放到缓冲区,然后将512-numSize%512的数据填入缓冲区,写入TF(SD)卡数据,然后再写剩余的数据
br=512; //写入512个数据
res1 = f_write(&fsrc, buffer, br, &bw);
f_close(&fsrc);//关闭目标文件 本条函数即时保存写入的数据,又是关闭目标文件,如有很多数据要写入,但不需要现在关闭可以调用f_sync函数,但是调用 f_sync前必把S_READONLY == 0可用
}
}
}
}
文件函数的返回代码 处理报告
void die ( FRESULT res )
{
switch (res)
{
case FR_OK: USART_OUT(USART1,"FR_OK");break;
case FR_DISK_ERR: USART_OUT(USART1,"FR_DISK_ERR");break;
case FR_INT_ERR: USART_OUT(USART1,"FR_INT_ERR");break;
case FR_NOT_READY: USART_OUT(USART1,"FR_NOT_READY");break;
case FR_NO_FILE: USART_OUT(USART1,"FR_NO_FILE");break;
case FR_NO_PATH: USART_OUT(USART1,"FR_NO_PATH");break;
case FR_INVALID_NAME: USART_OUT(USART1,"FR_INVALID_NAME");break;
case FR_DENIED: USART_OUT(USART1,"FR_DENIED");break;
case FR_EXIST: USART_OUT(USART1,"FR_EXIST");break;
case FR_INVALID_OBJECT: USART_OUT(USART1,"FR_INVALID_OBJECT");break;
case FR_WRITE_PROTECTED: USART_OUT(USART1,"FR_WRITE_PROTECTED");break;
case FR_INVALID_DRIVE: USART_OUT(USART1,"FR_INVALID_DRIVE");break;
case FR_NOT_ENABLED: USART_OUT(USART1,"FR_NOT_ENABLED");break;
case FR_NO_FILESYSTEM: USART_OUT(USART1,"FR_NO_FILESYSTEM");break;
case FR_MKFS_ABORTED: USART_OUT(USART1,"FR_MKFS_ABORTED");break;
case FR_TIMEOUT: USART_OUT(USART1,"FR_TIMEOUT");break;
case FR_LOCKED: USART_OUT(USART1,"FR_LOCKED");break;
case FR_NOT_ENOUGH_CORE: USART_OUT(USART1,"FR_NOT_ENOUGH_CORE");break;
case FR_TOO_MANY_OPEN_FILES: USART_OUT(USART1,"FR_TOO_MANY_OPEN_FILES");break;
}
printf ("
");
}