OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10295|回复: 39

U盘MP3 音乐能播放但不知为什么音乐播放速度慢 麻烦各位解答下~

[复制链接]

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
发表于 2012-4-18 09:59:08 | 显示全部楼层 |阅读模式
做一个U盘MP3 ,现在音乐能播放就是 播放的速度慢  像慢放一样,改SPI的速率 也不起作用,不知为什么?求指导 ~谢谢!
STM32的两个SPI 同时使用作为主机: 与VS1003,CH376S通信。


/******************************SPI1及VS1003端口初始化*******************************/
void SPI1_Init(void)
{  
RCC->APB2ENR|=1<<2;       //PORTA时钟使能  
RCC->APB2ENR|=1<<12;      //SPI1时钟使能 
/*VS1003端口初始化*/   
GPIOA->CRL&=0XFFF0000F; 
GPIOA->CRL|=0X00038330;//(XREST)PA1推挽输出. (XDCS)PA2推挽输出. (DREQ)PA3上拉输入. (XCS)PA4推挽输出    
GPIOA->ODR|=1 << 3; 

//这里只针对SPI口初始化
GPIOA->CRL&=0X000FFFFF; 
GPIOA->CRL|=0XBBB00000;//PA5.6.7复用    
GPIOA->ODR|=0X7<<5;    //PA5.6.7上拉
// GPIOA->ODR|=1<<6; 
SPI1->CR1|=0<<10;//全双工模式
SPI1->CR1|=1<<9; //软件nss管理
SPI1->CR1|=1<<8;  

SPI1->CR1|=1<<2; //SPI主机
SPI1->CR1|=0<<11;//8bit数据格式
SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1
// SPI1->CR1 &= ~(1<<1); //空闲模式下SCK为0,所以此位CPOL=0
// SPI1->CR1 |= 0<<0;    //数据采样从第一个时间边沿开始,CPHA=0 

// SPI1->CR1|=1<<3; //Fsck=Fcpu/4
SPI1->CR1|=1<<5; //Fsck=Fcpu/32

// SPI1->CR1|=0<<7; //MSBfirst
SPI1->CR1 &= ~(1<<7); //MSBfirst 
// SPI1->CR1|=1<<13; //CRC 计算多项式   
SPI1->CR1|=1<<6; //SPI设备使能
SPI1_ReadWriteByte(0xff);//启动传输  
}



/*****************************SPI2及CH376端口初始化*************************************/

void SPI2_Init(void)
{  
RCC->APB2ENR|=1<<3;       //PORTB时钟使能
RCC->APB2ENR|=1<<5;       //PORTD时钟使能  
RCC->APB1ENR|=1<<14;      //SPI2时钟使能 
/*CH376端口初始化*/   
// GPIOD->CRL &= 0XF0FF0FFF; //(SCS)PD3推挽输出    (INT#)PD6输入
// GPIOD->CRL |= 0X08003000;
// GPIOD->ODR |= 1 << 6;

GPIOD->CRH &= 0XFF00FFFF; //(SCS)PD12推挽输出    (INT#)PD13输入
GPIOD->CRH |= 0X00430000;


//这里只针对SPI2口初始化
GPIOB->CRH&=0X000FFFFF; 
GPIOB->CRH|=0XBBB00000;//PB.13,PB.14,PB.15复用    
// GPIOB->ODR|=1<<14;     //PB.14上拉
GPIOB->ODR|=0x7<<13;     //PB.14上拉
SPI2->CR1|=0<<10;//全双工模式
SPI2->CR1|=1<<9; //软件nss管理
SPI2->CR1|=1<<8;  

SPI2->CR1|=1<<2; //SPI主机
SPI2->CR1|=0<<11;//8bit数据格式

// SPI2->CR1|=0<<1; //空闲模式下SCK为0 CPOL=0
// SPI2->CR1|=0<<0; //数据采样从第1个时间边沿开始,CPHA=0  
// SPI2->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
// SPI2->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1
 
SPI2->CR1 &= ~(1<<1); //空闲模式下SCK为0,所以此位CPOL=0
SPI2->CR1 |= 0<<0;    //数据采样从第一个时间边沿开始,CPHA=0

// SPI2->CR1|=3<<3; //Fsck=Fcpu/16
SPI2->CR1|=1<<3; //Fsck=Fcpu/4

SPI2->CR1 &= ~(1<<7); //MSBfirst 
// SPI2->CR1|=0<<7; //MSBfirst  
// SPI2->CR1|=1<<13; //CRC 计算多项式
SPI2->CR1|=1<<6; //SPI设备使能
SPI2_ReadWriteByte(0xff);//启动传输  
}   



