【音频解码芯片】VS1503音频解码芯片的应用

因为学习播放 mp3 用到了 VS1503,故对其命令、寄存器以及编程代码进行分析。

那种杂七杂八的就不介绍了,又没啥用,介绍一堆以后连看都不看!


【音频解码芯片】VS1503音频解码芯片的应用_第1张图片

我真的累了啊 ~ 为了学音乐播放器居然要看这么老多东西!!!!!

【音频解码芯片】VS1503音频解码芯片的应用_第2张图片

啊啊啊啊啊!都搞懂了吗?????


VS1503

支持的音频解码:Ogg Vorbis, MP3, AAC, WMA and WAV PCM + ADPCM

拥有一个高性能的DSP处理器核VS_DSP,16K的指令RAM,0.5K的数据RAM,通过SPI控制,具有8个可用的通用IO口和一个串口,芯片内部还带了一个可变采样率的立体声ADC(支持咪头或线路输入)、一个高性能立体声DAC及音频耳机放大器。

  • 支持音量调节、高低音控制和EarSpeaker空间效果。
  • 自带耳机驱动器,可驱动30 欧负载的耳机。
  • 自带8个GPIO,可用于控制外设/作为I2S接口(外接DAC )。
  • 可通过加载patch,实现新功能添加。

VS1053通过SPI接口来接受输入的音频数据流,它可以是一个从机,也可以作为独立的机。

通过SPI口向VS1053不停的输入音频数据,它就会自动解码(硬解)

采用VS1002本地模式(新模式)进行控制!

【音频解码芯片】VS1503音频解码芯片的应用_第3张图片

VS1053的SPI数据传送,分为SDI和SCI,分别用来传输数据/命令。SDI采用SPI协议,不过,数据传输受DREQ控制,主机在判断DREQ有效(高电平)之后,直接发送数据即可(一次可以发送32个字节)。

要接的线:(就是通过SPI协议控制的)

名称 说明 解释
XCS 片选输入(低电平有效) 命令片选(低电平有效)
XDCS 数据片选/字节同步 数据片选(低电平有效)
SCK SPI时钟总线 SPI信号线
SI SPI数据输入线 SPI信号线
SO SPI数据输出线 SPI信号线
DREQ 数据请求 数据请求信号(高电平有效),通知单片机VS1053是否可以接收数据
RST 复位(低电平有效) 复位信号线,低电平有效

SCI串行总线

SCI串行总线命令接口包含了一个指令字节、一个地址字节和一个16位的数据字。读写操作可以读写单个寄存器,在SCK的上升沿读出数据位,所以主机必须在下降沿刷新数据。SCI的字节数据总是高位在前低位在后的。第一个字节指令字节,只有2个指令,也就是读和写,读为0X03写为0X02

【音频解码芯片】VS1503音频解码芯片的应用_第4张图片 SCI读时序图
【音频解码芯片】VS1503音频解码芯片的应用_第5张图片 SCI写时序图

写指令为:0X02,数据通过SI写入VS1053, SO则一直维持低电平。

注意:在读和写时序图中,DREQ信号上都产生了一个短暂的低脉冲,也就是执行时间,在写入和读出VS1053的数据之后,它需要一些时间来处理内部的事情,这段时间,是不允许外部打断的。所以,在SCI操作之前,最好判断一下DREQ是否为高电平,如果不是,则等待DREQ变为高。


VS1053寄存器

VS1053有16个寄存器,啊 ~ 挺多!

【音频解码芯片】VS1503音频解码芯片的应用_第6张图片

写入每个寄存器的值就可以执行特定的操作!具体功能可参照数据手册
 

1、MODE寄存器(0X00)

【音频解码芯片】VS1503音频解码芯片的应用_第7张图片

SM_RESET(0000 0000 0000 0010):软件复位,建议在每播放一首歌曲之后,软复位一次。
SM_SDINEW(0000 1000 0000 0000):模式设置位,设置为1,选择VS1002新模式(本地模式)。

2、BASS寄存器(0X02)

【音频解码芯片】VS1503音频解码芯片的应用_第8张图片

该寄存器可以用于设置VS1053的高低音效,通过这个寄存器以上位的一些设置,我们可以随意配置自己喜欢的音效(其实就是高低音的调节)。

注意EarSpeaker效果由MODE寄存器控制。

3、CLOCKF寄存器(0X03)

【音频解码芯片】VS1503音频解码芯片的应用_第9张图片

