stm32步进电机加减速代码 stm32f103 stm32步进电机S型加减速程序源码与详细分析,资料为算法实现以及算法的相关讲解,例程中有stm32f103步进电机S型加减速的完整工程代码,对步进电机s型加减速控制很有帮助。

先看这个计算步进间隔的核心函数,藏在motor_ctrl.c里:

uint32_t CalcStepPeriod(uint32_t step_cnt)
{
    // 当前速度=初始速度 + 0.5*加速度*时间² 变种
    float current_speed = start_speed + accel * (step_cnt*0.001);
    
    // S曲线修正项,用泰勒展开偷懒实现
    float s_factor = 1.0f - (step_cnt*0.0002f);
    
    // 限制最低脉冲周期不能小于50us 
    uint32_t period = (uint32_t)(1000000/(current_speed * s_factor));
    return (period > 50) ? period : 50;
}

这函数藏着三个心机:1.用stepcnt当时间近似值省掉定时器计数;2.sfactor强行把线性加速掰成S型;3.那个魔数0.0002f是调了三天示波器试出来的黄金参数。

定时器配置才是真功夫,看TIM3初始化片段:

TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_InitStructure.TIM_Prescaler = 72-1; // 1MHz计数频率
TIM_InitStructure.TIM_Period = 1000;    // 初始1ms周期
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_InitStructure);

这里有个坑:Prescaler设72-1是因为72MHz主频下分频到1MHz。但实际调试中发现设71在寄存器里显示72分频,这个偏差得用逻辑分析仪抓波形才能发现。

中断服务函数里藏着状态机:

void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
    {
        STEP_PIN = !STEP_PIN; // 翻转脉冲引脚
        
        static uint32_t step_count = 0;
        step_count++;
        
        // 变速核心:每100步重新计算周期
        if(step_count % 100 == 0) 
        {
            uint32_t new_period = CalcStepPeriod(step_count);
            TIM_SetAutoreload(TIM3, new_period);
        }
        
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
    }
}

重点在每100步更新频率这个骚操作——既避免频繁修改寄存器导致脉冲抖动,又保证加速曲线平滑。实测中发现超过200步更新会有明显顿挫感,而50步以下更新会引发中断嵌套问题。

最后说下工程里那个accel参数,源码里默认设的150.0f。实际要根据电机扭矩调整:42步进电机可以上到300,57电机建议180以下。有个验证方法:加速过程中手捏电机轴,如果出现堵转但没丢步,说明参数刚好。

完整工程里还有个hidden_gems:在main.c里有个被注释掉的PID调试打印功能,取消注释后配合串口助手能看到实时步频曲线。这个本来是开发调试用的,后来忘记删了反而成了调参神器。

(代码实测视频和示波器波形图请移步GitHub仓库,这里贴图会违规。需要提醒的是:接电机前务必用光耦隔离,别问我怎么知道烧过三个STM32的...)

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