// SPI总线速度设置 
#define SPI_SPEED_2   0
#define SPI_SPEED_4   1
#define SPI_SPEED_8   2
#define SPI_SPEED_16  3
#define SPI_SPEED_32  4
#define SPI_SPEED_256 5

//SPI 速度设置函数
//SpeedSet:
//SPI_SPEED_2   2分频   (SPI 36M@sys 72M)
//SPI_SPEED_8   8分频   (SPI 9M@sys 72M)
//SPI_SPEED_16  16分频  (SPI 4.5M@sys 72M)
//SPI_SPEED_256 256分频 (SPI 281.25K@sys 72M)
void SPI1_SetSpeed(u8 SpeedSet)
{
SPI1->CR1&=0XFFC7;//Fsck=Fcpu/256
if(SpeedSet==SPI_SPEED_2)//二分频
{
SPI1->CR1|=0<<3;//Fsck=Fpclk/2=36Mhz
}
else if(SpeedSet==SPI_SPEED_4)//4分频 
{
SPI1->CR1|=1<<3;//Fsck=Fpclk/4=18Mhz
}
else if(SpeedSet==SPI_SPEED_8)//八分频 
{
SPI1->CR1|=2<<3;//Fsck=Fpclk/8=9Mhz
}else if(SpeedSet==SPI_SPEED_16)//十六分频
{
SPI1->CR1|=3<<3;//Fsck=Fpclk/16=4.5Mhz
}else if(SpeedSet==SPI_SPEED_32)//32分频
{
SPI1->CR1|=1<<5;//Fsck=Fpclk/32=2.25Mhz
}else //256分频
{
SPI1->CR1|=7<<3; //Fsck=Fpclk/256=281.25Khz 低速模式
}
SPI1->CR1|=1<<6; //SPI设备使能  
}


这是初始化程序~

还有 SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1


SPI2->CR1 &= ~(1<<1); //空闲模式下SCK为0,所以此位CPOL=0
SPI2->CR1 |= 0<<0;    //数据采样从第一个时间边沿开始,CPHA=0
SPI1 和SPI2要设置成一样吗?我对SPI不是很了解?



以下为主函数