该寄存器用来设置时钟频率、倍频等相关信息。其中:SC_FREQ是以4Khz为步进的一个时钟寄存器,当外部时钟是12.288M的时候,设置为0即可

XTALI是外部晶振的时钟频率(单位为:Hz )。CLKI是内部时钟频率。由于我们使用的是12.288M的晶振,在这里设置此寄存器的值为0X9800,也就是设置内部时钟频率为输入时钟频率的3倍,倍频增量为1.5倍。

4、DECODE_TIME寄存器(0X04)

该寄存器是一个存放解码时间的寄存器,以秒钟为单位,我们通过读取该寄存器的值,就可以得到解码时间。不过,它是一个累计时间,在每首歌播放之前,需要把它清空一下,以得到这首歌的准确解码时间。

5、HDAT0&HDAT1寄存器(0X08&0X09)

这两个寄存器,是数据流头寄存器,不同的音频文件,读出来的值意义不一样,我们可以通过这两个寄存器来获取音频文件的码率,从而可以计算音频文件的总长度。

6、VOL寄存器(0X0B)

该寄存器用于控制VS1053的输出音量,该寄存器可以分别控制左右声道的音量,每个声道的控制范围为0~254,每个增量代表0.5db的衰减,所以该值越小,代表音量越大。比如设置为0X0000则音量最大,而设置为0XFEFE则音量最小。

注意:如果设置VOL的值为0XFFFF,将使芯片进入掉电模式!


vs1053的控制

说不上谁抄谁,或者都是官方例程改的,野火的和正点原子的非常像。

初始化步骤

复位VS1053

包括硬复位和软复位,让VS1053恢复初始状态,准备解码下一首歌曲。在每首歌曲播放之前都可以执行一次硬件复位和软件复位,以便更好的播放音乐。

配置VS1053的相关寄存器

这里我们配置的寄存器包括VS1053的模式寄存器(MODE)、时钟寄存器(CLOCKF)、音调寄存器(BASS)、音量寄存器(VOL)等。

发送音频数据

经过以上配置以后,我们剩下来要做的事情,就是往VS1053里面发送音频数据,只要是VS1053支持的音频格式,直接往里面丢就可以了,VS1053会自动识别,并进行播放。不过,发送数据要在DREQ信号的控制下有序的进行,不能乱发。这个规则很简单:只要DREQ变高,就向VS1053发送32个字节。然后继续等待DREQ变高,直到音频数据发送完

寄存器定义

//写命令
#define VS_WRITE_COMMAND 	0x02
//读命令
#define VS_READ_COMMAND 	0x03

//SPI寄存器的定义
#define SPI_MODE        	0x00   
#define SPI_STATUS      	0x01   
#define SPI_BASS        	0x02   
#define SPI_CLOCKF      	0x03   
#define SPI_DECODE_TIME 	0x04   
#define SPI_AUDATA      	0x05   
#define SPI_WRAM        	0x06   
#define SPI_WRAMADDR    	0x07   
#define SPI_HDAT0       	0x08   
#define SPI_HDAT1       	0x09  
#define SPI_AIADDR      	0x0a   
#define SPI_VOL         	0x0b   
#define SPI_AICTRL0     	0x0c   
#define SPI_AICTRL1     	0x0d   
#define SPI_AICTRL2     	0x0e   
#define SPI_AICTRL3     	0x0f 

//关于SCI_MODE每位功能的定义
#define SM_DIFF         	0x01   
#define SM_JUMP         	0x02   
#define SM_RESET        	0x04   
#define SM_OUTOFWAV     	0x08   
#define SM_PDOWN        	0x10   
#define SM_TESTS        	0x20   
#define SM_STREAM       	0x40   
#define SM_PLUSV        	0x80   
#define SM_DACT         	0x100   
#define SM_SDIORD       	0x200   
#define SM_SDISHARE     	0x400   
#define SM_SDINEW       	0x800   
#define SM_ADPCM        	0x1000   
#define SM_ADPCM_HP     	0x2000 		 

//这几个没弄明白
#define I2S_CONFIG			0XC040
#define GPIO_DDR			0XC017
#define GPIO_IDATA			0XC018
#define GPIO_ODATA			0XC019

配置结构体定义

其中,__packed 起到字节对齐的作用。因为正点原子的开发板还带有喇叭,故还有个喇叭控制。

