打印
[STM8]

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

[复制链接]
618|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
南国先生|  楼主 | 2016-11-13 14:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
该如何使用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的控制管脚的配置如下:

[cpp] view plain copy


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


沙发
heisexingqisi| | 2016-11-13 17:01 | 只看该作者
学习了,不知道这个芯片现在好买不好买,贵不贵。

使用特权

评论回复
板凳
南国先生|  楼主 | 2016-11-13 17:02 | 只看该作者

根据上面这个时序图,SCI的Read函数如下面所示:

[cpp] view plain copy


  • 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);                                          
  • }  

[cpp] view plain copy


  • 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函数如下:

[cpp] view plain copy


  • 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);   
  • }   

[cpp] view plain copy


  • 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进行初始化操作:

[cpp] view plain copy


  • 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的函数:

[cpp] view plain copy


  • 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);  
  • }  
[url=][/url]

到这里,如果正弦测试正常通过,那么基本上完成了对VS1003B的使用。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

160

帖子

3

粉丝