u8 u8SectorBuf[512];
int main(void)
{
u8 u8Result;
u8 u8Length;
    u8 *pu8Temp = u8SectorBuf;
    u32 u32FileLen = 0;
    u32 u32DataCnt = 0;
    u32 i,j;

Stm32_Clock_Init(9);      //72M
delay_init(72);          //延时初始化
uart_init(72, 9600);    //设置串口1的波特率
// LED_Init();
// LED2 = 1;
Vs1003_Init();   //Vs1003的初始化
Vs1003SoftReset();  //软复位VS1003

VsRamTest();  //RAM测试
  VsSineTest();      //VS1003正弦测试

CH376_Init();
while(1)
      {
    
if(CH376DiskConnect()==USB_INT_SUCCESS)   /* 检查U盘是否连接,不支持SD卡 */
{

USART1_SendByte(0xe3);
if(CH376DiskMount()==USB_INT_SUCCESS)  /* 初始化磁盘并测试磁盘是否就绪 */
{

u8Length = CH376ReadBlock(pu8Temp); /*从当前主机端点的接收缓冲区读取数据块,返回长度*/
if (u8Length != 0)
            {
        CH376DiskQuery((u32 *)pu8Temp); /*查询磁盘剩余空间信息,扇区数*/
        strcpy((char*)pu8Temp, "\\光辉岁月.MP3");            
        u8Result = CH376FileOpen(pu8Temp);   // 打开文件

USART1_SendByte(0xe5);

                if (u8Result == USB_INT_SUCCESS)
                {
              
                        u32FileLen = CH376GetFileSize();  /* 获取文件大小 */                   

                        while (u32DataCnt < u32FileLen)
                        {
                        pu8Temp = u8SectorBuf;
                        CH376SecRead(pu8Temp, 1, 0); /*以扇区为单位从当前位置读取数据块,不支持SD卡*/
                        u32DataCnt += 512;
                
                        VS_XDCS_CLR();   /*VS_XDCS = 0,选择vs1003的数据接口 */

                        i = 0;
                          while (i < 512)
                        {
while(VS_DREQ==0); //等待DREQ为高                        
                            for (j=0; j<32; j++)
                            {
                            SPI1_ReadWriteByte(*pu8Temp++);
                            }
                  i += 32;
}
                                    VS_XDCS_SET();   /*VS_XDCS = 1*/   
                                        }
           }
       }
   
        }
 }

}


/**************************************************************************************/
//软复位VS1003
void Vs1003SoftReset(void)
{  
u8 retry;   
while((VS_DREQ)==0);//等待软件复位结束
SPI1_ReadWriteByte(0X00);//启动传输
retry=0;
while(Vs1003_REG_Read(SPI_MODE)!=0x0804)// 软件复位,新模式  
{
Vs1003_CMD_Write(SPI_MODE,0x0804);// 软件复位,新模式
delay_ms(2);//等待至少1.35ms 
if(retry++>100)break; 
}  
while (VS_DREQ == 0);//等待软件复位结束   

retry=0;
while(Vs1003_REG_Read(SPI_CLOCKF)!=0X9800)//设置vs1003的时钟,3倍频 ,1.5xADD 
{
Vs1003_CMD_Write(SPI_CLOCKF,0X9800);//设置vs1003的时钟,3倍频 ,1.5xADD
if(retry++>100)break; 
}   
retry=0;
while(Vs1003_REG_Read(SPI_AUDATA)!=0XBB81)//设置vs1003的采样率,采样率48K,立体声 
{
Vs1003_CMD_Write(SPI_AUDATA,0XBB81);//设置vs1003的采样率,采样率48K,立体声 
if(retry++>100)break; 
}
//Vs1003_CMD_Write(SPI_CLOCKF,0X9800);    
//Vs1003_CMD_Write(SPI_AUDATA,0XBB81); //采样率48k,立体声
VS_SET_VOL(VS_VOLT,VS_BASS);  
ResetDecodeTime();//复位解码时间    
    //向vs1003发送4个字节无效数据,用以启动SPI发送
    VS_XDCS_CLR();//选中数据传输
SPI1_ReadWriteByte(0XFF);
SPI1_ReadWriteByte(0XFF);
SPI1_ReadWriteByte(0XFF);
SPI1_ReadWriteByte(0XFF);
VS_XDCS_SET();//取消数据传输
delay_ms(20);


//硬复位MP3
void Mp3Reset(void)
{
VS_XRESET_CLR();
delay_ms(20);
VS_XDCS_SET(); //取消数据传输
VS_XCS_SET();//取消数据传输
delay_ms(5);//!!!!自己加的
VS_XRESET_SET();
delay_ms(5);//!!!!自己加的    
while(VS_DREQ==0); //等待DREQ为高
delay_ms(20);  
}

//向VS1003写命令
//address:命令地址
//data:命令数据
void Vs1003_CMD_Write(u8 address,u16 data)
{  
    while(VS_DREQ==0);//等待空闲
SPI1_SetSpeed(SPI_SPEED_256);//低速 
 
VS_XDCS_SET(); //MP3_DATA_CS=1;
VS_XCS_CLR(); //MP3_CMD_CS=0; 
SPI1_ReadWriteByte(VS_WRITE_COMMAND);//发送VS1003的写命令
SPI1_ReadWriteByte(address); //地址
SPI1_ReadWriteByte(data>>8); //发送高八位
SPI1_ReadWriteByte(data); //第八位
VS_XCS_SET();         //MP3_CMD_CS=1; 
SPI1_SetSpeed(SPI_SPEED_16);//高速


//向VS1003写数据
void Vs1003_DATA_Write(u8 data)
{
VS_XDCS_CLR();   //MP3_DATA_CS=0;
//while(VS_DREQ==0);  //VS1003的DREQ为高才能写入数据????这句可以不要??
while(VS_DREQ==0);  //此处为改动!!!!!!!!!
SPI1_ReadWriteByte(data);
VS_XDCS_SET();  //MP3_DATA_CS=1;
VS_XCS_SET();   //MP3_CMD_CS=1; 
}         
//读VS1003的寄存器           
//读VS1003
//注意不要用倍速读取,会出错
u16 Vs1003_REG_Read(u8 address)
u16 temp=0; 
    while(VS_DREQ==0);//非等待空闲状态 
SPI1_SetSpeed(SPI_SPEED_256);//低速 
VS_XDCS_SET();       //MP3_DATA_CS=1;
VS_XCS_CLR();        //MP3_CMD_CS=0;
SPI1_ReadWriteByte(VS_READ_COMMAND);//发送VS1003的读命令
SPI1_ReadWriteByte(address);        //地址
temp=SPI1_ReadWriteByte(0xff); //读取高字节
temp=temp<<8;
temp+=SPI1_ReadWriteByte(0xff); //读取低字节
VS_XCS_SET();       //MP3_CMD_CS=1; 
SPI1_SetSpeed(SPI_SPEED_16);//高速
    return temp; 
}  




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-4-18 10:37:23 | 显示全部楼层
是无问题的.
音乐播放慢,你看看是别的哪里的问题.
之前也有朋友遇到过慢的问题....
不过用的是我们的板子.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-18 10:55:02 | 显示全部楼层
SPI1 是和 VS1003通信的 ,然后 SPI2 是和 文件管理芯片CH376通信的 ~ 板子都是自己做的 。能播放音乐就是像在 慢放一样。如果是硬件问题有可能哪里出问题?  软件的话 正弦测试是通过的 ,
       
        SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1


SPI2->CR1 &= ~(1<<1); //空闲模式下SCK为0,所以此位CPOL=0
SPI2->CR1 |= 0<<0;    //数据采样从第一个时间边沿开始,CPHA=0
        这个地方设置不一样,但是都是对同一个寄存器操作 ,这个会有影响吗?
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-18 12:10:00 | 显示全部楼层
自己顶一个~
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-4-18 12:35:51 | 显示全部楼层
回复【3楼】Ray12345:
---------------------------------
1,有可能是你SPI速度设置的太低了.你检查一下.
2,有可能是你DREQ信号采集没搞好,检查一下.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-18 12:39:30 | 显示全部楼层
恩 好的~谢谢原子哥!我试试看
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-18 13:53:32 | 显示全部楼层
SPI的速度设置已经都在4M以上了
SPI1->CR1|=3<<3; //Fsck=Fcpu/16   = 4.5M

SPI2->CR1|=3<<3; //Fsck=Fcpu/16
速度应该没什么问题。

DREQ在复位的时候是3.3V应该也没什么问题。

奇怪的是当SPI设置改为下面的情况时,听到乱七八糟的声音,偶尔几句正常能听出来  语速是正确的,但是一首歌 一会就放完了感觉数据发送得太快了。就是下面这样设置的 , 这里搞不明白是为什么:
/*****************VS1003*****************************/
SPI1->CR1|=0<<1; //空闲模式下SCK为0    CPOL=0
SPI1->CR1|=0<<0; //数据采样从第1个时间边沿开始, CPHA=0


 /*****************CH376S*****************************/
SPI2->CR1 &= ~(1<<1); //空闲模式下SCK为0,所以此位CPOL=0
SPI2->CR1 |= 0<<0;    //数据采样从第一个时间边沿开始,CPHA=0
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-4-18 14:02:20 | 显示全部楼层
回复【7楼】Ray12345:
---------------------------------
有些器件对SCK和采样时间是很敏感的.
VS1003的你就参考我们的设计.
CH376的话,没玩过,你自己摸索下.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-18 23:24:22 | 显示全部楼层
纠结了很久,还是没找到原因?
设置了VS1003的速度为4.5M也还是不行~~~
 SPI1_SetSpeed(SPI_SPEED_16); // //高速,对VS1003B,最大值不能超过36.864/6Mhz,这里设置为4.5M
if(CH376DiskConnect()==USB_INT_SUCCESS)    /* 检查U盘是否连接,不支持SD卡 */
{

if(CH376DiskMount()==USB_INT_SUCCESS)  /* 初始化磁盘并测试磁盘是否就绪 */
{


u8Length = CH376ReadBlock(pu8Temp); /*从当前主机端点的接收缓冲区读取数据块,返回长度
if (u8Length != 0)
     {
         CH376DiskQuery((u32 *)pu8Temp); /*查询磁盘剩余空间信息,扇区数*/
         strcpy((char*)pu8Temp, "\\风.MP3");            
         u8Result = CH376FileOpen(pu8Temp);    // 打开文件

         if (u8Result == USB_INT_SUCCESS)
         {
                USART1_SendByte(0xe5);
//LED2 = 1;
             u32FileLen = CH376GetFileSize();  /* 获取文件大小 */                   

             while (u32DataCnt < u32FileLen)
             {
                pu8Temp = u8SectorBuf;
                 CH376SecRead(pu8Temp, 1, 0); /*以扇区为单位从当前位置读取数据块,不支持SD卡*/
                 u32DataCnt += 512;
                
                 i = 0;                  
                 while (i < 512)       //循环发送512个字节 
{  
   while (VS_DREQ == 0); //等待DREQ为高                          
   VS_XDCS = 0;
for (j=0; j<32; j++)
                     {
                         SPI1_ReadWriteByte(*pu8Temp++);
                     }
                          i += 32;
       VS_XDCS = 1;                    
}
 
                      }
        }
        }
     }
    }
  }

