<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空间效果(用耳机虚拟现场空间效果) ●单时钟操作12..13MHz ●内部PLL锁相环时钟倍频器 ●低功耗 ●内含高性能片上立体声DAC,两声道间无相位差 ●过零交差侦测和平滑的音量调整 ●内含能驱动30 欧负载的耳机驱动器 ●模拟,数字,I/O 单独供电 ●为用户代码和数据准备的16KB片上RAM ●可扩展外部DAC的I2S接口 ●用于控制和数据的串行接口(SPI) ●可被用作微处理器的从机 ●特殊应用的SPI Flash引导 ●供调试用途的UART接口 ●新功能可以通过软件和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 SCI读时序 从图49.1.2可以看出,向VS1053读取数据,通过先拉低XCS(VS_XCS),然后发送读指令(0X03),再发送一个地址,最后,我们在SO线(VS_MISO)上就可以读到输出的数据了。而同时SI(VS_MOSI)上的数据将被忽略。 看完了SCI的读,我们再来看看SCI的写时序,如图49.1.3所示: 图49.1.3 SCI写时序 图49.1.3中,其时序和图49.1.2基本类似,都是先发指令,再发地址。不过写时序中,我们的指令是写指令(0X02),并且数据是通过SI写入VS1053的, SO则一直维持低电平。细心的读者可能发现了,在这两个图中,DREQ信号上都产生了一个短暂的低脉冲,也就是执行时间。这个不难理解,我们在写入和读出VS1053的数据之后,它需要一些时间来处理内部的事情,这段时间,是不允许外部打断的,所以,我们在SCI操作之前,最好判断一下DREQ是否为高电平,如果不是,则等待DREQ变为高。 了解了VS1053的SPI读写,我们再来看看VS1053的SCI寄存器,VS1053的所有SCI寄存器如表49.1.3所示:
表49.1.3 SCI寄存器 VS1053总共有16个SCI寄存器,这里我们不介绍全部的寄存器,仅仅介绍几个我们在本章需要用到的寄存器。 首先是MODE寄存器,该寄存器用于控制VS1053的操作,是最关键的寄存器之一,该寄存器的复位值为0x0800,其实就是默认设置为新模式。表49.1.4是MODE寄存器的各位描述: 表49.1.4 MODE寄存器各位描述 这个寄存器,我们这里只介绍一下第2和第11位,也就是SM_RESET和SM_SDINEW。其他位,我们用默认的即可。这里SM_RESET,可以提供一次软复位,建议在每播放一首歌曲之后,软复位一次。SM_SDINEW为模式设置位,这里我们选择的是VS1002新模式(本地模式),所以设置该位为1(默认的设置)。其他位的详细介绍,请参考VS1053的数据手册。 接着我们看看BASS寄存器,该寄存器可以用于设置VS1053的高低音效。该寄存器的各位描述如表49.1.5所示: 表49.1.5 BASS寄存器各位描述 通过这个寄存器以上位的一些设置,我们可以随意配置自己喜欢的音效(其实就是高低音的调节)。VS1053的EarSpeaker效果则由MODE寄存器控制,请参考表49.1.4。 接下来,我们介绍一下CLOCKF寄存器,这个寄存器用来设置时钟频率、倍频等相关信息,该寄存器的各位描述如表49.1.6所示: 表49.1.6 CLOCKF寄存器各位描述 此寄存器,重点说明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 |
RE:【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第四十九章 音乐播放器实验