程序编写主要有三个部分:定时器初始化,DAC初始化,定时器中断服务程序,WAV播放程序。
定时器初始化:
void Timerx_Init(u16 arr,u16 psc)
{
NVIC_InitTypeDef
NVIC_InitStructure;
RCC->APB1ENR|=1<<1;//TIM3时钟使能
TIM3->ARR=arr; //设定计数器自动重装值
TIM3->
SC=psc; //预分频器7200,得到10KHz的计数时钟
TIM3->DIER|=1<<0; //允许更新中断
TIM3->DIER|=1<<6; //允许触发中断
TIM3->CR1|=0x01; //使能定时器3
//优先级设置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel
= TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority
= 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority
= 3;
NVIC_InitStructure.NVIC_IRQChannelCmd =
ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
DAC初始化:
#include "dac.h"
extern u16 digital;
void MyDAC_Init(void)//DAC channel1
Configuration
{
unsigned int tmpreg1=0,tmpreg2=0;
RCC->APB2ENR|=1<<2;//使能PORTA时钟
RCC->APB1ENR|=RCC_APB1Periph_DAC;//使能DAC时钟
GPIOA->CRL&=0XFFF0FFFF;
GPIOA->CRL|=0X00040000;//PA4浮空输入
tmpreg1=DAC->CR;//Get the DAC CR value
tmpreg1&=~(CR_CLEAR_Mask<<DAC_Channel_1);
tmpreg2=(DAC_Trigger_Software|DAC_WaveGeneration_None|DAC_LFSRUnmask_Bits8_0|DAC_OutputBuffer_Enable);
tmpreg1|=tmpreg2<<DAC_Channel_1;
DAC->CR=tmpreg1;//Write to DAC CR
DAC->CR|=CR_EN_Set<<DAC_Channel_1;//DAC通道1使能,PA4自动连接到DAC
DAC1_SetData(0x000);
#if
0
tmpreg1=DAC->CR;//Get the DAC CR
value
tmpreg1&=~(CR_CLEAR_Mask<<DAC_Channel_2);
tmpreg2=(DAC_Trigger_Software|DAC_WaveGeneration_None|DAC_LFSRUnmask_Bits8_0|DAC_OutputBuffer_Enable);
tmpreg1|=tmpreg2<<DAC_Channel_2;
DAC->CR=tmpreg1;
DAC->CR|=CR_EN_Set<<DAC_Channel_2;
DAC2_SetData(0x000);
#endif
}
void DAC1_SetData(u16 data)
{
DAC->DHR12R1=data;//通道1的12位右对齐数据
DAC->SWTRIGR|=0x01;//软件启动转换
}
void DAC2_SetData(u16 data)
{
DAC->DHR12R2=data;//通道2的12位右对齐数据
DAC->SWTRIGR|=0x02;//软件启动转换
}
定时器中断服务程序:
void TIM3_IRQHandler(void)
{
u16
temp;
if(TIM3->SR&0X0001)//溢出中断
{
if(CHanalnum==1)//单声道
{
if(Bitnum==8)//8位精度
{
DAC->DHR12R1=wav_buf[DApc]*10/volume;
DAC->DHR12R2=wav_buf[DApc]*10/volume;
DAC->SWTRIGR
|=0x01;
DApc++;
}
else
if(Bitnum==16)
{
temp=(((u8)(wav_buf[DApc+1]-0x80)<<4)|(wav_buf[DApc]>>4))*10/volume;
DAC->DHR12L1=temp;
DAC->DHR12L2=temp;
DAC->SWTRIGR|=0x01;
DApc+=2;
}
}
else
if(CHanalnum==2)
{
if(Bitnum==8)
{
DAC->DHR12R1=wav_buf[DApc]*10/volume;
DApc++;
DAC->DHR12R2=wav_buf[DApc]*10/volume;
DApc++;
DAC->SWTRIGR|=0x01;
}
else
if(Bitnum==16)
{ DAC->DHR12L1=(((u8)(wav_buf[DApc+1]-0x80)<<4)|(wav_buf[DApc]>>4))*10/volume; DApc+=2; DAC->DHR12L2=(((u8)(wav_buf[DApc+1]-0x80)<<4)|(wav_buf[DApc]>>4))*10/volume;
DApc+=2;
DAC->SWTRIGR|=0x01;
}
}
if(DApc==16384)
{
DApc=0;
DACdone=1;
}
}
TIM3->SR&=~(1<<0);
}
WAV初始化:
u8 WAV_Init(u8* wav_buf)
{
if(Check_Ifo(wav_buf,"RIFF"))
return
1;
wav1.wavlen=Get_num(wav_buf+4,4);
printf("\n\rwav1.wavlen
= %ld\n\r",wav1.wavlen);
//if(Check_Ifo(wav_buf+8,"WAVE"))return 2;//WAVE错误标志
//if(Check_Ifo(wav_buf+12,"fmt "))return 3;//fmt错误标志
wav1.formart=Get_num(wav_buf+20,2);//格式类别
printf("\n\rwav1.formart
= %d\n\r",wav1.formart);
wav1.CHnum=Get_num(wav_buf+22,2);//通道数
printf("\n\rwav1.CHnum
= %d\n\r",wav1.CHnum);
CHanalnum=wav1.CHnum;
wav1.SampleRate=Get_num(wav_buf+24,4);//采样率
printf("\n\rwav1.SampleRate
= %ld\n\r",wav1.SampleRate);
wav1.speed=Get_num(wav_buf+28,4);//音频转换数率
printf("\n\rwav1.speed
= %ld\n\r",wav1.speed);
wav1.ajust=Get_num(wav_buf+32,2);//数据块调速数
printf("\n\rwav1.ajust
= %d\n\r",wav1.ajust);
wav1.SampleBits=Get_num(wav_buf+34,2);//样本数据位数
printf("\n\rwav1.SampleBits
= %d\n\r",wav1.SampleBits);
Bitnum=wav1.SampleBits;
//if(Check_Ifo(wav_buf+36,"data"))return 4;//数据标志错误
wav1.DATAlen=Get_num(wav_buf+40,4);//数据长度
printf("\n\rwav1.DATAlen
= %d\n\r",wav1.DATAlen);
if(wav1.wavlen<0x100000)
{
printf("\n\rwav1.wavlen
= %dkb\n\r",(wav1.wavlen)>>10);
}
else
{
printf("\n\rwav1.wavlen
= %dMb\n\r",(wav1.wavlen)>>20);
}
if(wav1.formart==1)
printf("\n\rWAV
PCM\n\r");
if(wav1.CHnum==1)
printf("\n\rsingle\n\r");
else
printf("\n\rstereo\n\r");
printf("\n\rwav1.SampleRate
= %dkHz\n\r",(wav1.SampleRate)/1000);
printf("\n\rwav1.speed
= %dbps\n\r",(wav1.speed)/1000);
printf("\n\rwav1.SampleBits
= %dbit\n\r",wav1.SampleBits);
return
0;
}
u8 Check_Ifo(u8* pbuf1,u8* pbuf2)
{
u8
i;
for(i=0;i<4;i++)
if(pbuf1!=pbuf2)
return
1;
return
0;
}
u32 Get_num(u8* pbuf,u8 len)
{
u32 num;
if(len==2)num=(pbuf[1]<<8)|pbuf[0];
else
if(len==4)num=(pbuf[3]<<24)|(pbuf[2]<<16)|(pbuf[1]<<8)|pbuf[0];
return
num;
}
WAV播放:
u8 Playwav(char *file)
{
FIL
fwav;
FRESULT
Res;
UINT
BR;
unsigned
char i;
unsigned
int times;
Res
= f_open(&fwav, file, FA_OPEN_EXISTING | FA_READ);
if(Res
!= FR_OK)
{
printf("\n\ropen
file error : %d\n\r",Res);
}
else
{
Res = f_read(&fwav, wav_buf,
sizeof(wav_buf), &BR); /* Read a
chunk of src file */
if(Res==FR_OK)
{
WAV_Init(wav_buf);
DACdone=0;
DApc=44;
//跳过头信息
Timerx_Init(1000000/wav1.SampleRate,72);
//定时器初始化
times=(wav1.DATAlen>>10)-1;
//计算数据大小
for(i=0;i<times/32;i++)//循环一次转换32KB数据
{
while(!DACdone);//等待前面16384字节转换完成 DACdone=0;
Res
= f_read(&fwav, wav_buf, 16384, &BR);
while(!DACdone);// 等待前面16384字节转换完成
DACdone=0;
Res
= f_read(&fwav, wav_buf, 16384, &BR);//读取数据
}
}
else
{
printf("\n\rread
file error : %d\n\r",Res);
}
f_close(&fwav);
}
return 0;
}