VS1003的读写跟 原子的例子一样~
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 17:37:07 | 显示全部楼层
SPI1_SetSpeed(SPI_SPEED_16);   //高速,对VS1003B,最大值不能超过36.864/6Mhz,这里设置为4.5M



例程里面是  SPI1_SetSpeed(SPI_SPEED_8);  这个已经是9M了,我试了一下,在向VS1003发送数据前把SPI的速度设置为9M:     SPI1_SetSpeed(SPI_SPEED_8);   结果就没声音了,改回 SPI1_SetSpeed(SPI_SPEED_16); 又继续慢速播放,请问是什么原因啊??
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 17:41:08 | 显示全部楼层
看下楼主怎么定义DREQ的,我遇到过这样的问题,72M主频,SPI8分频是没问题的,我当时是DREQ出了问题
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 17:58:54 | 显示全部楼层
//初始化VS1003的IO口  
void Vs1003_Init(void)
{
      
RCC->APB2ENR |= 1 << 2;      //使能PA时钟
// RCC->APB2ENR |= 1 << 3;      //使能PB时钟
   
    /*PA.1,PA.2,PA.4为推挽输出  A3上拉输入 */
GPIOA->CRL &= 0XFFF0000F;     //PA4为推挽输出
GPIOA->CRL |= 0X00038330;
GPIOA->ODR|=(1<<1)|(1<<2)|(1<<3)|(1<<4); //PA1,2,3,4上拉
// GPIOA->ODR |= 1<<3;          //PA3上拉
    SPI1_Init();                 //初始化VS1003的SPI

// Mp3Reset();        //复位VS1003
}


