一、系统概述
步进电机加减速控制是工业自动化、3D打印、机器人等领域的核心需求,通过梯形加减速算法可实现电机平稳启停,避免失步和过冲。本设计基于STM32F103C8T6,采用定时器中断+脉冲频率动态调整实现梯形加减速,支持正反转、速度调节、步数控制,具备高精度、低抖动、易扩展特点,适用于42步进电机(如17HS4401) 驱动。
二、系统架构与硬件设计
1. 系统架构
GPIO
两相四线
定时器TIM2
GPIO
GPIO
供电
控制命令
STM32F103C8T6
步进电机驱动器 如A4988
42步进电机 17HS4401
脉冲输出 控制步数/速度
方向控制 DIR
使能控制 EN
电源 12V/2A
按键/上位机
2. 核心硬件选型
| 模块 | 型号/参数 | 功能 |
|---|---|---|
| 主控 | STM32F103C8T6(72MHz,64KB Flash) | 脉冲生成、加减速算法、方向控制 |
| 驱动器 | A4988(支持微步细分,最大2A/相) | 放大STM32脉冲信号,驱动电机绕组 |
| 电机 | 42步进电机(17HS4401,1.8°/步) | 执行机构(200步/圈,无细分时) |
| 电源 | 12V/2A开关电源 | 驱动器供电(电机相电流1.5A) |
3. 关键电路设计
- 脉冲输出 :STM32的PA0(TIM2_CH1) 接驱动器PUL引脚,通过定时器PWM模式生成脉冲;
- 方向控制 :PA1接驱动器DIR引脚(高/低电平控制正反转);
- 使能控制 :PA2接驱动器EN引脚(低电平使能,高电平禁用);
- 电流限制:A4988的VREF引脚通过电位器调节,限制电机相电流(1.5A对应VREF≈0.75V)。
三、软件设计(C语言实现,基于STM32 HAL库)
1. 开发环境
- IDE:STM32CubeIDE(V1.13.0)
- 库:STM32 HAL库(V1.11.0)
- 核心算法:梯形加减速(加速→匀速→减速)
2. 核心参数定义
| 参数 | 符号 | 单位 | 说明 |
|---|---|---|---|
| 总步数 | total_steps |
步 | 电机需转动的总步数(如360°=200步) |
| 最大速度 | max_speed |
步/秒 | 匀速阶段的最大脉冲频率 |
| 加速度 | acceleration |
步/秒² | 速度变化率(加速/减速阶段) |
| 当前步数 | current_step |
步 | 已转动步数 |
| 当前速度 | current_speed |
步/秒 | 当前脉冲频率 |
3. 主程序流程
c
#include "stm32f1xx_hal.h"
#include "stepper_motor.h"
// 系统状态
StepperState stepper = {
.total_steps = 200, // 目标步数:200步(1圈)
.max_speed = 100, // 最大速度:100步/秒
.acceleration = 50, // 加速度:50步/秒²
.current_step = 0,
.current_speed = 0,
.direction = 1, // 1:正转,0:反转
.is_running = 0
};
int main(void) {
HAL_Init();
SystemClock_Config(); // 72MHz主频
Stepper_Init(); // 初始化GPIO、定时器
// 启动电机(正转200步)
Stepper_Start(&stepper, 200, 1);
while (1) {
if (stepper.is_running == 0) {
// 转动完成后,反转200步
Stepper_Start(&stepper, 200, 0);
}
HAL_Delay(100);
}
}
4. 关键模块实现
(1)步进电机初始化(stepper_motor.c)
c
#include "stepper_motor.h"
#include "tim.h"
// 初始化GPIO和定时器
void Stepper_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 使能GPIOA时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置DIR(PA1)、EN(PA2)为推挽输出
GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置定时器TIM2(PA0,脉冲输出)
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 72-1; // 72MHz/72=1MHz(1μs计数)
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000-1; // 初始周期1ms(1kHz,1步/ms=1000步/秒)
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim2);
HAL_TIM_Base_Start_IT(&htim2); // 启动定时器中断
// 使能电机
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
}
// 定时器中断回调函数(每1μs进入一次)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM2) {
Stepper_UpdatePulse(&stepper); // 更新脉冲输出
}
}
(2)梯形加减速算法(stepper_motor.c)
核心逻辑:根据当前速度、加速度、剩余步数,计算下一步的速度和脉冲间隔,实现加速→匀速→减速过渡。
c
// 步进电机状态结构体
typedef struct {
uint32_t total_steps; // 总步数
uint32_t current_step; // 当前步数
float max_speed; // 最大速度(步/秒)
float acceleration; // 加速度(步/秒²)
float current_speed; // 当前速度(步/秒)
uint8_t direction; // 方向(1:正转, 0:反转)
uint8_t is_running; // 运行状态
} StepperState;
// 更新脉冲输出(定时器中断中调用)
void Stepper_UpdatePulse(StepperState *motor) {
if (!motor->is_running) return;
// 1. 计算加速阶段步数(v²=2as → s=v²/(2a))
float accel_steps = (motor->max_speed * motor->max_speed) / (2 * motor->acceleration);
float decel_steps = accel_steps; // 减速阶段步数与加速相同
float cruise_steps = motor->total_steps - accel_steps - decel_steps;
// 2. 判断当前阶段(加速/匀速/减速)
if (motor->current_step < accel_steps) {
// 加速阶段:v = a*t → 速度线性增加
motor->current_speed += motor->acceleration * 0.001f; // 0.001s=1ms(定时器周期)
if (motor->current_speed > motor->max_speed) {
motor->current_speed = motor->max_speed;
}
} else if (motor->current_step < (accel_steps + cruise_steps)) {
// 匀速阶段:保持最大速度
motor->current_speed = motor->max_speed;
} else {
// 减速阶段:v = v0 - a*t → 速度线性减小
motor->current_speed -= motor->acceleration * 0.001f;
if (motor->current_speed < 0) motor->current_speed = 0;
}
// 3. 生成脉冲(当前速度>0时输出一步)
if (motor->current_speed > 0) {
// 设置方向
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, motor->direction ? GPIO_PIN_SET : GPIO_PIN_RESET);
// 输出脉冲(通过定时器翻转IO,此处简化为直接置位/复位)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
HAL_Delay(1); // 脉冲宽度1μs(实际需用定时器精确控制)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
// 更新步数
motor->current_step++;
if (motor->current_step >= motor->total_steps) {
motor->is_running = 0; // 完成转动
}
}
}
// 启动电机转动
void Stepper_Start(StepperState *motor, uint32_t steps, uint8_t dir) {
motor->total_steps = steps;
motor->current_step = 0;
motor->current_speed = 0;
motor->direction = dir;
motor->is_running = 1;
}
(3)关键参数计算(以200步、100步/秒、50步/秒²为例)
- 加速阶段步数 :saccel=vmax22a=10022×50=100步s_{accel}=\frac{v_{max}^2}{2a}=\frac{100^2}{2×50}=100步saccel=2avmax2=2×501002=100步
- 减速阶段步数 :sdecel=100步s_{decel}=100步sdecel=100步
- 匀速阶段步数 :scruise=200−100−100=0步s_{cruise}=200−100−100=0步scruise=200−100−100=0步(无匀速,直接加减速)
- 加速时间 :taccel=vmaxa=10050=2秒t_{accel}=\frac{v_{max}}{a}=\frac{100}{50}=2秒taccel=avmax=50100=2秒
- 总转动时间 :ttotal=taccel+tdecel=4秒t_{total}=t_{accel}+t_{decel}=4秒ttotal=taccel+tdecel=4秒
参考代码 基于STM32的步进电机加减速程序 www.youwenfan.com/contentcss/161328.html
四、系统测试与优化
1. 测试指标
| 参数 | 指标 | 测试方法 |
|---|---|---|
| 转动精度 | ±1步(200步时) | 标记电机轴,测量实际转动角度 |
| 加减速平稳性 | 无失步/过冲 | 示波器观察脉冲频率变化(梯形曲线) |
| 最大速度 | 100-500步/秒(可调) | 改变max_speed参数,测试电机响应 |
| 功耗 | <1W(待机),<5W(运行) | 万用表测量电源电流 |
2. 优化方向
- S形加减速:替代梯形加减速,通过正弦曲线调整速度,进一步降低冲击(需增加计算复杂度);
- 微步控制:A4988支持1/16微步,将1.8°/步细分为0.1125°/步,提高运动平滑度;
- 闭环控制:增加编码器反馈,实现位置闭环(如1000线编码器,精度提升10倍);
- 低功耗:空闲时关闭定时器时钟,降低STM32功耗(<10μA)。
五、总结
本设计基于STM32实现了步进电机梯形加减速控制,通过定时器中断动态调整脉冲频率,结合运动学公式计算加减速阶段参数,实现电机平稳启停。系统具备代码简洁、参数可调、易扩展特点,可直接应用于3D打印机、机械臂、自动化设备等场景。