😃 因为学习播放 mp3 用到了 VS1503,故对其命令、寄存器以及编程代码进行分析。
那种杂七杂八的就不介绍了,又没啥用,介绍一堆以后连看都不看!
我真的累了啊 ~ 为了学音乐播放器居然要看这么老多东西!!!!!
啊啊啊啊啊!都搞懂了吗?????
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本地模式(新模式)进行控制!
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。
写指令为:0X02,数据通过SI写入VS1053, SO则一直维持低电平。
注意:在读和写时序图中,DREQ信号上都产生了一个短暂的低脉冲,也就是执行时间,在写入和读出VS1053的数据之后,它需要一些时间来处理内部的事情,这段时间,是不允许外部打断的。所以,在SCI操作之前,最好判断一下DREQ是否为高电平,如果不是,则等待DREQ变为高。
VS1053寄存器
😶 VS1053有16个寄存器,啊 ~ 挺多!
写入每个寄存器的值就可以执行特定的操作!具体功能可参照数据手册
1、MODE寄存器(0X00)
SM_RESET(0000 0000 0000 0010):软件复位,建议在每播放一首歌曲之后,软复位一次。
SM_SDINEW(0000 1000 0000 0000):模式设置位,设置为1,选择VS1002新模式(本地模式)。
2、BASS寄存器(0X02)
该寄存器可以用于设置VS1053的高低音效,通过这个寄存器以上位的一些设置,我们可以随意配置自己喜欢的音效(其实就是高低音的调节)。
注意:EarSpeaker效果由MODE寄存器控制。
3、CLOCKF寄存器(0X03)
该寄存器用来设置时钟频率、倍频等相关信息。其中: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<len;)
{
addr = patch[i++];
n = patch[i++];
if(n & 0x8000U) //RLE run, replicate n samples
{
n &= 0x7FFF;
val = patch[i++];
while(n--)VS_WR_Cmd(addr, val);
}else //copy run, copy n sample
{
while(n--)
{
val = patch[i++];
VS_WR_Cmd(addr, val);
}
}
}
}
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); //设置空间效果
}
就这些东西,只不过看手册也能写出来!
文章来源:https://www.toymoban.com/news/detail-416231.html
到这里就结束了,晚安啦各位!!文章来源地址https://www.toymoban.com/news/detail-416231.html
到了这里,关于【音频解码芯片】VS1503音频解码芯片的应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!