//VS10xx与外部接口定义(未包含MISO,MOSI,SCK)
#define VS_DREQ     Ain(3)   //DREQ 数据请求PA3
#define VS_XRESET   Aout(1)  //RST
#define VS_XCS      Aout(4)   //XCS
#define VS_XDCS     Aout(2)   //XDCS 

回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:00:25 | 显示全部楼层
我看过您的程序,你是 DREQ的 宏定义上有问题吧 
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:03:58 | 显示全部楼层
SPIx_SetSpeed(SPI_SPEED_8);//高速,对VS1003B,最大值不能超过36.864/6Mhz,这里设置为4.5M 
这个设置已经是9M了 超过36.864/6Mhz  了,怎么还可以呢
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 18:04:11 | 显示全部楼层
嗯,少个括号,纠结一下午,哈哈
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:04:45 | 显示全部楼层
回复【11楼】以枫之名:
---------------------------------
//初始化VS1003的IO口   
void Vs1003_Init(void) 

        
RCC->APB2ENR |= 1 << 2;      //使能PA时钟 
// RCC->APB2ENR |= 1 << 3;      //使能PB时钟 
    
    /*PA.1,PA.2,PA.4为推挽输出  A3上拉输入 */ 
GPIOA->CRL &= 0XFFF0000F;     //PA4为推挽输出 
GPIOA->CRL |= 0X00038330; 
GPIOA->ODR|=(1<<1)|(1<<2)|(1<<3)|(1<<4); //PA1,2,3,4上拉 
// GPIOA->ODR |= 1<<3;          //PA3上拉 
    SPI1_Init();                 //初始化VS1003的SPI 