__packed typedef struct 
{							  
	u8 mvol;		//主音量,范围:0~254
	u8 bflimit;		//低音频率限定,范围:2~15(单位:10Hz)
	u8 bass;		//低音,范围:0~15.0表示关闭.(单位:1dB)
	u8 tflimit;		//高音频率限定,范围:1~15(单位:Khz)
	u8 treble;		//高音,范围:0~15(单位:1.5dB)(原本范围是:-8~7,通过函数修改了);
	u8 effect;		//空间效果设置.0,关闭;1,最小;2,中等;3,最大.
	u8 speakersw;	//板载喇叭开关,0,关闭;1,打开 
	u8 saveflag; 	//保存标志,0X0A,保存过了;其他,还从未保存	   
}_vs10xx_obj;

两家的代码出奇的一致!是官方例程吗?还是互相抄袭??

接口的定义

#define VS_DREQ_IN						GPIO_ReadInputDataBit(VS_GPIO_DREQ_PORT,VS_DREQ)

#define VS_XDCS_SET						GPIO_SetBits(VS_GPIO_XDCS_PORT,VS_XDCS)
#define VS_XDCS_CLR						GPIO_ResetBits(VS_GPIO_XDCS_PORT,VS_XDCS)

#define VS_XCS_SET						GPIO_SetBits(VS_SPIGPIO_PORT,VS_XCS)
#define VS_XCS_CLR						GPIO_ResetBits(VS_SPIGPIO_PORT,VS_XCS)

#define VS_RST_SET						GPIO_SetBits(VS_GPIO_RST_PORT,VS_RST)
#define VS_RST_CLR						GPIO_ResetBits(VS_GPIO_RST_PORT,VS_RST)

控制VS1053的函数

其中,需要说明:SPI用的是STM32硬件SPI。

1、读寄存器:VS_RD_Reg(u8 address)

//读VS10XX的寄存器           
//address:寄存器地址
//返回值:读到的值
//注意不要用倍速读取,会出错
u16 VS_RD_Reg(u8 address)
{ 
	u16 temp=0;    	 
    while(VS_DREQ_IN==0);    //非等待空闲状态 	
    /*
     * DREQ为高电平的时候,VS1053B可接受最少32字节的数据。
     * DREQ为低电平,不能向VS1053B发送数据。 
     */	  
	VS_SPI_SpeedLow();    //SPI低速模式
	VS_XDCS_SET;    //置XDCS为1       
	VS_XCS_CLR;    //置XCS为0
	VS_SPI_ReadWriteByte(VS_READ_COMMAND);	//发送VS10XX的读命令
	VS_SPI_ReadWriteByte(address);       	//地址
	temp=VS_SPI_ReadWriteByte(0xff); 		//读取高字节
	temp=temp<<8;
	temp+=VS_SPI_ReadWriteByte(0xff); 		//读取低字节
	VS_XCS_SET;    //置XCS为1     
	VS_SPI_SpeedHigh();    //SPI低速模式  
   return temp; 
}  

2、读RAM:VS_WRAM_Read(u16 addr)

//读取VS10xx的RAM
//addr:RAM地址
//返回值:读到的值
u16 VS_WRAM_Read(u16 addr) 
{ 
	u16 res;			   	  
 	VS_WR_Cmd(SPI_WRAMADDR, addr);    //写命令,SPI_WRAMADDR为RAM读写基地址寄存器
	res=VS_RD_Reg(SPI_WRAM);    //SPI_WRAM,RAM读写  
 	return res;
} 

3、写RAM:VS_WRAM_Write(u16 addr,u16 val)

//写VS10xx的RAM
//addr:RAM地址
//val:要写入的值 
void VS_WRAM_Write(u16 addr,u16 val) 
{  		   	  
 	VS_WR_Cmd(SPI_WRAMADDR,addr);	//写RAM地址 
	while(VS_DREQ_IN==0);    //低电平不能写入	   
	VS_WR_Cmd(SPI_WRAM,val);    //写RAM值 
} 

4、写数据:VS_WR_Data(u8 data)

//向VS10XX写数据
//data:要写入的数据
void VS_WR_Data(u8 data)
{
	VS_SPI_SpeedHigh();    //高速,对VS1003B,最大值不能超过36.864/4Mhz,这里设置为9M 
	VS_XDCS_CLR;    //置XDCS为0   
	VS_SPI_ReadWriteByte(data);    //SPI写数据接口
	VS_XDCS_SET;    //置XDCS为0        
}   

