STM8L151 使用硬件SPI驱动VS1003B MP3解码芯片

该如何使用STM8L的硬件SPI去驱动VS1003B?
这个问题分两部分来思考,一是STM8L的SPI部分该如何配置以及与VS1003B相连的控制管脚该如何配置,二是关于VS1003B的时序以及指令使用。
由于STM8L的SPI部分与VS1003B的SPI部分进行相互通信,先看看VS1003B的SPI特性,才能对STM8L进行配置。
在VS1003B中SPI模式定义如下:

STM8L151 使用硬件SPI驱动VS1003B MP3解码芯片_第1张图片

其中XDCS为发送MP3数据是的芯片控制管脚,XCS为发送VS1003B指令的控制管脚,在手册中亦有对SPI通信速度的说明,见下图:

STM8L151 使用硬件SPI驱动VS1003B MP3解码芯片_第2张图片

上图中CLKI在手册中为:36.864Mhz

STM8L151 使用硬件SPI驱动VS1003B MP3解码芯片_第3张图片

故上面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,该协议的发送时序图如下:

STM8L151 使用硬件SPI驱动VS1003B MP3解码芯片_第4张图片

根据上面这个时序图,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 写的时序如下图:

STM8L151 使用硬件SPI驱动VS1003B MP3解码芯片_第5张图片
根据该时序图,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的使用。

你可能感兴趣的:(SPI,mp3,STM8L,VS1003)