// Mp3Reset();         //复位VS1003 



//VS10xx与外部接口定义(未包含MISO,MOSI,SCK) 
#define VS_DREQ     Ain(3)    //DREQ 数据请求PA3 
#define VS_XRESET   Aout(1)   //RST 
#define VS_XCS      Aout(4)    //XCS 
#define VS_XDCS     Aout(2)    //XDCS 
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 18:06:07 | 显示全部楼层
回复【14楼】Ray12345:
---------------------------------
这个就不知道了,像SD卡,最高18M,我设置36M也没问题- -,我在8分频下播放是没问题的
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:06:14 | 显示全部楼层
回复【15楼】以枫之名:
---------------------------------我已经纠结了几天了,各种不明白啊
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 18:07:07 | 显示全部楼层
回复【16楼】Ray12345:
---------------------------------
DREQ下拉试试
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:09:20 | 显示全部楼层
回复【17楼】以枫之名:
---------------------------------

while (u32DataCnt < u32FileLen)
             {
                SPI2_SetSpeed(SPI2_SPEED_4);//高速
                pu8Temp = u8SectorBuf;
                 CH376SecRead(pu8Temp, 1, 0); /*以扇区为单位从当前位置读取数据块,不支持SD卡*/
                 u32DataCnt += 512;
                
--->我设置成SPI1_SPEED_8就播不出声音
                                        
                SPI1_SetSpeed(SPI1_SPEED_16); //高速,对VS1003B,设置为4.5M  

                  VS_XDCS = 0;         /*VS_XDCS = 0,选择vs1003的数据接口 */
                 i = 0;                  
                 while (i < 512)       //循环发送512个字节 
{  
   while (VS_DREQ == 0); //等待DREQ为高                          
//   VS_XDCS = 0;
for (j=0; j<32; j++)
                     {
                         SPI1_ReadWriteByte(*pu8Temp++);
                     }
                          i += 32;
   //        VS_XDCS = 1;                    
}
VS_XDCS = 1;    /*VS_XDCS = 1*/     
                      }
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 18:10:08 | 显示全部楼层
把PA3设置为下拉试试
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 18:10:54 | 显示全部楼层
GPIOA->ODR |= 1<<3;          //PA3上拉  
这个去掉
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 18:15:55 | 显示全部楼层
错了,应该是上拉,我搞错了
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:16:14 | 显示全部楼层
  /*PA.1,PA.2,PA.4为推挽输出  A3上拉输入 */  
GPIOA->CRL &= 0XFFF0000F;     //PA4为推挽输出  
GPIOA->CRL |= 0X00038330;  
GPIOA->ODR|=(1<<1)|(1<<2)|(1<<3)|(1<<4); //PA1,2,3,4上拉

0X8就是 上/下拉 输入模式  
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 18:17:26 | 显示全部楼层
嗯,我也是这么设置的
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:18:53 | 显示全部楼层
原子的例程里是这样的


//初始化VS10XX的IO口  
void VS_Init(void)
{
RCC->APB2ENR|=1<<2;   //PORTA时钟使能 
  
GPIOA->CRL&=0XFFF0FFFF; //PA4 XDCS
GPIOA->CRL|=0X00030000; 
GPIOA->CRH&=0XFFF00FF0; //PA8 XCSA11 DQA12 RST
GPIOA->CRH|=0X00083003;   
GPIOA->ODR|=(1<<4)|(1<<8)|(1<<11)|(1<<12); //PA4,8,11,12上拉   
SPIx_Init(); //初始化SPI 
}   
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:21:08 | 显示全部楼层
回复【23楼】以枫之名:
---------------------------------
那句 已经是注释掉了的
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 18:30:02 | 显示全部楼层
回复【27楼】Ray12345:
---------------------------------
确实应该上拉的,是我搞错了,我的设置和原子哥的一样
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:33:33 | 显示全部楼层
这是与VS1003有关的函数:

