请问我的music程序烧录到板子里后,能够播放声音,但却只有单一的一个高频声音是怎么回事?
程序如下:
#include"710defs.h"
#include"AC97.h"
#include"HB_it.h"
/*播放缓冲区的首地址*/
#define base_addres 0x100000
/*播放数据*/
UINT8 PlayData[] = {
#include "8k.dat"
};
UINT32 PCM_QUEUE_LEN = (512*1024);
UINT _uPlayVol = 0x1f1f;
UINT16 sPlayVolume = 0;
BOOL PlayLastBlock;
volatile UINT _uPcmQHead;
/*延时函数*/
static void Delay(int nCnt)
{
volatile int loop;
for (loop=0; loop<nCnt; loop++);
}
/*播放函数*/
INT PlayCallback(UINT8 *pucBuff, UINT32 uDataLen)
{
UINT nLen;
nLen = PCM_QUEUE_LEN - _uPcmQHead;
/*将数据从PCM队列中取出放到DMA缓存区*/
if (nLen >= uDataLen)
{
memcpy(pucBuff, &PlayData[_uPcmQHead], uDataLen);
_uPcmQHead = (_uPcmQHead + uDataLen) % PCM_QUEUE_LEN;
}
else
{
memcpy(pucBuff, &PlayData[_uPcmQHead], nLen);
memcpy(&pucBuff[nLen], PlayData, uDataLen - nLen);
_uPcmQHead = uDataLen - nLen;
}
return 0;
}
/* 读AC97寄存器*/
static UINT16 ac97_read_register(INT nIdx)
{
UINT volatile nWait;
/* 置起R_WB位并写入寄存器地址 */
REG_ACTL_ACOS1 = (0x80 | nIdx);
/* 设置帧是否有效和有效的时隙 */
REG_ACTL_ACOS0 = 0x11;
Delay(100);
/* 检查AC_ACTL_ACCON的AC_R_FINISH位是否被置高,若被置高,说明读数据缓存区已经准备好给CPU读取 */
for (nWait = 0; nWait < 0x10000; nWait++)
{
if (REG_ACTL_ACCON & AC_R_FINISH)
break;
}
REG_ACTL_ACOS0 = 0;
Delay(100);
return (REG_ACTL_ACIS2 & 0xFFFF);
}
/* 写AC97寄存器*/
static INT ac97_write_register(INT nIdx, UINT16 sValue)
{
volatile UINT nWait;
/* 清R_WB位并写入寄存器地址*/
REG_ACTL_ACOS1 = nIdx;
/* 写入AC97寄存器的值*/
REG_ACTL_ACOS2 = sValue;
/* 设置帧的有效位和有效的时隙*/
REG_ACTL_ACOS0 = 0x13;
Delay(100);
/* 检查AC_ACTL_ACCON的AC_W_FINISH位,若被清零,说明AC-LINK控制数据输出缓存已经被CPU移到编解码器*/
for (nWait = 0; nWait < 0x10000; nWait++)
{
if (!(REG_ACTL_ACCON & AC_W_FINISH))
break;
}
/*若读回的值和写入的值相同,则说明写入成功*/
while (ac97_read_register(nIdx) != sValue);
REG_ACTL_ACOS0 = 0;
return 0;
}
/*初始化AC97*/
UINT8 Initac97()
{
/*使能音频控制器和AC-LINK接口*/
REG_ACTL_CON = REG_ACTL_CON | IIS_AC_PIN_SEL | AUDIO_EN | ACLINK_EN | PFIFO_EN | RFIFO_EN | T_DMA_IRQ | R_DMA_IRQ | DMA_EN;
Delay(1000);
/*stereo模式*/
REG_ACTL_RESET = REG_ACTL_RESET | 0x3000;
/* 重启音频控制器 */
REG_ACTL_RESET = REG_ACTL_RESET | ACTL_RESET_BIT;
Delay(1000);
REG_ACTL_RESET = REG_ACTL_RESET & ~ACTL_RESET_BIT;
Delay(1000);
/* 重启AC97接口 */
REG_ACTL_RESET = REG_ACTL_RESET | AC_RESET;
Delay(1000);
REG_ACTL_RESET = REG_ACTL_RESET & ~AC_RESET;
Delay(1000);
/* 冷启动AC97 */
REG_ACTL_ACCON = REG_ACTL_ACCON | AC_C_RES;
Delay(1000);
REG_ACTL_ACCON = REG_ACTL_ACCON & ~AC_C_RES;
Delay(1000);
/* 检查AC97的ACTL_ACIS0的CODEC_READY位,若置起则说明AC97准备好了 */
while(!(REG_ACTL_ACIS0 & 0x10));
Delay(100);
/*选择麦克 1;3D控制 关;looback 关*/
ac97_write_register(AC97_GENERAL_PURPOSE, 0);
return 0;
}
UINT8 StartPlay(INT nSamplingRate)
{
/* 使能VRA(variable rate audio)并设置播放采样率*/
ac97_write_register(AC97_EXT_AUDIO_CTRL, ac97_read_register(AC97_EXT_AUDIO_CTRL)|0x1);
ac97_write_register(AC97_FRONT_DAC_RATE, nSamplingRate);
/*设置DMA基地址和目的地址长度*/
REG_ACTL_PDSTB = base_addres;
REG_ACTL_PDST_LENGTH = 0x1000;
PlayLastBlock = 0;
/* 开始播放 */
REG_ACTL_ACOS0 = 0x1c; //设置数据传输时隙有效
REG_ACTL_PSR = 0x3;
REG_ACTL_RESET = REG_ACTL_RESET | AC_PLAY;
return 0;
}
/* 设置音量 */
INT SetPlayVolume(UINT8 ucLeftVol, UINT8 ucRightVol)
{
INT nLData, nRData;
if (ucLeftVol == 0)
nLData = 0x80;
else
nLData = 31 - (ucLeftVol & 0x1f);
if (ucRightVol == 0)
nRData = 0x80;
else
nRData = 31 - (ucRightVol & 0x1f);
sPlayVolume = (nLData << 8) | nRData;
if (ucLeftVol == 0)
nLData = 0x80;
else
nLData = 62 - ucLeftVol*2;
if (ucRightVol == 0)
nRData = 0x80;
else
nRData = 62 - ucRightVol*2;
_uPlayVol = (nLData << 8) | nRData;
/* 设置音量 */
ac97_write_register(AC97_PCM_OUT_VOLUME, sPlayVolume ); //PCM数据输出音量
ac97_write_register(AC97_AUX_OUT_VOLUME, _uPlayVol); //耳机音量设置
ac97_write_register(AC97_MASTER_VOLUME, _uPlayVol); //全局音量设置
return 0;
}
UINT8 StopPlay()
{
/* 停止播放 */
REG_ACTL_RESET = REG_ACTL_RESET & ~AC_PLAY;
REG_ACTL_ACOS0 = 0;
/*关闭音频播放中断 */
REG_AIC_MDCR = REG_AIC_MDCR | 0x40;
return 0;
}
int main(void)
{
PCM_QUEUE_LEN = sizeof (PlayData);
_uPcmQHead = 0;
/* 设置I/O连接到音频 */
REG_GPIO_CFG0 = 0x155;
/*// GPIO4,1:输入 GPIO0,2,3:输出 */
REG_GPIO_DIR0 = 0xd;
/*使能音频时钟 */
REG_CLKSEL = REG_CLKSEL|0x10000;
Initac97();
/* 使能AC97播放中断 */
REG_AIC_SCR6 = 0x41;
REG_AIC_MECR = 0x40;
SetPlayVolume(30,30);
StartPlay(2000);
/* 检查是否播放完成 */
while(_uPcmQHead<(PCM_QUEUE_LEN-4096));
StopPlay();
} |