5、写命令:VS_WR_Cmd(u8 address,u16 data)

//向VS1053写命令
//address:命令地址
//data:命令数据
void VS_WR_Cmd(u8 address,u16 data)
{  
	while(VS_DREQ_IN==0);    //等待空闲		  
	VS_SPI_SpeedLow();    //低速 	   
	VS_XDCS_SET;    //置XDCS为1 
	VS_XCS_CLR;    //置XCS为0,片选 
	VS_SPI_ReadWriteByte(VS_WRITE_COMMAND);    //发送VS10XX的写命令
	VS_SPI_ReadWriteByte(address);    //地址
	VS_SPI_ReadWriteByte(data>>8);    //发送高八位
	VS_SPI_ReadWriteByte(data);    //低八位
	VS_XCS_SET;    //置XCS为1,取消片选            
	VS_SPI_SpeedHigh();    //高速	   
} 

6、硬复位:VS_HD_Reset(void)

//硬复位MP3
//返回1:复位失败;0:复位成功	   
u8 VS_HD_Reset(void)
{
	u8 retry=0;
	VS_RST_CLR;    //复位置0
	Delay_ms(20);
	VS_XDCS_SET;    //取消数据传输
	VS_XCS_SET;    //取消数据传输
	VS_RST_SET;    //复位置1   
	while(VS_DREQ_IN==0 && retry<200)    //等待DREQ为高
	{
		retry++;
		Delay_us(50);
	};
	Delay_ms(20);	
	if(retry>=200)return 1;    //复位超过200*50us,复位失败
	else return 0;    //复位成功	    		 
}

7、软复位:VS_Soft_Reset(void)

//软复位VS10XX
void VS_Soft_Reset(void)
{	 
	u8 retry=0;  				   
	while(VS_DREQ_IN==0);    //等待软件复位结束	   
	VS_SPI_ReadWriteByte(0Xff);    //启动传输
	retry=0;
	while(VS_RD_Reg(SPI_MODE)!=0x0800)    //读寄存器,软件复位,新模式,0x0800缺省值  
	{
		VS_WR_Cmd(SPI_MODE,0x0804);		//写寄存器MODE,软件复位,新模式	    
		Delay_ms(2);    //等待至少1.35ms 
		if(retry++>100)break; 	    
	}	 		 
	while(VS_DREQ_IN==0);    //等待软件复位结束	 
	retry=0;
	while(VS_RD_Reg(SPI_CLOCKF)!=0X9800)    //设置VS1053的时钟,3倍频 ,1.5xADD 
	{    
        /*
         * 0x8000:1000 0000 0000 0000 是3.5倍频啊 
         * 0x1800:0001 1000 0000 0000 是2.0乘数啊
         * 也就是说,这个注释不对,可能原来的函数被修改了!!
         */
		VS_WR_Cmd(SPI_CLOCKF,0X9800);	//设置VS1053的时钟,3倍频 ,1.5xADD
		if(retry++>100)break; 	    
	}	 
	Delay_ms(20);
}

7、RAM测试函数:VS_Ram_Test(void)

用来确定VS1053是否正常工作

//ram 测试 
//返回值:RAM测试结果
// VS1003如果得到的值为0x807F,则表明完好;VS1053为0X83FF																	 
u16 VS_Ram_Test(void)
{ 
	VS_HD_Reset();    //硬复位     
 	VS_WR_Cmd(SPI_MODE,0x0820);    //进入VS10XX的测试模式
	while (VS_DREQ_IN==0);    // 等待DREQ为高			   
 	VS_SPI_SpeedLow();    //低速 
	VS_XDCS_CLR;    // XDCS = 0
	VS_SPI_ReadWriteByte(0x4d);
	VS_SPI_ReadWriteByte(0xea);
	VS_SPI_ReadWriteByte(0x6d);
	VS_SPI_ReadWriteByte(0x54);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	Delay_ms(150);
	VS_XDCS_SET;    //XDCS = 1
	return VS_RD_Reg(SPI_HDAT0);// VS1053如果得到的值为0x83FF,则表明完好;   
}     					   

8、正弦测试:VS_Sine_Test(void)

