使用FATFS只是完成了一个基本的文件读写,有时候我们需要扩展一些功能,比如MP3实验,需要上一曲下一曲的切换,扩展的代码如下

//显示目录下所有文件
u8 ShowFileList(u8* dirPath)
{
u8 *pname; //带路径的文件名,最终生成的文件名
char *fn; //文件名(不带目录名称)
u16 fileNameLength = ; //文件长度
u16 showPos = ; //当前显示的坐标
FILINFO* fileinfo = malloc(sizeof(FILINFO));//文件信息
DIR* dir = malloc(sizeof(DIR));
#if _USE_LFN//使能长文件名
fileinfo->lfsize = _MAX_LFN * + ;
fileinfo->lfname = malloc(fileinfo->lfsize);
#endif
pname = malloc(fileinfo->lfsize);//申请动态内存
//检测动态内存是否申请成功,任何一个失败都不能继续
if((pname == NULL)||(dir == NULL)||(fileinfo == NULL)||(fileinfo->lfname == NULL) )
{
free(fileinfo);
free(dir);
free(fileinfo->lfname);
free(pname);
return ;//失败
}
sdCardFsResult = f_opendir(dir,(const TCHAR*)dirPath); //打开一个目录
if(sdCardFsResult == FR_OK)
{
while()//循环查找文件
{
sdCardFsResult = f_readdir(dir, fileinfo); //读取目录下的一个文件
if (sdCardFsResult != FR_OK || fileinfo->fname[] == ) break; //错误了/到末尾了,退出
#if _USE_LFN //根据是否使用长文件名来选择一个文件
fn = *fileinfo->lfname ? fileinfo->lfname : fileinfo->fname;
#else
fn = fileinfo.fname;
#endif
strcpy((char*)pname,(const TCHAR*)dirPath); //复制路径(目录)
strcat((char*)pname,(const char*)"\\"); //将文件名接在后面
strcat((char*)pname,(const char*)fn); //将文件名接在后面
fileNameLength = strlen((char*)pname);
Show_Str(,showPos,LCD_X_SIZE,LCD_Y_SIZE,pname,,,LCD_BLACK);
showPos += *(((fileNameLength*)/)+);//每次显示完成看还能加多少,最多就能显示一页
if(showPos >= )break;//超过最大长度,结束循环
}
//关闭文件夹
f_closedir(dir);
//结束的时候要释放内存
free(fileinfo);
free(dir);
free(fileinfo->lfname);
free(pname);
return ;
}
else
{
free(fileinfo);
free(dir);
free(fileinfo->lfname);
free(pname);
return ;//目录打开失败
}
} //显示目录下所有文件,从指定的起始位置开始显示
//文件起始从1开始
u8 ShowFileListStart(u8* dirPath,u8 start)
{
u8 *pname; //带路径的文件名,最终生成的文件名
char *fn; //文件名(不带目录名称)
u16 fileNameLength = ; //文件长度
u8 count = ; //遍历文件计数器
u16 showPos = ; //当前显示的坐标
FILINFO* fileinfo = malloc(sizeof(FILINFO));//文件信息
DIR* dir = malloc(sizeof(DIR));
#if _USE_LFN//使能长文件名
fileinfo->lfsize = _MAX_LFN * + ;
fileinfo->lfname = malloc(fileinfo->lfsize);
#endif
pname = malloc(fileinfo->lfsize);//申请动态内存
//检测动态内存是否申请成功,任何一个失败都不能继续
if((pname == NULL)||(dir == NULL)||(fileinfo == NULL)||(fileinfo->lfname == NULL) )
{
free(fileinfo);
free(dir);
free(fileinfo->lfname);
free(pname);
return ;//失败
}
sdCardFsResult = f_opendir(dir,(const TCHAR*)dirPath); //打开一个目录
if(sdCardFsResult == FR_OK)
{
while()//循环查找文件
{
sdCardFsResult = f_readdir(dir, fileinfo); //读取目录下的一个文件
if (sdCardFsResult != FR_OK || fileinfo->fname[] == ) break; //错误了/到末尾了,退出
#if _USE_LFN //根据是否使用长文件名来选择一个文件
fn = *fileinfo->lfname ? fileinfo->lfname : fileinfo->fname;
#else
fn = fileinfo.fname;
#endif
count++;
if(count >= start)
{
strcpy((char*)pname,(const TCHAR*)dirPath); //复制路径(目录)
strcat((char*)pname,(const char*)"\\"); //将文件名接在后面
strcat((char*)pname,(const char*)fn); //将文件名接在后面
fileNameLength = strlen((char*)pname);
Show_Str(,showPos,LCD_X_SIZE,LCD_Y_SIZE,pname,,,LCD_BLACK);
showPos += *(((fileNameLength*)/)+);//每次显示完成看还能加多少,最多就能显示一页
if(showPos >= )break;//超过最大长度,结束循环
}
}
//关闭文件夹
f_closedir(dir);
//结束的时候要释放内存
free(fileinfo);
free(dir);
free(fileinfo->lfname);
free(pname);
return ;
}
else
{
free(fileinfo);
free(dir);
free(fileinfo->lfname);
free(pname);
return ;//目录打开失败
}
} //从文件夹中获取特定文件的文件名(包含完整路径)
//索引index从1开始
u8* GetFileNameFormDir(u8* dirPath,u8 index)
{
u8 *pname; //带路径的文件名,最终生成的文件名
char *fn; //文件名(不带目录名称)
u8 count = ; //遍历文件计数器
u16 showPos = ; //当前显示的坐标
FILINFO* fileinfo = malloc(sizeof(FILINFO));//文件信息
DIR* dir = malloc(sizeof(DIR));
#if _USE_LFN//使能长文件名
fileinfo->lfsize = _MAX_LFN * + ;
fileinfo->lfname = malloc(fileinfo->lfsize);
#endif
pname = malloc(fileinfo->lfsize);//申请动态内存
//检测动态内存是否申请成功,任何一个失败都不能继续
if((pname == NULL)||(dir == NULL)||(fileinfo == NULL)||(fileinfo->lfname == NULL) )
{
free(fileinfo);
free(dir);
free(fileinfo->lfname);
free(pname);
return NULL;//失败
}
sdCardFsResult = f_opendir(dir,(const TCHAR*)dirPath); //打开一个目录
if(sdCardFsResult == FR_OK)
{
while()//循环查找文件
{
sdCardFsResult = f_readdir(dir, fileinfo); //读取目录下的一个文件
if (sdCardFsResult != FR_OK || fileinfo->fname[] == ) break; //错误了/到末尾了,退出
#if _USE_LFN //根据是否使用长文件名来选择一个文件
fn = *fileinfo->lfname ? fileinfo->lfname : fileinfo->fname;
#else
fn = fileinfo.fname;
#endif
count++;
if(count == index)
{
strcpy((char*)pname,(const TCHAR*)dirPath); //复制路径(目录)
strcat((char*)pname,(const char*)"\\"); //将文件名接在后面
strcat((char*)pname,(const char*)fn); //将文件名接在后面
//找到了,返回文件名,那就有一个指针没有释放,要注意后期释放
//关闭文件夹
f_closedir(dir);
free(fileinfo);
free(dir);
free(fileinfo->lfname);
return pname;
}
}
//关闭文件夹
f_closedir(dir);
//结束的时候要释放内存
free(fileinfo);
free(dir);
free(fileinfo->lfname);
free(pname);
return NULL;
}
else
{
free(fileinfo);
free(dir);
free(fileinfo->lfname);
free(pname);
return NULL;//目录打开失败
}
} //返回文件数量
u16 GetFileCount(u8* dirPath)
{
u16 fileCount = ;
FILINFO* fileinfo = malloc(sizeof(FILINFO));//文件信息
DIR* dir = malloc(sizeof(DIR));
#if _USE_LFN//使能长文件名
fileinfo->lfsize = _MAX_LFN * + ;
fileinfo->lfname = malloc(fileinfo->lfsize);
#endif
//检测动态内存是否申请成功,任何一个失败都不能继续
if((dir == NULL)||(fileinfo == NULL))
{
free(fileinfo);
free(dir);
#if _USE_LFN//使能长文件名
free(fileinfo->lfname);
#endif
return ;//失败
}
sdCardFsResult = f_opendir(dir,(const TCHAR*)dirPath); //打开一个目录
if(sdCardFsResult == FR_OK)
{
while()//循环查找文件
{
sdCardFsResult = f_readdir(dir, fileinfo); //读取目录下的一个文件
if (sdCardFsResult != FR_OK || fileinfo->fname[] == ) break; //错误了/到末尾了,退出
fileCount++;
}
//关闭文件夹
f_closedir(dir);
//结束的时候要释放内存
free(fileinfo);
free(dir);
#if _USE_LFN//使能长文件名
free(fileinfo->lfname);
#endif
return fileCount;
}
else
{
free(fileinfo);
free(dir);
#if _USE_LFN//使能长文件名
free(fileinfo->lfname);
#endif
return ;//目录打开失败
}
}

