新手上路
- 积分
- 21
- 金钱
- 21
- 注册时间
- 2018-6-7
- 在线时间
- 1 小时
|

楼主 |
发表于 2018-6-9 13:30:10
|
显示全部楼层
原子哥,经过调整,目前MP3能得到解码信息,DAC也可以发声,但是听到的是有规律的杂音,可以麻烦帮我看一下代码吗?感谢!
[mw_shl_code=c,true]#include "wave.h"
#include "mp3.h"
#include "string.h"
#include "mp3dec.h"
#include "wm8978.h"
#include "i2s.h"
//__align(8)
//uint16_t Mp3DecodeBuf[DECODEBUFSIZE];
short *Mp3DecodeBuf;
FIL Mp3File;
mp3Info Mp3Info;
uint8_t* Readptr; //MP3解码读指针
int32_t ByteLeft;//buffer还剩余的有效数据
uint8_t InitMp3InfoFlag;
HMP3Decoder Mp3Decoder;
uint32_t DmaBufSize;
/*==========================================================*/
unsigned char DACbz_mp3;
unsigned char CH_mp3;
unsigned int DApc_mp3;
unsigned char buffer_switch;
HMP3Decoder hMP3Decoder;
FIL f_MP3;
//int16_t *buffer1={0x00};
//int16_t *buffer2={0x00};
short *buffer1;
short *buffer2;
void TIM3_IRQHandler(void)
{
if(TIM3->SR&0X0001)//溢出中断
{
if(CH_mp3==1)//单声道
{
if(buffer_switch==0)
{
DAC->DHR12R1=(((uint16_t)buffer1[DApc_mp3]+0x8000)>>4);//*10/volume;
DAC->DHR12R2=(((uint16_t)buffer1[DApc_mp3]+0x8000)>>4);//*10/volume;
DApc_mp3++;
DAC->SWTRIGR|=0x03;//软件启动两个通道的转换
}
else
{
DAC->DHR12R1=(((uint16_t)buffer2[DApc_mp3]+0x8000)>>4);//*10/volume;
DAC->DHR12R2=(((uint16_t)buffer2[DApc_mp3]+0x8000)>>4);//*10/volume;
DApc_mp3++;
DAC->SWTRIGR|=0x03;//软件启动两个通道的转换
}
}
else //if(CH_mp3==2)//立体声 10110010 10110010
{
if(buffer_switch==0)
{
DAC->DHR12R1=(((uint16_t)buffer1[DApc_mp3]+0x8000)>>4);//*10/volume;
DApc_mp3++;
DAC->DHR12R2=(((uint16_t)buffer1[DApc_mp3]+0x8000)>>4);//*10/volume;
DApc_mp3++;
DAC->SWTRIGR|=0x03;//软件启动两个通道的转换
}
else
{
DAC->DHR12R1=(((uint16_t)buffer2[DApc_mp3]+0x8000)>>4);//*10/volume;
DApc_mp3++;
DAC->DHR12R1=(((uint16_t)buffer2[DApc_mp3]+0x8000)>>4);//*10/volume;
DApc_mp3++;
DAC->SWTRIGR|=0x03;//软件启动两个通道的转换
}
}
if(DApc_mp3==2304)/// //1帧MP3输出2304数据
{
DApc_mp3=0;
DACbz_mp3=1;
}
}
TIM3->SR&=~(1<<0);//清除中断标志位
}
//设置NVIC分组
//NVIC_Group:NVIC分组 0~4 总共5组
//CHECK OK
//091209
void MY_NVIC_PriorityGroupConfig(unsigned char NVIC_Group)
{
uint32_t temp,temp1;
temp1=(~NVIC_Group)&0x07;//取后三位
temp1<<=8;
temp=SCB->AIRCR; //读取先前的设置
temp&=0X0000F8FF; //清空先前分组
temp|=0X05FA0000; //写入钥匙
temp|=temp1;
SCB->AIRCR=temp; //设置分组
}
//设置NVIC
//NVIC_PreemptionPriority:抢占优先级
//NVIC_SubPriority :响应优先级
//NVIC_Channel :中断编号
//NVIC_Group :中断分组 0~4
//注意优先级不能超过设定的组的范围!否则会有意想不到的错误
//组划分:
//组0:0位抢占优先级,4位响应优先级
//组1:1位抢占优先级,3位响应优先级
//组2:2位抢占优先级,2位响应优先级
//组3:3位抢占优先级,1位响应优先级
//组4:4位抢占优先级,0位响应优先级
//NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
//CHECK OK
//100329
void MY_NVIC_Init(unsigned char NVIC_PreemptionPriority,unsigned char NVIC_SubPriority,unsigned char NVIC_Channel,unsigned char NVIC_Group)
{
uint32_t temp;
unsigned char IPRADDR=NVIC_Channel/4; //每组只能存4个,得到组地址
unsigned char IPROFFSET=NVIC_Channel%4;//在组内的偏移
IPROFFSET=IPROFFSET*8+4; //得到偏移的确切位置
MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf;//取低四位
if(NVIC_Channel<32)NVIC->ISER[0]|=1<<NVIC_Channel;//使能中断位(要清除的话,相反操作就OK)
else NVIC->ISER[1]|=1<<(NVIC_Channel-32);
NVIC->IP[IPRADDR]|=temp<<IPROFFSET;//设置响应优先级和抢断优先级
}
//通用定时器4中断初始化
//这里始终选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器4!
void Timer3_Init(unsigned int arr,unsigned int psc)
{
RCC->APB1ENR|=1<<1;//TIM3时钟使能
TIM3->ARR=arr; //设定计数器自动重装值//刚好1ms
TIM3->PSC=psc; //预分频器7200,得到10Khz的计数时钟
//这两个东东要同时设置才可以使用中断
TIM3->DIER|=1<<0; //允许更新中断
TIM3->DIER|=1<<6; //允许触发中断
TIM3->CR1|=0x01; //使能定时器3
MY_NVIC_Init(1,3,0x1D,2);//抢占1,子优先级3,组2
}
void DAC1_SetData(unsigned int data)
{
DAC->DHR12R1=data;//通道1的12位右对齐数据
DAC->SWTRIGR|=0x01;//软件启动转换
}
void DAC2_SetData(unsigned int data)
{
DAC->DHR12R2=data;//通道2的12位右对齐数据
DAC->SWTRIGR|=0x02;//软件启动转换
}
void Dac1_Init(void)//DAC channel1 Configuration
{
unsigned int tmpreg1=0,tmpreg2=0;
RCC->APB2ENR|=1<<2;//使能PORTA时钟
RCC->APB1ENR|=0x20000000;//使能DAC时钟
GPIOA->CRL&=0XFF00FFFF;
GPIOA->CRL|=0X00440000;//PA4,5 浮空输入
tmpreg1=DAC->CR;//Get the DAC CR value
tmpreg1&=~(0x00000FFE<<0x00000000);//Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits
tmpreg2=(0x0000003C|0x00000000|0x00000800|0x00000000);
tmpreg1|=tmpreg2<<0x00000000;//Calculate CR register value depending on DAC_Channel
DAC->CR=tmpreg1;//Write to DAC CR
DAC->CR|=0x00000001<<0x00000000;//DAC Channel1使能,PA4自动连接到DAC
DAC1_SetData(0x000);
tmpreg1=DAC->CR;//Get the DAC CR value
tmpreg1&=~(0x00000FFE<<0x00000010);//Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits
tmpreg2=(0x0000003C|0x00000000|0x00000800|0x00000000);
tmpreg1|=tmpreg2<<0x00000010;//Calculate CR register value depending on DAC_Channel
DAC->CR=tmpreg1;//Write to DAC CR
DAC->CR|=0x00000001<<0x00000010;//DAC Channel2使能,PA5自动连接到DAC
DAC2_SetData(0x000);
}
/************************************************************************************/
/*
* File Name : Convert_Stereo μ¥éùμàμ?á¢ì?éù×a??
* Description : I have do some modification in Subband() function due to the long time of
* decode.Using PolyphaseMono() function which is used in decode mono mp3,to decode
* Stereo,so must use this funtion to convert mono to Stereo.
* Input : Adress of buffer data
* Output : None
* Return : None
*/
/************************************************************************************/
void Convert_Stereo(short *buffer)
{
int i,j,k=0;
for(i=0;i<(2304/64);i++) //36
{
for(j=31+i*64,k=j+32;j>=0+i*64;j--,k-=2)
{
buffer[k]=buffer[j];
buffer[k-1]=buffer[j];
}
}
}
/***********************************************************************************/
/*
* File Name : Convert_Mono
* Description : ?o3?oóμ?μ¥éùμàMP3?a???÷μ??ò?ü£???ì?211152°?×?£??a??1|?ü*????±?μ¥éùμàμ?á¢ì?éù?£
* Input : Adress of buffer data
* Output : None
* Return : None
*/
/***********************************************************************************/
void Convert_Mono(short *buffer)
{
int i;
for (i = 1152 - 1; i >= 0; i--)
{
buffer[i * 2] = buffer;
buffer[i * 2 + 1] = buffer;
}
}
uint8_t PlayMp3File(char* path)
{
uint8_t res=0;
uint32_t br=0;
//uint32_t Mp3DataStart=0;
CloseFileFlag=0;
EndFileFlag=0;
FillBufFlag=0xFF;
//ID3V2_TagHead *TagHead;
Mp3DecodeBuf=buffer1;
Mp3Decoder=MP3InitDecoder();
if(Mp3Decoder==0)
{
printf("Init Mp3Decoder failed!\r\n");
//res=4;
//break;
}
Dac1_Init();
res=f_open(&Mp3File,(TCHAR*)path,FA_READ);
while(1)
{
if(res!=FR_OK)
{
printf("Open file failed!\r\n");
res=1;
break;
}
CloseFileFlag=1;
res=f_read(&Mp3File,TempBuf,WAVEFILEBUFSIZE,&br);
if(res!=FR_OK)
{
printf("Read file failed!\r\n");
res=2;
break;
}
Readptr=TempBuf;
ByteLeft=br;
FillMp3Buf(WaveFileBuf+DmaBufSize/2);
//break;
}
f_close(&Mp3File);
TIM4->CR1&=~0x01;//关定时器,切歌时不产生噪音
DAC->CR&=0<<0; //关闭DAC1
MP3FreeDecoder(Mp3Decoder);
return 0;
}
uint32_t FillMp3Buf(uint8_t *Buf)
{
uint32_t br=0;
int32_t Offset;
int32_t err=0;
//int32_t i;
uint16_t *PlayPtr;
//uint16_t *Mp3Ptr;
MP3FrameInfo Mp3FrameInfo;
int8_t init=0;
Offset=MP3FindSyncWord(Readptr,ByteLeft); //在readptr位置,开始查找同步字符
if(Offset<0) //没有找到同步字符,跳出帧解码循环
{
printf("Can not play the file!\r\n");
return 1;
}
Readptr+=Offset; //MP3读指针偏移到同步字符处.
ByteLeft-=Offset; //buffer里面的有效数据个数,必须减去偏移量
//printf("ByteLeft=%d\r\n",ByteLeft);
if(ByteLeft<MAINBUF_SIZE*2)//当数组内容小于2倍MAINBUF_SIZE的时候,必须补充新的数据进来.
{
memmove(TempBuf,Readptr,ByteLeft);//移动readptr所指向的数据到buffer里面,数据量大小为:bytesleft
/*
ReadBytesNum=WAVEFILEBUFSIZE-ByteLeft;
if(ReadBytesNum%2)
ReadBytesNum-=1;
f_read(&Mp3File,TempBuf+ByteLeft,ReadBytesNum,&br);//补充余下的数据
printf("rd=%d,br=%d\r\n",ReadBytesNum,br);
if(br<ReadBytesNum)
{
memset(TempBuf+ByteLeft+br,0,WAVEFILEBUFSIZE-ByteLeft-br);
//EndFileFlag=1;
}
ByteLeft=ByteLeft+ReadBytesNum;
*/
f_read(&Mp3File,TempBuf+ByteLeft,WAVEFILEBUFSIZE-ByteLeft,&br);//补充余下的数据
//printf("rd=%d,br=%d\r\n",WAVEFILEBUFSIZE-ByteLeft,br);
if(br<WAVEFILEBUFSIZE-ByteLeft)
{
memset(TempBuf+ByteLeft+br,0,WAVEFILEBUFSIZE-ByteLeft-br);
EndFileFlag=1;
}
ByteLeft=WAVEFILEBUFSIZE;
Readptr=TempBuf;
}
err=MP3Decode(Mp3Decoder,&Readptr,&ByteLeft,Mp3DecodeBuf,0);//解码一帧MP3数据
//printf("Decode error:%d\r\n",err);
if(err!=0)
{
printf("Decode error:%d\r\n",err);
return 2;
}
if(InitMp3InfoFlag==0)
{
MP3GetLastFrameInfo(Mp3Decoder,&Mp3FrameInfo); //得到刚刚解码的MP3帧信息
Mp3Info.bitsPerSample=Mp3FrameInfo.bitsPerSample;
Mp3Info.nChans=Mp3FrameInfo.nChans;
Mp3Info.OutSamples=Mp3FrameInfo.outputSamps;
Mp3Info.samprate=Mp3FrameInfo.samprate;
printf("bitsPerSample=%d\r\n",Mp3Info.bitsPerSample);
printf("nChans=%d\r\n",Mp3Info.nChans);
printf("OutSamples=%d\r\n",Mp3Info.OutSamples);
printf("samprate=%d\r\n",Mp3Info.samprate);
InitMp3InfoFlag=1;
if(init==0) //根据MP3帧信息初始化音频接口
{
Timer3_Init(1000000/(Mp3Info.samprate),71);// 1MHz的计数频率,产生和采样率一样的中断频率
CH_mp3=Mp3Info.nChans; //几声道
init=1;// //1帧MP3输出2304pcm数据
}
if(Mp3Info.nChans==1)Convert_Mono(Mp3DecodeBuf);//单声道
else Convert_Stereo(Mp3DecodeBuf);//立体声
while(!DACbz_mp3); //等待转换完成
DACbz_mp3=0; //定时器中断会置1
if(buffer_switch == 0) //双缓存切换
{
Mp3DecodeBuf=buffer1;
buffer_switch = 1;
}
else
{
Mp3DecodeBuf=buffer2;
buffer_switch = 0;
}
if(Mp3Info.bitsPerSample!=16)
{
printf("Can not play the file!\r\n");
return 3;
}
}
//Mp3Ptr=Mp3DecodeBuf;
PlayPtr=(uint16_t*)Buf;
/*if(Mp3Info.nChans==2)
{
for(i=0;i<Mp3Info.OutSamples;i++)
{
PlayPtr=Mp3Ptr;
}
}
else
{
for(i=0;i<Mp3Info.OutSamples;i++)
{
PlayPtr[0]=Mp3Ptr[0];
PlayPtr[1]=Mp3Ptr[0];
PlayPtr+=2;
Mp3Ptr+=1;
}
}*/
return 0;
}
[/mw_shl_code] |
|