搜索
bottom↓
回复: 10

各位大神帮我看看:stm32f103+vs1003的代码移植到stm32f407就不行

[复制链接]

出0入0汤圆

发表于 2014-10-22 17:47:26 | 显示全部楼层 |阅读模式
本帖最后由 smog 于 2014-10-23 17:29 编辑

程序在stm32f103上运行是没问题的,vs1003也正常播放,但我移植到stm32f407上,正弦测试可以,但播放音乐时就好像快进了一样,声音噼噼啪啪的响,30秒左右就播放完一首歌了,移植上就只改了IO的配置!
看了很久也没找出是哪里的问题!
贴上移植前后的代码,大家帮我看看怎么回事?
移植前的初始化代码(stm32f103):

//SPI1初始化
void SPI1_Init(void)
{            
        GPIO_InitTypeDef GPIO_InitStructure;
          SPI_InitTypeDef  SPI_InitStructure;
         
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE );//PORTB,SPI2时钟使能

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PA5.6.7复用推挽  
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); //PA5.6.7上拉
                       
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                //设置SPI工作模式:设置为主SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                //设置SPI的数据大小:SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                //选择了串行时钟的稳态:时钟悬空高
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //数据捕获于第二个时钟沿
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;                //定义波特率预分频的值:波特率预分频值为16
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC值计算的多项式
        SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

        SPI_Cmd(SPI1, ENABLE); //使能SPI外设
       
        SPI1_ReadWriteByte(0xff);//启动传输       
}

//初始化VS10XX的IO口         
void VS_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOF, ENABLE);         //使能PB端口时钟
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;                                 //PC13
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                  //输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;         //PE6
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
        GPIO_Init(GPIOE, &GPIO_InitStructure);

                                                                                                                  //PF6,PF7
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
        GPIO_Init(GPIOF, &GPIO_InitStructure);       
          
        SPI1_Init();         
}          


移植后的初始化代码(stm32f407):

//SPI1初始化
void SPI1_Init(void)
{            
        GPIO_InitTypeDef GPIO_InitStructure;
          SPI_InitTypeDef  SPI_InitStructure;
         
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_SPI1, ENABLE );//PORTB,SPI1时钟使能
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

        /* 配置PA5、PA6、PA7链接到SPI1 */
       GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;         //PA5.6.7复用推挽
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
          GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); //PA5.6.7上拉
                       
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                //设置SPI工作模式:设置为主SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                //设置SPI的数据大小:SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                //选择了串行时钟的稳态:时钟悬空高
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //数据捕获于第二个时钟沿
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;                //定义波特率预分频的值:波特率预分频值为16
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC值计算的多项式
        SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

        SPI_Cmd(SPI1, ENABLE); //使能SPI外设
       
        SPI1_ReadWriteByte(0xff);//启动传输       
}

//初始化VS10XX的IO口         
void VS_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF, ENABLE);         //使能PB端口时钟
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;                                 //PC13
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;  //输入
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP; //上拉
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;        //推挽
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;         //PE6
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;          //输出
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;        //推挽
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOE, &GPIO_InitStructure);
                                                                                                                  //PF6,PF7
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;          //输出
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;        //推挽
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
        GPIO_Init(GPIOF, &GPIO_InitStructure);                                                                                                       
          
        SPI1_Init();         
}          


主函数:

