STM8L151 使用硬件SPI驅動VS1003B MP3解碼芯片

該如何使用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的使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章