<div style="padding-bottom: 5px; line-height: 1.5; background-color: rgb(255,255,255); margin: 0px; padding-left: 5px; padding-right: 5px; color: rgb(0,0,0); font-size: 12px; padding-top: 5px"><a name="_Toc342394360">49.1 VS1053简介
VS1053是继VS1003后荷兰VLSI公司出品的又一款高性能解码芯片。该芯片可以实现对MP3/OGG/WMA/FLAC/WAV/AAC/MIDI等音频格式的解码,同时还可以支持ADPCM/OGG等格式的编码,性能相对以往的VS1003提升不少。VS1053拥有一个高性能的DSP处理器核VS_DSP,16K的指令RAM,0.5K的数据RAM,通过SPI控制,具有8个可用的通用IO口和一个串口,芯片内部还带了一个可变采样率的立体声ADC(支持咪头/咪头+线路/2线路)、一个高性能立体声DAC及音频耳机放大器。
VS1053的特性如下:
●支持众多音频格式解码,包括OGG/MP3/WMA/WAV/FLAC(需要加载patch)/MIDI/AAC等。
●对话筒输入或线路输入的音频信号进行OGG(需要加载patch)/IMA ADPCM编码
●带有EarSpeaker空间效果(用耳机虚拟现场空间效果)
●新功能可以通过软件和8 GPIO 添加
VS1053相对于它的前辈VS1003,增加了编解码格式的支持(比如支持OGG/FLAC,还支持OGG编码,VS1003不支持)、增加了GPIO数量到8个(VS1003只有4个)、增加了内部指令RAM容量到16KiB(VS1003只有5.5KiB)、增加了I2S接口(VS1003没有)、支持EarSpeaker空间效果(VS1003不支持)等。同时VS1053的DAC相对于VS1003有不少提高,同样的歌曲,用VS1053播放,听起来比1003效果好很多。
VS1053的封装引脚和VS1003完全兼容,所以如果你以前用的是VS1003,则只需要把VS1003换成VS1053,就可以实现硬件更新,电路板完全不用修改。不过需要注意的是VS1003的CVDD是2.5V,而VS1053的CVDD是1.8V,所以你还需要把稳压芯片也变一下,其他都可以照旧了。
VS1053通过SPI接口来接受输入的音频数据流,它可以是一个系统的从机,也可以作为独立的主机。这里我们只把它当成从机使用。我们通过SPI口向VS1053不停的输入音频数据,它就会自动帮我们解码了,然后从输出通道输出音乐,这时我们接上耳机就能听到所播放的歌曲了。
ALIENTEK战舰STM32开发板,自带了一颗VS1053音频编解码芯片,所以,我们直接可以通过开发板来播放各种音频格式,实现一个音乐播放器。战舰STM32开发板自带的VS1053解码芯片电路原理图,如图49.1.1所示:
图49.1.1 ALIENTEK 音频解码模块原理图 VS1053通过7根线同STM32连接,他们是:VS_MISO、VS_MOSI、VS_SCK、VS_XCS、VS_XDCS、VS_DREQ和VS_RST。这7根线同STM32的连接关系如表49.1.1所示:
表49.1.1 VS1053各信号线与STM32连接关系
其中VS_RST是VS1053的复位信号线,低电平有效。VS_DREQ是一个数据 请求信号,用来通知主机,VS1053可以接收数据与否。VS_MISO、VS_MOSI和VS_SCK则是VS1053的SPI接口他们在VS_XCS和VS_XDCS下面来执行不同的操作。从上表可以看出,VS1053的SPI是接在STM32的SPI1上面的。
VS1053的SPI支持两种模式:1,VS1002有效模式(即新模式)。2,VS1001兼容模式。这里我们仅介绍VS1002有效模式(此模式也是VS1053的默认模式)。表49.1.2是在新模式下VS1053的SPI信号线功能描述:
表49.1.2 VS1053新模式下SPI口信号线功能
VS1053的SPI数据传送,分为SDI和SCI,分别用来传输数据/命令。SDI和前面介绍的SPI协议一样的,不过VS1053的数据传输是通过DREQ控制的,主机在判断DREQ有效(高电平)之后,直接发送即可(一次可以发送32个字节)。
这里我们重点介绍一下SCI。SCI串行总线命令接口包含了一个指令字节、一个地址字节和一个16位的数据字。读写操作可以读写单个寄存器,在SCK的上升沿读出数据位,所以主机必须在下降沿刷新数据。SCI的字节数据总是高位在前低位在后的。第一个字节指令字节,只有2个指令,也就是读和写,读为0X03,写为0X02。
一个典型的SCI读时序如图49.1.2所示:
从图49.1.2可以看出,向VS1053读取数据,通过先拉低XCS(VS_XCS),然后发送读指令(0X03),再发送一个地址,最后,我们在SO线(VS_MISO)上就可以读到输出的数据了。而同时SI(VS_MOSI)上的数据将被忽略。
看完了SCI的读,我们再来看看SCI的写时序,如图49.1.3所示:
图49.1.3中,其时序和图49.1.2基本类似,都是先发指令,再发地址。不过写时序中,我们的指令是写指令(0X02),并且数据是通过SI写入VS1053的, SO则一直维持低电平。细心的读者可能发现了,在这两个图中,DREQ信号上都产生了一个短暂的低脉冲,也就是执行时间。这个不难理解,我们在写入和读出VS1053的数据之后,它需要一些时间来处理内部的事情,这段时间,是不允许外部打断的,所以,我们在SCI操作之前,最好判断一下DREQ是否为高电平,如果不是,则等待DREQ变为高。
了解了VS1053的SPI读写,我们再来看看VS1053的SCI寄存器,VS1053的所有SCI寄存器如表49.1.3所示:
VS1053总共有16个SCI寄存器,这里我们不介绍全部的寄存器,仅仅介绍几个我们在本章需要用到的寄存器。
首先是MODE寄存器,该寄存器用于控制VS1053的操作,是最关键的寄存器之一,该寄存器的复位值为0x0800,其实就是默认设置为新模式。表49.1.4是MODE寄存器的各位描述:
这个寄存器,我们这里只介绍一下第2和第11位,也就是SM_RESET和SM_SDINEW。其他位,我们用默认的即可。这里SM_RESET,可以提供一次软复位,建议在每播放一首歌曲之后,软复位一次。SM_SDINEW为模式设置位,这里我们选择的是VS1002新模式(本地模式),所以设置该位为1(默认的设置)。其他位的详细介绍,请参考VS1053的数据手册。
接着我们看看BASS寄存器,该寄存器可以用于设置VS1053的高低音效。该寄存器的各位描述如表49.1.5所示:
通过这个寄存器以上位的一些设置,我们可以随意配置自己喜欢的音效(其实就是高低音的调节)。VS1053的EarSpeaker效果则由MODE寄存器控制,请参考表49.1.4。
接下来,我们介绍一下CLOCKF寄存器,这个寄存器用来设置时钟频率、倍频等相关信息,该寄存器的各位描述如表49.1.6所示:
此寄存器,重点说明SC_FREQ,SC_FREQ是以4Khz为步进的一个时钟寄存器,当外部时钟不是12.288M的时候,其计算公式为:
SC_FREQ=(XTALI-8000000)/4000
式中为XTALI的单位为Hz。表49.1.6中CLKI是内部时钟频率,XTALI是外部晶振的时钟频率。由于我们使用的是12.288M的晶振,在这里设置此寄存器的值为0X9800,也就是设置内部时钟频率为输入时钟频率的3倍,倍频增量为1.0倍。
接下来,我们看看DECODE_TIME这个寄存器。该寄存器是一个存放解码时间的寄存器,以秒钟为单位,我们通过读取该寄存器的值,就可以得到解码时间了。不过它是一个累计时间,所以我们需要在每首歌播放之前把它清空一下,以得到这首歌的准确解码时间。
HDAT0和HDTA1是两个数据流头寄存器,不同的音频文件,读出来的值意义不一样,我们可以通过这两个寄存器来获取音频文件的码率,从而可以计算音频文件的总长度。这两个寄存器的详细介绍,请参考VS1053的数据手册。
最后我们介绍一下VOL这个寄存器,该寄存器用于控制VS1053的输出音量,该寄存器可以分别控制左右声道的音量,每个声道的控制范围为0~254,每个增量代表0.5db的衰减,所以该值越小,代表音量越大。比如设置为0X0000则音量最大,而设置为0XFEFE则音量最小。注意:如果设置VOL的值为0XFFFF,将使芯片进入掉电模式!
关于VS1053的介绍,我们就介绍到这里,更详细的介绍请看VS1053的数据手册。接下来我们说说如何控制通过最简单的步骤,来控制VS1053播放一首歌曲。
1) 复位VS1053
这里包括了硬复位和软复位,是为了让VS1053的状态回到原始状态,准备解码下一首歌曲。这里建议大家在每首歌曲播放之前都执行一次硬件复位和软件复位,以便更好的播放音乐。
2) 配置VS1053的相关寄存器
这里我们配置的寄存器包括VS1053的模式寄存器(MODE)、时钟寄存器(CLOCKF)、音调寄存器(BASS)、音量寄存器(VOL)等。
3) 发送音频数据
当经过以上两步配置以后,我们剩下来要做的事情,就是往VS1053里面扔音频数据了,只要是VS1053支持的音频格式,直接往里面丢就可以了,VS1053会自动识别,并进行播放。不过发送数据要在DREQ信号的控制下有序的进行,不能乱发。这个规则很简单:只要DREQ变高,就向VS1053发送32个字节。然后继续等待DREQ变高,直到音频数据发送完。
经过以上三步,我们就可以播放音乐了。这一部分就先介绍到这里。
<a name="_Toc342394362">49.3 软件设计
打开上一章的工程,首先在HARDWARE文件夹所在的文件夹下新建一个APP的文件夹。在该文件夹里面新建mp3player.c和mp3player.h两个文件。并将APP文件夹加入头文件包含路径。
然后在HARDWARE文件夹下新建一个VS10XX的文件夹,在该文件夹里面新建VS10XX.c、VS10XX.h和flac.h等三个文件。
首先打开VS10XX.c,里面的代码我们不一一贴出了,这里挑几个重要的函数给大家介绍一下,首先要介绍的是VS_Soft_Reset,该函数用于软复位VS1003,其代码如下:
//软复位VS10XX
void VS_Soft_Reset(void)
{
u8 retry=0;
while(VS_DQ==0); //等待软件复位结束
VS_SPI_ReadWriteByte(0Xff);//启动传输
retry=0;
while(VS_RD_Reg(SPI_MODE)!=0x0800)// 软件复位,新模式
{
VS_WR_Cmd(SPI_MODE,0x0804);// 软件复位,新模式
delay_ms(2);//等待至少1.35ms
if(retry++>100)break;
}
while(VS_DQ==0);//等待软件复位结束
retry=0;
while(VS_RD_Reg(SPI_CLOCKF)!=0X9800)//设置VS10XX的时钟,3倍频 ,1.5xADD
{
VS_WR_Cmd(SPI_CLOCKF,0X9800);//设置VS10XX的时钟,3倍频 ,1.5xADD
if(retry++>100)break;
}
delay_ms(20);
}
该函数比较简单,先配置一下VS1053的模式顺便执行软复位操作,在软复位结束之后,再设置好时钟,完成一次软复位。接下来,我们介绍一下VS_WR_Cmd函数,该函数用于向VS1003写命令,代码如下:
//向VS10XX写命令
//address:命令地址
//data:命令数据
void VS_WR_Cmd(u8 address,u16 data)
{
while(VS_DQ==0);//等待空闲
VS_SPI_SpeedLow();//低速
VS_XDCS=1; ;
VS_XCS=0;
VS_SPI_ReadWriteByte(VS_WRITE_COMMAND);//发送VS10XX的写命令
VS_SPI_ReadWriteByte(address); //地址
VS_SPI_ReadWriteByte(data>>8); //发送高八位
VS_SPI_ReadWriteByte(data); //第八位
VS_XCS=1;
VS_SPI_SpeedHigh(); //高速
}
该函数用于向VS1053发送命令,这里要注意VS1053的写操作比读操作快(写1/4 CLKI,读1/7 CLKI),虽然说写寄存器最快可以到1/4CLKI,但是经实测在1/4CLKI的时候会出错,所以在写寄存器的时候最好把SPI速度调慢点,然后在发送音频数据的时候,就可以1/4CLKI的速度了。有写命令的函数,当然也有读命令的函数了。VS_RD_Reg用于读取VS1053的寄存器的内容。该函数代码如下:
//读VS10XX的寄存器
//address:寄存器地址
//返回值:读到的值
//注意不要用倍速读取,会出错
u16 VS_RD_Reg(u8 address)
{
u16 temp=0;
while(VS_DQ==0);//非等待空闲状态
VS_SPI_SpeedLow();//低速
VS_XDCS=1;
VS_XCS=0;
VS_SPI_ReadWriteByte(VS_READ_COMMAND); //发送VS10XX的读命令
VS_SPI_ReadWriteByte(address); //地址
temp=VS_SPI_ReadWriteByte(0xff); //读取高字节
<div style="margin: 5px 0px"> temp=temp |