……
……
//一段纯音频数据数组
unsigned char music[] = {
0xF9, 0xFF, 0xF5, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xF9, 0xFF,
0xF6, 0xFF, 0xF6, 0xFF, 0xFA, 0xFF, 0xFD, 0xFF, 0xFA, 0xFF, 0xFA, 0xFF, 0xF7, 0xFF, 0xF6, 0xFF,
……
……
};
int result;
int remainder;
char flag;
char cmd;
char play_state;
void __irq uartISR(void)
{
char ch;
rSUBSRCPND |= 0x1;
rSRCPND |= 0x1<<28;
rINTPND |= 0x1<<28;
ch=rURXH0;
switch(ch)
{
case 0x55:
//播放
cmd = 1;
break;
case 0x1:
//静音
cmd = 0x11;
break;
case 0x2:
//音量提高
cmd = 0x12;
break;
case 0x3:
//音量降低
cmd = 0x13;
break;
case 0x66:
//停止
cmd = 0x2;
break;
case 0x77:
//暂停
cmd = 0x3;
break;
}
rUTXH0=ch;
}
//放音子程序
void playsound(unsigned char *buffer,int length)
{
//用于计算音频数据的长度是否超过DMA所能传输的字节数范围
//这里音频数据的通道位数为16位,因此需要length除以2
remainder = (length>>1) & 0xfffff;
//余数
result = (length>>1) / 0x100000;
//商
play_state = 1;
//置播放标志
rGPBDAT = rGPBDAT & ~(L3M|L3C|L3D) |(L3M|L3C);
//配置1341,详细讲解请看上一篇文章
WriteL3(0x14 + 2,1);
WriteL3(0x60,0);
WriteL3(0x14 + 2,1);
WriteL3(0x10,0);
WriteL3(0x14 + 2,1);
WriteL3(0xc1,0);
//配置IIS
rIISPSR
= 3<<5|3;
rIISCON
= (1<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1);
//发送IIS的DMA使能
rIISMOD
= (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0);
rIISFCON = (1<<15)|(1<<13); //发送FIFO为DMA
//配置DMA
rDISRC2 = (U32)buffer;
//DMA的源基址为音频数据数组的首地址
rDISRCC2 = (0<<1)|(0<<0);
//AHB,源地址递增
rDIDST2 = (U32)IISFIFO;
//DMA的目的基址为IIS的FIFO
rDIDSTC2 = (0<<2)| (1<<1)|(1<<0);
//当传输计数值为0时中断,APB,目的地址不变
if (result == 0)
//所传输的字节数没有超出DMA的最大传输范围
{
flag = 0;
//清标志,表示没有超出范围,进入DMA中断后结束DMA操作
//握手模式,PCLK同步,传输计数中断,单元传输,单步服务模式,IISSDO,
//硬件请求模式,非自动重载,半字,
rDCON2 = (1<<31) | (0<<30) | (1<<29) | (0<<28) | (0<<27) | (0<<24) | (1<<23) | (1<<22) | (1<<20) | (remainder);
}
else
//所传输的字节数超出了DMA的最大传输范围
{
flag = 1;
//置标志,表示超出范围
rDCON2 = (1<<31) | (0<<30) | (1<<29) | (0<<28) | (0<<27) | (0<<24) | (1<<23) | (1<<22) | (1<<20) | (0xfffff);
}
rDMASKTRIG2=(0<<2)|(1<<1)|0;
//不停止DMA,DMA通道开启,非软件触发
//启动IIS
rIISCON |= 0x1;
}
void __irq DMA_end(void)
{
rSRCPND |= 0x1<<19;
rINTPND |= 0x1<<19;
if (flag == 0)
//DMA传输完毕
{
rIISCON = 0x0;
//关闭IIS
rIISFCON = 0x0;
//清IIS的FIFO
rDMASKTRIG2=1<<2;
//停止DMA
play_state = 0;
//清播放标志
}
else
//DMA没有传输完毕,继续传输
{
result --;
//商递减
rDISRC2 += 0x200000;
//DMA源基址递增。因为传输的数据是半字,所以这里递增0x200000
if (result == 0 )
//只剩下余数部分需要传输
{
rDCON2=(rDCON2&(~0xfffff))|(remainder);
//需要重新设置传输计数值
flag=0;
//清标志
}
rDMASKTRIG2=(0<<2)|(1<<1)|0;
//需要重新设置DMA通道的开启
}
} |