其中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 写的时序如下图:
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的使用。