CC2530驱动步进电机实现方案
一、硬件设计
1.1 硬件连接
CC2530引脚分配:
P1_0 (GPIO1) -> 步进电机 A相
P1_1 (GPIO2) -> 步进电机 B相
P1_2 (GPIO3) -> 步进电机 C相
P1_3 (GPIO4) -> 步进电机 D相
P1_4 (GPIO5) -> 方向控制 (可选)
P1_5 (GPIO6) -> 使能控制 (可选)
P1_6 (GPIO7) -> 速度控制PWM
1.2 驱动电路
推荐使用ULN2003或L293D驱动芯片:
CC2530 (3.3V) -> ULN2003 -> 步进电机 (5-12V)
+5V-12V
|
CC2530 P1.0 -- IN1 -- OUT1 -- 电机A相
CC2530 P1.1 -- IN2 -- OUT2 -- 电机B相
CC2530 P1.2 -- IN3 -- OUT3 -- 电机C相
CC2530 P1.3 -- IN4 -- OUT4 -- 电机D相
|
GND
二、完整驱动程序
2.1 头文件定义
// stepper_motor.h
#ifndef __STEPPER_MOTOR_H
#define __STEPPER_MOTOR_H
#include "ioCC2530.h"
#include <stdint.h>
#include <stdbool.h>
// 步进电机类型
typedef enum {
STEPPER_28BYJ_48 = 0, // 28BYJ-48 5V 4相5线
STEPPER_NEMA_17 = 1, // NEMA17 2相4线
STEPPER_CUSTOM = 2 // 自定义
} StepperType;
// 工作模式
typedef enum {
MODE_WAVE = 0, // 单4拍 (波驱动)
MODE_FULL = 1, // 双4拍 (全步进)
MODE_HALF = 2, // 8拍 (半步进)
MODE_MICRO = 3 // 微步进
} StepMode;
// 旋转方向
typedef enum {
DIRECTION_CW = 0, // 顺时针
DIRECTION_CCW = 1 // 逆时针
} Direction;
// 速度单位
typedef enum {
SPEED_RPM = 0, // 转/分钟
SPEED_RPS = 1, // 转/秒
SPEED_HZ = 2, // 步进频率(Hz)
SPEED_DELAY = 3 // 步进延迟(us)
} SpeedUnit;
// 电机状态
typedef enum {
STATE_STOPPED = 0,
STATE_RUNNING = 1,
STATE_ACCEL = 2,
STATE_DECEL = 3,
STATE_ERROR = 4
} MotorState;
// 电机参数结构
typedef struct {
StepperType type; // 电机类型
uint16_t steps_per_rev; // 每转步数
uint8_t gear_ratio; // 减速比
uint16_t rated_voltage; // 额定电压(mV)
uint16_t rated_current; // 额定电流(mA)
uint8_t phase_count; // 相数
} MotorParams;
// 电机配置结构
typedef struct {
uint8_t pin_a; // A相引脚
uint8_t pin_b; // B相引脚
uint8_t pin_c; // C相引脚
uint8_t pin_d; // D相引脚
uint8_t pin_enable; // 使能引脚
uint8_t pin_direction; // 方向引脚
uint8_t pin_step; // 步进脉冲引脚
StepMode mode; // 工作模式
Direction direction; // 方向
uint16_t speed; // 速度值
SpeedUnit speed_unit; // 速度单位
uint16_t acceleration; // 加速度
uint16_t deceleration; // 减速度
} MotorConfig;
// 步进电机控制结构
typedef struct {
MotorParams params; // 电机参数
MotorConfig config; // 配置
MotorState state; // 状态
int32_t position; // 当前位置(步)
int32_t target; // 目标位置(步)
uint32_t speed; // 当前速度(us/步)
uint32_t min_speed; // 最小速度(us/步)
uint32_t max_speed; // 最大速度(us/步)
uint16_t step_index; // 步进索引
uint32_t step_count; // 已走步数
uint32_t last_step_time;// 上次步进时间
uint8_t is_enabled; // 使能状态
} StepperMotor;
// 函数声明
void Stepper_Init(StepperMotor *motor, const MotorParams *params);
void Stepper_Config(StepperMotor *motor, const MotorConfig *config);
void Stepper_Enable(StepperMotor *motor);
void Stepper_Disable(StepperMotor *motor);
void Stepper_SetSpeed(StepperMotor *motor, uint16_t speed, SpeedUnit unit);
void Stepper_SetDirection(StepperMotor *motor, Direction dir);
void Stepper_Rotate(StepperMotor *motor, Direction dir, uint32_t steps);
void Stepper_RotateDegrees(StepperMotor *motor, Direction dir, float degrees);
void Stepper_RotateRevolutions(StepperMotor *motor, Direction dir, float revs);
void Stepper_Stop(StepperMotor *motor);
void Stepper_Brake(StepperMotor *motor);
void Stepper_SetPosition(StepperMotor *motor, int32_t position);
int32_t Stepper_GetPosition(StepperMotor *motor);
void Stepper_Goto(StepperMotor *motor, int32_t target);
void Stepper_GotoDegrees(StepperMotor *motor, float degrees);
void Stepper_Update(StepperMotor *motor);
void Stepper_SetAcceleration(StepperMotor *motor, uint16_t accel, uint16_t decel);
void Stepper_SetLimits(StepperMotor *motor, uint32_t min_speed, uint32_t max_speed);
MotorState Stepper_GetState(StepperMotor *motor);
uint32_t Stepper_GetRemainingSteps(StepperMotor *motor);
float Stepper_GetSpeedRPM(StepperMotor *motor);
void Stepper_Calibrate(StepperMotor *motor);
// 预设电机参数
extern const MotorParams MOTOR_28BYJ_48;
extern const MotorParams MOTOR_NEMA_17;
#endif
2.2 主驱动程序
// stepper_motor.c
#include "stepper_motor.h"
#include <string.h>
// 预设电机参数
const MotorParams MOTOR_28BYJ_48 = {
.type = STEPPER_28BYJ_48,
.steps_per_rev = 32, // 单4拍每转步数
.gear_ratio = 64, // 减速比
.rated_voltage = 5000, // 5V
.rated_current = 100, // 100mA
.phase_count = 4
};
const MotorParams MOTOR_NEMA_17 = {
.type = STEPPER_NEMA_17,
.steps_per_rev = 200, // 标准1.8度步距角
.gear_ratio = 1, // 无减速
.rated_voltage = 12000, // 12V
.rated_current = 400, // 400mA
.phase_count = 2
};
// 步进序列定义
// 单4拍 (波驱动): A-B-C-D
static const uint8_t wave_sequence[4] = {
0b0001, // A
0b0010, // B
0b0100, // C
0b1000 // D
};
// 双4拍 (全步进): AB-BC-CD-DA
static const uint8_t full_sequence[4] = {
0b0011, // A+B
0b0110, // B+C
0b1100, // C+D
0b1001 // D+A
};
// 8拍 (半步进): A-AB-B-BC-C-CD-D-DA
static const uint8_t half_sequence[8] = {
0b0001, // A
0b0011, // A+B
0b0010, // B
0b0110, // B+C
0b0100, // C
0b1100, // C+D
0b1000, // D
0b1001 // D+A
};
// 微步进 (16细分) - 简化版
static const uint8_t micro_sequence[16] = {
0b1000, 0b1100, 0b0100, 0b0110,
0b0010, 0b0011, 0b0001, 0b1001,
0b1000, 0b1100, 0b0100, 0b0110,
0b0010, 0b0011, 0b0001, 0b1001
};
// 全局变量
static uint32_t system_tick = 0;
// 初始化步进电机
void Stepper_Init(StepperMotor *motor, const MotorParams *params) {
if (!motor || !params) return;
memset(motor, 0, sizeof(StepperMotor));
// 复制参数
memcpy(&motor->params, params, sizeof(MotorParams));
// 计算实际每转步数
motor->params.steps_per_rev *= motor->params.gear_ratio;
// 默认配置
motor->config.mode = MODE_FULL;
motor->config.direction = DIRECTION_CW;
motor->config.speed = 100; // 默认100 RPM
motor->config.speed_unit = SPEED_RPM;
motor->config.acceleration = 100; // 100步/秒²
motor->config.deceleration = 100;
// 状态初始化
motor->state = STATE_STOPPED;
motor->position = 0;
motor->target = 0;
motor->step_index = 0;
motor->step_count = 0;
motor->last_step_time = 0;
motor->is_enabled = 0;
// 速度限制
motor->min_speed = 2000; // 2ms/步 = 0.5步/秒
motor->max_speed = 500; // 500us/步 = 2000步/秒
// 初始化GPIO
GPIO_Init();
printf("Stepper motor initialized. Steps per rev: %d\n",
motor->params.steps_per_rev);
}
// 配置电机
void Stepper_Config(StepperMotor *motor, const MotorConfig *config) {
if (!motor || !config) return;
memcpy(&motor->config, config, sizeof(MotorConfig));
// 配置GPIO引脚
if (motor->config.pin_a) {
P1SEL &= ~(1 << motor->config.pin_a);
P1DIR |= (1 << motor->config.pin_a);
}
if (motor->config.pin_b) {
P1SEL &= ~(1 << motor->config.pin_b);
P1DIR |= (1 << motor->config.pin_b);
}
if (motor->config.pin_c) {
P1SEL &= ~(1 << motor->config.pin_c);
P1DIR |= (1 << motor->config.pin_c);
}
if (motor->config.pin_d) {
P1SEL &= ~(1 << motor->config.pin_d);
P1DIR |= (1 << motor->config.pin_d);
}
if (motor->config.pin_enable) {
P1SEL &= ~(1 << motor->config.pin_enable);
P1DIR |= (1 << motor->config.pin_enable);
}
if (motor->config.pin_direction) {
P1SEL &= ~(1 << motor->config.pin_direction);
P1DIR |= (1 << motor->config.pin_direction);
}
if (motor->config.pin_step) {
P1SEL &= ~(1 << motor->config.pin_step);
P1DIR |= (1 << motor->config.pin_step);
}
// 设置速度
Stepper_SetSpeed(motor, motor->config.speed, motor->config.speed_unit);
printf("Stepper motor configured.\n");
}
// 使能电机
void Stepper_Enable(StepperMotor *motor) {
if (!motor || motor->is_enabled) return;
if (motor->config.pin_enable) {
P1 |= (1 << motor->config.pin_enable); // 使能引脚高电平有效
}
motor->is_enabled = 1;
printf("Motor enabled.\n");
}
// 禁用电机
void Stepper_Disable(StepperMotor *motor) {
if (!motor || !motor->is_enabled) return;
// 关闭所有相
if (motor->config.pin_a) P1 &= ~(1 << motor->config.pin_a);
if (motor->config.pin_b) P1 &= ~(1 << motor->config.pin_b);
if (motor->config.pin_c) P1 &= ~(1 << motor->config.pin_c);
if (motor->config.pin_d) P1 &= ~(1 << motor->config.pin_d);
if (motor->config.pin_enable) {
P1 &= ~(1 << motor->config.pin_enable); // 禁用
}
motor->is_enabled = 0;
motor->state = STATE_STOPPED;
printf("Motor disabled.\n");
}
// 设置速度
void Stepper_SetSpeed(StepperMotor *motor, uint16_t speed, SpeedUnit unit) {
if (!motor) return;
motor->config.speed = speed;
motor->config.speed_unit = unit;
// 转换为us/步
uint32_t step_delay_us = 0;
switch (unit) {
case SPEED_RPM: {
// RPM转us/步
float steps_per_sec = (speed * motor->params.steps_per_rev) / 60.0f;
if (steps_per_sec > 0) {
step_delay_us = (uint32_t)(1000000.0f / steps_per_sec);
}
break;
}
case SPEED_RPS: {
// RPS转us/步
float steps_per_sec = speed * motor->params.steps_per_rev;
if (steps_per_sec > 0) {
step_delay_us = (uint32_t)(1000000.0f / steps_per_sec);
}
break;
}
case SPEED_HZ: {
// Hz转us/步
if (speed > 0) {
step_delay_us = 1000000 / speed;
}
break;
}
case SPEED_DELAY: {
// 直接使用延迟
step_delay_us = speed;
break;
}
}
// 应用速度限制
if (step_delay_us < motor->min_speed) {
step_delay_us = motor->min_speed;
} else if (step_delay_us > motor->max_speed) {
step_delay_us = motor->max_speed;
}
motor->speed = step_delay_us;
printf("Speed set: %u us/step (%.2f RPM)\n",
motor->speed, Stepper_GetSpeedRPM(motor));
}
// 设置方向
void Stepper_SetDirection(StepperMotor *motor, Direction dir) {
if (!motor) return;
motor->config.direction = dir;
if (motor->config.pin_direction) {
if (dir == DIRECTION_CW) {
P1 &= ~(1 << motor->config.pin_direction);
} else {
P1 |= (1 << motor->config.pin_direction);
}
}
}
// 单步运行
static void Stepper_Step(StepperMotor *motor) {
if (!motor || !motor->is_enabled) return;
// 获取步进序列
const uint8_t *sequence = NULL;
uint8_t seq_length = 0;
switch (motor->config.mode) {
case MODE_WAVE:
sequence = wave_sequence;
seq_length = 4;
break;
case MODE_FULL:
sequence = full_sequence;
seq_length = 4;
break;
case MODE_HALF:
sequence = half_sequence;
seq_length = 8;
break;
case MODE_MICRO:
sequence = micro_sequence;
seq_length = 16;
break;
}
if (!sequence) return;
// 更新步进索引
if (motor->config.direction == DIRECTION_CW) {
motor->step_index++;
if (motor->step_index >= seq_length) {
motor->step_index = 0;
}
} else {
if (motor->step_index == 0) {
motor->step_index = seq_length - 1;
} else {
motor->step_index--;
}
}
// 获取当前步进值
uint8_t step_value = sequence[motor->step_index];
// 输出到GPIO
if (motor->config.pin_a) {
if (step_value & 0x01) {
P1 |= (1 << motor->config.pin_a);
} else {
P1 &= ~(1 << motor->config.pin_a);
}
}
if (motor->config.pin_b) {
if (step_value & 0x02) {
P1 |= (1 << motor->config.pin_b);
} else {
P1 &= ~(1 << motor->config.pin_b);
}
}
if (motor->config.pin_c) {
if (step_value & 0x04) {
P1 |= (1 << motor->config.pin_c);
} else {
P1 &= ~(1 << motor->config.pin_c);
}
}
if (motor->config.pin_d) {
if (step_value & 0x08) {
P1 |= (1 << motor->config.pin_d);
} else {
P1 &= ~(1 << motor->config.pin_d);
}
}
// 更新位置
if (motor->config.direction == DIRECTION_CW) {
motor->position++;
} else {
motor->position--;
}
motor->step_count++;
motor->last_step_time = system_tick;
}
// 旋转指定步数
void Stepper_Rotate(StepperMotor *motor, Direction dir, uint32_t steps) {
if (!motor || steps == 0) return;
Stepper_Enable(motor);
Stepper_SetDirection(motor, dir);
motor->target = motor->position + (dir == DIRECTION_CW ? steps : -steps);
motor->state = STATE_RUNNING;
printf("Rotating %u steps %s\n", steps,
dir == DIRECTION_CW ? "CW" : "CCW");
}
// 旋转指定角度
void Stepper_RotateDegrees(StepperMotor *motor, Direction dir, float degrees) {
if (!motor || degrees == 0) return;
// 计算步数
float steps = (degrees / 360.0f) * motor->params.steps_per_rev;
uint32_t step_count = (uint32_t)steps;
Stepper_Rotate(motor, dir, step_count);
}
// 旋转指定圈数
void Stepper_RotateRevolutions(StepperMotor *motor, Direction dir, float revs) {
if (!motor || revs == 0) return;
uint32_t steps = (uint32_t)(revs * motor->params.steps_per_rev);
Stepper_Rotate(motor, dir, steps);
}
// 停止电机
void Stepper_Stop(StepperMotor *motor) {
if (!motor) return;
motor->state = STATE_STOPPED;
motor->target = motor->position; // 清除目标
printf("Motor stopped at position: %ld\n", motor->position);
}
// 急停
void Stepper_Brake(StepperMotor *motor) {
if (!motor) return;
// 立即停止,保持当前位置
motor->state = STATE_STOPPED;
motor->target = motor->position;
// 保持当前相序,提供保持扭矩
// 不关闭相电流
printf("Motor braked at position: %ld\n", motor->position);
}
// 设置绝对位置
void Stepper_SetPosition(StepperMotor *motor, int32_t position) {
if (!motor) return;
motor->position = position;
printf("Position set to: %ld\n", position);
}
// 获取当前位置
int32_t Stepper_GetPosition(StepperMotor *motor) {
return motor ? motor->position : 0;
}
// 移动到绝对位置
void Stepper_Goto(StepperMotor *motor, int32_t target) {
if (!motor) return;
int32_t delta = target - motor->position;
if (delta == 0) return;
Direction dir = (delta > 0) ? DIRECTION_CW : DIRECTION_CCW;
uint32_t steps = (uint32_t)abs(delta);
Stepper_Enable(motor);
motor->target = target;
motor->state = STATE_RUNNING;
printf("Goto position: %ld (delta: %ld)\n", target, delta);
}
// 移动到绝对角度
void Stepper_GotoDegrees(StepperMotor *motor, float degrees) {
if (!motor) return;
// 计算目标步数
int32_t target_steps = (int32_t)((degrees / 360.0f) * motor->params.steps_per_rev);
Stepper_Goto(motor, target_steps);
}
// 设置加速度
void Stepper_SetAcceleration(StepperMotor *motor, uint16_t accel, uint16_t decel) {
if (!motor) return;
motor->config.acceleration = accel;
motor->config.deceleration = decel;
printf("Acceleration: %u steps/s², Deceleration: %u steps/s²\n",
accel, decel);
}
// 设置速度限制
void Stepper_SetLimits(StepperMotor *motor, uint32_t min_speed, uint32_t max_speed) {
if (!motor) return;
motor->min_speed = min_speed;
motor->max_speed = max_speed;
// 重新应用速度限制
if (motor->speed < min_speed) {
motor->speed = min_speed;
} else if (motor->speed > max_speed) {
motor->speed = max_speed;
}
printf("Speed limits: min=%uus, max=%uus\n", min_speed, max_speed);
}
// 获取状态
MotorState Stepper_GetState(StepperMotor *motor) {
return motor ? motor->state : STATE_ERROR;
}
// 获取剩余步数
uint32_t Stepper_GetRemainingSteps(StepperMotor *motor) {
if (!motor) return 0;
int32_t remaining = motor->target - motor->position;
return (remaining > 0) ? remaining : -remaining;
}
// 获取当前转速(RPM)
float Stepper_GetSpeedRPM(StepperMotor *motor) {
if (!motor || motor->speed == 0) return 0;
float steps_per_sec = 1000000.0f / motor->speed;
float rpm = (steps_per_sec * 60.0f) / motor->params.steps_per_rev;
return rpm;
}
// 更新函数 (在主循环中调用)
void Stepper_Update(StepperMotor *motor) {
if (!motor || !motor->is_enabled) return;
// 检查是否到达目标
if (motor->position == motor->target) {
if (motor->state == STATE_RUNNING) {
motor->state = STATE_STOPPED;
printf("Target reached. Position: %ld\n", motor->position);
}
return;
}
// 检查是否需要执行下一步
uint32_t current_time = system_tick;
uint32_t elapsed = current_time - motor->last_step_time;
if (elapsed >= motor->speed) {
// 执行步进
Stepper_Step(motor);
// 简单的加减速控制
if (motor->state == STATE_ACCEL) {
// 加速
if (motor->speed > motor->min_speed + 100) {
motor->speed -= 10; // 增加速度
} else {
motor->state = STATE_RUNNING;
}
} else if (motor->state == STATE_DECEL) {
// 减速
uint32_t remaining = Stepper_GetRemainingSteps(motor);
if (remaining < 50 && motor->speed < motor->max_speed) {
motor->speed += 20; // 减慢速度
}
}
}
}
// 校准函数
void Stepper_Calibrate(StepperMotor *motor) {
if (!motor) return;
printf("Starting calibration...\n");
// 找到零点
Stepper_Enable(motor);
Stepper_SetDirection(motor, DIRECTION_CW);
// 旋转到已知位置
for (int i = 0; i < 100; i++) {
Stepper_Step(motor);
Delay_us(2000); // 慢速旋转
}
// 设置零点
Stepper_SetPosition(motor, 0);
printf("Calibration complete. Position reset to 0.\n");
}
2.3 GPIO和延时函数
// cc2530_utils.c
#include "stepper_motor.h"
// 系统时钟初始化
void SystemClock_Init(void) {
// 使用32MHz外部晶振
SLEEPCMD &= ~0x04; // 开启晶振
while(!(SLEEPSTA & 0x40)); // 等待晶振稳定
CLKCONCMD = 0x80; // 选择32MHz外部晶振
while(CLKCONSTA != 0x80); // 等待切换完成
}
// 初始化GPIO
void GPIO_Init(void) {
// 配置P1口为普通IO
P1SEL = 0x00; // 所有引脚为GPIO
P1DIR = 0xFF; // 所有引脚为输出
P1 = 0x00; // 初始低电平
}
// 微秒延时
void Delay_us(uint16_t us) {
// 32MHz下,每个循环约0.0625us
// 需要调整根据实际时钟频率
while(us--) {
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
}
}
// 毫秒延时
void Delay_ms(uint16_t ms) {
while(ms--) {
Delay_us(1000);
}
}
// 定时器1初始化 (用于系统时钟)
void Timer1_Init(void) {
// 配置Timer1为16位定时器,用于系统时钟
T1CTL = 0x0E; // 128分频,自由运行模式
T1CCTL0 = 0x00; // 通道0比较模式
T1CC0H = 0x00; // 比较值高位
T1CC0L = 0xFF; // 比较值低位
// 启用中断
T1CCTL0 |= 0x20; // 启用比较中断
IEN1 |= 0x02; // 启用Timer1中断
EA = 1; // 启用全局中断
}
// Timer1中断服务程序
#pragma vector = T1_VECTOR
__interrupt void Timer1_ISR(void) {
system_tick++; // 系统时钟递增
T1STAT &= ~0x01; // 清除中断标志
}
三、高级控制功能
3.1 加减速控制
// acceleration.c
#include "stepper_motor.h"
// 梯形加减速控制
typedef struct {
uint32_t acceleration; // 加速度 (steps/s²)
uint32_t deceleration; // 减速度 (steps/s²)
uint32_t max_speed; // 最大速度 (steps/s)
uint32_t min_speed; // 最小速度 (steps/s)
uint32_t current_speed; // 当前速度 (steps/s)
uint32_t target_speed; // 目标速度 (steps/s)
uint32_t distance; // 总距离 (steps)
uint32_t position; // 当前位置 (steps)
uint32_t accelerate_steps; // 加速段步数
uint32_t decelerate_steps; // 减速段步数
uint32_t cruise_steps; // 匀速段步数
uint8_t state; // 状态: 0=加速, 1=匀速, 2=减速
} TrapezoidalProfile;
// 初始化梯形加减速
void Trapezoidal_Init(TrapezoidalProfile *profile,
uint32_t accel, uint32_t decel,
uint32_t max_speed, uint32_t min_speed) {
profile->acceleration = accel;
profile->deceleration = decel;
profile->max_speed = max_speed;
profile->min_speed = min_speed;
profile->current_speed = min_speed;
profile->state = 0;
}
// 计算梯形加减速参数
uint8_t Trapezoidal_Calculate(TrapezoidalProfile *profile, uint32_t distance) {
if (distance == 0) return 0;
profile->distance = distance;
profile->position = 0;
// 计算能达到的最大速度
uint32_t max_reachable_speed = profile->min_speed;
// 加速距离
uint32_t accel_distance = (profile->max_speed * profile->max_speed -
profile->min_speed * profile->min_speed) /
(2 * profile->acceleration);
// 减速距离
uint32_t decel_distance = (profile->max_speed * profile->max_speed -
profile->min_speed * profile->min_speed) /
(2 * profile->deceleration);
// 检查是否能达到最大速度
if (distance >= (accel_distance + decel_distance)) {
// 梯形加减速
profile->accelerate_steps = accel_distance;
profile->decelerate_steps = decel_distance;
profile->cruise_steps = distance - accel_distance - decel_distance;
profile->target_speed = profile->max_speed;
} else {
// 三角形加减速
// 计算能达到的最大速度
float v_max_sq = (2 * profile->acceleration * profile->deceleration * distance) /
(profile->acceleration + profile->deceleration) +
profile->min_speed * profile->min_speed;
uint32_t v_max = (uint32_t)sqrt(v_max_sq);
if (v_max > profile->max_speed) {
v_max = profile->max_speed;
}
profile->accelerate_steps = (v_max * v_max -
profile->min_speed * profile->min_speed) /
(2 * profile->acceleration);
profile->decelerate_steps = (v_max * v_max -
profile->min_speed * profile->min_speed) /
(2 * profile->deceleration);
profile->cruise_steps = 0;
profile->target_speed = v_max;
}
return 1;
}
// 获取下一步延迟
uint32_t Trapezoidal_GetNextDelay(TrapezoidalProfile *profile) {
uint32_t delay_us = 0;
// 计算当前速度对应的延迟
if (profile->current_speed > 0) {
delay_us = 1000000 / profile->current_speed; // 转换为us/步
}
// 更新速度和位置
profile->position++;
// 判断当前阶段
if (profile->position < profile->accelerate_steps) {
// 加速阶段
profile->state = 0;
profile->current_speed = profile->min_speed +
(profile->acceleration * profile->position) / 1000;
if (profile->current_speed > profile->target_speed) {
profile->current_speed = profile->target_speed;
}
} else if (profile->position < (profile->accelerate_steps + profile->cruise_steps)) {
// 匀速阶段
profile->state = 1;
profile->current_speed = profile->target_speed;
} else if (profile->position < profile->distance) {
// 减速阶段
profile->state = 2;
uint32_t decel_pos = profile->position -
(profile->accelerate_steps + profile->cruise_steps);
profile->current_speed = profile->target_speed -
(profile->deceleration * decel_pos) / 1000;
if (profile->current_speed < profile->min_speed) {
profile->current_speed = profile->min_speed;
}
} else {
// 完成
profile->current_speed = profile->min_speed;
}
return delay_us;
}
// 集成到步进电机控制
void Stepper_MoveWithProfile(StepperMotor *motor,
TrapezoidalProfile *profile,
uint32_t steps,
Direction dir) {
if (!motor || !profile || steps == 0) return;
// 计算梯形加减速参数
if (!Trapezoidal_Calculate(profile, steps)) {
return;
}
// 设置方向和启用
Stepper_Enable(motor);
Stepper_SetDirection(motor, dir);
motor->target = motor->position + (dir == DIRECTION_CW ? steps : -steps);
motor->state = STATE_RUNNING;
printf("Moving with trapezoidal profile: %u steps\n", steps);
// 主循环中调用
while (motor->state == STATE_RUNNING) {
if (profile->position < profile->distance) {
// 获取下一个延迟
uint32_t delay_us = Trapezoidal_GetNextDelay(profile);
// 执行步进
Stepper_Step(motor);
// 应用延迟
Delay_us(delay_us);
// 更新电机位置
if (dir == DIRECTION_CW) {
motor->position++;
} else {
motor->position--;
}
// 检查是否到达目标
if (motor->position == motor->target) {
motor->state = STATE_STOPPED;
printf("Move complete.\n");
}
} else {
motor->state = STATE_STOPPED;
}
}
}
3.2 PWM速度控制
// pwm_speed_control.c
#include "stepper_motor.h"
// PWM控制结构
typedef struct {
uint8_t pwm_pin; // PWM引脚
uint16_t frequency; // PWM频率(Hz)
uint8_t duty_cycle; // 占空比(0-100%)
uint8_t is_running; // 运行状态
} PWM_Controller;
// 初始化PWM
void PWM_Init(PWM_Controller *pwm, uint8_t pin, uint16_t freq) {
pwm->pwm_pin = pin;
pwm->frequency = freq;
pwm->duty_cycle = 0;
pwm->is_running = 0;
// 配置引脚
P1SEL &= ~(1 << pin); // GPIO功能
P1DIR |= (1 << pin); // 输出模式
P1 &= ~(1 << pin); // 初始低电平
// 配置Timer3为PWM模式
// CC2530 Timer3支持PWM输出
PERCFG |= 0x20; // 选择Timer3备用位置2
P1SEL |= (1 << pin); // 外设功能
T3CTL = 0x00; // 停止定时器
T3CCTL0 = 0x1C; // 比较模式,输出模式
T3CTL |= 0x04; // 启动定时器
}
// 设置PWM频率
void PWM_SetFrequency(PWM_Controller *pwm, uint16_t freq) {
pwm->frequency = freq;
// 计算比较值
// 公式: T = 1/f = (T3CC0 + 1) * (1/32MHz)
uint32_t compare_value = 32000000UL / freq;
if (compare_value > 0xFFFF) compare_value = 0xFFFF;
T3CC0 = (uint16_t)(compare_value - 1);
}
// 设置占空比
void PWM_SetDutyCycle(PWM_Controller *pwm, uint8_t duty) {
if (duty > 100) duty = 100;
pwm->duty_cycle = duty;
// 计算比较值
uint16_t compare_value = (T3CC0 + 1) * duty / 100;
T3CC1 = compare_value; // 通道1用于占空比控制
}
// 启动PWM
void PWM_Start(PWM_Controller *pwm) {
pwm->is_running = 1;
T3CTL |= 0x04; // 启动定时器
}
// 停止PWM
void PWM_Stop(PWM_Controller *pwm) {
pwm->is_running = 0;
T3CTL &= ~0x04; // 停止定时器
P1 &= ~(1 << pwm->pwm_pin); // 输出低电平
}
// 步进电机速度PWM控制
void Stepper_SetSpeedPWM(StepperMotor *motor, PWM_Controller *pwm, uint8_t speed_percent) {
if (!motor || !pwm) return;
// 限制速度范围
if (speed_percent > 100) speed_percent = 100;
// 根据百分比计算实际速度
uint32_t min_delay = motor->max_speed; // 最快速度对应最小延迟
uint32_t max_delay = motor->min_speed; // 最慢速度对应最大延迟
uint32_t delay_us = max_delay - (max_delay - min_delay) * speed_percent / 100;
motor->speed = delay_us;
// 设置PWM占空比 (用于视觉反馈或其他控制)
PWM_SetDutyCycle(pwm, speed_percent);
printf("Speed set to %u%% (delay: %uus)\n", speed_percent, delay_us);
}
参考代码 CC2530驱动步进电机可以实现正反转及速度 www.youwenfan.com/contentcnv/103352.html
四、应用示例
4.1 主程序示例
// main.c
#include "stepper_motor.h"
#include <stdio.h>
// 全局变量
StepperMotor motor;
PWM_Controller pwm;
TrapezoidalProfile profile;
// 系统初始化
void System_Init(void) {
// 初始化系统时钟
SystemClock_Init();
// 初始化定时器
Timer1_Init();
// 初始化GPIO
GPIO_Init();
// 初始化串口 (用于调试输出)
UART_Init(115200);
printf("System initialized.\n");
}
// 测试函数1: 基本控制
void Test_BasicControl(void) {
printf("\n=== Test 1: Basic Control ===\n");
// 初始化电机
Stepper_Init(&motor, &MOTOR_28BYJ_48);
// 配置引脚
MotorConfig config = {
.pin_a = 0, // P1.0
.pin_b = 1, // P1.1
.pin_c = 2, // P1.2
.pin_d = 3, // P1.3
.pin_enable = 4, // P1.4
.mode = MODE_FULL,
.direction = DIRECTION_CW,
.speed = 10, // 10 RPM
.speed_unit = SPEED_RPM
};
Stepper_Config(&motor, &config);
// 使能电机
Stepper_Enable(&motor);
// 测试正转
printf("Rotating clockwise 1 revolution...\n");
Stepper_RotateRevolutions(&motor, DIRECTION_CW, 1.0);
while (Stepper_GetState(&motor) == STATE_RUNNING) {
Stepper_Update(&motor);
Delay_ms(1);
}
Delay_ms(1000);
// 测试反转
printf("Rotating counter-clockwise 1 revolution...\n");
Stepper_RotateRevolutions(&motor, DIRECTION_CCW, 1.0);
while (Stepper_GetState(&motor) == STATE_RUNNING) {
Stepper_Update(&motor);
Delay_ms(1);
}
// 禁用电机
Stepper_Disable(&motor);
printf("Test 1 completed.\n");
}
// 测试函数2: 速度控制
void Test_SpeedControl(void) {
printf("\n=== Test 2: Speed Control ===\n");
Stepper_Enable(&motor);
// 测试不同速度
uint8_t speeds[] = {5, 10, 20, 30, 50};
uint8_t num_speeds = sizeof(speeds) / sizeof(speeds[0]);
for (uint8_t i = 0; i < num_speeds; i++) {
printf("Testing speed: %u RPM\n", speeds[i]);
// 设置速度
Stepper_SetSpeed(&motor, speeds[i], SPEED_RPM);
// 旋转半圈
Stepper_RotateDegrees(&motor, DIRECTION_CW, 180);
while (Stepper_GetState(&motor) == STATE_RUNNING) {
Stepper_Update(&motor);
Delay_ms(1);
}
Delay_ms(500);
}
Stepper_Disable(&motor);
printf("Test 2 completed.\n");
}
// 测试函数3: 位置控制
void Test_PositionControl(void) {
printf("\n=== Test 3: Position Control ===\n");
Stepper_Enable(&motor);
Stepper_SetPosition(&motor, 0); // 重置位置
// 设置速度为20 RPM
Stepper_SetSpeed(&motor, 20, SPEED_RPM);
// 移动到不同角度
float angles[] = {0, 90, 180, 270, 360, 180, 90, 0};
uint8_t num_angles = sizeof(angles) / sizeof(angles[0]);
for (uint8_t i = 0; i < num_angles; i++) {
printf("Moving to angle: %.0f degrees\n", angles[i]);
Stepper_GotoDegrees(&motor, angles[i]);
while (Stepper_GetState(&motor) == STATE_RUNNING) {
Stepper_Update(&motor);
Delay_ms(1);
// 显示当前位置
static uint32_t last_display = 0;
if (system_tick - last_display > 100) {
float current_angle = (Stepper_GetPosition(&motor) * 360.0f) /
motor.params.steps_per_rev;
printf(" Current angle: %.1f\n", current_angle);
last_display = system_tick;
}
}
Delay_ms(1000);
}
Stepper_Disable(&motor);
printf("Test 3 completed.\n");
}
// 测试函数4: 加减速控制
void Test_AccelerationControl(void) {
printf("\n=== Test 4: Acceleration Control ===\n");
Stepper_Enable(&motor);
// 初始化梯形加减速
Trapezoidal_Init(&profile, 1000, 1000, 2000, 100);
// 设置加减速参数
Stepper_SetAcceleration(&motor, 500, 500);
Stepper_SetLimits(&motor, 1000, 5000); // 1ms-5ms延迟
printf("Moving with acceleration...\n");
// 使用加减速移动
Stepper_MoveWithProfile(&motor, &profile, 1000, DIRECTION_CW);
Delay_ms(2000);
printf("Moving back...\n");
Stepper_MoveWithProfile(&motor, &profile, 1000, DIRECTION_CCW);
Stepper_Disable(&motor);
printf("Test 4 completed.\n");
}
// 测试函数5: PWM速度控制
void Test_PWMControl(void) {
printf("\n=== Test 5: PWM Speed Control ===\n");
// 初始化PWM
PWM_Init(&pwm, 6, 1000); // P1.6, 1kHz
Stepper_Enable(&motor);
// 测试不同PWM占空比
for (uint8_t duty = 10; duty <= 100; duty += 10) {
printf("PWM Duty: %u%%\n", duty);
// 设置速度
Stepper_SetSpeedPWM(&motor, &pwm, duty);
// 启动PWM
if (duty > 0) {
PWM_Start(&pwm);
} else {
PWM_Stop(&pwm);
}
// 旋转
Stepper_RotateDegrees(&motor, DIRECTION_CW, 90);
while (Stepper_GetState(&motor) == STATE_RUNNING) {
Stepper_Update(&motor);
Delay_ms(1);
}
Delay_ms(500);
}
PWM_Stop(&pwm);
Stepper_Disable(&motor);
printf("Test 5 completed.\n");
}
// 主函数
int main(void) {
// 系统初始化
System_Init();
printf("CC2530 Stepper Motor Controller\n");
printf("===============================\n");
// 运行所有测试
Test_BasicControl();
Delay_ms(2000);
Test_SpeedControl();
Delay_ms(2000);
Test_PositionControl();
Delay_ms(2000);
Test_AccelerationControl();
Delay_ms(2000);
Test_PWMControl();
printf("\nAll tests completed!\n");
while (1) {
// 主循环
// 可以添加其他功能,如串口命令控制
HandleUART_Commands();
Delay_ms(10);
}
return 0;
}
4.2 串口命令控制
// uart_control.c
#include "stepper_motor.h"
// 串口命令处理
void HandleUART_Commands(void) {
if (UART_Available()) {
char cmd = UART_Read();
switch (cmd) {
case 'e': // 使能
Stepper_Enable(&motor);
printf("Motor enabled\n");
break;
case 'd': // 禁用
Stepper_Disable(&motor);
printf("Motor disabled\n");
break;
case 'f': // 前进
Stepper_SetDirection(&motor, DIRECTION_CW);
Stepper_Rotate(&motor, DIRECTION_CW, 100);
printf("Forward 100 steps\n");
break;
case 'b': // 后退
Stepper_SetDirection(&motor, DIRECTION_CCW);
Stepper_Rotate(&motor, DIRECTION_CCW, 100);
printf("Backward 100 steps\n");
break;
case 's': // 停止
Stepper_Stop(&motor);
printf("Stopped\n");
break;
case '1': // 低速
Stepper_SetSpeed(&motor, 5, SPEED_RPM);
printf("Speed: 5 RPM\n");
break;
case '2': // 中速
Stepper_SetSpeed(&motor, 20, SPEED_RPM);
printf("Speed: 20 RPM\n");
break;
case '3': // 高速
Stepper_SetSpeed(&motor, 50, SPEED_RPM);
printf("Speed: 50 RPM\n");
break;
case 'p': // 位置查询
printf("Position: %ld steps\n", Stepper_GetPosition(&motor));
break;
case 'r': // 复位位置
Stepper_SetPosition(&motor, 0);
printf("Position reset to 0\n");
break;
case 'h': // 帮助
printf("Commands:\n");
printf(" e - Enable motor\n");
printf(" d - Disable motor\n");
printf(" f - Forward 100 steps\n");
printf(" b - Backward 100 steps\n");
printf(" s - Stop\n");
printf(" 1 - Low speed (5 RPM)\n");
printf(" 2 - Medium speed (20 RPM)\n");
printf(" 3 - High speed (50 RPM)\n");
printf(" p - Get position\n");
printf(" r - Reset position\n");
printf(" h - Help\n");
break;
default:
printf("Unknown command: %c\n", cmd);
break;
}
}
}
五、调试和优化
5.1 调试工具
// debug_tools.c
#include "stepper_motor.h"
// 性能监控
typedef struct {
uint32_t step_count;
uint32_t error_count;
uint32_t start_time;
uint32_t total_time;
float avg_speed;
uint32_t max_delay;
uint32_t min_delay;
} PerformanceMonitor;
// 调试信息打印
void Debug_PrintInfo(StepperMotor *motor) {
static uint32_t last_print = 0;
if (system_tick - last_print > 1000) { // 每秒打印一次
printf("\n--- Motor Status ---\n");
printf("State: %s\n",
motor->state == STATE_STOPPED ? "Stopped" :
motor->state == STATE_RUNNING ? "Running" :
motor->state == STATE_ACCEL ? "Accelerating" :
motor->state == STATE_DECEL ? "Decelerating" : "Error");
printf("Position: %ld steps\n", motor->position);
printf("Target: %ld steps\n", motor->target);
printf("Speed: %.2f RPM\n", Stepper_GetSpeedRPM(motor));
printf("Step delay: %u us\n", motor->speed);
printf("Enabled: %s\n", motor->is_enabled ? "Yes" : "No");
printf("Mode: %s\n",
motor->config.mode == MODE_WAVE ? "Wave" :
motor->config.mode == MODE_FULL ? "Full" :
motor->config.mode == MODE_HALF ? "Half" : "Micro");
printf("Direction: %s\n",
motor->config.direction == DIRECTION_CW ? "CW" : "CCW");
printf("-------------------\n");
last_print = system_tick;
}
}
// 错误检测
void Debug_CheckErrors(StepperMotor *motor) {
static uint32_t last_position = 0;
static uint32_t stall_counter = 0;
// 检查是否堵转
if (motor->state == STATE_RUNNING) {
if (motor->position == last_position) {
stall_counter++;
if (stall_counter > 100) { // 连续100次没动
printf("ERROR: Motor stall detected!\n");
Stepper_Stop(motor);
Stepper_Disable(motor);
}
} else {
stall_counter = 0;
}
} else {
stall_counter = 0;
}
last_position = motor->position;
}
5.2 电源管理
// power_management.c
#include "stepper_motor.h"
// 低功耗模式
void Enter_SleepMode(void) {
// 当电机停止时进入睡眠模式
PCON |= 0x01; // 进入空闲模式
// 等待中断唤醒
__asm__("NOP");
}
// 电流限制
void Current_Limit(StepperMotor *motor) {
// 根据温度限制电流
static uint8_t overheat_count = 0;
// 模拟温度检测
uint8_t temperature = Read_Temperature();
if (temperature > 50) {
overheat_count++;
if (overheat_count > 10) {
// 过热保护
printf("WARNING: Overheat detected! Reducing current.\n");
// 降低占空比或进入节能模式
if (motor->is_enabled) {
// 切换到节能模式
motor->config.mode = MODE_WAVE; // 单4拍更省电
printf("Switched to power saving mode.\n");
}
}
} else {
overheat_count = 0;
}
}
六、项目配置
6.1 IAR工程配置
Project Options:
- Device: CC2530F256
- Code model: Near
- Data model: Large
- Calling convention: IDATA reentrant
- Optimization: High for speed
Linker:
- Config file: lnk51ew_cc2530.xcl
- Code bank: BANK0
- Stack size: 0x100
- Heap size: 0x100
6.2 编译选项
# Makefile
CC = sdcc
CFLAGS = -mmcs51 --model-large --stack-auto --xram-size 8192
LDFLAGS = -mmcs51 --model-large --xram-size 8192 --code-size 0x8000
TARGET = stepper_motor
SRCS = main.c stepper_motor.c cc2530_utils.c \
acceleration.c pwm_speed_control.c \
uart_control.c debug_tools.c
all: $(TARGET).hex
$(TARGET).hex: $(TARGET).ihx
packihx $(TARGET).ihx > $(TARGET).hex
$(TARGET).ihx: $(SRCS:.c=.rel)
$(CC) $(LDFLAGS) -o $(TARGET).ihx $^
%.rel: %.c
$(CC) $(CFLAGS) -c $<
clean:
rm -f *.asm *.lst *.rel *.sym *.rst *.map *.mem *.ihx *.hex