gdszzyq 发表于 2022-4-14 15:48

GD芯片带多路步进电机工作不正常,请高手们指点一下

我原来用的是STM32F103VBT6这款芯片做的控制板,想用GD32F103VBT6替换,于是做了几块样板测试,我用原ST库写的程序只是修改了那几个超时参数,其它都不变直接烧进去GD的板子上测试,我的产品带5路步进电机,发现当3路以上步进电机同时运转时出现严重丢步情况,而且是在空载的情况下。
同样的程序在ST的板子上都用了几年了都没有问题。论坛上有人说要用GD的库改才行,于是我把程序全部改成GD库的,但一样出现这样情况,找了代理商的FAE找不到原因,我写了个程序同时输出7路PWM信号,用示波器观察波形正常,我怀疑是加减速过程出现问题,但没办法用示波器观察到这个过程,请问大家有没有遇到类似的问题?真的想换GD芯片,ST的太贵了,请高手帮帮我,万分感谢!

gdszzyq 发表于 2022-4-14 15:59

void PWM_Init(void)
{
        timer_parameter_struct timer_initpara;
        timer_oc_parameter_struct timer_ocintpara ;
        rcu_periph_clock_enable(RCU_TIMER2); //TIM2时钟使能
        rcu_periph_clock_enable(RCU_TIMER1); //TIM1时钟使能
        timer_initpara.period            = 65535; //自动重装载寄存器周期的值
        timer_initpara.prescaler         = 0;//先不装入分频值
        timer_initpara.clockdivision   = 0;
        timer_initpara.alignedmode       = TIMER_COUNTER_UP;
        timer_init(TIMER2,&timer_initpara);    //TIM2
        timer_init(TIMER1,&timer_initpara);    //TIM1       
        timer_prescaler_config(TIMER2,PrescalerValue,TIMER_PSC_RELOAD_NOW);   //预分频值即时装入TIM2
        timer_prescaler_config(TIMER1,PrescalerValue,TIMER_PSC_RELOAD_NOW);   //预分频值即时装入TIM1
       //定时器2的CC1配置输出比较模式   
        timer_ocintpara.outputstate= TIMER_CCX_ENABLE;
        timer_ocintpara.ocnpolarity= TIMER_OCN_POLARITY_HIGH;//输出极性
        timer_channel_output_config(TIMER2,TIMER_CH_0,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,First_Motor_Time_Step);   //比较寄存器值
        timer_channel_output_mode_config(TIMER2,TIMER_CH_0,TIMER_OC_MODE_TIMING);   //输出比较触发模式
        timer_channel_output_shadow_config(TIMER2,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);//禁止TIM_CCR1寄存器预装

//定时器2的CC2配置输出比较模式   
        timer_ocintpara.outputstate= TIMER_CCX_ENABLE;
        timer_ocintpara.ocnpolarity= TIMER_OCN_POLARITY_HIGH;//输出极性
        timer_channel_output_config(TIMER2,TIMER_CH_1,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,First_Motor_Time_Step);   //比较寄存器值
        timer_channel_output_mode_config(TIMER2,TIMER_CH_1,TIMER_OC_MODE_TIMING);   //输出比较触发模式
        timer_channel_output_shadow_config(TIMER2,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);//禁止TIM_CCR1寄存器预装

   
    //定时器2的CC3配置输出比较模式   
        timer_ocintpara.outputstate= TIMER_CCX_ENABLE;
        timer_ocintpara.ocnpolarity= TIMER_OCN_POLARITY_HIGH;//输出极性
        timer_channel_output_config(TIMER2,TIMER_CH_2,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,First_Motor_Time_Step);   //比较寄存器值
        timer_channel_output_mode_config(TIMER2,TIMER_CH_2,TIMER_OC_MODE_TIMING);   //输出比较触发模式
        timer_channel_output_shadow_config(TIMER2,TIMER_CH_2,TIMER_OC_SHADOW_DISABLE);//禁止TIM_CCR2寄存器预装
       
    //定时器2的CC4配置输出比较模式   
        timer_ocintpara.outputstate= TIMER_CCX_ENABLE;
        timer_ocintpara.ocnpolarity= TIMER_OCN_POLARITY_HIGH;//输出极性
        timer_channel_output_config(TIMER2,TIMER_CH_3,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_3,First_Motor_Time_Step);   //比较寄存器值
        timer_channel_output_mode_config(TIMER2,TIMER_CH_3,TIMER_OC_MODE_TIMING);   //输出比较触发模式
        timer_channel_output_shadow_config(TIMER2,TIMER_CH_3,TIMER_OC_SHADOW_DISABLE);//禁止TIM_CCR1寄存器预装

    //配置TIM2中断
        nvic_irq_enable(TIMER2_IRQn,0,1);
   
        timer_enable(TIMER2);//开启定时器2
       
    //定时器1的CC1配置输出比较模式   
        timer_ocintpara.outputstate= TIMER_CCX_ENABLE;
        timer_ocintpara.ocnpolarity= TIMER_OCN_POLARITY_HIGH;//输出极性
        timer_channel_output_config(TIMER1,TIMER_CH_0,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_0,First_Motor_Time_Step);   //比较寄存器值
        timer_channel_output_mode_config(TIMER1,TIMER_CH_0,TIMER_OC_MODE_TIMING);   //输出比较触发模式
        timer_channel_output_shadow_config(TIMER1,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);//禁止TIM_CCR1寄存器预装
       
    //定时器1的CC2配置输出比较模式   
        timer_ocintpara.outputstate= TIMER_CCX_ENABLE;
        timer_ocintpara.ocnpolarity= TIMER_OCN_POLARITY_HIGH;//输出极性
        timer_channel_output_config(TIMER1,TIMER_CH_1,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_1,First_Motor_Time_Step);   //比较寄存器值
        timer_channel_output_mode_config(TIMER1,TIMER_CH_1,TIMER_OC_MODE_TIMING);   //输出比较触发模式
        timer_channel_output_shadow_config(TIMER1,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);//禁止TIM_CCR1寄存器预装

    //定时器1的CC3配置输出比较模式   
        timer_ocintpara.outputstate= TIMER_CCX_ENABLE;
        timer_ocintpara.ocnpolarity= TIMER_OCN_POLARITY_HIGH;//输出极性
        timer_channel_output_config(TIMER1,TIMER_CH_2,&timer_ocintpara);
        timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_2,First_Motor_Time_Step);   //比较寄存器值
        timer_channel_output_mode_config(TIMER1,TIMER_CH_2,TIMER_OC_MODE_TIMING);   //输出比较触发模式
        timer_channel_output_shadow_config(TIMER1,TIMER_CH_2,TIMER_OC_SHADOW_DISABLE);//禁止TIM_CCR1寄存器预装
    //配置TIM1中断
        nvic_irq_enable(TIMER1_IRQn,0,2);

        timer_enable(TIMER1);//开启定时器1
}
void TIMER2_IRQHandler(void)   //TIM2中断
{
        if (timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_CH0) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
        {
                First_Motor_Step=!First_Motor_Step;
                if(First_Motor_Step==1)First_Motor_Step_Count++;
                TIMER_CH0CV(TIMER2)+=First_Motor_Time_Step;
                timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_CH0);
        }
        if (timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_CH1) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
        {
                Second_Motor_Step=!Second_Motor_Step;
                if(Second_Motor_Step==1)Second_Motor_Step_Count++;
                TIMER_CH1CV(TIMER2)+=Second_Motor_Time_Step;
                timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_CH1);
        }
        if (timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_CH2) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
        {
                Third_Motor_Step=!Third_Motor_Step;               
                if(Third_Motor_Step==1)Third_Motor_Step_Count++;
                TIMER_CH2CV(TIMER2)+=Third_Motor_Time_Step;
                timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_CH2);
        }
        if (timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_CH3) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
        {
                Seventh_Motor_Step=!Seventh_Motor_Step;
                if(Seventh_Motor_Step==1)Seventh_Motor_Step_Count++;
                TIMER_CH3CV(TIMER2)+=Seventh_Motor_Time_Step;
                timer_interrupt_flag_clear(TIMER2,TIMER_INT_FLAG_CH3);
        }
}
void TIMER1_IRQHandler(void)   //TIM1中断
{
        if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH0) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
        {
                Fourth_Motor_Step=!Fourth_Motor_Step;
                if(Fourth_Motor_Step==1)Fourth_Motor_Step_Count++;
                TIMER_CH0CV(TIMER1)+=Fourth_Motor_Time_Step;
                timer_interrupt_flag_clear(TIMER1,TIMER_INT_FLAG_CH0);
        }
        if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH1) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
        {
                Fifth_Motor_Step=!Fifth_Motor_Step;
                if(Fifth_Motor_Step==1)Fifth_Motor_Step_Count++;
                TIMER_CH1CV(TIMER1)+=Fifth_Motor_Time_Step;
                timer_interrupt_flag_clear(TIMER1,TIMER_INT_FLAG_CH1);
        }
        if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH2) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
        {
                Sixth_Motor_Step=!Sixth_Motor_Step;
                if(Sixth_Motor_Step==1)Sixth_Motor_Step_Count++;
                TIMER_CH2CV(TIMER1)+=Sixth_Motor_Time_Step;
                timer_interrupt_flag_clear(TIMER1,TIMER_INT_FLAG_CH2);
        }
}

