📄 vs10xx.c
字号:
#include "vs10XX.h"
#include "delay.h"
#include "mmc_sd.h"
#include "spi.h"
#include "usart.h"
#include "spec_rew.h"
//VS10XX的全功能函数
//支持SIN测试和RAM测试
//并加入了VS10XX的频谱显示代码,不过说实话不咋地,还不如自己写的频谱分析,怀疑是不是真实的频谱变换?
//正点原子@SCUT
//V1.1
//VS10XX设置参数
//0,高音控制;1,最低频限;2,低音控制;3,最低频限
//0,henh.1,hfreq.2,lenh.3,lfreq 5,主音量
u8 VS10XXram[5]={0,0,0,0,250};
//软复位VS10XX
void VS_Soft_Reset(void)
{
u8 retry;
while(VS_DQ==0);//等待软件复位结束
SPIx_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;
}
// while(VS_RD_Reg(SPI_AUDATA)!=0XBB81)//设置VS10XX的时钟,3倍频 ,1.5xADD
// {
// VS_WR_Cmd(SPI_AUDATA,0XBB81);
// if(retry++>100)break;
// }
//VS_WR_Cmd(SPI_CLOCKF,0X9800);
//VS_WR_Cmd(SPI_AUDATA,0XBB81); //采样率48k,立体声
//向VS10XX发送4个字节无效数据,用以启动SPI发送
VS_XDCS=0;//选中数据传输
SPIx_ReadWriteByte(0XFF);
SPIx_ReadWriteByte(0XFF);
SPIx_ReadWriteByte(0XFF);
SPIx_ReadWriteByte(0XFF);
VS_XDCS=1;//取消数据传输
delay_ms(20);
}
//硬复位MP3
//返回1:复位失败
//返回0:复位成功
u8 VS_HD_Reset(void)
{
u8 retry=0;
VS_RST=0;
delay_ms(20);
VS_XDCS=1;//取消数据传输
VS_XCS=1;//取消数据传输
VS_RST=1;
while(VS_DQ==0&&retry<200)//等待DREQ为高
{
retry++;
delay_us(50);
};
delay_ms(20);
if(retry>=200)return 1;
else return 0;
}
//正弦测试
void VS_Sine_Test(void)
{
VS_HD_Reset();
VS_WR_Cmd(0x0b,0X2020); //设置音量
VS_WR_Cmd(SPI_MODE,0x0820);//进入VS10XX的测试模式
while(VS_DQ== 0); //等待DREQ为高
//printf("mode sin:%x\n",VS_RD_Reg(SPI_MODE));
//向VS10XX发送正弦测试命令:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00
//其中n = 0x24, 设定VS10XX所产生的正弦波的频率值,具体计算方法见VS10XX的datasheet
SPIx_SetSpeed(SPI_SPEED_64);//低速
VS_XDCS=0;//选中数据传输
SPIx_ReadWriteByte(0x53);
SPIx_ReadWriteByte(0xef);
SPIx_ReadWriteByte(0x6e);
SPIx_ReadWriteByte(0x24);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
delay_ms(100);
VS_XDCS=1;
//退出正弦测试
VS_XDCS=0;//选中数据传输
SPIx_ReadWriteByte(0x45);
SPIx_ReadWriteByte(0x78);
SPIx_ReadWriteByte(0x69);
SPIx_ReadWriteByte(0x74);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
delay_ms(100);
VS_XDCS=1;
//再次进入正弦测试并设置n值为0x44,即将正弦波的频率设置为另外的值
VS_XDCS=0;//选中数据传输
SPIx_ReadWriteByte(0x53);
SPIx_ReadWriteByte(0xef);
SPIx_ReadWriteByte(0x6e);
SPIx_ReadWriteByte(0x44);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
delay_ms(100);
VS_XDCS=1;
//退出正弦测试
VS_XDCS=0;//选中数据传输
SPIx_ReadWriteByte(0x45);
SPIx_ReadWriteByte(0x78);
SPIx_ReadWriteByte(0x69);
SPIx_ReadWriteByte(0x74);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
delay_ms(100);
VS_XDCS=1;
}
//ram 测试
void VS_Ram_Test(void)
{
u16 regvalue ;
VS_HD_Reset();
VS_WR_Cmd(SPI_MODE,0x0820);// 进入VS10XX的测试模式
while (VS_DQ==0); // 等待DREQ为高
SPIx_SetSpeed(SPI_SPEED_64);//低速
VS_XDCS=0; // xDCS = 1,选择VS10XX的数据接口
SPIx_ReadWriteByte(0x4d);
SPIx_ReadWriteByte(0xea);
SPIx_ReadWriteByte(0x6d);
SPIx_ReadWriteByte(0x54);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
SPIx_ReadWriteByte(0x00);
delay_ms(50);
VS_XDCS=1;
regvalue=VS_RD_Reg(SPI_HDAT0); // 如果得到的值为0x807F,则表明完好。
printf("regvalueH:%x\n",regvalue);//输出结果
}
//向VS10XX写命令
//address:命令地址
//data:命令数据
void VS_WR_Cmd(u8 address,u16 data)
{
while(VS_DQ==0);//等待空闲
SPIx_SetSpeed(SPI_SPEED_64);//低速
VS_XDCS=1; //MP3_DATA_CS=1;
VS_XCS=0; //MP3_CMD_CS=0;
SPIx_ReadWriteByte(VS_WRITE_COMMAND);//发送VS10XX的写命令
SPIx_ReadWriteByte(address); //地址
SPIx_ReadWriteByte(data>>8); //发送高八位
SPIx_ReadWriteByte(data); //第八位
VS_XCS=1; //MP3_CMD_CS=1;
SPIx_SetSpeed(SPI_SPEED_8);//高速
}
//向VS10XX写数据
void VS_WR_Data(u8 data)
{
SPIx_SetSpeed(SPI_SPEED_8);//高速,对VS1003B,最大值不能超过36.864/4Mhz,这里设置为9M
VS_XDCS=0; //MP3_DATA_CS=0;
SPIx_ReadWriteByte(data);
VS_XDCS=1; //MP3_DATA_CS=1;
}
//读VS10XX的寄存器
//读VS10XX
//注意不要用倍速读取,会出错
u16 VS_RD_Reg(u8 address)
{
u16 temp=0;
while(VS_DQ==0);//非等待空闲状态
SPIx_SetSpeed(SPI_SPEED_64);//低速
VS_XDCS=1; //MP3_DATA_CS=1;
VS_XCS=0; //MP3_CMD_CS=0;
SPIx_ReadWriteByte(VS_READ_COMMAND);//发送VS10XX的读命令
SPIx_ReadWriteByte(address); //地址
temp=SPIx_ReadWriteByte(0xff); //读取高字节
temp=temp<<8;
temp+=SPIx_ReadWriteByte(0xff); //读取低字节
VS_XCS=1; //MP3_CMD_CS=1;
SPIx_SetSpeed(SPI_SPEED_8);//高速
return temp;
}
//FOR WAV HEAD0 :0X7761 HEAD1:0X7665
//FOR MIDI HEAD0 :other info HEAD1:0X4D54
//FOR WMA HEAD0 :data speed HEAD1:0X574D
//FOR MP3 HEAD0 :data speed HEAD1:ID
//比特率预定值
const u16 bitrate[2][16]=
{
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}
};
//返回Kbps的大小
//得到mp3&wma的波特率
u16 GetHeadInfo(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:return 0;//WAV格式
case 0X4D54:return 1;//MIDI格式
case 0X574D://WMA格式
{
HEAD1=HEAD0*2/25;
if((HEAD1%10)>5)return HEAD1/10+1;
else return HEAD1/10;
}
default://MP3格式
{
HEAD1>>=3;
HEAD1=HEAD1&0x03;
if(HEAD1==3)HEAD1=1;
else HEAD1=0;
return bitrate[HEAD1][HEAD0>>12];
}
}
}
//重设解码时间
void ResetDecodeTime(void)
{
VS_WR_Cmd(SPI_DECODE_TIME,0x0000);
VS_WR_Cmd(SPI_DECODE_TIME,0x0000);//操作两次
}
//得到mp3的播放时间n sec
u16 GetDecodeTime(void)
{
return VS_RD_Reg(SPI_DECODE_TIME);
}
//加载频谱分析的代码到VS10XX
void LoadPatch(void)
{
u16 i;
for (i=0;i<943;i++)VS_WR_Cmd(atab[i],dtab[i]);
delay_ms(10);
}
//得到频谱数据
void GetSpec(u8 *p)
{
u8 byteIndex=0;
u8 temp;
VS_WR_Cmd(SPI_WRAMADDR,0x1804);
for (byteIndex=0;byteIndex<14;byteIndex++)
{
temp=VS_RD_Reg(SPI_WRAM)&0x63;//取小于100的数
*p++=temp;
}
}
//设定VS10XX播放的音量和高低音
void set1003(void)
{
u8 t;
u16 bass=0; //暂存音调寄存器值
u16 volt=0; //暂存音量值
u8 vset=0; //暂存音量值
vset=255-VS10XXram[4];//取反一下,得到最大值,表示最大的表示
volt=vset;
volt<<=8;
volt+=vset;//得到音量设置后大小
//0,henh.1,hfreq.2,lenh.3,lfreq
for(t=0;t<4;t++)
{
bass<<=4;
bass+=VS10XXram[t];
}
VS_WR_Cmd(SPI_BASS,bass);//BASS
VS_WR_Cmd(SPI_VOL,volt); //设音量
}
//初始化VS10XX的IO口
void VS_Init(void)
{
RCC->APB2ENR|=1<<2; //PORTA时钟使能
GPIOA->CRL&=0XFFF0FFFF;//PA4 XDCS
GPIOA->CRL|=0X00030000;
GPIOA->CRH&=0XFFF00FF0;//PA8 XCS;PA11 DQ;PA12 RST
GPIOA->CRH|=0X00083003;
GPIOA->ODR|=(1<<4)|(1<<8)|(1<<11)|(1<<12);//PA4,8,11,12上拉
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -