基于AVR单片机MP3 和数码相框设计专题
本帖最后由 tmfwt 于 2013-5-13 12:10 编辑我把自己之前学习AVR时做的一些应用程序放在这里和大家分享,参考的资料大多来源于网络。经过自己重新设计,实现一些简易的功能。这个专题主要把MP3和数码相框的一些资料放在这里和大家分享:
一. 一个最简单的MP3,实现声音播放测试 ,主应用函数如下:
#include "VS1003B.h"
#include "MMC_SD.h"
#include"FAT.h"
#include "TFT.h"
extern WORD SectorsPerClust; //每簇扇区数
extern WORD FirstDataSector; //第一个数据扇区数
extern BYTE FAT32_Enable;
struct FileInfoStruct FileInfo;//文件信息
struct direntry MusicInfo; //要播放的mp3文件信息
uint16 totalsongs; //总的音乐文件数目
uint8 type; //文件类型
uint16 ToneSize=0x828;
#define MP3 1
#define WMA 2
#define MID 3
#define REPET_ALL 0
#define REPET_ONE 1
#define RANDOM 2
void delay_us(uint us)
{
uint i;
for(i=us;i>0;i--);
}
void Delay(uint16 ms)
{
uint16 i,j;
for(j=ms;j>0;j--)
for(i=1141;i>0;i--);
}
/*********************************************************************
- 功能描述:SD卡初始化
- 隶属模块:应用层
- 函数属性:外部
*********************************************************************/
voidSDCardInit()
{
unsigned char retry=0;
OSCCAL = 0x00; //最小RC振荡频率
delay_us(0x00ff);
MMC_SD_Init(); //初始化spi口
delay_us(0x00ff);
while(MMC_SD_Reset()) //初始化SD卡
{
if(++retry>20)
{
TFT_CleanScreen(RED);
while(1);
}
}
OSCCAL = 0xff; //最大RC振荡频
}
/*********************************************************************
- 功能描述:文件系统初始化
- 隶属模块:应用层
- 函数属性:外部
*********************************************************************/
void FATInit()
{
unsigned char retry=0;
if(FAT_Init()) //初始化文件系统 支持FAT16和FAT32
{
if(++retry>20)
{
TFT_CleanScreen(GREEN);
while(1);
}
}
}
/*********************************************************************
- 功能描述:vs1003B初始化
- 隶属模块:应用层
- 函数属性:外部
*********************************************************************/
void InitVS1003()
{
unsigned char retry=0;
if(VS1003B_Init())
{
if(++retry>20)
{
TFT_CleanScreen(YELLOW);
while(1);
}
}
}
void PlayTone(void)
{
DWORD p;
uchar* buffer;
uint16 totalsect;
uint16 leftbytes;
totalsect = ToneSize/512; //计算扇区数 //calculate the total sectors
leftbytes = ToneSize%512; //计算剩余的字节数 //calculate the left bytes
uint16 count=0;
uint16 keylen;
uchar flag=1;
DWORD sector=0;
uchar i=0;
uchar type=1;
uint16 vol;
uchar vol_temp =99;
vol = (uint8)(255-(vol_temp*255)/100);
vol =(vol<<8) + vol;
VS1003B_SetVolume(vol);
if(type != MID)
VS1003B_Fill2048Zero();
Search("\\",&MusicInfo,&totalsongs,&type); //搜索根目下的歌曲 不包含子目录
p = MusicInfo.deStartCluster+(((unsigned long)MusicInfo.deHighClust)<<16);//读文件首簇
totalsect = MusicInfo.deFileSize/512; //计算扇区数
leftbytes = MusicInfo.deFileSize%512; //计算剩余的字节数
sector=0;
while(1)
{
for(;i<SectorsPerClust;i++) //一个簇 //a cluster
{
buffer=malloc(512);
FAT_LoadPartCluster(p,i,buffer); //读一个扇区 //read a sector
count=0;
while(count<512)
{
if(flag==0)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
else if(type == MID)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
if(VS1003B_NeedData() && flag) //根据需要送数据//send datahonoring DREQ
{
VS1003B_Write32B(&buffer);
count += 32;
if(keylen)keylen--; //用于键处理 //for key processing
if(sector == totalsect && count >= leftbytes) //如果文件已结束 //if this is the end of the file
{
if(type == MID)//waiting the midi file was decoded
VS1003B_Fill2048Zero();
i=SectorsPerClust;
break;
} //文件结束 //file ended
if(count == 511)
{
break;
} //512字节送完跳出 //break if a sector was sent
}
}
sector++;
free(buffer);
}
i=0;//重置簇内扇区计数
p=FAT_NextCluster(p);
if(p == 0x0fffffff || p == 0x0ffffff8 || (FAT32_Enable == 0 && p== 0xffff))
break;
}
}
int main()
{
TFT_Lcd_Init();
SDCardInit();
FATInit();
InitVS1003();
TFT_CleanScreen(BLACK);
PlayTone();
return 0;
}
本帖最后由 tmfwt 于 2013-5-13 12:10 编辑
大家在使用这个程序做测试时,务必保证SD,TFT 和 VS1003模块能正常工作。 本帖最后由 tmfwt 于 2013-5-13 19:35 编辑
二、使用按键控制,歌曲切换
具体实现方法参见 Mp3.c 文件 实现案例:
好贴怎么没人顶呢?我还没搞过彩屏啊 嗯,触摸屏和sd卡还不是很懂,需要接触下了。 三、 使用按键控制,歌曲切换 ,音量控制,暂停,并加载字库
主要函数:
void PlayTone()
{
DWORD p;
uchar* buffer;
uint8 mode=0; //单曲重复
uint8 songs=1; //默认放第一首歌
uint16 totalsect;
uint16 leftbytes;
uint16 count=0;
uint16 keylen;
uchar flag=1;
DWORD sector=0;
uchar i=0,j;
uchar type=1;
uint16 vol;
uchar vol_temp =99;
if(totalsongs==0)
return; //如果没有歌曲则异常退出
unsigned long rand_val;
//---------------------------------------------------------------------
//---------------------------------------------------------------------
vol = (uint8)(255-(vol_temp*255)/100); //初始化声音
vol =(vol<<8) + vol;
VS1003B_SetVolume(vol);
//**********************************************************************
next:
if(type != MID)
VS1003B_Fill2048Zero();
count=0; //清基数
flag=1;
while(count<2048 && (type != MID)) //recommand 2048 zeros honoring DREQ befor soft reset
{ //用于从wma跳出到下一首歌,和一首歌结束填充数据//midi格式不需要
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0)
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00); //填充0
count++;
}
if(count == 2047)break;
}
}
VS1003B_SoftReset(); //soft reset //in case of playing wma files//软件复位
Search("\\MP3",&MusicInfo,&songs,&type); //搜索根目下的歌曲 不包含子目录
p = MusicInfo.deStartCluster+(((unsigned long)MusicInfo.deHighClust)<<16);//读文件首簇
totalsect = MusicInfo.deFileSize/512; //计算扇区数
leftbytes = MusicInfo.deFileSize%512; //计算剩余的字节数
i=0;
sector=0;
while(1)
{
keylen=0;
for(;i<SectorsPerClust;i++) //一个簇 //a cluster
{
buffer=malloc(512);
FAT_LoadPartCluster(p,i,buffer); //读一个扇区 //read a sector
VS1003B_SPI_High(); //调到适合vs1003的速度
count=0;
while(count<512)
{
if(flag==0)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
else if(type == MID)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
/*
if(VS1003B_NeedData() && flag) //根据需要送数据 //send datahonoring DREQ
{
VS1003B_Write32B(&buffer);
count += 32;
if(keylen)keylen--; //用于键处理 //for key processing
if(sector == totalsect && count >= leftbytes) //如果文件已结束 //if this is the end of the file
{
if(type == MID)//waiting the midi file was decoded
VS1003B_Fill2048Zero();
i=SectorsPerClust;
break;
} //文件结束 //file ended
if(count == 511){ break;} //512字节送完跳出 //break if a sector was sent
}
*/
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 && flag)//根据需要送数据
{
for(j=0;j<32;j++)//每次送32个数据
{
VS1003B_WriteDAT(buffer);
count++;
}
if(keylen) keylen--;//用于键处理
if(sector == totalsect && count >= leftbytes)//如果文件已结束
{
if(type == MID)//waiting the midi file was decoded
{//对于mid音乐要接着送2048个零
count=0;
while(count<2048)//recommand 2048 zeros honoring DREQ goto next songs
{
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 )
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00);
count++;
}
if(count == 2047)break;
}
}
}
i=SectorsPerClust;
break;
}//文件结束
if(count == 511)
{
break;
}//512字节送完跳出
}
//////////////////////////////键盘控制函数///////////////////////////////////////////
//------------------------------------------------------------------------------------
if(!(KEYIN&NEXT)) //下一曲
{
while(!(KEYIN&NEXT));
songs++;
if(songs > totalsongs)songs=1;
free(buffer);
goto next;
}
else if(!(KEYIN&PREV)) //上一曲
{
while(!(PINC&PREV));
songs--;
if(songs == 1)songs=totalsongs;
free(buffer);
goto next;
}
else if((KEYIN&STOP)==0 && keylen==0) //暂停
{
while(!(KEYIN&STOP));
keylen=10000;
if(flag)flag=0;
else flag=1;
}
else if((KEYIN&UP)==0 && keylen==0) //音量+
{
if(!(PINC&UP))
{
keylen=200;
vol=vol-((uint)(1<<8)+1);
if(vol<=0x0101) vol=0x0101;
else VS1003B_WriteCMD(0x0b,vol);
}
}
else if((KEYIN&DOWN)==0 && keylen==0) //音量-
{
if(!(KEYIN&DOWN))
{
keylen=200;
vol=vol+((uint)(1<<8)+1);
if(vol>=0xFEFE) vol=0xFEFE;
else VS1003B_WriteCMD(0x0b,vol);
}
}
////////////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------
}
sector++;
free(buffer);
}
i=0; //重置簇内扇区计数
p=FAT_NextCluster(p);
if(p == 0x0fffffff || p == 0x0ffffff8 || (FAT32_Enable == 0 && p== 0xffff))
{
if(mode==REPET_ALL)songs++;
if(songs>totalsongs)
songs=1;
goto next;
}
}
} 本帖最后由 tmfwt 于 2013-5-15 18:54 编辑
四、功能介绍
(1) 歌曲切换 ,音量控制,暂停,并加载字库
(2) 可以显示歌曲的名字
主要功能函数如下:
void PlayTone()
{
uint16 i,j;
DWORD p;
uchar* buffer;
uint8 mode=0; //单曲重复
uint8 songs=1; //默认放第一首歌
uint16 totalsect;
uint16 leftbytes;
uint16 count=0;
uint16 keylen;
uchar flag=1;
DWORD sector=0;
uint16 vol;
uint16 temp;
uchar vol_temp =99;
if(totalsongs==0)
return; //如果没有歌曲则异常退出
unsigned long rand_val;
LongNameFlag=0; //显示短歌名
//---------------------------------------------------------------------
//---------------------------------------------------------------------
vol = (uint8)(255-(vol_temp*255)/100); //初始化声音
vol =(vol<<8) + vol;
VS1003B_SetVolume(vol);
//**********************************************************************
next:
if(type != MID)
VS1003B_Fill2048Zero();
count=0; //清基数
flag=1;
while(count<2048 && (type != MID)) //recommand 2048 zeros honoring DREQ befor soft reset
{ //用于从wma跳出到下一首歌,和一首歌结束填充数据//midi格式不需要
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0)
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00); //填充0
count++;
}
if(count == 2047)break;
}
}
VS1003B_SoftReset(); //soft reset //in case of playing wma files//软件复位
//-----------------------------------------------------------------------------
//=============================歌曲类型判定程序部分=============================
//******************************************************************************
Search("\\MP3",&MusicInfo,&songs,&type); //搜索根目下的歌曲 不包含子目录
for(j=0;j<MAX_LONG_NAME_SIZE/2;j++) /* cut off the extension, only leave the name*/
{
if(((unsigned int*)LongNameBuffer) == 0)
{
((unsigned int*)LongNameBuffer) = 0;
break;
}
}
//--------------------------------------------------------------------------------------------
//------------------------------------显示歌曲名程序------------------------------------------
if(LongNameFlag)
{
if(HanziEnable)
{
buffer = malloc(MAX_LONG_NAME_SIZE);
if(buffer==0)
return 1;
i=0;
j=0;
while(1)
{
temp = ((unsigned int *)LongNameBuffer);
if(temp==0)
{
buffer = '.';
while(1)
{
temp = ((unsigned int *)LongNameBuffer);
if(temp == 0)
break; /* end */
buffer = (uint8)temp;
}
break;
}
else if(temp<0x80)
{
buffer=(uint8)temp;
}
else if(temp<0x4e00)
{
*((unsigned int*)&(buffer)) = "?";
j+=2;
}
else if(temp<0x9fa6)
{
if(Unicode_to_GBK((unsigned char *)&temp))return 1;
*((unsigned int*)&(buffer)) = temp;
j+=2;
}
else
{
*((unsigned int*)&(buffer)) = "?";
j+=2;
}
}
buffer = 0;
BackColor=BLACK;
LCDRePain(10,100);
LCD_PrintfStr16(10,100,buffer,RED);
}
else
{
LCD_PrintfStr16(10,100,"显示失败!",RED);
}
}
else
{
for(j=0;j<8;j++)
{
if(MusicInfo.deName==0x20)break;
LongNameBuffer=MusicInfo.deName;
}
//LongNameBuffer='\0';
LongNameBuffer='.';
count = j+3;
for(count=0;count<3;count++)LongNameBuffer=MusicInfo.deExtension;
LongNameBuffer='\0';
if(HanziEnable)
{
BackColor=BLACK;
LCDRePain(10,100);
LCD_PrintfStr16(10,100,LongNameBuffer,RED);
}
else
{
LCD_PrintfStr16(10,100,"显示失败!",RED);
}
}
//-------------------------------------------------------------------------------------------
BackColor=BLACK; //定义字体背景色
LCDRePain(10,10);
//显示歌曲类型
switch(type)
{
case MP3:LCD_PrintfStr16(10,10,"MP3",GREEN);break;
case WMA:LCD_PrintfStr16(10,10,"WMV",GREEN);break;
case MID:LCD_PrintfStr16(10,10,"MID",GREEN);break;
default:break;
}
//=============================================================================================
//------------------------------------------播放歌曲程序部分==================================
//=============================================================================================
p = MusicInfo.deStartCluster+(((unsigned long)MusicInfo.deHighClust)<<16);//读文件首簇
totalsect = MusicInfo.deFileSize/512; //计算扇区数
leftbytes = MusicInfo.deFileSize%512; //计算剩余的字节数
i=0;
sector=0;
while(1)
{
//-----------------------------------------------------------------------
keylen=0;
for(;i<SectorsPerClust;i++) //一个簇 //a cluster
{
buffer=malloc(512);
FAT_LoadPartCluster(p,i,buffer); //读一个扇区 //read a sector
VS1003B_SPI_High(); //调到适合vs1003的速度
count=0;
while(count<512)
{
if(flag==0)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
else if(type == MID)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
/*
if(VS1003B_NeedData() && flag) //根据需要送数据 //send datahonoring DREQ
{
VS1003B_Write32B(&buffer);
count += 32;
if(keylen)keylen--; //用于键处理 //for key processing
if(sector == totalsect && count >= leftbytes) //如果文件已结束 //if this is the end of the file
{
if(type == MID)//waiting the midi file was decoded
VS1003B_Fill2048Zero();
i=SectorsPerClust;
break;
} //文件结束 //file ended
if(count == 511){ break;} //512字节送完跳出 //break if a sector was sent
}
*/
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 && flag)//根据需要送数据
{
for(j=0;j<32;j++)//每次送32个数据
{
VS1003B_WriteDAT(buffer);
count++;
}
if(keylen) keylen--;//用于键处理
if(sector == totalsect && count >= leftbytes)//如果文件已结束
{
if(type == MID)//waiting the midi file was decoded
{//对于mid音乐要接着送2048个零
count=0;
while(count<2048)//recommand 2048 zeros honoring DREQ goto next songs
{
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 )
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00);
count++;
}
if(count == 2047)break;
}
}
}
i=SectorsPerClust;
break;
}//文件结束
if(count == 511)
{
break;
}//512字节送完跳出
}
//////////////////////////////键盘控制函数///////////////////////////////////////////
//------------------------------------------------------------------------------------
if(!(KEYIN&NEXT)) //下一曲
{
while(!(KEYIN&NEXT));
songs++;
if(songs > totalsongs)songs=1;
free(buffer);
goto next;
}
else if(!(KEYIN&PREV)) //上一曲
{
while(!(PINC&PREV));
songs--;
if(songs == 1)songs=totalsongs;
free(buffer);
goto next;
}
else if((KEYIN&STOP)==0 && keylen==0) //暂停
{
while(!(KEYIN&STOP));
keylen=10000;
if(flag)
{
flag=0;
BackColor=BLACK; //定义字体背景色
LCDRePain(10,200);
LCD_PrintfStr16(10,200,"STOP",RED);
}
else
{
flag=1;
BackColor=BLACK; //定义字体背景色
LCDRePain(10,200);
LCD_PrintfStr16(10,200,"PLAY",RED);
}
}
else if((KEYIN&UP)==0 && keylen==0) //音量+
{
if(!(PINC&UP))
{
keylen=200;
vol=vol-((uint)(1<<8)+1);
if(vol<=0x0101) vol=0x0101;
else VS1003B_WriteCMD(0x0b,vol);
}
}
else if((KEYIN&DOWN)==0 && keylen==0) //音量-
{
if(!(KEYIN&DOWN))
{
keylen=200;
vol=vol+((uint)(1<<8)+1);
if(vol>=0xFEFE) vol=0xFEFE;
else VS1003B_WriteCMD(0x0b,vol);
}
}
////////////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------
}
sector++;
free(buffer);
}
i=0; //重置簇内扇区计数
p=FAT_NextCluster(p);
if(p == 0x0fffffff || p == 0x0ffffff8 || (FAT32_Enable == 0 && p== 0xffff))
{
if(mode==REPET_ALL)songs++;
if(songs>totalsongs)
songs=1;
goto next;
}
}
}
本帖最后由 tmfwt 于 2013-5-15 22:12 编辑
tmfwt 发表于 2013-5-13 19:34 static/image/common/back.gif
二、使用按键控制,歌曲切换
具体实现方法参见 Mp3.c 文件
使用按键控制,歌曲切换.
主要功能函数如下:
void PlayTone()
{
DWORD p;
uchar* buffer;
uint8 mode=0; //单曲重复
uint8 songs; //默认放第一首歌
uint16 totalsect;
uint16 leftbytes;
uint16 count=0;
uint16 keylen;
uchar flag=1;
DWORD sector=0;
uchar i=0,j;
uchar type=1;
uint16 vol;
uchar vol_temp =99;
if(totalsongs==0)
return; //如果没有歌曲则异常退出
unsigned long rand_val;
//---------------------------------------------------------------------
//---------------------------------------------------------------------
next:
vol = (uint8)(255-(vol_temp*255)/100);
vol =(vol<<8) + vol;
VS1003B_SetVolume(vol);
if(type != MID)
VS1003B_Fill2048Zero();
count=0; //清基数
flag=1;
while(count<2048 && (type != MID)) //recommand 2048 zeros honoring DREQ befor soft reset
{ //用于从wma跳出到下一首歌,和一首歌结束填充数据//midi格式不需要
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0)
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00); //填充0
count++;
}
if(count == 2047)break;
}
}
VS1003B_SoftReset(); //soft reset //in case of playing wma files//软件复位
Search("\\MP3",&MusicInfo,&songs,&type); //搜索根目下的歌曲 不包含子目录
p = MusicInfo.deStartCluster+(((unsigned long)MusicInfo.deHighClust)<<16);//读文件首簇
totalsect = MusicInfo.deFileSize/512; //计算扇区数
leftbytes = MusicInfo.deFileSize%512; //计算剩余的字节数
i=0;
sector=0;
while(1)
{
keylen=0;
for(;i<SectorsPerClust;i++) //一个簇 //a cluster
{
buffer=malloc(512);
FAT_LoadPartCluster(p,i,buffer); //读一个扇区 //read a sector
VS1003B_SPI_High(); //调到适合vs1003的速度
count=0;
while(count<512)
{
if(flag==0)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
else if(type == MID)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
/*
if(VS1003B_NeedData() && flag) //根据需要送数据 //send datahonoring DREQ
{
VS1003B_Write32B(&buffer);
count += 32;
if(keylen)keylen--; //用于键处理 //for key processing
if(sector == totalsect && count >= leftbytes) //如果文件已结束 //if this is the end of the file
{
if(type == MID)//waiting the midi file was decoded
VS1003B_Fill2048Zero();
i=SectorsPerClust;
break;
} //文件结束 //file ended
if(count == 511){ break;} //512字节送完跳出 //break if a sector was sent
}
*/
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 && flag)//根据需要送数据
{
for(j=0;j<32;j++)//每次送32个数据
{
VS1003B_WriteDAT(buffer);
count++;
}
if(keylen) keylen--;//用于键处理
if(sector == totalsect && count >= leftbytes)//如果文件已结束
{
if(type == MID)//waiting the midi file was decoded
{//对于mid音乐要接着送2048个零
count=0;
while(count<2048)//recommand 2048 zeros honoring DREQ goto next songs
{
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 )
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00);
count++;
}
if(count == 2047)break;
}
}
}
i=SectorsPerClust;
break;
}//文件结束
if(count == 511)
{
break;
}//512字节送完跳出
}
//////////////////////////////键盘控制函数///////////////////////////////////////////
//------------------------------------------------------------------------------------
if(!(PINC&NEXT)) //下一曲
{
while(!(PINC&NEXT));
songs++;
if(songs > totalsongs)songs=1;
free(buffer);
goto next;
}
else if(!(PINC&PREV)) //上一曲
{
while(!(PINC&PREV));
songs--;
if(songs == 1)songs=totalsongs;
free(buffer);
goto next;
}
else if((PINC&STOP)==0 && keylen==0) //暂停
{
while(!(PINC&STOP));
keylen=10000;
if(flag)flag=0;
else flag=1;
}
else if((PINC&UP)==0 && keylen==0) //音量+
{
if(!(PINC&UP))
{
keylen=200;
vol=vol-((uint)(1<<8)+1);
if(vol<=0x0101) vol=0x0101;
else VS1003B_WriteCMD(0x0b,vol);
}
}
else if((PINC&DOWN)==0 && keylen==0) //音量-
{
if(!(PINC&DOWN))
{
keylen=200;
vol=vol+((uint)(1<<8)+1);
if(vol>=0xFEFE) vol=0xFEFE;
else VS1003B_WriteCMD(0x0b,vol);
}
}
////////////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------
}
sector++;
free(buffer);
}
i=0;//重置簇内扇区计数
p=FAT_NextCluster(p);
if(p == 0x0fffffff || p == 0x0ffffff8 || (FAT32_Enable == 0 && p== 0xffff))
{
if(mode==REPET_ALL)songs++;
if(songs>totalsongs)
songs=1;
goto next;
}
}
} 一个UI 界面:
五、功能介绍1.歌曲切换 ,音量控制,暂停,并加载字库
2.可以显示歌曲的名字
3. 可以显示图片 ,控制符号
主功能函数:
void PlayTone()
{
uint16 i,j;
DWORD p;
uchar* buffer;
uint8 mode=0; //单曲重复
uint8 songs=1; //默认放第一首歌
uint16 totalsect;
uint16 leftbytes;
uint16 count=0;
uint16 keylen;
uchar flag=1;
DWORD sector=0;
uint16 vol;
uint16 temp;
uchar vol_temp =99;
if(totalsongs==0)
return; //如果没有歌曲则异常退出
unsigned long rand_val;
LongNameFlag=0; //显示短歌名
//---------------------------------------------------------------------
//---------------------------------------------------------------------
vol = (uint8)(255-(vol_temp*255)/100); //初始化声音
vol =(vol<<8) + vol;
VS1003B_SetVolume(vol);
//**********************************************************************
next:
if(type != MID)
VS1003B_Fill2048Zero();
count=0; //清基数
flag=1;
while(count<2048 && (type != MID)) //recommand 2048 zeros honoring DREQ befor soft reset
{ //用于从wma跳出到下一首歌,和一首歌结束填充数据//midi格式不需要
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0)
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00); //填充0
count++;
}
if(count == 2047)break;
}
}
VS1003B_SoftReset(); //soft reset //in case of playing wma files//软件复位
//-----------------------------------------------------------------------------
//=============================歌曲类型判定程序部分=============================
//******************************************************************************
SearchMP3("\\MP3",&MusicInfo,&songs,&type); //搜索根目下的歌曲 不包含子目录
//SearchInit();
//Search(&MusicInfo,&songs,&type);
for(j=0;j<MAX_LONG_NAME_SIZE/2;j++) /* cut off the extension, only leave the name*/
{
if(((unsigned int*)LongNameBuffer) == 0)
{
((unsigned int*)LongNameBuffer) = 0;
break;
}
}
//--------------------------------------------------------------------------------------------
//------------------------------------显示歌曲名程序------------------------------------------
if(LongNameFlag)
{
if(HanziEnable)
{
buffer = malloc(MAX_LONG_NAME_SIZE);
if(buffer==0)
return 1;
i=0;
j=0;
while(1)
{
temp = ((unsigned int *)LongNameBuffer);
if(temp==0)
{
buffer = '.';
while(1)
{
temp = ((unsigned int *)LongNameBuffer);
if(temp == 0)
break; /* end */
buffer = (uint8)temp;
}
break;
}
else if(temp<0x80)
{
buffer=(uint8)temp;
}
else if(temp<0x4e00)
{
*((unsigned int*)&(buffer)) = "?";
j+=2;
}
else if(temp<0x9fa6)
{
if(Unicode_to_GBK((unsigned char *)&temp))return 1;
*((unsigned int*)&(buffer)) = temp;
j+=2;
}
else
{
*((unsigned int*)&(buffer)) = "?";
j+=2;
}
}
buffer = 0;
BackColor=BLACK;
LCDRePain(10,100);
LCD_PrintfStr16(10,100,buffer,RED);
}
else
{
LCD_PrintfStr16(10,100,"显示失败!",RED);
}
}
else
{
for(j=0;j<8;j++)
{
if(MusicInfo.deName==0x20)break;
LongNameBuffer=MusicInfo.deName;
}
//LongNameBuffer='\0';
LongNameBuffer='.';
count = j+3;
for(count=0;count<3;count++)LongNameBuffer=MusicInfo.deExtension;
LongNameBuffer='\0';
if(HanziEnable)
{
BackColor=BLACK;
LCDRePain(10,100);
LCD_PrintfStr16(10,100,LongNameBuffer,RED);
}
else
{
LCD_PrintfStr16(10,100,"显示失败!",RED);
}
}
//-------------------------------------------------------------------------------------------
BackColor=BLACK; //定义字体背景色
LCDRePain(10,10);
Print_ICON1_12(50,15,0,RED);
//显示歌曲类型
switch(type)
{
case MP3:LCD_PrintfStr16(10,15,"MP3",GREEN);break;
case WMA:LCD_PrintfStr16(10,15,"WMV",GREEN);break;
case MID:LCD_PrintfStr16(10,15,"MID",GREEN);break;
case WAV:LCD_PrintfStr16(10,15,"WAV",GREEN);break;
default:break;
}
//=============================================================================================
//------------------------------------------播放歌曲程序部分==================================
//=============================================================================================
p = MusicInfo.deStartCluster+(((unsigned long)MusicInfo.deHighClust)<<16);//读文件首簇
totalsect = MusicInfo.deFileSize/512; //计算扇区数
leftbytes = MusicInfo.deFileSize%512; //计算剩余的字节数
i=0;
sector=0;
while(1)
{
//-----------------------------------------------------------------------
keylen=0;
for(;i<SectorsPerClust;i++) //一个簇 //a cluster
{
buffer=malloc(512);
FAT_LoadPartCluster(p,i,buffer); //读一个扇区 //read a sector
VS1003B_SPI_High(); //调到适合vs1003的速度
count=0;
while(count<512)
{
if(flag==0)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
else if(type == MID)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
/*
if(VS1003B_NeedData() && flag) //根据需要送数据 //send datahonoring DREQ
{
VS1003B_Write32B(&buffer);
count += 32;
if(keylen)keylen--; //用于键处理 //for key processing
if(sector == totalsect && count >= leftbytes) //如果文件已结束 //if this is the end of the file
{
if(type == MID)//waiting the midi file was decoded
VS1003B_Fill2048Zero();
i=SectorsPerClust;
break;
} //文件结束 //file ended
if(count == 511){ break;} //512字节送完跳出 //break if a sector was sent
}
*/
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 && flag)//根据需要送数据
{
for(j=0;j<32;j++)//每次送32个数据
{
VS1003B_WriteDAT(buffer);
count++;
}
if(keylen) keylen--;//用于键处理
if(sector == totalsect && count >= leftbytes)//如果文件已结束
{
if(type == MID)//waiting the midi file was decoded
{//对于mid音乐要接着送2048个零
count=0;
while(count<2048)//recommand 2048 zeros honoring DREQ goto next songs
{
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 )
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00);
count++;
}
if(count == 2047)break;
}
}
}
i=SectorsPerClust;
break;
}//文件结束
if(count == 511)
{
break;
}//512字节送完跳出
}
//////////////////////////////键盘控制函数///////////////////////////////////////////
//------------------------------------------------------------------------------------
if(!(KEYIN&NEXT)) //下一曲
{
while(!(KEYIN&NEXT));
songs++;
if(songs > totalsongs)songs=1;
free(buffer);
goto next;
}
else if(!(KEYIN&PREV)) //上一曲
{
while(!(PINC&PREV));
songs--;
if(songs == 1)songs=totalsongs;
free(buffer);
goto next;
}
else if((KEYIN&STOP)==0 && keylen==0) //暂停
{
while(!(KEYIN&STOP));
keylen=10000;
if(flag)
{
flag=0;
BackColor=BLACK; //定义字体背景色
LCDRePain(10,200);
LCD_PrintfStr16(10,200,"STOP",RED);
}
else
{
flag=1;
BackColor=BLACK; //定义字体背景色
LCDRePain(10,200);
LCD_PrintfStr16(10,200,"PLAY",RED);
}
}
else if((KEYIN&UP)==0 && keylen==0) //音量+
{
if(!(PINC&UP))
{
keylen=200;
vol=vol-((uint)(1<<8)+1);
if(vol<=0x0101) vol=0x0101;
else VS1003B_WriteCMD(0x0b,vol);
}
}
else if((KEYIN&DOWN)==0 && keylen==0) //音量-
{
if(!(KEYIN&DOWN))
{
keylen=200;
vol=vol+((uint)(1<<8)+1);
if(vol>=0xFEFE) vol=0xFEFE;
else VS1003B_WriteCMD(0x0b,vol);
}
}
////////////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------
}
sector++;
free(buffer);
}
i=0; //重置簇内扇区计数
p=FAT_NextCluster(p);
if(p == 0x0fffffff || p == 0x0ffffff8 || (FAT32_Enable == 0 && p== 0xffff))
{
if(mode==REPET_ALL)songs++;
if(songs>totalsongs)
songs=1;
goto next;
}
}
}
六、功能介绍
1.歌曲切换 ,音量控制,暂停,并加载字库
2.可以显示歌曲的名字
3. 可以显示图片 ,控制符号
4. 显示图片的数目
5. 显示解码时间
6. 显示歌曲数目
7. 显示播放符号
主功能函数:
void PlayTone()
{
uint8 min,sec;
uint16 i,j;
DWORD p;
uchar* buffer;
uint8 mode=0; //单曲重复
uint16 totalsect;
uint16 leftbytes;
uint16 count=0;
uint16 keylen;
uchar flag=1;
DWORD sector=0;
uint16 vol;
uint16 temp;
uchar vol_temp =99;
uint8 time;
uint16 decodetime;
songs=1; //启动时,播放第一首曲
if(totalsongs==0)
return; //如果没有歌曲则异常退出
unsigned long rand_val;
LongNameFlag=0; //显示短歌名
//---------------------------------------------------------------------
//---------------------------------------------------------------------
vol = (uint8)(255-(vol_temp*255)/100); //初始化声音
vol =(vol<<8) + vol;
VS1003B_SetVolume(vol);
//**********************************************************************
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
next:
if(type != MID)
VS1003B_Fill2048Zero();
count=0; //清基数
flag=1;
while(count<2048 && (type != MID)) //recommand 2048 zeros honoring DREQ befor soft reset
{ //用于从wma跳出到下一首歌,和一首歌结束填充数据//midi格式不需要
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0)
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00); //填充0
count++;
}
if(count == 2047)break;
}
}
VS1003B_SoftReset(); //soft reset //in case of playing wma files//软件复位
//-----------------------------------------------------------------------------
//=============================歌曲类型判定程序部分=============================
//******************************************************************************
SearchMP3("\\MP3",&MusicInfo,&songs,&type); //搜索根目下的歌曲 不包含子目录
//SearchInit();
//Search(&MusicInfo,&songs,&type);
for(j=0;j<MAX_LONG_NAME_SIZE/2;j++) /* cut off the extension, only leave the name*/
{
if(((unsigned int*)LongNameBuffer) == 0)
{
((unsigned int*)LongNameBuffer) = 0;
break;
}
}
//-------------------------------------------------------------------------------------------
/****************************************************/
time = '0';
time = '0';
time = ':';
time = '0';
time = '0';
time = '\0';
decodetime = -1; /* for display the lyric which is at time 00:00 */
/******************************************************/
//--------------------------------------------------------------------------------------------
//------------------------------------显示歌曲名程序------------------------------------------
if(LongNameFlag)
{
if(HanziEnable)
{
buffer = malloc(MAX_LONG_NAME_SIZE);
if(buffer==0)
return 1;
i=0;
j=0;
while(1)
{
temp = ((unsigned int *)LongNameBuffer);
if(temp==0)
{
buffer = '.';
while(1)
{
temp = ((unsigned int *)LongNameBuffer);
if(temp == 0)
break; /* end */
buffer = (uint8)temp;
}
break;
}
else if(temp<0x80)
{
buffer=(uint8)temp;
}
else if(temp<0x4e00)
{
*((unsigned int*)&(buffer)) = "?";
j+=2;
}
else if(temp<0x9fa6)
{
if(Unicode_to_GBK((unsigned char *)&temp))return 1;
*((unsigned int*)&(buffer)) = temp;
j+=2;
}
else
{
*((unsigned int*)&(buffer)) = "?";
j+=2;
}
}
buffer = 0;
BackColor=BLACK;
LCDRePain(10,100);
LCD_PrintfStr16(10,100,buffer,RED);
}
else
{
LCD_PrintfStr16(10,100,"显示失败!",RED);
}
}
else
{
for(j=0;j<8;j++)
{
if(MusicInfo.deName==0x20)break;
LongNameBuffer=MusicInfo.deName;
}
//LongNameBuffer='\0';
LongNameBuffer='.';
count = j+3;
for(count=0;count<3;count++)LongNameBuffer=MusicInfo.deExtension;
LongNameBuffer='\0';
if(HanziEnable)
{
BackColor=BLACK;
LCDRePain(10,100);
LCD_PrintfStr16(10,100,LongNameBuffer,RED);
}
else
{
LCD_PrintfStr16(10,100,"显示失败!",RED);
}
}
//-------------------------------------------------------------------------------------------
DisplaySongsNum(); //显示歌曲数目
Print_ICON1_12(150,15,0,RED,BLACK,1); //小喇叭
LCD_PutGB1616_String(10,200,"PLAY",RED,BLACK,1);
Print_ICON_12(100,200,0,RED,BLACK,1); //显示正在播放
LCD_PutGB1616_String(130,200,time,RED,BLACK,1);
//显示歌曲类型
switch(type)
{
case MP3:LCD_PutGB1616_String(10,15,"MP3",GREEN,BLACK,1);break;
case WMA:LCD_PutGB1616_String(10,15,"WMV",GREEN,BLACK,1);break;
case MID:LCD_PutGB1616_String(10,15,"MID",GREEN,BLACK,1);break;
case WAV:LCD_PutGB1616_String(10,15,"WAV",GREEN,BLACK,1);break;
default:break;
}
//=============================================================================================
//------------------------------------------播放歌曲程序部分==================================
//=============================================================================================
p = MusicInfo.deStartCluster+(((unsigned long)MusicInfo.deHighClust)<<16);//读文件首簇
totalsect = MusicInfo.deFileSize/512; //计算扇区数
leftbytes = MusicInfo.deFileSize%512; //计算剩余的字节数
i=0;
sector=0;
while(1)
{
//-----------------------------------------------------------------------
keylen=0;
for(;i<SectorsPerClust;i++) //一个簇 //a cluster
{
buffer=malloc(512);
FAT_LoadPartCluster(p,i,buffer); //读一个扇区 //read a sector
VS1003B_SPI_High(); //调到适合vs1003的速度
count=0;
while(count<512)
{
if(flag==0)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
else if(type == MID)
{
if(keylen)
{
delay_us(100);
keylen--;
}
}
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 && flag)//根据需要送数据
{
for(j=0;j<32;j++)//每次送32个数据
{
VS1003B_WriteDAT(buffer);
count++;
}
if(keylen) keylen--;//用于键处理
if(sector == totalsect && count >= leftbytes)//如果文件已结束
{
if(type == MID)//waiting the midi file was decoded
{//对于mid音乐要接着送2048个零
count=0;
while(count<2048)//recommand 2048 zeros honoring DREQ goto next songs
{
if((VS1003B_PIN & _BV(VS1003B_DREQ))!=0 )
{
for(j=0;j<32;j++)
{
VS1003B_WriteDAT(0x00);
count++;
}
if(count == 2047)break;
}
}
}
i=SectorsPerClust;
break;
}//文件结束
if(count == 511)
{
break;
}//512字节送完跳出
else if(VS1003B_ReadDecodeTime() != decodetime)
{
decodetime = VS1003B_ReadDecodeTime();
min = decodetime/60;
sec = decodetime%60;
if(min>99);
else if(HanziEnable)
{
time = min/10 + 0x30;
time = min%10 + 0x30;
time = sec/10 + 0x30;
time = sec%10 + 0x30;
LCD_PutGB1616_String(130,200,time,RED,BLACK,1);
}
else
{
time = min/10 + 0x30;
time = min%10 + 0x30;
time = sec/10 + 0x30;
time = sec%10 + 0x30;
LCD_PutGB1616_String(130,200,time,RED,BLACK,1);
}
}
}
//////////////////////////////键盘控制函数///////////////////////////////////////////
//------------------------------------------------------------------------------------
if(!(KEYIN&NEXT)) //下一曲
{
while(!(KEYIN&NEXT));
songs++;
if(songs > totalsongs)songs=1;
free(buffer);
goto next;
}
else if(!(KEYIN&PREV)) //上一曲
{
while(!(PINC&PREV));
songs--;
if(songs == 1)songs=totalsongs;
free(buffer);
goto next;
}
else if((KEYIN&STOP)==0 && keylen==0) //暂停
{
while(!(KEYIN&STOP));
keylen=10000;
if(flag)
{
flag=0;
BackColor=BLACK; //定义字体背景色
LCD_PutGB1616_String(10,200,"STOP",RED,BLACK,1);
Print_ICON_12(100,200,1,RED,BLACK,1); //显示暂停
}
else
{
flag=1;
BackColor=BLACK; //定义字体背景色
LCD_PutGB1616_String(10,200,"PLAY",RED,BLACK,1);
Print_ICON_12(100,200,0,RED,BLACK,1); //显示正在播放
}
}
else if((KEYIN&UP)==0 && keylen==0) //音量+
{
if(!(PINC&UP))
{
keylen=200;
vol=vol-((uint)(1<<8)+1);
if(vol<=0x0101) vol=0x0101;
else VS1003B_WriteCMD(0x0b,vol);
}
}
else if((KEYIN&DOWN)==0 && keylen==0) //音量-
{
if(!(KEYIN&DOWN))
{
keylen=200;
vol=vol+((uint)(1<<8)+1);
if(vol>=0xFEFE) vol=0xFEFE;
else VS1003B_WriteCMD(0x0b,vol);
}
}
////////////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------
}
sector++;
free(buffer);
}
i=0;
p=FAT_NextCluster(p); //重置簇内扇区计数
if(p == 0x0fffffff || p == 0x0ffffff8 || (FAT32_Enable == 0 && p== 0xffff))
{
if(mode==REPET_ALL)
songs++;
if(songs>totalsongs)
songs=1;
goto next;
}
}
}
Code:
mark,以后参考 刚好做毕设在此先谢了楼主{:titter:}
页:
[1]