王久强 发表于 2022-4-14 16:18

使用的内部晶振还是外部的,会不会时钟不准

alienmiller 发表于 2022-4-14 17:47

不知道是不是这个原因,以前用 STC 控制步进电机时发现多定时器同时工作容易出问题。

gdszzyq 发表于 2022-4-14 21:32

王久强 发表于 2022-4-14 16:18
使用的内部晶振还是外部的,会不会时钟不准

外部晶振,除了mcu不一样其他全部一样

gdszzyq 发表于 2022-4-14 21:35

alienmiller 发表于 2022-4-14 17:47
不知道是不是这个原因,以前用 STC 控制步进电机时发现多定时器同时工作容易出问题。 ...

.如果是这样就是芯片问题,我想不至于吧,stc的我也有用,3个定时器控3路步进电机没问题,定时器有点特别而己

onebank 发表于 2022-4-15 08:39

会不会是电机一起运行的时候把电压拉低了,记得GD的工作电压范围比ST的要小一些。

m564522634 发表于 2022-4-15 13:38

先把电机断开,抓下同时开启5路控制信号的时候信号正常不,如果正常估计要查硬件了

gdszzyq 发表于 2022-4-15 14:28

m564522634 发表于 2022-4-15 13:38
先把电机断开,抓下同时开启5路控制信号的时候信号正常不,如果正常估计要查硬件了...

我测试的这台设备是可以正常工作的,只是换了一块MCU是GD的就不行,我只有普通的单路示波器,而且还不能实时抓取,只能实时看1路波形,我不接电机的情况下开启7路PWM信号,一路一路的情况下看波形是正常的,无法知道加速过程波形是否正常,而且我的电机不是一直运转的,是周期性的往复运转,比如正转一圈,停止0.1秒,再反转一圈,就这样循环运转。每次启动都有个加速的过程,我怀疑是加速过程出了问题,只有2路以下同时运转都没问题,超过3路就出问题,5路就更严重。

gdszzyq 发表于 2022-4-15 14:31

onebank 发表于 2022-4-15 08:39
会不会是电机一起运行的时候把电压拉低了,记得GD的工作电压范围比ST的要小一些。 ...

我是用驱动器的,而且所有输出的IO都带驱动电路的,那点电流怎么可能把电压拉低。

xdqfc 发表于 2022-4-15 15:04

看中断的抢占级都是一样,咱有点怀疑是不是被中断影响了,假如是这样,就必须提高CPU主频速度,或者修改一下中断优先级。或者中断程序做一下处理,考虑两个中断同时出现的情况(即使是一个定时器里面)。

xdqfc 发表于 2022-4-15 15:10

看样子是一个定时器带了4个PWM输出,先用一个定时器输出看看,看一下会不会有影响,没有的话,再加另外一组。


