发新帖我要提问
12
返回列表
打印

GD32F130精准延时SPI_DMA_TX发送数据讨论贴

[复制链接]
楼主: mrhw
手机看帖
扫描二维码
随时随地手机跟帖
21
作为GD的技术支持,看了此贴后,希望能够细致了解具体信息,这样才能够更有效的解决您的问题。如果方便,请留下联系方式,或者发送邮件至csli@gigadevice.com

使用特权

评论回复
22
GONGO| | 2014-12-1 16:56 | 只看该作者
有这样的现象,应该是因为 SPI 的分频造成的,  和 DMA、中断、TIM3 都没有关系。
所以分频值越小,一致性越好。还与 APB clock 有关。

SPI 发送,从写数据到 SPI->DR 到实际发送到总线,可能会有一个 SPI 时钟内的延时( 0<= 延时值 <= SPI CLK )。这个一般没什么影响。

如果不想要这个延时,需要每次发送前 执行 RCC_APB2PeriphResetCmd ,复位SPI,
然后重新配置SPI,再发送,应该可以解决。

使用特权

评论回复
评分
参与人数 1威望 +8 收起 理由
sunmeat + 8 还是专家厉害
23
itachier| | 2014-12-2 15:02 | 只看该作者
我没有回答错误哦,你加我QQ我帮你解决问题你又不加,或者你这边留着联系方式也行啊。

使用特权

评论回复
24
mrhw|  楼主 | 2014-12-2 19:54 | 只看该作者
GONGO 发表于 2014-12-1 16:56
有这样的现象,应该是因为 SPI 的分频造成的,  和 DMA、中断、TIM3 都没有关系。
所以分频值越小,一致性越 ...

确实跟SPI的分频有很大关系,明天按你的处理方法试一下

使用特权

评论回复
25
776072084| | 2014-12-3 15:26 | 只看该作者
GONGO 发表于 2014-12-1 16:56
有这样的现象,应该是因为 SPI 的分频造成的,  和 DMA、中断、TIM3 都没有关系。
所以分频值越小,一致性越 ...

根据楼主提供的部分代码,复现了整个工程,按照这种方法是可以解决问题的。:handshake

使用特权

评论回复
26
mrhw|  楼主 | 2014-12-3 16:45 | 只看该作者
本帖最后由 mrhw 于 2014-12-3 20:09 编辑
GONGO 发表于 2014-12-1 16:56
有这样的现象,应该是因为 SPI 的分频造成的,  和 DMA、中断、TIM3 都没有关系。
所以分频值越小,一致性越 ...

按GONGO大拿的解决方法:  我将代码调整为

void EXTI2_3_IRQHandler(void)
{



        EXTI_ClearITPendingBit(EXTI_Line2);               

        TIM_Cmd(TIM3, ENABLE); //开启TIM3,TIM3优级抢占优先级较高,计算任何还没有完成时就会进入TIM3中断,
        DMA_Cmd(DMA1_Channel3, DISABLE);
        SPI_DMA_InitStructure.DMA_BufferSize = 18;
        SPI_DMA_InitStructure.DMA_MemoryBaseAddr = data[0];
        DMA_Init(DMA1_Channel3, &SPI_DMA_InitStructure);

        RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);
       
        //SPI_Re_init();
                       
        RCC_APB2PeriphClockCmd( RCC_AHBPeriph_GPIOB, ENABLE);
                         
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
                       
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_0);
                         
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_0);
                                                  
        GPIO_Init(GPIOB, &SPI_GPIO_InitStructure);

        SPI_I2S_DeInit(SPI1);
                         
        SPI_Init(SPI1, &SPI_InitStructure);
                         
        SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
                            
        SPI_Cmd(SPI1, ENABLE);

        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

        {
                //计算任务
                //每次的计算任务都会顺利完成
        }                                 



}
经过这样的处理在TIM中使能SPI_DMA_TX ,发出数据的时间对齐性已经较好了,72M下比48M下对齐程序更好。
但48M下有一个缺点:
RCC_APB2PeriphReset 到  SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE)即从复位到再次配置好SPI,用的时间太久了(可能不是代码太多,也许是复位配置SPI外设需要时间),当TIM中断已经使能SPI_DMA_TX时,并不能立即发出数据,这时SPI的复位和配置还没有完成呢,待完成时发出完整的数据,发出时间上的对齐性较好,使用这种方式受到的限制是延时比较大。

为解决延时比较大的问题,另一种方式是先发送数据,发送完成时,执行复位和重新配置SPI,以便于下次立即可以发送数据,经过实际测试这种方式不如在数据发送之前复位和重新配置SPI的时间对齐性好。


目前总结出的最佳方式为:工作在72M下,在发送数据前复位和重新配置SPI,在72M下复位和配置SPI的速度大大加快,从复位开始8us的延时就可以发送出数据了(时间对齐性较好).

为工作在72M下,只有将GD32F130替换为GD32F150了,GD32F130超频到72M暂时没发现问题, 不同工作环境怕是不稳定!

   

使用特权

评论回复
27
sunmeat| | 2014-12-7 09:10 | 只看该作者
mrhw 发表于 2014-12-3 16:45
按GONGO大拿的解决方法:  我将代码调整为

void EXTI2_3_IRQHandler(void)

把复位的代码换成寄存器操作看看,还可以再加大频率一点点的,哈哈

使用特权

评论回复
28
GONGO| | 2014-12-15 13:52 | 只看该作者
本帖最后由 GONGO 于 2014-12-15 14:00 编辑
mrhw 发表于 2014-12-3 16:45
按GONGO大拿的解决方法:  我将代码调整为

void EXTI2_3_IRQHandler(void)

void EXTI2_3_IRQHandler(void)
{



        EXTI_ClearITPendingBit(EXTI_Line2);               

        TIM_Cmd(TIM3, ENABLE); //开启TIM3,TIM3优级抢占优先级较高,计算任何还没有完成时就会进入TIM3中断,
        DMA_Cmd(DMA1_Channel3, DISABLE);
        SPI_DMA_InitStructure.DMA_BufferSize = 18;
        SPI_DMA_InitStructure.DMA_MemoryBaseAddr = data[0];
        DMA_Init(DMA1_Channel3, &SPI_DMA_InitStructure);



/*                                                                                              这里有点繁琐了, 只 Reset SPI 即可
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);                                    不必操作 GPIO 吧!
        
        //SPI_Re_init();
                        
        RCC_APB2PeriphClockCmd( RCC_AHBPeriph_GPIOB, ENABLE);
                        
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
                        
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_0);
                        
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_0);
                                                  
        GPIO_Init(GPIOB, &SPI_GPIO_InitStructure);
*/


        SPI_I2S_DeInit(SPI1);--------------------------------------------------------------- 这个函数已经有 APB_CLK 复位功能了

                                                                                                                                                                                                                                    所以有这一句就应该可以了吧

        SPI_Init(SPI1, &SPI_InitStructure);
                        
        SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
                           
        SPI_Cmd(SPI1, ENABLE);

        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

        {
                //计算任务
                //每次的计算任务都会顺利完成
        }                                 



}


另外,这里之所以时间长,应该是代码多的。
你删掉多余部分后,还是慢的话,就直接操作寄存器好了!

使用特权

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

本版积分规则