//正弦测试 
void VS_Sine_Test(void)
{											    
	VS_HD_Reset();    //硬复位
	VS_WR_Cmd(0x0b,0X2020);	  //设置音量	 
 	VS_WR_Cmd(SPI_MODE,0x0820);    //进入VS10XX的测试模式     
	while(VS_DREQ_IN==0);    //等待DREQ为高
	//printf("mode sin:%x\n",VS_RD_Reg(SPI_MODE));
 	//向VS1053发送正弦测试命令:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00
 	//其中n = 0x24, 设定VS1053所产生的正弦波的频率值,具体计算方法见VS1053的datasheet
	VS_SPI_SpeedLow();    //低速 

	VS_XDCS_CLR;    //选中数据传输
	VS_SPI_ReadWriteByte(0x53);
	VS_SPI_ReadWriteByte(0xef);
	VS_SPI_ReadWriteByte(0x6e);
	VS_SPI_ReadWriteByte(0x24);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	Delay_ms(100);
	VS_XDCS_SET;
    //退出正弦测试

    VS_XDCS_CLR;//选中数据传输
	VS_SPI_ReadWriteByte(0x45);
	VS_SPI_ReadWriteByte(0x78);
	VS_SPI_ReadWriteByte(0x69);
	VS_SPI_ReadWriteByte(0x74);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	Delay_ms(100);
	VS_XDCS_SET;		 

    //再次进入正弦测试并设置n值为0x44,即将正弦波的频率设置为另外的值
    VS_XDCS_CLR;//选中数据传输      
 	VS_SPI_ReadWriteByte(0x53);
	VS_SPI_ReadWriteByte(0xef);
	VS_SPI_ReadWriteByte(0x6e);
	VS_SPI_ReadWriteByte(0x44);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	Delay_ms(100);
 	VS_XDCS_SET;
    //退出正弦测试

    VS_XDCS_CLR;//选中数据传输
	VS_SPI_ReadWriteByte(0x45);
	VS_SPI_ReadWriteByte(0x78);
	VS_SPI_ReadWriteByte(0x69);
	VS_SPI_ReadWriteByte(0x74);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	VS_SPI_ReadWriteByte(0x00);
	Delay_ms(100);
	VS_XDCS_SET; 
}	 

9、设置SPI为高速模式:VS_SPI_SpeedHigh(void)

//设置到高速模式
//SPI设置接口函数
void VS_SPI_SpeedHigh(void)
{						  
	SPI_SetSpeed(SPI_BaudRatePrescaler_8);		 
}

10、设置SPI为低速模式:VS_SPI_SpeedLow(void)

//设置到低速模式 
//SPI设置接口函数
void VS_SPI_SpeedLow(void)
{								 
	SPI_SetSpeed(SPI_BaudRatePrescaler_32);    //SPI_SetSpeed可设置到SPI文件中
}

SPI1_SetSpeed(u8 SpeedSet)

void SPI1_SetSpeed(u8 SpeedSet)
{
	assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
	SPI1->CR1&=0XFFC7; 
	SPI1->CR1|=SpeedSet;
	SPI_Cmd(SPI1,ENABLE);     //这是SPI1\2之类的需要设置!!
}

11、SPI读写函数:VS_SPI_ReadWriteByte(u8 data)

//移植时候的接口
//data:要写入的数据
//返回值:读到的数据
u8 VS_SPI_ReadWriteByte(u8 data)
{			  	 
	return SPI1_ReadWriteByte(data);	  
}

SPI1_ReadWriteByte(u8 TxData)

//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI1_ReadWriteByte(u8 TxData)
{				   			 
	/* Loop while DR register in not emplty */
    //检查指定的SPI标志位设置与否:发送缓存空标志位
	while(SPI_I2S_GetFlagStatus(VS_SPI,SPI_I2S_FLAG_TXE) == RESET);
	
	/* Send byte through the SPI1 peripheral */
    //通过外设SPIx发送一个数据
	SPI_I2S_SendData(VS_SPI, writedat);
	
	/* Wait to receive a byte */
    //检查指定的SPI标志位设置与否:接受缓存非空标志位
	while(SPI_I2S_GetFlagStatus(VS_SPI, SPI_I2S_FLAG_RXNE) == RESET);
	
	/* Return the byte read from the SPI bus */
    //返回通过SPIx最近接收的数据	
	return SPI_I2S_ReceiveData(VS_SPI);数据					    
}

12、初始化VS10xx:VS_Init(void)

配置GPIO接口,配置SPI初始化。函数就不附了。

13、设置播放速度:VS_Set_Speed(u8 t)