onebank 发表于 2022-4-15 15:38

gdszzyq 发表于 2022-4-15 14:31
我是用驱动器的,而且所有输出的IO都带驱动电路的,那点电流怎么可能把电压拉低。 ...

既然怀疑加速过程有问题那就把加速过程去掉,全部低速跑看会不会丢步。买个逻辑分析仪看PWM挺方便

lifeforrent 发表于 2022-4-15 15:44

定义的结构体都是局部变量,调用库函数初始化一下,输出PWM为什么要用TIMER_OC_MODE_TIMING不是很理解

gdszzyq 发表于 2022-4-15 16:48

xdqfc 发表于 2022-4-15 15:10
看样子是一个定时器带了4个PWM输出,先用一个定时器输出看看,看一下会不会有影响,没有的话,再加另外一组 ...

试过用一个定时器输出4路PWM,也一样出这样,PWM的周期最短才100微妙,就算是7路电机同时抢中断也就差别几个微妙而已,对电机影响可忽略。

gdszzyq 发表于 2022-4-15 16:55

onebank 发表于 2022-4-15 15:38
既然怀疑加速过程有问题那就把加速过程去掉,全部低速跑看会不会丢步。买个逻辑分析仪看PWM挺方便 ...

低速是没问题的,就是快了才这样,,所以加速没办法去掉,去掉了电机肯定丢步的。电机每分钟600转,这个速度用ST的MCU带负载工作都正常的,现在是空载测试都丢步,所有电机单独运转都没问题,只是3路以上同时转才有问题,而且越多越严重。

gdszzyq 发表于 2022-4-15 17:01

lifeforrent 发表于 2022-4-15 15:44
定义的结构体都是局部变量,调用库函数初始化一下,输出PWM为什么要用TIMER_OC_MODE_TIMING不是很理解 ...

我就是先初始化结构体成员变量才调用函数的,没必要再调用库函数初始化吧,另外TIM_OCMode_PWM这个模式我没研究过,而且这种要指定端口输出PWM信号吧,有什么不一样吗?

onebank 发表于 2022-4-15 17:20

gdszzyq 发表于 2022-4-15 16:55
低速是没问题的,就是快了才这样,,所以加速没办法去掉,去掉了电机肯定丢步的。电机每分钟600转,这个 ...

我觉得可以从以下三个方面检查下:
1、你说的加速过程问题,可以把加速时间拉长看看会不会丢步;
2、电源负载太大导致GD32工作异常,可以看下整个运行过程中GD供电是否异常;
3、可以将电机控制之外的所有代码屏蔽试一下。例如是否有在中断写flash那些操作,是否有更高优先级的中断做比较耗时的控制等。

onebank 发表于 2022-4-15 17:33

还有定时器比较通道的初始值我觉得可以岔开一点,设以下的样子
Fourth_Motor_Time_Step*0/4,
Fourth_Motor_Time_Step*1/4,
Fourth_Motor_Time_Step*2/4,
Fourth_Motor_Time_Step*3/4,

13226636021 发表于 2022-4-15 18:05

是不是用的FLASH超出了GD的高速FLASH区,如果代码在低速FLASH区跑算法这些肯定不行的,GD的低速区没什么用,听着好听,三年前就遇到过这个坑了
页: [1] 2 3
查看完整版本: GD芯片带多路步进电机工作不正常,请高手们指点一下