CC2530驱动步进电机实现方案

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

 

专注于matlab/simulink,电子电路,编程