要实现的功能:
测试51单片机控制VS1003播放一小段单片机内部存好音频。为后续
工作:通过CH375播放U盘中的音频文件打下基础。
模块选择:
1>音频解码DSP 我用的VS1003。
因为是要先验证功能的实现,所以买的现成VS1003模块,这样比自己制版焊接元件方便多了,也不会错过对底层了解的机会,重要的是价格也还可以接受。
2>控制芯片MCU 我用的89C52。
因为手头只有这个单片机,所以就拿来用了。参数:FLASH ROM=8K,RAM=256B,时钟频率=11.0592MHZ。
stc89c52
最小系统
vs1003模块
阅读VS1003数据手册获取VS1003播放音频的最简单方式:
VS1003上电后要先进行初始化之后才可以解码播放音频文件。
复位过程:
硬件复位->软件复位->设置重低音增强->设置时钟->设置采样率->设置声道音量。
这是代码:
/************************************************
//初始化VS1003
*************************************************/
void Mp3Reset(void)
{
XRESET=0;//硬件复位
delay(100);//延时
XDCS=XCS=1;//拉高指令和数据片选电位
XRESET=1;//结束硬件复位
wr_command(0x00,0x08,0x04);//软件复位:SCI_MODE = 0x0804;表示使用软件复位。
delay(10);//延时
DREQ=1;
while(!DREQ); //软件复位结束
wr_command(0x02,0x00,0x55);//设置重低音提升:SPI_BASS = 0x0055;表示50Hz以下低音获得5db提升,高音不提升。
delay(10);
wr_command(0x03,0x98,0x00);//设置VS1003的时钟:SCI_CLOCKF = 0x9800;表示3倍频,倍频增量1.5x,时钟频率12.288MHZ。
delay(10);
wr_command(0x05,0xbb,0x81);//设置VS1003的采样率:SPI_AUDATA = 0xBB81,采样率48khz,立体声
delay(10);
wr_command(0x0b,0x10,0x10);//音量左声道-17*0.5db,右声道-17*0.5db。
delay(10);
spi_write(0);//向vs1003发送4个字节无效数据,用以启动SPI发送
spi_write(0);
spi_write(0);
spi_write(0);
}
/************************************************/
wr_command( )表示寄存器中写入16位的指令数据。
寄存器写入指令需要按照如下顺序:
拉低SCI指令片选->发送写操作码->发送寄存器地址->发送高8位指令数据->发送低8位指令数据->拉高SCI指令片选当DREQ是低电位时是不允许对寄存器进行操作的,这段时间是在进行内部刷新寄存器。所以在发送指令之前还要检测一下DREQ的电位值。
这是代码:
/************************************************
//VS1003内部寄存器写入指令
*************************************************/
void wr_command(unsigned char addr,unsigned char hdat,unsigned char ldat )//寄存器地址,指令高位,指令低位
{
DREQ=1;//拉高DREQ电位,等待电位回落
while(!DREQ);//等待直到VS1003可以接受数据
XCS=0;//开SCI指令片选
spi_write(0x02);//发送读操作码
spi_write(addr);//地址
spi_write(hdat);//数据字高位
spi_write(ldat);//数据字地位
XCS=1;//关SCI指令片选
}
/************************************************/
spi_write()表示通过spi通信协议给vs1003发送一个8位数据。
vs1003通信spi协议上升沿读取数据,下降沿写入数据。
vs1003接收数据按照高位优先。
SI VS1003的数据接收线
SCLK 通信时钟
dat0-dat7 dat的0-7位数据
避免使用循环降低效率,采用简单的方式。
代码在这里:
/************************************************
//spi 方式给VS1003发送数据
*************************************************/
void spi_write(unsigned char x)
{
dat=x; //将x赋值给可位寻址的变量dat
SI=dat7;//高位数据保持
SCLK=0;//拉低时钟电位,开始检测输入的数据
SCLK=1;//抬高时钟电位,检测输入完毕,开始刷入
SI=dat6;
SCLK=0;
SCLK=1;
SI=dat5;
SCLK=0;
SCLK=1;
SI=dat4;
SCLK=0;
SCLK=1;
SI=dat3;
SCLK=0;
SCLK&#