有了这一套API就可以组合实现音乐播放器了如下

FIL* currentMusic;        //当前播放音乐文件指针
u8* musicDataBuffer; //音乐文件缓存数组
u8 playState = ; //当前音乐状态,为0标识暂停 为1标识正在播放
u16 sendMusicCount; //当前缓冲区已经发送的音乐文件计数
UINT readCount; //每次读取文件的字符数量
UINT fileReadLength; //文件已经读取的数据总量
u16 currentMusicIndex; //当前音乐文件在音乐文件夹中的位置
u16 musicCount; //当前文件夹中音乐文件的总数 //音乐初始化
//返回0成功 返回1失败
u8 Music_Init(void)
{
u8* name = NULL;
FRESULT result;
//默认初始化选中第一个文件,并且播放暂停
musicCount = GetFileCount("0:音乐");//初始化文件总数
if(musicCount == )return ;//初始化失败
else
{
currentMusicIndex = ;//当前处于第一首歌曲
name = GetFileNameFormDir("0:音乐",currentMusicIndex);//获取当前歌曲名
fileReadLength = ;
readCount = ;
sendMusicCount = ;
playState = ;
LCD_ShowString(,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)" ",LCD_BLACK);
LCD_ShowString(,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)"MP3 STATUS: PALYING ",LCD_BLACK);
LCD_ShowString(,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)" ",LCD_BLACK);
LCD_ShowNum(,,currentMusicIndex,,LCD_BLACK);
LCD_ShowChar(+,,'/',,LCD_BLACK);
LCD_ShowNum(+,,musicCount,,LCD_BLACK);
musicDataBuffer = NULL;
currentMusic = malloc(sizeof(FIL));
//打开第一首歌曲
result = f_open(currentMusic,(TCHAR*)name,FA_READ);
Show_Str(,,LCD_X_SIZE,LCD_Y_SIZE," ",,,LCD_BLACK);
Show_Str(,,LCD_X_SIZE,LCD_Y_SIZE,name,,,LCD_BLACK);
//打开之后要把名称缓存关闭
if(name != NULL)
{
free(name);
}
if(result == FR_OK)
{
VS_Soft_Reset();
musicDataBuffer = malloc();//申请512字节缓存
if(musicDataBuffer == NULL)return ;//初始化失败
//打开成功
VS_SPI_SpeedHigh();
return ;
}
else
{
//打开失败
return ;
}
}
} //播放当前音乐,正常循环
void Player_Current_Music(void)
{
u16 playtime=;//播放时间
u16 time=;// 总时间
u16 f_kbps=;//歌曲文件位率
if(playState == )
{
//持续播放,首先要检查有没有文件打开
if(currentMusic == NULL)
{
return;//没有文件打开
}
else
{
if(fileReadLength == currentMusic->fsize)//已经读取的长度为文件总长度
{
//不在读取,发送完了事
if(sendMusicCount >= readCount)
{
//已经发送完了,不再发送数据
// free(musicDataBuffer);//释放缓存数组
//调用函数,自动切换下一首歌
Switch_Next_Music();
return;
}
else
{
//还需要发送
if(VS_Send_MusicData(musicDataBuffer+sendMusicCount))
{ }
else
{
//发送成功,数据增长
sendMusicCount+=;
}
}
}
else
{
if((fileReadLength%(*)) == )
{
//显示解码时间和当前播放时间以及位率
f_kbps=VS_Get_HeadInfo(); //获得比特率
playtime=VS_Get_DecodeTime(); //得到解码时间
if(f_kbps)time=(currentMusic->fsize/f_kbps)/;//得到秒钟数 (文件长度(字节)/(1000/8)/比特率=持续秒钟数
if(f_kbps)
{
//显示当前播放时间
LCD_ShowNum(,,playtime/,,LCD_BLACK); //分钟
LCD_ShowChar(+,,':',,LCD_BLACK);
LCD_ShowNum(+,,playtime%,,LCD_BLACK); //秒钟
LCD_ShowChar(+,,'/',,LCD_BLACK);
//显示总时间
LCD_ShowNum(+,,time/,,LCD_BLACK); //分钟
LCD_ShowChar(+,,':',,LCD_BLACK);
LCD_ShowNum(+,,time%,,LCD_BLACK); //秒钟
//显示码率
LCD_ShowNum(+,,f_kbps,,LCD_BLACK); //显示位率
LCD_ShowString(+,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)"Kbps",LCD_BLACK);
}
}
//还有读取机会
if(sendMusicCount < readCount)
{
//发送数据
if(VS_Send_MusicData(musicDataBuffer+sendMusicCount))
{
//发送失败,等待下一次发送 }
else
{
//发送成功,数据增长
sendMusicCount+=;
}
}
else
{
//读取下一次数据
f_read(currentMusic,musicDataBuffer,,&readCount);
fileReadLength += readCount;
sendMusicCount = ;
if(readCount > )
{
//发送数据
if(VS_Send_MusicData(musicDataBuffer+sendMusicCount))
{
//发送失败,等待下一次发送 }
else
{
//发送成功,数据增长
sendMusicCount+=;
}
}
}
}
} }
else
{
//音乐暂停,啥都不干
}
} //切换下一个音乐,按键down键
void Switch_Next_Music(void)
{
u8* name = NULL;
FRESULT result;
//第一步是切歌曲
VS_Restart_Play();
//第二步,关闭之前的文件,释放之前使用的缓存
if(currentMusic != NULL)
{
f_close(currentMusic); //关闭文件
free(currentMusic); //释放文件缓存
}
//将文件相关的变量都初始化
if(currentMusicIndex == musicCount)currentMusicIndex = ;//到开头之后转到末尾
else currentMusicIndex++;
fileReadLength = ;
readCount = ;
sendMusicCount = ;
if(musicDataBuffer != NULL)free(musicDataBuffer);//释放缓存
//第三步,重新打开新的文件
name = GetFileNameFormDir("0:音乐",currentMusicIndex);//获取当前歌曲名
currentMusic = malloc(sizeof(FIL));
//打开第一首歌曲
result = f_open(currentMusic,(TCHAR*)name,FA_READ);
Show_Str(,,LCD_X_SIZE,LCD_Y_SIZE," ",,,LCD_BLACK);
Show_Str(,,LCD_X_SIZE,LCD_Y_SIZE,name,,,LCD_BLACK);
if(name != NULL)
{
free(name);
}
if(result == FR_OK)
{
musicDataBuffer = malloc();//申请512字节缓存
//读取第一段
f_read(currentMusic,musicDataBuffer,,&readCount);
fileReadLength+= readCount;
}
VS_Set_All(); //设置音量等信息
VS_Reset_DecodeTime(); //复位解码时间
VS_SPI_SpeedHigh(); //等待传输数据
LCD_ShowString(,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)" ",LCD_BLACK);
LCD_ShowNum(,,currentMusicIndex,,LCD_BLACK);
LCD_ShowChar(+,,'/',,LCD_BLACK);
LCD_ShowNum(+,,musicCount,,LCD_BLACK);
} //切换上一个音乐,按键up键
void Switch_Prev_Music(void)
{
u8* name = NULL;
FRESULT result;
//第一步是切歌曲
VS_Restart_Play();
//第二步,关闭之前的文件,释放之前使用的缓存
if(currentMusic != NULL)
{
f_close(currentMusic); //关闭文件
free(currentMusic); //释放文件缓存
}
//将文件相关的变量都初始化
if(currentMusicIndex == )currentMusicIndex = musicCount;//到末尾之后转到开头
else currentMusicIndex--;
fileReadLength = ;
readCount = ;
sendMusicCount = ;
if(musicDataBuffer != NULL)free(musicDataBuffer);//释放缓存
//第三步,重新打开新的文件
while(name == NULL)
{
name = GetFileNameFormDir("0:音乐",currentMusicIndex);//获取当前歌曲名
Delay_Ms();
}
currentMusic = malloc(sizeof(FIL));
//打开第一首歌曲
result = f_open(currentMusic,(TCHAR*)name,FA_READ);
Show_Str(,,LCD_X_SIZE,LCD_Y_SIZE," ",,,LCD_BLACK);
Show_Str(,,LCD_X_SIZE,LCD_Y_SIZE,name,,,LCD_BLACK);
if(name != NULL)
{
free(name);
}
if(result == FR_OK)
{
musicDataBuffer = malloc();//申请512字节缓存
//读取第一段
f_read(currentMusic,musicDataBuffer,,&readCount);
fileReadLength+= readCount;
}
VS_Set_All(); //设置音量等信息
VS_Reset_DecodeTime(); //复位解码时间
VS_SPI_SpeedHigh(); //等待传输数据
LCD_ShowString(,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)" ",LCD_BLACK);
LCD_ShowNum(,,currentMusicIndex,,LCD_BLACK);
LCD_ShowChar(+,,'/',,LCD_BLACK);
LCD_ShowNum(+,,musicCount,,LCD_BLACK);
} //音乐暂停,按键left键
void Pause_Mucis(void)
{
playState = ;
LCD_ShowString(,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)" ",LCD_BLACK);
LCD_ShowString(,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)"MP3 STATUS: PAUSE ",LCD_BLACK);
} //音乐继续
void Continue_Music(void)
{
playState = ;
//加入是一首歌放完了自动进入的暂停状态就要重新启动这首歌
LCD_ShowString(,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)" ",LCD_BLACK);
LCD_ShowString(,,LCD_X_SIZE,LCD_Y_SIZE,(u8*)"MP3 STATUS: PLAYING ",LCD_BLACK);
}

