|
我现在程序可以完整的播放整个音乐,只是不时掺杂一些像播放划伤光盘类似的噪声,请大家给我指点下,以下是我程序
void Delay(u32 nTime)
{
unsigned int i;
unsigned long j;
for(i = nTime;i > 0;i--)
for(j = 1000;j > 0;j--);
}
void Delay_us(u32 nTime)
{
unsigned int i;
//unsigned long j;
for(i = nTime;i > 0;i--);
//for(j = 1000;j > 0;j--);
}
unsigned char SPIPutChar(unsigned char outb)
{
while (SPI_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET);
SPI_SendData(SPI2, outb);
while (SPI_GetFlagStatus(SPI2, SPI_FLAG_RXNE) == RESET);
return SPI_ReceiveData(SPI2);
}
void Mp3SoftReset(void)
{
Mp3WriteRegister (SPI_MODE, 0x08, 0x04); // 软件复位
Delay(1);
while (GPIO_ReadInputData(GPIOE) & MP3_DREQ == 0); // 等待软件复位结束
//Mp3WriteRegister(SPI_CLOCKF, 0x40, 0x00); // 设置vs1003的时钟,3倍频
Mp3WriteRegister(SPI_CLOCKF, 0x98, 0x00);
//Mp3WriteRegister (SPI_AUDATA, 0xac, 0x44); // 采样率48k,立体声
Mp3WriteRegister(SPI_BASS, 0x42, 0x56); // 设置重音
//Mp3WriteRegister(SPI_BASS, 0x00, 0xf6); // 设置重音
Mp3SetVolume(0x20,0x20); // 设置音量
Delay(1);
//向vs1003发送4个字节无效数据,用以启动SPI发送
Mp3SelectData();
SPIPutChar(0);
SPIPutChar(0);
SPIPutChar(0);
SPIPutChar(0);
Mp3DeselectData();
}
void Mp3Reset(void)
{
//Mp3SoftReset();
Mp3PutInReset(); //xReset = 0 复位vs1003
Delay(100);
SPIPutChar(0xff); //发送一个字节的无效数据,启动SPI传输
Mp3DeselectControl(); //xCS = 1
Mp3DeselectData(); //xDCS = 1
Mp3ReleaseFromReset(); //xRESET = 1
Delay(100); //延时100ms
while (GPIO_ReadInputData(GPIOE) & MP3_DREQ == 0); //等待DREQ为高
Delay(100);
Mp3SoftReset(); //vs1003软复位
}
void Mp3WriteRegister(unsigned char addressbyte, unsigned char highbyte, unsigned char lowbyte)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
Mp3DeselectData(); //XDCS
Delay_us(1);
Mp3SelectControl(); //~XCS
Delay_us(1); //XCS = 0
SPIPutChar(VS_WRITE_COMMAND); //发送写寄存器命令
SPIPutChar(addressbyte); //发送寄存器的地址
SPIPutChar(highbyte); //发送待写数据的高8位
SPIPutChar(lowbyte); //发送待写数据的低8位
Delay_us(1);
Mp3DeselectControl(); //XCS
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
}
u16 Mp3ReadRegister(unsigned char addressbyte)
{
u16 resultvalue = 0;
Mp3DeselectData();
Mp3SelectControl(); //XCS = 0
SPIPutChar(VS_READ_COMMAND); //发送读寄存器命令
SPIPutChar(addressbyte); //发送寄存器的地址
resultvalue = SPIGetChar() << 8;//读取高8位数据
resultvalue |= SPIGetChar(); //读取低8位数据
Mp3DeselectControl();
return resultvalue; //返回16位寄存器的值
}
u8 FAT_init(void)
{
//u16 BPBbytesPerSec; // 每扇区的字节数
u16 BPBRevdFATSec; // FAT1前的保留扇区数
u8 ParNumberFATs; // 该分区上的FAT份数
//u16 BPBRootDirCunt; // 根目录项数
u16 BPBTotSector16; // 16位扇区数
u16 BPBFATPerSec16; // 16bit每FAT占用的扇区数
u16 BPBhiddsector; // 该分区系统隐藏扇区数
u32 BPBTotSector32; // 32位扇区数
u32 DataClusterCount; // 数据区簇数
u32 Sector; // 扇区变量
GPIO_SetBits(GPIOC, GPIO_Pin_9);
GPIO_ResetBits(GPIOC, GPIO_Pin_12);
MSD_ReadBlock(buffer, 0, 512); // 读SD卡0扇区
if((0xEB != buffer[0])&&(0xE9 != buffer[0])) // 如果0扇区不是DBR
{
if((0x55 != buffer[510])||(0xAA != buffer[511])) return MBR_ERR; // MBR错误! 是否为结束
Sector = ((u32)buffer[454])| // 载入MBR里DPT中的DBR偏移量,只用低2字节
((u32)buffer[455]<<8);
MSD_ReadBlock(buffer, Sector, 512); // 读DBR所在扇区
if((0xEB != buffer[0])&&(0xE9 != buffer[0]))
return DBR_ERR; // 如果不是DBR则报错:磁盘未格式化!
}
//-----------------------------------------------------------------
// BPBbytesPerSec = ((uint16)buffer[11])| // 每扇区字节数
// ((uint16)buffer[12]<<8);
BPBSecPerClust = buffer[13]; // 每簇扇区数
BPBRevdFATSec = ((u16)buffer[14])| // FAT1前的保留扇区数
((u16)buffer[15]<<8);
ParNumberFATs = buffer[16]; // 该分区上的FAT份数
// BPBRootDirCunt = ((uint16)buffer[17])| // 根目录项数,如果为0则可能是FAT32系统
// ((uint16)buffer[18]<<8);
BPBTotSector16 = ((u16)buffer[19])| // 16位扇区数
((u16)buffer[20]<<8);
BPBFATPerSec16 = ((u16)buffer[22])| // 每FAT占用的扇区数,16bit
((u16)buffer[23]<<8);
BPBhiddsector = ((u16)buffer[28])| // 系统隐藏扇区数,只用低2字节
((u16)buffer[29]<<8);
BPBTotSector32 = ((u32)buffer[32])| // 32位扇区数
((u32)buffer[33]<<8)|
((u32)buffer[34]<<16)|
((u32)buffer[35]<<24);
//-----------------------------------------------------------------
// 获得逻辑总扇区数
if(BPBTotSector32 == 0)
{
if(BPBTotSector16 == 0) return SECTORS_ERR; //扇区数报错:磁盘错误!
else BPBTotSector32 = BPBTotSector16;
}
FirstFATSector = BPBhiddsector + BPBRevdFATSec;
// 首FAT起始扇区=系统隐藏扇区数+FAT1前的保留扇区数
FirstDirSector = FirstFATSector + BPBFATPerSec16 * ParNumberFATs;
// 根目录起始扇区=首FAT起始扇区 +(每FAT占用的扇区数 × 该分区上的FAT份数)
FirstDataSector = FirstDirSector + 32;
// 数据区起始扇区=根目录起始扇区 + 根目录占用扇区
DataClusterCount= (BPBTotSector32 - FirstDataSector + BPBhiddsector)/BPBSecPerClust;
// 数据区簇数=(BPB中磁盘总数-数据区起始扇区+系统隐藏扇区数)/每簇的扇区数
if(DataClusterCount<4085) return CLUSTER_COUNT_ERR;
// 报错:文件系统不被支持!
else if(DataClusterCount<=65525) //FAT16
{
DirSecitemCunt = FAT16;
// FAT16目录项数的基数
return FAT16;
// 文件系统:FAT16
}
else if(DataClusterCount> 65525) //FAT32
{
DirSecitemCunt = FAT32;
// FAT32目录项数的基数
BPBFATPerSec16 = ((u16)buffer[36])|
((u16)buffer[37]<<8);
// FAT32每FAT占用的扇区数,只用低2字节
FirstDirSector = FirstFATSector + BPBFATPerSec16 * ParNumberFATs;
// 根目录起始扇区=首FAT起始扇区+(每FAT占用的扇区数×该分区上的FAT份数)
FirstDataSector = FirstDirSector + BPBSecPerClust;
// 数据区起始扇区=根目录起始扇区 + 每簇扇区数(单个根目录占用扇区)
FirstDircluster = ((u32)buffer[44])|
// FAT32根目录首簇号
((u32)buffer[45]<<8)|
((u32)buffer[46]<<16)|
((u32)buffer[47]<<24);
return FAT32;
// 文件系统:FAT32
}
return 0;
}
//-----------------------------------------------------------------
// 函数名:FatNextCluster
// 功 能:获取FAT链中的下一簇号
// 参 数:当前簇号
// 返回值:FAT1下一簇号
//-----------------------------------------------------------------
u32 GetNextCluster(u32 cluster)
{
// u16 k;
u16 offset;
u32 sector;
// 簇号的扇区内偏移变量
if(FatClusSec != FirstFATSector +(cluster>>DirSecitemCunt))
// 当前簇号所在FAT扇区=上次的FAT扇区,则在FAT缓冲里找下一簇号
{
FatClusSec = FirstFATSector +(cluster>>DirSecitemCunt);
//cluster=FirstFATSector+FatClusSec;
// 该簇号所在的FAT扇区=FAT1起始扇区+簇号/FAT每扇区目录项数
MSD_ReadBlock(buffer, FatClusSec, 512);
// 读当前簇号所在的新FAT扇区
}
if(DirSecitemCunt==FAT16)
{
offset =(cluster % 256) <<1;
// FAT扇区内的簇偏移量=(簇号%每扇区目录项数)×单个FAT项字节数
sector=((u16)buffer[offset])|
// 获取簇号内容
((u16)buffer[offset+1]<<8);
}
else
{
//offset =(cluster % 128) <<2;
offset =(cluster % 128);
//cluster=((u32)buffer[offset])|
//((u32)buffer[offset+1]<<8)|
//((u32)buffer[offset+2]<<16)|
//((u32)buffer[offset+3]<<24);
sector=((unsigned long *)buffer)[offset];
}
return sector;
// 返回簇号
}
u16 Baozhan_Play(u16 item,u8 *buf ) // item=0 搜索根目录下的 mp3文件并返回数量,不播放
{ // item≠0 从item开始播放
u8 Cnt; // 普通变量
u8 DirSecCout; // 根目录扇区变量
u16 coun; // 扇区内偏移变量
u16 Entry=0; // mp3文件数量
u32 FileClus; // mp3文件簇号
u32 FileSect; // mp3文件长度/扇区变量
u32 totalsect; // 文件拥有的扇区数
u16 leftbytes; // 文件剩余字节
u8 n; // 簇扇区变量
u8 j; // 播放字节变量
u16 count; // 播放缓冲区指针变量
u32 LBA32; // 32bit绝对扇区变量
// u32 Rootcluster; // FAT32根目录簇号暂存变量
u8 Playbuf[512];
GPIO_SetBits(GPIOC, GPIO_Pin_9); //拉高存储器
GPIO_ResetBits(GPIOC, GPIO_Pin_12);//拉低读卡器
// Rootcluster = FirstDircluster;
// FAT32根目录首簇号赋给暂存变量
if(DirSecitemCunt==FAT16) DirSecCout=32;
// FAT16根目录为32扇区
else DirSecCout=BPBSecPerClust;
// FAT32单个根目录为一簇的扇区数,分多个簇段
LBA32 = (u32)FirstDirSector;
for(Cnt=0;Cnt<DirSecCout;Cnt++)
// 在DirSecCout个根目录扇区内搜索
{
if(0 == item) MSD_ReadBlock(buffer, (LBA32+Cnt), 512); // 搜索歌曲
for(coun=0;coun<512;coun+=32) // 目录项基数为32字节
{
if(0 != item) MSD_ReadBlock(buffer, (LBA32+Cnt), 512); // 播放歌曲
if(('.' != buffer[coun])&&(0x00 != buffer[coun])&&(0xE5 != buffer[coun])&&(0x0F != buffer[coun+11]))// 确保是正确可访问文?
{ //文件名32个字节整数倍的开头
if(( buffer[coun+0] == buf[0])&&( buffer[coun+1] == buf[1])&&( buffer[coun+2] == buf[2])&&
( buffer[coun+3] == buf[3])&&( buffer[coun+4] == buf[4])&&( buffer[coun+5] == buf[5])&&
( buffer[coun+6] == buf[6])&&( buffer[coun+7] == buf[7])&&('M' == buffer[coun+8])&&
('P' == buffer[coun+9])&&('3' == buffer[coun+10]))
Entry++;
if((item == Entry)&&(0 != Entry)) // 如果相等开始播放
{
/*printf1(0x77);printf1(0x77);printf1(0x77);printf1(0x77);printf1(0x77);printf1(0x77);printf1(0x77);
printf1( buffer[coun+0]);printf1( buffer[coun+1]);printf1( buffer[coun+2]);printf1( buffer[coun+3]);
printf1( buffer[coun+4]);printf1( buffer[coun+5]);printf1( buffer[coun+6]);printf1( buffer[coun+7]);
printf1( buffer[coun+8]);printf1( buffer[coun+9]); printf1( buffer[coun+10]); */
Mp3Reset(); // 播放前软复位VS1003b
if(DirSecitemCunt==FAT16)
{
FileClus = 0;
FileClus = ((u16)buffer[coun+26])|((u16)buffer[coun+27]<<8); // 获取FAT16文件首簇号
}
else
{
FileClus = ((u32)buffer[coun+26])|((u32)buffer[coun+27]<<8)|
((u32)buffer[coun+20]<<16)|((u32)buffer[coun+21]<<24); // 获取FAT32文件首簇号
}
FileSect = ((u32)buffer[coun+28])|((u32)buffer[coun+29]<<8)|
((u32)buffer[coun+30]<<16)|((u32)buffer[coun+31]<<24); // 获取文件长度
totalsect = FileSect / 512; // 计算文件拥有的扇区数
if(totalsect<4) goto Exit; // 如果文件小于2K
leftbytes = FileSect % 512; // 计算剩余的字节数
FatClusSec = 0; // 簇号所在的FAT扇区,每首歌播放前清0
while(1) // 音乐播放函数,一曲播放完退出
{
//FileSect=(FileClus-2)*BPBSecPerClust+FirstDataSector-8; // 数据扇区=(簇号-2)×每簇扇区数+数据区起始扇区
FileSect=(FileClus-2)*BPBSecPerClust+FirstDataSector;
for(n=0;n<BPBSecPerClust;n++)// 播放一个簇的全部扇区
{
MSD_ReadBlock(Playbuf, (FileSect+n), 512);// 读一扇区数据到播放缓冲区
count=0;
Mp3DeselectControl();
//Mp3SelectData();
while(count<512)
{
// if (GPIO_ReadInputData(GPIOE) & MP3_DREQ == 0); //等待DREQ为高向VS1003b发送32字节数据
//if ((GPIO_ReadInputData(GPIOE) & MP3_DREQ) != 0)
{
Mp3SelectData();
for(j=0;j<32;j++)
{
SPIPutChar(Playbuf[count]);
count++;
// Delay(20);
Delay_us(150);
while (GPIO_ReadInputData(GPIOE) & MP3_DREQ == 0);
}
Mp3DeselectData();
// if((0 ==totalsect)&&(count>=leftbytes)) goto Exit; // 文件结束?
// if((n+1 ==BPBSecPerClust)&&(count==32)) FileClus=GetNextCluster(FileClus);
if(count==511) break;
// 播放一簇文件的最后一个扇区时加载下一簇号
if((DirSecitemCunt==FAT16 && FileClus==0x0000FFFF)||(FileClus==0x0FFFFFFF)) goto Exit;
// 防止读取簇号意外出错
}
}
//Delay(2000);
totalsect--; // 文件拥有扇区数减1
if((0 ==totalsect)&&(count>=leftbytes)) goto Exit; // 文件结束?
//if((n+1 ==BPBSecPerClust)&&(count==32)) FileClus=GetNextCluster(FileClus);
// if((DirSecitemCunt==FAT16 && FileClus==0x0000FFFF)||(FileClus==0x0FFFFFFF)) goto Exit;
}
//Delay(10000);
// FileClus = FileClus;
FileClus=GetNextCluster(FileClus);
//Mp3DeselectData();
}
Exit:
count=2048; // 放完一首歌,向VS1003b填充2048个0
//Mp3SelectData();
while(count)
{
if (GPIO_ReadInputData(GPIOE) & MP3_DREQ == 0); //等待DREQ为高
//if (GPIO_ReadInputData(GPIOE) & MP3_DREQ )
{
Mp3SelectData();
for(j=0;j<32;j++)
{
SPIPutChar(0);
count--;
}
Mp3DeselectData();
}
}
//Mp3DeselectData();
item++; // 放完一首歌加1,否则不能继续播放
}
}
}
}
return Entry; // 返回根目录下mp3文件数量
} |
|