//向VS1003写命令
//address:命令地址
//data:命令数据
void Vs1003_CMD_Write(u8 address,u16 data)
{  
u16 retry=0;
    while(VS_DREQ==0&&(retry++)<0xfffe)retry++; //等待空闲    
SPI1_SetSpeed(SPI1_SPEED_64);     //64分频速度      
VS_XDCS=1; 
VS_XCS=0;      
SPI1_ReadWriteByte(VS_WRITE_COMMAND);//发送VS10XX的写命令
SPI1_ReadWriteByte(address); //地址
SPI1_ReadWriteByte(data>>8); //发送高八位
SPI1_ReadWriteByte(data);  //第八位
VS_XCS=1;               
SPI1_SetSpeed(SPI1_SPEED_8);  //8分频速度


//向VS1003写数据
void Vs1003_DATA_Write(u8 data)
{
VS_XDCS=0;   //MP3_DATA_CS=0;
// while(VS_DREQ==0);   //此处为改动
SPI1_ReadWriteByte(data);
VS_XDCS=1;    //MP3_DATA_CS=1;
}         
//读VS1003的寄存器           
//读VS1003
//注意不要用倍速读取,会出错
u16 Vs1003_REG_Read(u8 address)
{  
u16 temp=0; 
u8 retry=0;
    while(VS_DREQ==0&&(retry++)<0XFE); //等待空闲   
if(retry>=0XFE)return 0;       
SPI1_SetSpeed(SPI1_SPEED_64); //64分频速度
VS_XDCS=1;       
VS_XCS=0;       
SPI1_ReadWriteByte(VS_READ_COMMAND);//发送VS10XX的读命令
SPI1_ReadWriteByte(address);        //地址
temp=SPI1_ReadWriteByte(0xff); //读取高字节
temp=temp<<8;
temp+=SPI1_ReadWriteByte(0xff);  //读取低字节
VS_XCS=1;      
SPI1_SetSpeed(SPI1_SPEED_8); //8分频速度
    return temp; 
}  


//软复位VS10XX
//注意,在这里设置完后,系统SPI时钟被修改成9M左右
void Vs1003SoftReset(void)
{  
u8 retry;
SPI1_SetSpeed(SPI1_SPEED_256);    //256分频 超低速 281.25Khz     
while((VS_DREQ)==0);//等待软件复位结束
SPI1_ReadWriteByte(0X00);//启动传输
retry=0;
while(Vs1003_REG_Read(SPI_MODE)!=0x0804)// 软件复位,新模式  
{
Vs1003_CMD_Write(SPI_MODE,0x0804);// 软件复位,新模式
delay_ms(2);//等待至少1.35ms 
if(retry++>100)break; 
}     
while (VS_DREQ == 0);//等待软件复位结束    

retry=0;
while(Vs1003_REG_Read(SPI_CLOCKF)!=0X9800)//设置vs1003的时钟,3倍频 ,1.5xADD 
{
Vs1003_CMD_Write(SPI_CLOCKF,0X9800);//设置vs1003的时钟,3倍频 ,1.5xADD
if(retry++>100)break; 
}    
retry=0;
while(Vs1003_REG_Read(SPI_AUDATA)!=0XBB81)//设置vs1003的采样率,采样率48K,立体声 
{
Vs1003_CMD_Write(SPI_AUDATA,0XBB81);//设置vs1003的采样率,采样率48K,立体声 
if(retry++>100)break; 
}
//Vs1003_CMD_Write(SPI_CLOCKF,0X9800);      
//Vs1003_CMD_Write(SPI_AUDATA,0XBB81); //采样率48k,立体声
VS_SET_VOL(VS_VOLT,VS_BASS);  
ResetDecodeTime();//复位解码时间     
    //向vs1003发送4个字节无效数据,用以启动SPI发送
SPI1_SetSpeed(SPI1_SPEED_8);      //8分频速度
    VS_XDCS=0; //选中数据传输 记得,这里一定要传送0X00
SPI1_ReadWriteByte(0X00);
SPI1_ReadWriteByte(0X00);
SPI1_ReadWriteByte(0X00);
SPI1_ReadWriteByte(0X00);
VS_XDCS=1; //取消数据传输
// delay_ms(20);



//硬复位MP3
u8 Mp3Reset(void)
{
u8 retry=0;
VS_XDCS=1; //取消数据传输
VS_XCS=1; //取消指令传输
VS_XRESET=0;     
delay_ms(100);  
VS_XRESET=1;    
while(VS_DREQ==0&&retry<200)//等待DREQ为高
{
retry++;
delay_us(50);
};     
delay_ms(20);
if(retry>=200)return 1;
else return 0;
 
}
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 18:34:44 | 显示全部楼层
直接用原子哥的例程能播放吗
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:39:45 | 显示全部楼层
程序基本一样了,除了IO设置不一样~板子是我自己做的
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 18:42:08 | 显示全部楼层
就是设置 SPI1_SetSpeed(SPI1_SPEED_8);       //8分频速度 
U盘指示灯可以知道在读写数据,就是没有声音
回复 支持 反对

使用道具 举报

44

主题

260

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
253
金钱
253
注册时间
2012-3-8
在线时间
29 小时
发表于 2012-4-21 19:03:19 | 显示全部楼层
U盘读取我没试过,有没有像SD卡一样有字节地址和扇区地址之分?这个注意了吗
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 19:06:01 | 显示全部楼层
U盘和SD卡对VS1003其实差不多的操作

SPI2_SetSpeed(SPI2_SPEED_4);//高速
                pu8Temp = u8SectorBuf;
                 CH376SecRead(pu8Temp, 1, 0); /*以扇区为单位从当前位置读取数据块,不支持SD卡*/
                 u32DataCnt += 512;
                
    SPI1_SetSpeed(SPI1_SPEED_16); //高速,对VS1003B,设置为4.5M  
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-4-21 19:24:16 | 显示全部楼层
问题可能出在 CH376S的读写速度上
回复 支持 反对

使用道具 举报

4

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2012-4-18
在线时间
0 小时
 楼主| 发表于 2012-5-1 23:13:38 | 显示全部楼层
多谢原子哥和 以枫之名 的帮助,经过几番折腾,终于知道原因了,在仔细的检查程序的时候发现了一个问题就是在VS1003播放音乐之前没有对它进行硬复位和软复位,在这种情况下播放码率在64K以上的MP3时就像卡带机一样,也就是慢放。 当我在VS1003解码之前加上硬复位和软复位之后问题就解决了~~~检查程序一定要仔细
回复 支持 反对

使用道具 举报

4

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2012-3-26
在线时间
4 小时
发表于 2012-9-27 16:17:23 | 显示全部楼层
楼主我也在用spi2驱动CH376,现在发现它读写U盘特别的慢,请问你遇到到这个情况没
学无止境
回复 支持 反对

使用道具 举报

2

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
189
金钱
189
注册时间
2015-5-21
在线时间
43 小时
发表于 2015-5-21 09:31:22 | 显示全部楼层
回复【36楼】Ray12345:
--------------------------------我用51单片机IO口模拟的SPI通讯协议,这速度就很难控制了,不能播放,SPI的速度真的那么重要么,有没有什么好的办法来设置我的SPI速度啊
回复 支持 反对

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2016-4-4
在线时间
9 小时
发表于 2016-4-4 12:07:27 | 显示全部楼层
Ray12345 发表于 2012-5-1 23:13
多谢原子哥和&nbsp;以枫之名&nbsp;的帮助,经过几番折腾, ...

你好,我也遇到相同的问题了。请问你是硬复位在前还是软复位在前?我先硬复位发现DREQ引脚无法为高,程序卡在死循环了。。。
回复 支持 反对

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2016-4-4
在线时间
9 小时
发表于 2016-4-4 12:45:09 | 显示全部楼层
写命令的时候需要把速度设置为16分频或者32分频吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 18:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表