打印

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

[复制链接]
3029|60
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gdszzyq|  楼主 | 2022-4-14 15:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我原来用的是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 控制步进电机时发现多定时器同时工作容易出问题。

使用特权

评论回复
5
gdszzyq|  楼主 | 2022-4-14 21:32 | 只看该作者
王久强 发表于 2022-4-14 16:18
使用的内部晶振还是外部的,会不会时钟不准

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

使用特权

评论回复
6
gdszzyq|  楼主 | 2022-4-14 21:35 | 只看该作者
alienmiller 发表于 2022-4-14 17:47
不知道是不是这个原因,以前用 STC 控制步进电机时发现多定时器同时工作容易出问题。 ...

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

使用特权

评论回复
7
onebank| | 2022-4-15 08:39 | 只看该作者
会不会是电机一起运行的时候把电压拉低了,记得GD的工作电压范围比ST的要小一些。

使用特权

评论回复
8
m564522634| | 2022-4-15 13:38 | 只看该作者
先把电机断开,抓下同时开启5路控制信号的时候信号正常不,如果正常估计要查硬件了

使用特权

评论回复
9
gdszzyq|  楼主 | 2022-4-15 14:28 | 只看该作者
m564522634 发表于 2022-4-15 13:38
先把电机断开,抓下同时开启5路控制信号的时候信号正常不,如果正常估计要查硬件了  ...

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

使用特权

评论回复
10
gdszzyq|  楼主 | 2022-4-15 14:31 | 只看该作者
onebank 发表于 2022-4-15 08:39
会不会是电机一起运行的时候把电压拉低了,记得GD的工作电压范围比ST的要小一些。 ...

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

使用特权

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

使用特权

评论回复
12
xdqfc| | 2022-4-15 15:10 | 只看该作者
看样子是一个定时器带了4个PWM输出,先用一个定时器输出看看,看一下会不会有影响,没有的话,再加另外一组。


使用特权

评论回复
13
onebank| | 2022-4-15 15:38 | 只看该作者
gdszzyq 发表于 2022-4-15 14:31
我是用驱动器的,而且所有输出的IO都带驱动电路的,那点电流怎么可能把电压拉低。 ...

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

使用特权

评论回复
评论
gdszzyq 2022-4-15 17:06 回复TA
@onebank :明天我将加速时间加长点试试看,但我不明白ST也同样的加速周期(1毫秒),而且这个时间是用定时器产生的,应该是准确的,程序里我也没有用过软件延时,全时用定时器产生的延时实现的,不会说是因为GD的跑比较快而导致加速周期不一样 
onebank 2022-4-15 15:39 回复TA
或者弄个简单的梯形加速,加速时间调长一点 
14
lifeforrent| | 2022-4-15 15:44 | 只看该作者
定义的结构体都是局部变量,调用库函数初始化一下,输出PWM为什么要用TIMER_OC_MODE_TIMING不是很理解

使用特权

评论回复
15
gdszzyq|  楼主 | 2022-4-15 16:48 | 只看该作者
xdqfc 发表于 2022-4-15 15:10
看样子是一个定时器带了4个PWM输出,先用一个定时器输出看看,看一下会不会有影响,没有的话,再加另外一组 ...

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

使用特权

评论回复
16
gdszzyq|  楼主 | 2022-4-15 16:55 | 只看该作者
onebank 发表于 2022-4-15 15:38
既然怀疑加速过程有问题那就把加速过程去掉,全部低速跑看会不会丢步。买个逻辑分析仪看PWM挺方便 ...

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

使用特权

评论回复
17
gdszzyq|  楼主 | 2022-4-15 17:01 | 只看该作者
lifeforrent 发表于 2022-4-15 15:44
定义的结构体都是局部变量,调用库函数初始化一下,输出PWM为什么要用TIMER_OC_MODE_TIMING不是很理解 ...

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

使用特权

评论回复
18
onebank| | 2022-4-15 17:20 | 只看该作者
gdszzyq 发表于 2022-4-15 16:55
低速是没问题的,就是快了才这样,,所以加速没办法去掉,去掉了电机肯定丢步的。电机每分钟600转,这个 ...

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

使用特权

评论回复
19
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,

使用特权

评论回复
20
13226636021| | 2022-4-15 18:05 | 只看该作者
是不是用的FLASH超出了GD的高速FLASH区,如果代码在低速FLASH区跑算法这些肯定不行的,GD的低速区没什么用,听着好听,三年前就遇到过这个坑了

使用特权

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

本版积分规则

46

主题

322

帖子

3

粉丝