int main()
{
        u32 total,free;
        u16 res;
         u8 *databuf;
        u32 i;
        DIR dir;   //声明目录结构体,保存要打开的
        FILINFO fileinfo;//文件状态结构体
        u8 *pname;//带路径文件名
        u8 *file_name;//长文件名
        GPIO_InitTypeDef GPIO_InitStructure;

//        SysClockSet(HSE,21);//外部时钟,168MHz       
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); /*使能LED灯使用的GPIO时钟*/
        /* Configure LED Pins in output pushpull mode */
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_8|GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;   
        GPIO_Init(GPIOF, &GPIO_InitStructure);  
        GPIO_ResetBits(GPIOF,GPIO_Pin_8|GPIO_Pin_9);/*关闭所有的LED指示灯*/
       
        mem_init(SRAMIN);        //初始化内部内存池
        delay_init();       
        usart1_init(9600);
        TIM3Init(5000,16800);
        VS_Init();                          //初始化VS1003
        VS_Sine_Test();
        printf("\r\n系统时钟:%dMHz\r\n",SysClockGet()/1000000);
        while(SD_Init() != SD_OK)
        {
                printf("SD Error!\r\n");
                delay_ms(2000);       
                delay_ms(1000);       
        }
        exfuns_init();                                                        //为fatfs相关变量申请内存                                 
        f_mount(0,fs[0]);                                                  //挂载SD卡  
        while(exf_getfree("0:",&total,&free))        //得到SD卡的总容量和剩余容量
        {
                printf("Fatfs Error!\r\n");
                delay_ms(1000);
        }
        printf(" SD卡总内存   : %d MB\r\n",total>>10);
        delay_ms(100);
        printf("SD卡可用内存 : %d MB\r\n",free>>10);
        delay_ms(100);

        databuf=(u8*)mymalloc(SRAMIN,4096);                //开辟4096字节的内存区域
        if(databuf==NULL) //内存申请失败.
                while(1)
                {
                printf("memery Error!\n");
                delay_ms(1000);
                }
        VS_Sine_Test();       
       
        fileinfo.lfsize=_MAX_LFN*2+1;                                                //长文件名最大长度
        fileinfo.lfname=mymalloc(SRAMIN,fileinfo.lfsize);        //为长文件缓存区分配内存
        pname=mymalloc(SRAMIN,fileinfo.lfsize);                                //为带路径的文件名分配内存
        file_name=mymalloc(SRAMIN,fileinfo.lfsize);                                //为长文件名分配内存
        while(f_opendir(&dir,"0:/MUSIC")!=FR_OK);//打开音乐文件夹
       
        while(1)
        {
loop:               
                while(f_readdir(&dir,&fileinfo)==FR_OK) //读目录信息到文件结构体
                {
                        if(fileinfo.fname[0]!=NULL)
                        {
                                file_name=(u8*)(*fileinfo.lfname?fileinfo.lfname:fileinfo.fname);        //获取文件名
                                printf("文件名:%s\n",file_name);
                                delay_ms(500);
                                res=f_typetell(file_name);        //获得文件后缀
                                printf("文件属性:%x\n",fileinfo.fattrib);
                                delay_ms(200);
                                if((res&0XF0)!=0X40)//取高四位,看看是不是音乐文件       
                                        goto loop;//如果不是音乐文件,读取下一个文件
                                strcpy((char*)pname,"0:/MUSIC/");                                //复制路径(目录)
                                strcat((char*)pname,(const char*)file_name);                          //将文件名接在后面
                                VS_Restart_Play();                                          //重启播放
                                VS_Set_All();                                                //设置音量等信息                          
                                VS_Reset_DecodeTime();                                        //复位解码时间                                                                                                                                  
                                res=f_open(file1,(const TCHAR*)pname,FA_READ);//打开文件         
                                if(res==0)//打开成功.
                                {
                                        VS_SPI_SpeedHigh();        //高速                                                  
                                        do
                                        {
                                               
                                                res=f_read(file1,databuf,4096,(UINT*)&br);//读出4096个字节  
                                                i=0;
                                               
                                                do//主播放循环
                                                        {         
                                                        if(VS_Send_MusicData(databuf+i)==0)//给VS10XX发送音频数据
                                                        {
                                                                i+=32;
                                                                LED1=0;
                                                        }
                                                        else
                                                        {
                                                                LED1=1;
                                                        }
                                                        }while(i<4096);//循环发送4096个字节   

                                        }while(br==4096);
                                        f_close(file1);
                                }
                                else
                                        {
                                        printf("mp3 Error!\n");
                                        delay_ms(1000);
                                        }
                        }
                        else
                                while(f_opendir(&dir,"0:/MUSIC")!=FR_OK);//重新打开音乐文件夹
                       
                }
               
        }

       
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2014-10-22 17:54:07 | 显示全部楼层
帮顶!!!

出0入0汤圆

发表于 2014-10-22 19:48:17 | 显示全部楼层
SPI的时序是不是比F1的快了?

出0入0汤圆

发表于 2014-10-22 21:31:38 | 显示全部楼层
if(VS_Send_MusicData(databuf+i)==0)//给VS10XX发送音频数据
这句里面发送文件数据和DREQ脚的脉冲对上了么?感觉问题应该在这里。

出0入0汤圆

 楼主| 发表于 2014-10-22 23:34:27 | 显示全部楼层
heitu103 发表于 2014-10-22 19:48
SPI的时序是不是比F1的快了?

我开始也怀疑是时钟的问题,但看了下F1的APB2最大频率为72M,F4的APB2最大频率为84M,spi1的时钟试过8分频、16分频、32分频,都不行,
vs1003设置的时钟为12.288*3倍频,写入的最大时钟为12.288*3/4MHz=9.216MHz,只要不超过这个频率应该都没问题

出0入0汤圆

 楼主| 发表于 2014-10-22 23:38:03 | 显示全部楼层
wz18th 发表于 2014-10-22 21:31
if(VS_Send_MusicData(databuf+i)==0)//给VS10XX发送音频数据
这句里面发送文件数据和DREQ脚的脉冲对上了么 ...

u8 VS_Send_MusicData(u8* buf)
{
        u8 n;
        if(VS_DQ!=0)  //送数据给VS10XX
        {                                    
                VS_XDCS=0;  
        for(n=0;n<32;n++)
                {
                        VS_SPI_ReadWriteByte(buf[n]);                                
                }
                VS_XDCS=1;                                       
        }else return 1;
        return 0;//成功发送了
}
这个程序在F103上运行过,是没有问题的,我怀疑的是配置上那里错了

出0入0汤圆

 楼主| 发表于 2014-10-23 10:45:17 | 显示全部楼层
问题找出来了,这一句读取数据时出错了:res=f_read(file1,databuf,4096,(UINT*)&br);//读出4096个字节
每次读取数据大于1k,数据就乱了,还没清楚为什么会这样,F1是用spi读写SD卡的,F4是用SDIO读写SD卡的

出0入0汤圆

 楼主| 发表于 2014-10-23 10:55:57 | 显示全部楼层
问题又找出来了,fatfs的接口函数没改好,读写块的数恒为1,导致读写超过1k就出错

出0入0汤圆

发表于 2014-10-23 12:49:54 | 显示全部楼层
smog 发表于 2014-10-23 10:55
问题又找出来了,fatfs的接口函数没改好,读写块的数恒为1,导致读写超过1k就出错 ...

问题找到就好了。。过阵子我也要做个F4的播放器,之前是拿的103的SDIO做的,不知道F4上还会遇到什么问题。

出0入0汤圆

发表于 2017-1-10 17:28:21 | 显示全部楼层
最近也在琢磨着个,参考下楼主的

出20入0汤圆

发表于 2019-3-22 11:23:12 | 显示全部楼层
正在移植VS1003到F4,参考下楼主
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-23 20:46

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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