以前做毕业设计买了VS1003语音解码芯片和CH375优盘模块,现在有时间想做一个mp3播放器出来。参照的znFAT例程&SD卡驱动(STM32F103)第9个例程、振南电子SD卡MP3播放器程序和正点原子的mp3播放器程序。可实现播放优盘或TF卡根目录的所有mp3文件,增加4个独立按键,实现下一曲、上一曲切换,音量+、音量-的功能。显示mp3信息没用显示屏,用的串口直接输出到串口调试助手上。能够显示mp3文件名称,总大小,歌曲码率,歌曲总时长,播放时间等信息。
打开mp3文件后,获取文件总大小,vs1003的缓冲区每次至少要发送32字节,用for循环每次取每簇4096字节送给vs1003解码。按键处理程序要在这个for循环里面,不然没作用。
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "znfat.h"
#include "led.h"
#include "spi1.h"
#include "key.h"
#include "vs1003.h"
struct znFAT_Init_Args Init_Args; //初始化参数集合
struct FileInfo fileinfo; //文件信息集合
///
struct DateTime dt; //日期与时间
u8 pause=0;//暂停标志
u32 n_file=0;//mp3文件总数
u32 currentfile=0;
u8 databuff[4096]; //vs1003文件缓冲区
int main(void)
{
u8 vol=220; //音量
u16 bit,time,Total_time; //码率,播放时间,总时长
u16 i,j;
u32 res=0;//初始化标志位,成功为0,失败返回错误码
u32 len=0;
delay_init();
LED_Init();
uart_init(115200); //
printf("串口设置完毕rn");
KEY_Init(); //初始化按键
VS1003_GPIO_Init();
znFAT_Device_Init(); //存储设备初始化
printf("U盘初始化完毕rn");
znFAT_Select_Device(0,&Init_Args); //选择设备
res=znFAT_Init(); //文件系统初始化
printf("文件系统初始化完毕rn");
if(!res) //文件系统初始化成功,返回0
{
printf("Suc. to init FSrn");
printf("DBR(BPB)所在扇区号BPB_Sector_No: %drn",Init_Args.BPB_Sector_No);
printf("磁盘的总容量,单位KB,KBTotal_SizeKB: %drn",Init_Args.Total_SizeKB);
printf("每个扇区的字节数BytesPerSector: %drn",Init_Args.BytesPerSector);
printf("FAT表所占扇区数FATsectors: %drn",Init_Args.FATsectors);
printf("每簇的扇区数SectorsPerClust: %drn",Init_Args.SectorsPerClust);
printf("第一个FAT表所在扇区FirstFATSector: %drn",Init_Args.FirstFATSector);
printf("第一个目录所在扇区FirstDirSector: %drn",Init_Args.FirstDirSector);
printf("FSINFO扇区所在扇区FSsec: %drn",Init_Args.FSINFO_Sec);
printf("空闲簇的个数Next_Free_Cluster: %drn",Init_Args.Next_Free_Cluster);
printf("空闲簇的个数ýFreenCluster: %drn",Init_Args.Free_nCluster);
}
else //文件系统初始化失败
{
printf("Fail to init FS , Err Code: %drn",res);
}
//VS_Sine_Test();
VS_sin_test(0x24); //正弦测试,听到滴的一声
while(!znFAT_Open_File(&fileinfo,"/*.mp3",n_file,1))
{
printf("Suc. to open file.rn");
printf("================================rn");
printf("文件名称(Short 8.3):%srn",fileinfo.File_Name);
printf("文件大小:%d 字节rn",fileinfo.File_Size);
znFAT_Close_File(&fileinfo); //关闭文件
n_file++;
printf("mp3文件数量rn",n_file);
znFAT_Flush_FS(); //刷新文件系统
}
while(1)
{
VS_Reset_DecodeTime(); //复位解码时间
res=znFAT_Open_File(&fileinfo,"/*.mp3",currentfile++,1);
printf("res=%drn",res);
printf("文件名称(Short 8.3):%srn",fileinfo.File_Name);
printf("文件大小:%d 字节rn",fileinfo.File_Size);
printf("currentfile:%drn",currentfile);
for(i=0;i
{
len=znFAT_ReadData(&fileinfo,i*4096,4096,databuff);
j=0;
do
{
if(VS_Send_MusicData((u8*)databuff+j)==0){
j+=32;
}
}while(j<4096);
if(KEY_PRE==0) //下一曲 低电平有效
{
delay_ms(10);
if(KEY0==0){
while((KEY0==0));//松手检测
break;
}
}
if(KEY_NEX==0) //上一曲
{
delay_ms(10);
if(KEY1==0){
while((KEY1==0));//松手检测
if(currentfile>1)
currentfile-=2;
else currentfile=0;
break;
}
}
if(KEY_VUP==0) //音量加
{
delay_ms(10);
if(KEY2==0){
if(vol<250)
{
vol+=5;
VS_Set_Vol(vol);
}else vol=250;
}
}
if(KEY_VDN==0) //音量减
{
delay_ms(10);
if(KEY3==0){
LED1=!LED1;
if(vol>100)
{
vol-=5;
VS_Set_Vol(vol);
}else vol=100;
}
}
bit=VS_Get_HeadInfo(); //获取mp3文件码率
time= VS_Get_DecodeTime(); //获取mp3文件播放时间,1s变化一次
Total_time=(fileinfo.File_Size/bit)/125; //计算mp3文件总时长,单位s
printf("歌曲码率为:%d Kbpsrn",bit); //此处用串口显示信息,波特率太低播放会卡
printf("歌曲时间为:%d srn",time);
printf("歌曲总时间为:%d srn",Total_time);
}
znFAT_Close_File(&fileinfo); //关闭文件
VS_Flush_Buffer();//清空VS1003的数据缓冲区,此函数中最后将VS_XDCS置高,即关闭SDI
if(currentfile>=n_file)currentfile=0;
znFAT_Flush_FS(); //刷新文件系统
}
}
有些歌曲计算的时长和文件自身的时长一致,有些计算出来的要长一些。可能前面有空白扇区。
以前做毕业设计买了VS1003语音解码芯片和CH375优盘模块,现在有时间想做一个mp3播放器出来。参照的znFAT例程&SD卡驱动(STM32F103)第9个例程、振南电子SD卡MP3播放器程序和正点原子的mp3播放器程序。可实现播放优盘或TF卡根目录的所有mp3文件,增加4个独立按键,实现下一曲、上一曲切换,音量+、音量-的功能。显示mp3信息没用显示屏,用的串口直接输出到串口调试助手上。能够显示mp3文件名称,总大小,歌曲码率,歌曲总时长,播放时间等信息。
打开mp3文件后,获取文件总大小,vs1003的缓冲区每次至少要发送32字节,用for循环每次取每簇4096字节送给vs1003解码。按键处理程序要在这个for循环里面,不然没作用。
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "znfat.h"
#include "led.h"
#include "spi1.h"
#include "key.h"
#include "vs1003.h"
struct znFAT_Init_Args Init_Args; //初始化参数集合
struct FileInfo fileinfo; //文件信息集合
///
struct DateTime dt; //日期与时间
u8 pause=0;//暂停标志
u32 n_file=0;//mp3文件总数
u32 currentfile=0;
u8 databuff[4096]; //vs1003文件缓冲区
int main(void)
{
u8 vol=220; //音量
u16 bit,time,Total_time; //码率,播放时间,总时长
u16 i,j;
u32 res=0;//初始化标志位,成功为0,失败返回错误码
u32 len=0;
delay_init();
LED_Init();
uart_init(115200); //
printf("串口设置完毕rn");
KEY_Init(); //初始化按键
VS1003_GPIO_Init();
znFAT_Device_Init(); //存储设备初始化
printf("U盘初始化完毕rn");
znFAT_Select_Device(0,&Init_Args); //选择设备
res=znFAT_Init(); //文件系统初始化
printf("文件系统初始化完毕rn");
if(!res) //文件系统初始化成功,返回0
{
printf("Suc. to init FSrn");
printf("DBR(BPB)所在扇区号BPB_Sector_No: %drn",Init_Args.BPB_Sector_No);
printf("磁盘的总容量,单位KB,KBTotal_SizeKB: %drn",Init_Args.Total_SizeKB);
printf("每个扇区的字节数BytesPerSector: %drn",Init_Args.BytesPerSector);
printf("FAT表所占扇区数FATsectors: %drn",Init_Args.FATsectors);
printf("每簇的扇区数SectorsPerClust: %drn",Init_Args.SectorsPerClust);
printf("第一个FAT表所在扇区FirstFATSector: %drn",Init_Args.FirstFATSector);
printf("第一个目录所在扇区FirstDirSector: %drn",Init_Args.FirstDirSector);
printf("FSINFO扇区所在扇区FSsec: %drn",Init_Args.FSINFO_Sec);
printf("空闲簇的个数Next_Free_Cluster: %drn",Init_Args.Next_Free_Cluster);
printf("空闲簇的个数ýFreenCluster: %drn",Init_Args.Free_nCluster);
}
else //文件系统初始化失败
{
printf("Fail to init FS , Err Code: %drn",res);
}
//VS_Sine_Test();
VS_sin_test(0x24); //正弦测试,听到滴的一声
while(!znFAT_Open_File(&fileinfo,"/*.mp3",n_file,1))
{
printf("Suc. to open file.rn");
printf("================================rn");
printf("文件名称(Short 8.3):%srn",fileinfo.File_Name);
printf("文件大小:%d 字节rn",fileinfo.File_Size);
znFAT_Close_File(&fileinfo); //关闭文件
n_file++;
printf("mp3文件数量rn",n_file);
znFAT_Flush_FS(); //刷新文件系统
}
while(1)
{
VS_Reset_DecodeTime(); //复位解码时间
res=znFAT_Open_File(&fileinfo,"/*.mp3",currentfile++,1);
printf("res=%drn",res);
printf("文件名称(Short 8.3):%srn",fileinfo.File_Name);
printf("文件大小:%d 字节rn",fileinfo.File_Size);
printf("currentfile:%drn",currentfile);
for(i=0;i
{
len=znFAT_ReadData(&fileinfo,i*4096,4096,databuff);
j=0;
do
{
if(VS_Send_MusicData((u8*)databuff+j)==0){
j+=32;
}
}while(j<4096);
if(KEY_PRE==0) //下一曲 低电平有效
{
delay_ms(10);
if(KEY0==0){
while((KEY0==0));//松手检测
break;
}
}
if(KEY_NEX==0) //上一曲
{
delay_ms(10);
if(KEY1==0){
while((KEY1==0));//松手检测
if(currentfile>1)
currentfile-=2;
else currentfile=0;
break;
}
}
if(KEY_VUP==0) //音量加
{
delay_ms(10);
if(KEY2==0){
if(vol<250)
{
vol+=5;
VS_Set_Vol(vol);
}else vol=250;
}
}
if(KEY_VDN==0) //音量减
{
delay_ms(10);
if(KEY3==0){
LED1=!LED1;
if(vol>100)
{
vol-=5;
VS_Set_Vol(vol);
}else vol=100;
}
}
bit=VS_Get_HeadInfo(); //获取mp3文件码率
time= VS_Get_DecodeTime(); //获取mp3文件播放时间,1s变化一次
Total_time=(fileinfo.File_Size/bit)/125; //计算mp3文件总时长,单位s
printf("歌曲码率为:%d Kbpsrn",bit); //此处用串口显示信息,波特率太低播放会卡
printf("歌曲时间为:%d srn",time);
printf("歌曲总时间为:%d srn",Total_time);
}
znFAT_Close_File(&fileinfo); //关闭文件
VS_Flush_Buffer();//清空VS1003的数据缓冲区,此函数中最后将VS_XDCS置高,即关闭SDI
if(currentfile>=n_file)currentfile=0;
znFAT_Flush_FS(); //刷新文件系统
}
}
有些歌曲计算的时长和文件自身的时长一致,有些计算出来的要长一些。可能前面有空白扇区。
举报