//设置播放速度(仅VS1053有效) 
//t:0,1,正常速度;2,2倍速度;3,3倍速度;4,4倍速;以此类推
void VS_Set_Speed(u8 t)
{
	VS_WRAM_Write(0X1E04,t);		//写入播放速度 
}

14、得到码率(bps):VS_Get_HeadInfo(void)

码率在VS1053数据手册中解释了。MP3的码率是准的!!

//返回Kbps的大小
//返回值:得到的码率
u16 VS_Get_HeadInfo(void)
{
	unsigned int HEAD0;
	unsigned int HEAD1;  
 	HEAD0=VS_RD_Reg(SPI_HDAT0); 
    HEAD1=VS_RD_Reg(SPI_HDAT1);
    //printf("(H0,H1):%x,%x\n",HEAD0,HEAD1);
	switch(HEAD1)
	{        
			case 0x7665://WAV格式
			case 0X4D54://MIDI格式 
			case 0X4154://AAC_ADTS
			case 0X4144://AAC_ADIF
			case 0X4D34://AAC_MP4/M4A
			case 0X4F67://OGG
			case 0X574D://WMA格式
			case 0X664C://FLAC格式
			{
					//printf("HEAD0:%d\n",HEAD0);
					HEAD1=HEAD0*2/25;//相当于*8/100
					if((HEAD1%10)>5)return HEAD1/10+1;//对小数点第一位四舍五入
					else return HEAD1/10;
			}
			default://MP3格式,仅做了阶层III的表
			{
					HEAD1>>=3;
					HEAD1=HEAD1&0x03; 
					if(HEAD1==3)HEAD1=1;
					else HEAD1=0;
					return bitrate[HEAD1][HEAD0>>12];
			}
	}  
}

15、得到字节速率:VS_Get_ByteRate(void)

//得到平均字节数
//返回值:平均字节数速度
u32 VS_Get_ByteRate(void)
{
	return VS_WRAM_Read(0X1E05);    //读RAM,平均位速
}

16、得到填充字节:VS_Get_EndFillByte(void)

//得到需要填充的数字
//返回值:需要填充的数字
u16 VS_Get_EndFillByte(void)
{
	return VS_WRAM_Read(0X1E06);//填充字节
}  

17、向VS10xx发送32字节:VS_Send_MusicData(u8* buf)

//发送一次音频数据
//固定为32字节
//返回值:0,发送成功
//		 1,VS10xx不缺数据,本次数据未成功发送    
u8 VS_Send_MusicData(u8* buf)
{
	u8 n;
	if(VS_DREQ_IN!=0)  //送数据给VS10XX
	{			   	 
		VS_XDCS_CLR;  
        for(n=0;n<32;n++)
		{
			VS_SPI_ReadWriteByte(buf[n]);	 			
		}
		VS_XDCS_SET;     				   
	}else return 1;
	return 0;//成功发送了
}

18、重新开始下一首歌播放:VS_Restart_Play(void)

VS1053数据手册中也有提到!

这些定义之类的东西别问为什么!都是手册规定的!

//切歌
//通过此函数切歌,不会出现切换“噪声”				
void VS_Restart_Play(void)
{
	u16 temp;
	u16 i;
	u8 n;	  
	u8 vsbuf[32];
	for(n=0;n<32;n++)vsbuf[n]=0;//清零
	temp=VS_RD_Reg(SPI_MODE);	//读取SPI_MODE的内容
	temp|=1<<3;					//设置SM_CANCEL位
	temp|=1<<2;					//设置SM_LAYER12位,允许播放MP1,MP2
	VS_WR_Cmd(SPI_MODE,temp);	//设置取消当前解码指令
	for(i=0;i<2048;)			//发送2048个0,期间读取SM_CANCEL位.如果为0,则表示已经取消了当前解码
	{
		if(VS_Send_MusicData(vsbuf)==0)//每发送32个字节后检测一次
		{
			i+=32;						//发送了32个字节
   			temp=VS_RD_Reg(SPI_MODE);	//读取SPI_MODE的内容
 			if((temp&(1<<3))==0)break;	//成功取消了
		}	
	}
	if(i<2048)//SM_CANCEL正常
	{
		temp=VS_Get_EndFillByte()&0xff;//读取填充字节
		for(n=0;n<32;n++)vsbuf[n]=temp;//填充字节放入数组
		for(i=0;i<2052;)
		{
			if(VS_Send_MusicData(vsbuf)==0)i+=32;//填充	  
		}   	
	}else VS_Soft_Reset();  	//SM_CANCEL不成功,坏情况,需要软复位 	  
	temp=VS_RD_Reg(SPI_HDAT0); 
    temp+=VS_RD_Reg(SPI_HDAT1);
	if(temp)					//软复位,还是没有成功取消,放杀手锏,硬复位
	{
		VS_HD_Reset();		   	//硬复位
		VS_Soft_Reset();  		//软复位 
	} 
}