核心就是这两段代码,剩下的可以看工程代码,VS003的驱动以前写文章说过

http://download.csdn.net/detail/dengrengong/8542891

STM32音乐播放器,文件查找的实现的更多相关文章

  1. 解决Ubuntu14.04下Clementine音乐播放器不能播放wma文件的问题

    参考:Ubuntu 14.04 安装深度音乐的方法 问题描述:播放wma文件时提示"GStreamer插件未安装". 解决方法:安装gstreamer-ffmpeg插件即可解决问题 ...

  2. ios开发学习- 简易音乐播放器2 (基于iPhone4s屏幕尺寸)-- 歌词解析--plist文件应用--imageNamed图片加载耗内存

    声明:(部分图片来自网络,如果侵犯了您的权益请联系我,会尽快删除!) 又是音乐播放器,不过这次和上次不一样了,准确说这次更像播放器了,初学者不建议看这个,可以先看前面一个音乐播放器(1),当然 我没加 ...

  3. 网页播放音频、视频文件——基于web的html 5的音乐播放器(转载)

    文章转载自:开源中国社区 [http://www.oschina.net] 想通过手机客户端(支持 Android.iPhone 和 Windows Phone)访问开源中国:请点这里 HTML5 是 ...

  4. STM32实现Airplay音乐播放器

    AirPlay是苹果公司推出的一套无线音乐解决方案,我们手里的iPhone.iPad甚至是Apple Watch等设备还有电脑上的iTunes都支持AirPlay,但是支持AirPlay功能的音响设备 ...

  5. SE Springer小组之《Spring音乐播放器》可行性研究报告三、四

    3 对现有系统的分析 由于本次可行性分析主要是建立在团队自行实现一个音乐软件的目标上,并不是在一个现有系统的基础上开发改进的新系统.因此这里将分析一款市面上已经存在的音乐软件(以下称为W音乐),并为之 ...

  6. 音乐播放器 EasyMusic (一)

    EasyMusic 一. 代码获取 github 上链接为 https://github.com/VincentWYJ/EasyMusic, 感兴趣的朋友可以同步下来看, 欢迎提出宝贵意见或建议. 1 ...

  7. Android实现网络音乐播放器

    本文是一个简单的音乐播放器 布局代码 <?xml version="1.0" encoding="utf-8"?> <RelativeLayo ...

  8. 单片AT89C2051 + SD卡 + 3310LCD = 音乐播放器

    http://www.amobbs.com/thread-4503884-1-1.html 这个小玩意,采用 ATMEL 的传统51MCU作主控制芯片,加上SD卡和显示屏,就可以作简单的音乐播放器了, ...

  9. 在线音乐播放器-----酷狗音乐api接口抓取

    首先身为一个在线音乐播放器,需要前端和数据库的搭配使用. 在数据库方面,我们没有办法制作,首先是版权问题,再加上数据量.所以我们需要借用其他网络播放器的数据库. 但是这些在线播放器,如百度,酷狗,酷我 ...

随机推荐

  1. jave学习1--基础介绍

    java 技术主要分为三个部分: jave SE基础知识. 对于各个程序的开发语言都包含的基本数据类型,循环控制,数组,方法等. jave SE的面向对象部分. 所有的面向对象的概念,为最终的接口准备 ...

  2. Got Stucked in C++ Static Library Loading.. for some time

    I used to load library using 1 single .dll file, so when I happen to do method calling between 2 pro ...

  3. PoolManager 简单使用

    如图,创建空物体并命名 PoolManager,添加 脚本 spawn pool,并添加 如上图右边一些 参数,prefab为 Resources中 的预置体. 添加 空物体并 改名,如上图,并添加脚 ...

  4. 河南多校大一训练赛 E 开餐馆

    题目链接:http://acm.hust.edu.cn/vjudge/contest/125004#problem/E 密码:acm Description 北大信息学院的同学小明毕业之后打算创业开餐 ...

  5. 转:Loadrunner——Simulate a new user on each iteration设置

    最近在与大家的讨论中发现了LoadRunner的很多问题,出于解决问题的出发点,我也就相关自己不理解的问题在Google中搜索了一番,并通过一些实例也去实际操作了一遍,发现很多问题确实并不是那么难解决 ...

  6. POJ 2289 Jamie's Contact Groups

    二分答案+网络最大流 #include<cstdio> #include<cstring> #include<cmath> #include<vector&g ...

  7. 如何延长zencart1.5后台的登录时间而不退出

    2012-12-25 使用过zencart1.5版本的人都知道,后台登陆后,如果没有任何操作的话最长15分钟后就自动退出,这个对于后台管理是比较麻烦的.这个是zencart1.5在安全性上做的一个改进 ...

  8. hdu_3564_Another LIS(线段树+LIS)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3564 题意:给你N个数的位置.数i的位置为第i个数,比如 0 0 2,表示1插在第0个位置,此时数列为 ...

  9. MapReduce入门例子

    计算文档中不同单词的个数. hello you hello me 步骤如下:

  10. Android ---paint类

    引自:http://www.cnblogs.com/-OYK/archive/2011/10/25/2223624.html Android Paint和Color类   要绘图,首先得调整画笔,待画 ...