今天(星期六)我利用LPC1343的PWM做音频输出,并成功的循环播放了SD卡上的bg.wav歌曲(刘德华的《今天》)。播放十分流畅,高音低音丰富,现在边听《今天》边发贴,感觉还不错。
下面是步骤和各部分代码,和大家共享,全部代码和那个bg.wav文件见附件:
硬件改造部分:
0、今天先做单声道的。将一般的耳机的两根线直接焊接到开发板的P1_9和GND。这样我们就给LPC1343开发板加了一个耳机接口,以后他将为你提供动听的音乐。
可能有人会问:PWM出来的是PWM脉冲,你不滤波啊?其实可以不需要,只要你脉冲频率能够超出耳机的响应范围,他不会带来太大问题。当然有更好,我以后慢慢加。
至此硬件改造结束。
软件部分:
1、我用LPC1343的两个16位计时器(你可以选择LPC1343里4个计时器任何两个):一个提供PWM输出;一个做定时器。
2、PWM输出计时器在这里作为DAC,输出音频。我用了TIMER16_B1_MAT0,输出对应管脚P1_9。
//PWM初始化设置
unsigned short pwmizhouqi=256; //10000;
LPC_TMR16B1->TCR = 0; //关闭timer16B1
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<8); //只有提供了timer16B1的时钟后才能操作timer16B1
LPC_TMR16B1->TCR = 0; //关闭timer16B1
//LPC_TMR16B0->EMR = (1<<EMC3)|(1<<EMC2)|(1<<EMC1)|(1<<EMC0)|(1<<3)|0x01;
//1、将引脚PIO1_9设为CT16B1_MAT0功能:IOCON_PIO1_9[2:0]=B001
LPC_IOCON-> PIO1_9=0X01;
//2、设置CT16B1_MAT0的匹配值:设置TMR16B1MR0值 TMR16B1MR0=空白数
LPC_TMR16B1->MR0 = pwmizhouqi/2; //空闲期
//3、将CT16B1_MAT0的PWM模式打开:TMR16B0PWMC[0]=1
LPC_TMR16B1-> PWMC = 0x01; //注意:PWM周期的复位由MCR决定,而不是PWMC控制MAT3决定
//4、设置予分频寄存器
LPC_TMR16B1-> PR=0; //为0不予分频
//5、设置如果MR3和TC匹配,TC复位:TMR16B1MCR[10]=1
LPC_TMR16B1->MCR = 0x0400;
//6、设置CT16B0_MAT3的匹配值:设置TMR16B0MR3值 TMR16B0MR3=周期长度
LPC_TMR16B1->MR3 = pwmizhouqi; //PWM周期
//7、设置计数控制寄存器选择计时器模式(每个PCLK上升沿):TMR16B0CTCR[1:0]=B00;也可以选择其他值为CAP引脚
LPC_TMR16B1->CTCR = 0x00;
//8、启动计数:TMR16B0TCR[0]=1
LPC_TMR16B1->TCR |= 1;
3、另一个定时器TMR16B0根据WAVE文件的采样率而发生定时中断,定时控制输出PWM脉冲宽度。
//将TIMER0初始化成24000的中断,每计数到3000中断一次修改LPC_TMR16B1->MR0
nextreadpwm=512;
LPC_TMR16B0->TCR = 0; //关闭timer16B1
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7); //只有提供了timer16B0的时钟后才能操作timer16B0
LPC_TMR16B0->TCR = 0; //关闭timer16B1
//让MCR=0x03表示MR0匹配产生中断、复位
LPC_TMR16B0->MCR = 0x03;
//设置CT16B0_MAT0的匹配值:设置TMR16B0MR0值
LPC_TMR16B0->MR0 = 3000; //3000个周期
//3、将CT16B0_MAT0的PWM模式关闭:TMR16B0PWMC[0]=0
LPC_TMR16B0-> PWMC = 0x00; //注意:PWM周期的复位由MCR决定,而不是PWMC控制MAT3决定
//4、设置予分频寄存器
LPC_TMR16B0-> PR=0; //为0不予分频
//5、设置计数控制寄存器选择计时器模式(每个PCLK上升沿):TMR16B0CTCR[1:0]=B00;也可以选择其他值为CAP引脚
LPC_TMR16B0->CTCR = 0x00; //00
//6、启动计数:TMR16B0TCR[0]=1
NVIC_EnableIRQ(TIMER_16_0_IRQn);
LPC_TMR16B0->TCR |= 1;
4、两个计时器分工合作实现音频输出。
5、我是在前面发帖说过的“利用LPC1343实现SPI接口读SD卡的文件系统”的基础上开发的(直接用了zhaojun_xf版主的成果,基本没有什么改动。hehe!)。主程序不断读取(播放)SD上的WAV文件。
char isok=0;
AppSystemInit();
char tmpname[16]="bg.wav";
while (1)
{
//读取SD卡文件: bg.wav,
isok = AppFileRead(tmpname);
}
6、在TMR16B0的中断里,将读到的wav定时写入LPC_TMR16B1->MR0,发出声音。
void TIMER16_0_IRQHandler (void)
{
LPC_TMR16B0->IR = 1;
if (nextreadpwm>=BUFFER_SIZE)
return;
LPC_TMR16B1->MR0 = Buffer[nextreadpwm];
nextreadpwm++;
return;
}