基于STM32平台的步进电机S型曲线加减速驱动程序
一、系统架构设计
graph TD
A[主控MCU] --> B[定时器1-PWM输出]
A --> C[定时器2-速度调节]
B --> D[步进电机驱动器]
C --> B
D --> E[机械负载]
二、核心代码实现
1. 硬件初始化(CubeMX配置)
// 定时器1配置(PWM输出)
TIM_HandleTypeDef htim1;
void MX_TIM1_Init(void) {
TIM_OC_InitTypeDef sConfigOC = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 84-1; // 1MHz时钟
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1000-1; // 初始频率1kHz
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&htim1);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 50%占空比
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
}
// 定时器2配置(速度调节)
TIM_HandleTypeDef htim2;
void MX_TIM2_Init(void) {
htim2.Instance = TIM2;
htim2.Init.Prescaler = 8400-1; // 100Hz中断
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0xFFFF;
HAL_TIM_Base_Init(&htim2);
HAL_TIM_Base_Start_IT(&htim2);
}
2. S型曲线参数生成
#define ACCEL_STEPS 800 // 加速阶段步数
#define DECEL_STEPS 800 // 减速阶段步数
#define MAX_FREQ 20000 // 最大频率20kHz
#define MIN_FREQ 1000 // 最小频率1kHz
uint16_t accel_table[ACCEL_STEPS](@ref);
uint16_t decel_table[DECEL_STEPS](@ref);
// S型曲线数学变换
float sigmoid(float x) {
return 1.0f / (1.0f + expf(-x));
}
void GenerateSCurve() {
float flexible = 4.0f; // 曲线陡峭度参数
float x_scale = ACCEL_STEPS / 2.0f;
// 生成加速曲线
for(int i=0; i<ACCEL_STEPS; i++) {
float x = flexible * (i - x_scale) / x_scale;
float freq = MIN_FREQ + (MAX_FREQ-MIN_FREQ) * sigmoid(x);
accel_table[i](@ref)= (uint16_t)(SystemCoreClock / (freq * 2) - 1);
}
// 生成减速曲线(反向S曲线)
for(int i=0; i<DECEL_STEPS; i++) {
float x = flexible * (DECEL_STEPS - i - x_scale) / x_scale;
float freq = MIN_FREQ + (MAX_FREQ-MIN_FREQ) * sigmoid(x);
decel_table[i](@ref)= (uint16_t)(SystemCoreClock / (freq * 2) - 1);
}
}
3. 状态机控制
typedef enum {
ACCELERATE,
RUN,
DECELERATE,
STOPPED
} MotorState;
MotorState motor_state = STOPPED;
volatile uint32_t step_count = 0;
volatile uint16_t *current_table;
uint16_t table_index = 0;
void SetMotorState(MotorState new_state) {
motor_state = new_state;
table_index = 0;
switch(new_state) {
case ACCELERATE: current_table = accel_table; break;
case DECELERATE: current_table = decel_table; break;
default: break;
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if(htim->Instance == TIM2) {
step_count++;
// 状态切换逻辑
switch(motor_state) {
case ACCELERATE:
if(table_index >= ACCEL_STEPS) {
SetMotorState(RUN);
}
break;
case DECELERATE:
if(table_index >= DECEL_STEPS) {
SetMotorState(STOPPED);
}
break;
}
// 更新PWM参数
__HAL_TIM_SET_AUTORELOAD(&htim1, current_table[table_index](@ref);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1,
current_table[table_index](@ref)/ 2); // 50%占空比
table_index++;
}
}
4. 运动控制接口
void StartMotion(uint32_t total_steps) {
// 计算总步数
step_count = 0;
// 根据总步数自动计算加速/减速阶段
if(total_steps > ACCEL_STEPS*2) {
// 长距离运动:加速→匀速→减速
HAL_TIM_Base_Start_IT(&htim2);
SetMotorState(ACCELERATE);
} else {
// 短距离运动:直接S型加速减速
SetMotorState(ACCELERATE);
}
}
void StopMotion() {
HAL_TIM_Base_Stop_IT(&htim2);
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
motor_state = STOPPED;
}
三、关键参数优化
1. 曲线参数调整
| 参数 | 计算公式 | 典型值 |
|---|---|---|
| 加速时间 | T_acc = (ACCEL_STEPS × 100μs) | 80ms |
| 减速时间 | T_dec = (DECEL_STEPS × 100μs) | 80ms |
| 最大加速度 | a_max = (MAX_FREQ-MIN_FREQ)×1000 | 19kHz/ms |
| 峰值电流 | I_peak = V/(Rm + Ke×a_max) | 2A |
2. 硬件配置建议
// 电机驱动配置(以DRV8825为例)
#define DIR_PIN GPIO_PIN_0
#define STEP_PIN GPIO_PIN_1
#define EN_PIN GPIO_PIN_2
void Motor_GPIO_Init() {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
// 方向引脚
GPIO_InitStruct.Pin = DIR_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 步进引脚(使用定时器通道)
GPIO_InitStruct.Pin = STEP_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 使能引脚
GPIO_InitStruct.Pin = EN_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void Motor_Enable() {
HAL_GPIO_WritePin(GPIOA, EN_PIN, GPIO_PIN_RESET); // 低电平使能
}
四、调试与验证
1. 示波器观察要点
- PWM频率曲线:验证是否符合预期S型变化
- 脉冲宽度:确保占空比稳定在45%-55%之间
- 电流波形:观察是否出现异常尖峰
2. 性能测试数据
| 测试项目 | 测试条件 | 预期结果 |
|---|---|---|
| 启动平滑度 | 0→20000步/秒 | 加速度≤5000rad/s² |
| 停止精度 | 10000步停止 | 误差≤±2步 |
| 温升(连续运行) | 25℃环境/1小时 | ≤45℃ |
参考代码 带有S型曲线加减速的步进电机驱动程序 www.youwenfan.com/contentcnr/56714.html
五、扩展功能实现
1. 闭环控制集成
// 编码器中断处理
void Encoder_Callback() {
static int32_t encoder_count = 0;
encoder_count++;
// 位置闭环补偿
if(motor_state == RUN) {
int32_t error = target_pos - encoder_count;
if(abs(error) > 50) {
// 触发紧急停止
StopMotion();
}
}
}
2. 多轴同步控制
typedef struct {
TIM_HandleTypeDef *htim;
uint16_t *accel_table;
uint32_t step_count;
} MotorHandle;
void SyncMotion(MotorHandle *motors, uint8_t num) {
// 通过总线同步各轴时钟
for(uint8_t i=0; i<num; i++) {
__HAL_TIM_SET_AUTORELOAD(motors[i].htim,
motors[i].accel_table[table_index]);
}
}
六、常见问题解决方案
-
电机丢步
- 检查电流是否达到额定值(使用电流检测芯片)
- 增加细分设置(如1/16细分)
- 优化加减速曲线参数
-
过热问题
- 添加散热片
- 降低PWM频率(如从20kHz→15kHz)
- 增加死区时间(推荐≥2μs)
-
通信干扰
- 使用屏蔽线缆
- 添加RC滤波电路(100Ω+0.1μF)
- 优化PCB布局(地平面分割)