历史上的今天
今天是:2024年09月10日(星期二)
2018年09月10日 | STM8L151 使用硬件SPI驱动VS1003B MP3解码芯片
2018-09-10 来源:eefocus
该如何使用STM8L的硬件SPI去驱动VS1003B?
这个问题分两部分来思考,一是STM8L的SPI部分该如何配置以及与VS1003B相连的控制管脚该如何配置,二是关于VS1003B的时序以及指令使用。
由于STM8L的SPI部分与VS1003B的SPI部分进行相互通信,先看看VS1003B的SPI特性,才能对STM8L进行配置。
在VS1003B中SPI模式定义如下:
其中XDCS为发送MP3数据是的芯片控制管脚,XCS为发送VS1003B指令的控制管脚,在手册中亦有对SPI通信速度的说明,见下图:
上图中CLKI在手册中为:36.864Mhz
故上面SPI的通信速率在6.144MHz-9.216MHz之间,但在本例中根据6.144MHz来配置,在STM8L中主频最高为16MHz,故可以4分频得到4M的SPI速率,但在实际测试中,发现4分频后通信有时会失败,于是改为8分频降低通信速率,故SPI以及VS1003的控制管脚的配置如下:
CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, ENABLE);
//SPI_CLOCK:PB5, SPI_MOSI: PB6, SPI_MISO: PB7
GPIO_Init(GPIOB, GPIO_Pin_5, GPIO_Mode_Out_PP_High_Fast);
GPIO_Init(GPIOB, GPIO_Pin_6, GPIO_Mode_Out_PP_High_Fast);
//主机模式,配置为输入
GPIO_Init(GPIOB, GPIO_Pin_7, GPIO_Mode_In_PU_No_IT);
/* 初始化SPI */
SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_8, SPI_Mode_Master,\
SPI_CPOL_Low, SPI_CPHA_1Edge, \
SPI_Direction_2Lines_FullDuplex, SPI_NSS_Soft, 0x07);
SPI_Cmd(SPI1, ENABLE); /* 使能SPI */
/* 输入 */
GPIO_Init(VS_1003_DREQ_PORT, VS_1003_DREQ_PIN, GPIO_Mode_In_PU_No_IT);
GPIO_Init(VS_1003_XRST_PORT, VS_1003_XRST_PIN, GPIO_Mode_Out_PP_High_Fast);
/* 推挽输出 */
GPIO_Init(VS_1003_XDCS_PORT, VS_1003_XDCS_PIN, GPIO_Mode_Out_PP_High_Fast);
/* 推挽输出 */
GPIO_Init(VS_1003_XCS_PORT, VS_1003_XCS_PIN, GPIO_Mode_Out_PP_High_Fast);
当数据总线传送的是指令数据时,此时的通信协议在VS1003B中称为SCI,该协议的发送时序图如下:
根据上面这个时序图,SCI的Read函数如下面所示:
uint8_t VS1003_ReadByte(void)
{
/* Loop while DR register in not emplty */
while (SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_SendData(SPI1, 0);
/* Wait to receive a byte */
while (SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_ReceiveData(SPI1);
}
uint16_t VS1003_ReadRegister(uint8_t addressbyte)
{
uint16_t resultvalue = 0;
XDCS_SET(1);
XCS_SET(0);
VS1003_WriteByte(VS_READ_COMMAND); //发送读寄存器命令
VS1003_WriteByte((addressbyte)); //发送寄存器的地址
resultvalue = (uint16_t)(VS1003_ReadByte() << 8); //读取高8位数据
resultvalue |= VS1003_ReadByte(); //读取低8位数据
XCS_SET(1);
return resultvalue;//返回16位寄存器的值
}
SCI 写的时序如下图:
根据该时序图,SCI的Write函数如下:
uint8_t VS1003_WriteByte( uint8_t byte )
{
/* Loop while DR register in not emplty */
while (SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_SendData(SPI1, byte);
/* Wait to receive a byte */
while (SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_ReceiveData(SPI1);
}
void VS1003_WriteRegister(uint8_t addressbyte, uint8_t highbyte, uint8_t lowbyte)
{
XDCS_SET(1); //拉高XDCS电平
XCS_SET(0); //拉低XCS电平
VS1003_WriteByte( VS_WRITE_COMMAND );//发送写指令字节
VS1003_WriteByte( addressbyte );//发送地址字节
VS1003_WriteByte( highbyte ); //发送数据字的高字节
VS1003_WriteByte( lowbyte ); //发送数据字的低字节
XCS_SET(1); //拉高XCS电平
}
接下来对VS1003B进行初始化操作:
void VS1003_Init(void)
{
uint8_t BassEnhanceValue = 0x00; // 低音值先初始化为0
uint8_t TrebleEnhanceValue = 0x00; // 高音值先初始化为0
RST_SET(0);
Delayms( 10 ); // 10ms
VS1003_WriteByte(0xff); // 发送一个字节的无效数据,启动SPI传输
XDCS_SET(1);
XCS_SET(1);
RST_SET(1);
Delayus( 1000 );
VS1003_WriteRegister( SPI_MODE,0x08,0x00); // 进入VS1003的播放模式
VS1003_WriteRegister(3, 0x98, 0x00); // 设置vs1003的时钟,3倍频
VS1003_WriteRegister(5, 0xBB, 0x81); // 采样率48k,立体声
VS1003_WriteRegister(SPI_BASS, TrebleEnhanceValue, BassEnhanceValue);// 设置重低音
VS1003_WriteRegister(0x0b,0x00,0x00); // VS1003 音量
Delayus( 1000 );
while( DREQ == 0 ); // 等待DREQ为高 表示能够接受音乐数据输入
}
在VS1003B中有几种测试模式,如Sine Test、Pin Test、Memory Test,下面就贴一个Sine Test的函数:
void VS1003_TestSIN(void)
{
VS1003_WriteRegister(SCI_MODE, 0x08, 0x20);
while( DREQ == 0);
XDCS_SET(0);
VS1003_WriteByte(0x53);
VS1003_WriteByte(0xef);
VS1003_WriteByte(0x6e);
VS1003_WriteByte(0x44);
VS1003_WriteByte(0x00);
VS1003_WriteByte(0x00);
VS1003_WriteByte(0x00);
VS1003_WriteByte(0x00);
XDCS_SET(1);
XDCS_SET(0);
VS1003_WriteByte(0x45);
VS1003_WriteByte(0x78);
VS1003_WriteByte(0x69);
VS1003_WriteByte(0x74);
VS1003_WriteByte(0x00);
VS1003_WriteByte(0x00);
VS1003_WriteByte(0x00);
VS1003_WriteByte(0x00);
XDCS_SET(1);
while( DREQ == 0);
}
到这里,如果正弦测试正常通过,那么基本上完成了对VS1003B的使用。
史海拾趣
|
今天调试反激电源的时候发现一个问题: 4*1W的LED通电电流不变350MA,压降13.2V;随着通电时间的增加,电压逐渐降低到12.5V; 这种情况是不是可以解释为 :是不是 LED的阀门电压时随着温度的身高而降低; … 查看全部问答> |
|
今天很郁闷,话了很久写了个程序,就是按下16个矩阵键盘依次在数码管上显示1-16的平方。如按下第一个显示1,第二个显示4... 但是怎么只就显示第一个 到 第8个键呢,就是 是显示001 到081, 到案第十个键的时 ...… 查看全部问答> |
|
这些汇编器分别是哪些公司出的?有啥区别?那个最好? 80C51单片机常用的汇编器有:ASM51.EXE、A8051.EXE、MCS51.EXE和A51.EXE… 查看全部问答> |
|
最近做一个语音播放的东东,8KHz/16bits PCM 语音信号经过一个16bitPCM DAC 以8KHz的sampling rate playback.发现语音失真很严重,还伴随有噪音.人的语音都变调了很难听.小弟以前没做过语音相关的,不知道怎么解决?还望各位帮忙.   ...… 查看全部问答> |
|
电容触控很火,目前很多手机都用了电容触控屏,我们这些做小家电的总是后知后觉,现在才计划在下半年的新款电磁炉上改用电容触控代替之前的机械按钮(机械按钮是返修率和投诉率最高的部件,我个人举双手赞成更换新触摸技术),筒子们有什么好的方案 ...… 查看全部问答> |
|
用到"LM5002"芯片和"STP5NK50ZFP"MOS管,遇到问题,求助 我在设计的时候,用到了LM5002芯片。我建的电路图是按照该芯片的datasheet里应用电路的最后一张图(输入是3.1 - 60VDC,输出是12VDC) 问题是,在输入端我提供了一个电源,然后用两个电阻分压控制电压值供给LM5002(测试的电阻值在1K - 500K欧,测 ...… 查看全部问答> |