19、重设解码时间:VS_Reset_DecodeTime(void)

是累计计时的,每次切歌需要重置。

//重设解码时间                          
void VS_Reset_DecodeTime(void)
{
	VS_WR_Cmd(SPI_DECODE_TIME,0x0000);
	VS_WR_Cmd(SPI_DECODE_TIME,0x0000);//操作两次
}

20、得到解码时间:VS_Get_DecodeTime(void)

//得到mp3的播放时间n sec
//返回值:解码时长
u16 VS_Get_DecodeTime(void)
{ 		
	u16 dt=0;	 
	dt=VS_RD_Reg(SPI_DECODE_TIME);      
 	return dt;
} 	    					  

21、加载用户patch:VS_Load_Patch(u16 *patch,u16 len)

说实话,没看懂。

//vs10xx装载patch.
//patch:patch首地址
//len:patch长度
void VS_Load_Patch(u16 *patch,u16 len) 
{
	u16 i; 
	u16 addr, n, val; 	  			   
	for(i=0;i

22、设置主音量:VS_Set_Vol(u8 volx)

VS1053寄存器是值越小声音越大,但是习惯上是值越大声音越大,故取反一下!

//设定VS10XX播放的音量和高低音
//volx:音量大小(0~254)
void VS_Set_Vol(u8 volx)
{
    u16 volt=0; 			//暂存音量值
    volt=254-volx;			//取反一下,得到最大值,表示最大的表示 
	volt<<=8;
    volt+=254-volx;			//得到音量设置后大小
    VS_WR_Cmd(SPI_VOL,volt);//设音量 
}

23、设置高低音:VS_Set_Bass(u8 bfreq,u8 bass,u8 tfreq,u8 treble)

//设定高低音控制
//bfreq:低频上限频率	2~15(单位:10Hz)
//bass:低频增益			0~15(单位:1dB)
//tfreq:高频下限频率 	1~15(单位:Khz)
//treble:高频增益  	 	0~15(单位:1.5dB,小于9的时候为负数)
void VS_Set_Bass(u8 bfreq,u8 bass,u8 tfreq,u8 treble)
{
    u16 bass_set=0; //暂存音调寄存器值
    signed char temp=0;   	 
	if(treble==0)temp=0;	   		//变换
	else if(treble>8)temp=treble-8;
 	else temp=treble-9;  
	bass_set=temp&0X0F;				//高音设定
	bass_set<<=4;
	bass_set+=tfreq&0xf;			//高音下限频率
	bass_set<<=4;
	bass_set+=bass&0xf;				//低音设定
	bass_set<<=4;
	bass_set+=bfreq&0xf;			//低音上限    
	VS_WR_Cmd(SPI_BASS,bass_set);	//BASS 
}

24、设置音效:VS_Set_Effect(u8 eft)

//设定音效
//eft:0,关闭;1,最小;2,中等;3,最大.
void VS_Set_Effect(u8 eft)
{
	u16 temp;	 
	temp=VS_RD_Reg(SPI_MODE);	//读取SPI_MODE的内容
	if(eft&0X01)temp|=1<<4;		//设定LO
	else temp&=~(1<<5);			//取消LO
	if(eft&0X02)temp|=1<<7;		//设定HO
	else temp&=~(1<<7);			//取消HO						   
	VS_WR_Cmd(SPI_MODE,temp);	//设定模式    
}	 

25、全部设置:VS_Set_All(void)

//设置音量,音效等.
void VS_Set_All(void) 				
{			 
	VS_Set_Vol(vsset.mvol);			//设置音量
	VS_Set_Bass(vsset.bflimit,vsset.bass,vsset.tflimit,vsset.treble);  
	VS_Set_Effect(vsset.effect);	//设置空间效果
}

就这些东西,只不过看手册也能写出来!


【音频解码芯片】VS1503音频解码芯片的应用_第10张图片

到这里就结束了,晚安啦各位!!

你可能感兴趣的:(开发项目小知识点,音视频,stm32,嵌入式硬件,单片机)