其中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的使用。