基于51单片机的直流电机驱动系统设计

基于51单片机的直流电机驱动系统设计

系统总体设计

系统功能要求

  1. 基本控制:正转、反转、停止、调速
  2. 速度调节:PWM脉宽调制,多档位速度控制
  3. 保护功能:过流保护、过热保护
  4. 显示功能:速度显示、状态指示
  5. 人机交互:按键控制、旋钮调速

系统组成框图

┌─────────────────────────────────────────────┐
│           51单片机控制系统                  │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐    │
│  │ 主控芯片 │  │ 定时器  │  │ 中断系统│    │
│  │ STC89C52│  │   PWM   │  │         │    │
│  └─────────┘  └─────────┘  └─────────┘    │
│         │            │             │       │
└─────────┼────────────┼─────────────┼───────┘
          │            │             │
    ┌─────▼────┐ ┌─────▼────┐ ┌─────▼────┐
    │ 驱动电路 │ │ 按键输入 │ │ 显示模块 │
    │ L298N/H桥│ │ 矩阵键盘 │ │ 数码管   │
    └─────┬────┘ └──────────┘ └─────┬────┘
          │                         │
    ┌─────▼────┐              ┌─────▼────┐
    │ 直流电机 │              │ 状态指示 │
    │ 12V/24V  │              │ LED      │
    └──────────┘              └──────────┘

硬件电路设计

1. 主控电路设计

// 51单片机最小系统
// STC89C52RC引脚分配
#include <reg52.h>

// 系统时钟:11.0592MHz
#define FOSC 11059200L
#define T1MS (65536 - FOSC/12/1000)  // 1ms定时器初值

// 引脚定义
sbit MOTOR_IN1 = P1^0;  // 电机方向控制1
sbit MOTOR_IN2 = P1^1;  // 电机方向控制2
sbit MOTOR_ENA = P1^2;  // 电机使能/PWM输出

sbit KEY_START = P3^0;  // 启动/停止按键
sbit KEY_FORWARD = P3^1; // 正转按键
sbit KEY_REVERSE = P3^2; // 反转按键
sbit KEY_SPEED_UP = P3^3; // 加速按键
sbit KEY_SPEED_DOWN = P3^4; // 减速按键

sbit LED_RUN = P2^0;    // 运行指示灯
sbit LED_DIR = P2^1;    // 方向指示灯
sbit LED_FAULT = P2^2;  // 故障指示灯

sbit SEG_A = P0^0;      // 数码管段选A
sbit SEG_B = P0^1;      // 数码管段选B
sbit SEG_C = P0^2;      // 数码管段选C
sbit SEG_D = P0^3;      // 数码管段选D
sbit SEG_E = P0^4;      // 数码管段选E
sbit SEG_F = P0^5;      // 数码管段选F
sbit SEG_G = P0^6;      // 数码管段选G
sbit SEG_DP = P0^7;     // 数码管小数点

sbit DIGIT1 = P2^3;     // 数码管位选1
sbit DIGIT2 = P2^4;     // 数码管位选2
sbit DIGIT3 = P2^5;     // 数码管位选3
sbit DIGIT4 = P2^6;     // 数码管位选4

// ADC引脚(如果使用电位器调速)
sbit ADC_CS = P1^3;     // ADC片选
sbit ADC_CLK = P1^4;    // ADC时钟
sbit ADC_DIN = P1^5;    // ADC数据输入
sbit ADC_DOUT = P1^6;   // ADC数据输出

// 电流检测引脚
sbit CURRENT_SENSE = P1^7; // 电流检测输入

2. 电机驱动电路设计

/*
L298N电机驱动模块连接:
IN1 -> P1.0 (MOTOR_IN1)
IN2 -> P1.1 (MOTOR_IN2)
ENA -> P1.2 (MOTOR_ENA, PWM输出)
VCC -> 5V (逻辑电源)
VS  -> 12V/24V (电机电源)
OUT1 -> 电机正极
OUT2 -> 电机负极
GND -> 共地

电机控制真值表:
IN1  IN2  ENA  电机状态
 0    0    X    停止(自由停止)
 1    0    1    正转
 0    1    1    反转
 1    1    X    停止(刹车)
*/

// 电机状态定义
typedef enum {
    MOTOR_STOP = 0,     // 停止
    MOTOR_FORWARD = 1,  // 正转
    MOTOR_REVERSE = 2,  // 反转
    MOTOR_BRAKE = 3     // 刹车
} MotorState;

// 电机控制结构体
typedef struct {
    MotorState state;    // 当前状态
    uint8_t speed;       // 当前速度(0-100%)
    uint8_t max_speed;   // 最大速度限制
    uint8_t min_speed;   // 最小速度限制
    uint8_t acceleration; // 加速度
    uint8_t deceleration; // 减速度
} MotorControl;

3. 电源电路设计

/*
电源设计:
1. 主电源:12V/24V直流输入
2. 降压电路:
   - LM7805:5V稳压,为单片机供电
   - LM7812:12V稳压,为L298N逻辑部分供电
3. 滤波电路:
   - 输入电容:1000uF/35V电解电容
   - 输出电容:100uF/16V电解电容
   - 去耦电容:0.1uF陶瓷电容
4. 保护电路:
   - 保险丝:2A快熔保险
   - 防反接二极管:1N4007
   - TVS管:过压保护
*/

// 电源状态检测
sbit POWER_GOOD = P3^5;  // 电源正常检测
sbit OVER_CURRENT = P3^6; // 过流检测
sbit OVER_TEMP = P3^7;   // 过热检测

4. 保护电路设计

/*
保护电路设计:
1. 过流保护:
   - 使用ACS712电流传感器
   - 检测范围:0-5A
   - 输出:0-5V模拟信号
   
2. 过热保护:
   - 使用NTC热敏电阻
   - 检测电机温度
   - 超过阈值自动降速或停止
   
3. 欠压保护:
   - 检测电源电压
   - 低于阈值报警或停止
*/

// 保护参数
#define CURRENT_LIMIT 3000  // 电流限制3A
#define TEMP_LIMIT 80      // 温度限制80°C
#define VOLTAGE_MIN 10     // 最低电压10V
#define VOLTAGE_MAX 30     // 最高电压30V

软件程序设计

1. 主程序框架

#include <reg52.h>
#include <intrins.h>

// 全局变量定义
MotorControl motor = {0};  // 电机控制结构体
uint8_t display_buffer[4] = {0}; // 显示缓冲区
uint8_t key_value = 0;     // 按键值
uint16_t adc_value = 0;    // ADC值
uint8_t fault_flag = 0;    // 故障标志

// 函数声明
void System_Init(void);
void Timer_Init(void);
void Motor_Control(MotorState state, uint8_t speed);
void PWM_SetDuty(uint8_t duty);
void Key_Scan(void);
void Display_Update(void);
void ADC_Read(void);
void Protection_Check(void);
void Delay_ms(uint16_t ms);

// 主函数
void main(void) {
    System_Init();      // 系统初始化
    Timer_Init();       // 定时器初始化
    
    // 电机初始状态
    motor.state = MOTOR_STOP;
    motor.speed = 0;
    motor.max_speed = 100;
    motor.min_speed = 10;
    motor.acceleration = 5;
    motor.deceleration = 5;
    
    while(1) {
        Key_Scan();             // 按键扫描
        ADC_Read();             // ADC读取(电位器调速)
        Protection_Check();     // 保护检测
        Display_Update();       // 显示更新
        
        // 根据按键和ADC值更新电机状态
        Motor_Update();
        
        Delay_ms(10);           // 延时10ms
    }
}

// 系统初始化
void System_Init(void) {
    // 初始化IO口
    P0 = 0xFF;  // 数码管段选初始化为高电平
    P1 = 0xFF;  // 电机控制引脚初始化为高电平
    P2 = 0x00;  // 位选和LED初始化为低电平
    P3 = 0xFF;  // 按键引脚设置为输入
    
    // 初始化电机为停止状态
    MOTOR_IN1 = 0;
    MOTOR_IN2 = 0;
    MOTOR_ENA = 0;
    
    // 初始化指示灯
    LED_RUN = 0;
    LED_DIR = 0;
    LED_FAULT = 0;
    
    // 初始化数码管
    DIGIT1 = 0;
    DIGIT2 = 0;
    DIGIT3 = 0;
    DIGIT4 = 0;
}

// 定时器初始化
void Timer_Init(void) {
    // 定时器0:用于PWM生成
    TMOD |= 0x01;       // 定时器0,工作方式1
    TH0 = (65536 - 100) / 256;  // 100us中断
    TL0 = (65536 - 100) % 256;
    ET0 = 1;            // 允许定时器0中断
    TR0 = 1;            // 启动定时器0
    
    // 定时器1:用于数码管动态扫描
    TMOD |= 0x10;       // 定时器1,工作方式1
    TH1 = (65536 - 2000) / 256;  // 2ms中断
    TL1 = (65536 - 2000) % 256;
    ET1 = 1;            // 允许定时器1中断
    TR1 = 1;            // 启动定时器1
    
    EA = 1;             // 开启总中断
}

2. PWM脉宽调制实现

// PWM相关变量
uint8_t pwm_duty = 0;      // PWM占空比(0-100)
uint8_t pwm_counter = 0;   // PWM计数器
uint8_t pwm_period = 100;  // PWM周期(100个计数单位)

// 定时器0中断服务程序 - PWM生成
void Timer0_ISR(void) interrupt 1 {
    TH0 = (65536 - 100) / 256;  // 重装初值,100us
    TL0 = (65536 - 100) % 256;
    
    pwm_counter++;
    if(pwm_counter >= pwm_period) {
        pwm_counter = 0;
    }
    
    // 比较计数值和占空比,输出PWM
    if(pwm_counter < pwm_duty) {
        MOTOR_ENA = 1;  // 高电平
    } else {
        MOTOR_ENA = 0;  // 低电平
    }
}

// 设置PWM占空比
void PWM_SetDuty(uint8_t duty) {
    if(duty > 100) duty = 100;  // 限制在0-100%
    pwm_duty = duty;
}

// 设置PWM频率
void PWM_SetFrequency(uint16_t freq_hz) {
    uint16_t period;
    
    // 计算定时器重装值
    // 定时器时钟 = FOSC/12 = 921.6kHz
    // 每个计数周期 = 1/921.6k ≈ 1.085us
    // 需要的计数值 = 1/(freq_hz * pwm_period * 1.085us)
    
    period = 921600 / (freq_hz * pwm_period);
    if(period > 65535) period = 65535;
    
    // 更新定时器初值
    TH0 = (65536 - period) / 256;
    TL0 = (65536 - period) % 256;
}

// 电机控制函数
void Motor_Control(MotorState state, uint8_t speed) {
    // 检查故障标志
    if(fault_flag) {
        // 有故障,强制停止
        MOTOR_IN1 = 0;
        MOTOR_IN2 = 0;
        MOTOR_ENA = 0;
        motor.state = MOTOR_STOP;
        motor.speed = 0;
        return;
    }
    
    // 更新电机状态
    motor.state = state;
    
    // 限制速度范围
    if(speed > motor.max_speed) speed = motor.max_speed;
    if(speed < motor.min_speed && speed > 0) speed = motor.min_speed;
    
    // 设置PWM占空比
    PWM_SetDuty(speed);
    motor.speed = speed;
    
    // 根据状态设置方向引脚
    switch(state) {
        case MOTOR_STOP:
            MOTOR_IN1 = 0;
            MOTOR_IN2 = 0;
            LED_RUN = 0;
            LED_DIR = 0;
            break;
            
        case MOTOR_FORWARD:
            MOTOR_IN1 = 1;
            MOTOR_IN2 = 0;
            LED_RUN = 1;
            LED_DIR = 1;  // 正转指示灯
            break;
            
        case MOTOR_REVERSE:
            MOTOR_IN1 = 0;
            MOTOR_IN2 = 1;
            LED_RUN = 1;
            LED_DIR = 0;  // 反转指示灯
            break;
            
        case MOTOR_BRAKE:
            MOTOR_IN1 = 1;
            MOTOR_IN2 = 1;
            LED_RUN = 0;
            LED_DIR = 0;
            break;
    }
}

// 电机平滑加速
void Motor_Accelerate(uint8_t target_speed) {
    uint8_t current_speed = motor.speed;
    
    if(target_speed > current_speed) {
        // 加速过程
        while(current_speed < target_speed) {
            current_speed += motor.acceleration;
            if(current_speed > target_speed) {
                current_speed = target_speed;
            }
            PWM_SetDuty(current_speed);
            Delay_ms(50);  // 每50ms加速一次
        }
    } else if(target_speed < current_speed) {
        // 减速过程
        while(current_speed > target_speed) {
            current_speed -= motor.deceleration;
            if(current_speed < target_speed) {
                current_speed = target_speed;
            }
            PWM_SetDuty(current_speed);
            Delay_ms(50);  // 每50ms减速一次
        }
    }
    
    motor.speed = current_speed;
}

3. 按键扫描与处理

// 按键相关变量
uint8_t key_pressed = 0;      // 按键按下标志
uint8_t key_repeat = 0;       // 按键重复计数
uint8_t key_hold_time = 0;    // 按键保持时间

// 按键扫描函数
void Key_Scan(void) {
    static uint8_t key_last = 0xFF;  // 上次按键状态
    uint8_t key_current;
    
    // 读取按键状态
    key_current = P3 & 0x1F;  // 只读取P3.0-P3.4
    
    if(key_current != 0x1F) {
        // 有按键按下
        Delay_ms(10);  // 消抖
        
        key_current = P3 & 0x1F;
        if(key_current != 0x1F) {
            // 确认按键按下
            if(key_current != key_last) {
                // 新按键按下
                key_last = key_current;
                key_pressed = 1;
                key_hold_time = 0;
                key_repeat = 0;
            } else {
                // 按键保持
                key_hold_time++;
                if(key_hold_time > 30) {  // 保持300ms后开始重复
                    key_hold_time = 25;   // 重置保持时间
                    key_repeat++;
                    if(key_repeat > 3) {  // 快速重复
                        key_pressed = 1;
                    }
                }
            }
        }
    } else {
        // 无按键按下
        key_last = 0xFF;
        key_pressed = 0;
        key_hold_time = 0;
        key_repeat = 0;
    }
    
    // 处理按键事件
    if(key_pressed) {
        key_pressed = 0;
        
        if(KEY_START == 0) {
            // 启动/停止按键
            if(motor.state == MOTOR_STOP) {
                // 如果当前停止,启动电机
                Motor_Control(MOTOR_FORWARD, motor.speed);
            } else {
                // 如果当前运行,停止电机
                Motor_Control(MOTOR_STOP, 0);
            }
        }
        else if(KEY_FORWARD == 0) {
            // 正转按键
            Motor_Control(MOTOR_FORWARD, motor.speed);
        }
        else if(KEY_REVERSE == 0) {
            // 反转按键
            Motor_Control(MOTOR_REVERSE, motor.speed);
        }
        else if(KEY_SPEED_UP == 0) {
            // 加速按键
            if(motor.speed < 100) {
                motor.speed += 10;
                if(motor.speed > 100) motor.speed = 100;
                Motor_Accelerate(motor.speed);
            }
        }
        else if(KEY_SPEED_DOWN == 0) {
            // 减速按键
            if(motor.speed > 10) {
                motor.speed -= 10;
                if(motor.speed < 10) motor.speed = 10;
                Motor_Accelerate(motor.speed);
            }
        }
    }
}

// 电机状态更新函数
void Motor_Update(void) {
    static uint8_t last_speed = 0;
    
    // 检查是否需要更新速度
    if(adc_value != last_speed) {
        // 电位器调速
        uint8_t new_speed = adc_value / 10;  // 将0-1023映射到0-102
        if(new_speed > 100) new_speed = 100;
        
        if(new_speed != motor.speed) {
            Motor_Accelerate(new_speed);
            last_speed = new_speed;
        }
    }
}

4. ADC读取(电位器调速)

// ADC相关函数(使用外部ADC芯片,如ADC0804)
void ADC_Init(void) {
    ADC_CS = 1;     // 片选无效
    ADC_CLK = 0;    // 时钟低电平
}

// 读取ADC值
uint16_t ADC_ReadValue(void) {
    uint8_t i;
    uint16_t value = 0;
    
    ADC_CS = 0;     // 片选有效
    Delay_ms(1);    // 等待稳定
    
    // 启动转换
    ADC_CLK = 1;
    Delay_ms(1);
    ADC_CLK = 0;
    
    // 等待转换完成
    while(ADC_DOUT == 1);  // 等待低电平
    
    // 读取12位数据
    for(i = 0; i < 12; i++) {
        ADC_CLK = 1;
        Delay_ms(1);
        value <<= 1;
        value |= ADC_DOUT;
        ADC_CLK = 0;
        Delay_ms(1);
    }
    
    ADC_CS = 1;     // 片选无效
    return value;
}

// 定期读取ADC
void ADC_Read(void) {
    static uint16_t adc_buffer[8] = {0};
    static uint8_t adc_index = 0;
    uint32_t sum = 0;
    uint8_t i;
    
    // 读取ADC值
    adc_buffer[adc_index] = ADC_ReadValue();
    adc_index = (adc_index + 1) % 8;
    
    // 计算平均值滤波
    for(i = 0; i < 8; i++) {
        sum += adc_buffer[i];
    }
    
    adc_value = sum >> 3;  // 除以8
}

5. 保护检测功能

// 电流检测
uint16_t Current_Read(void) {
    uint16_t adc_value;
    float voltage;
    float current;
    
    // 读取电流检测ADC
    // 假设使用ACS712-05A,灵敏度185mV/A
    // 输出:VCC/2 + 0.185 * I
    
    adc_value = ADC_ReadValue();
    voltage = (adc_value * 5.0) / 4096.0;  // 假设5V参考,12位ADC
    
    // 计算电流
    current = (voltage - 2.5) / 0.185;  // 2.5V是零电流输出
    
    if(current < 0) current = -current;  // 取绝对值
    
    return (uint16_t)(current * 1000);  // 返回mA值
}

// 温度检测
uint8_t Temperature_Read(void) {
    uint16_t adc_value;
    float resistance;
    float temperature;
    
    // 读取NTC热敏电阻ADC
    // 使用10K NTC,B值3950
    adc_value = ADC_ReadValue();
    
    // 计算电阻(分压电路)
    resistance = 10000.0 * (4095.0 / adc_value - 1.0);
    
    // 计算温度(Steinhart-Hart方程)
    temperature = 1.0 / (1.0/298.15 + 1.0/3950.0 * log(resistance/10000.0));
    temperature = temperature - 273.15;  // 转换为摄氏度
    
    return (uint8_t)temperature;
}

// 电压检测
uint16_t Voltage_Read(void) {
    uint16_t adc_value;
    float voltage;
    
    // 读取电源电压ADC
    // 使用电阻分压,假设分压比10:1
    adc_value = ADC_ReadValue();
    voltage = (adc_value * 5.0) / 4096.0 * 11.0;  // 5V参考,11倍分压
    
    return (uint16_t)(voltage * 100);  // 返回0.01V单位
}

// 保护检测函数
void Protection_Check(void) {
    static uint8_t fault_count = 0;
    uint16_t current = Current_Read();
    uint8_t temperature = Temperature_Read();
    uint16_t voltage = Voltage_Read();
    
    // 检查过流
    if(current > CURRENT_LIMIT) {
        fault_flag |= 0x01;  // 设置过流标志
        LED_FAULT = 1;
        fault_count++;
    } else {
        fault_flag &= ~0x01;  // 清除过流标志
    }
    
    // 检查过热
    if(temperature > TEMP_LIMIT) {
        fault_flag |= 0x02;  // 设置过热标志
        LED_FAULT = 1;
        fault_count++;
    } else {
        fault_flag &= ~0x02;  // 清除过热标志
    }
    
    // 检查欠压/过压
    if(voltage < VOLTAGE_MIN * 100 || voltage > VOLTAGE_MAX * 100) {
        fault_flag |= 0x04;  // 设置电压异常标志
        LED_FAULT = 1;
        fault_count++;
    } else {
        fault_flag &= ~0x04;  // 清除电压异常标志
    }
    
    // 如果连续多次检测到故障,停止电机
    if(fault_count > 5) {
        Motor_Control(MOTOR_STOP, 0);
        fault_count = 0;
    }
    
    // 如果没有故障,清除故障指示灯
    if(fault_flag == 0) {
        LED_FAULT = 0;
        fault_count = 0;
    }
}

// 故障处理函数
void Fault_Handler(uint8_t fault_code) {
    // 停止电机
    Motor_Control(MOTOR_STOP, 0);
    
    // 显示故障代码
    display_buffer[0] = 0x0F;  // 显示"F"
    display_buffer[1] = fault_code / 10;
    display_buffer[2] = fault_code % 10;
    display_buffer[3] = 0x00;
    
    // 故障指示灯闪烁
    while(fault_flag) {
        LED_FAULT = ~LED_FAULT;
        Delay_ms(500);
    }
}

6. 数码管显示

// 数码管段码表(共阴极)
const uint8_t seg_code[] = {
    0x3F,  // 0
    0x06,  // 1
    0x5B,  // 2
    0x4F,  // 3
    0x66,  // 4
    0x6D,  // 5
    0x7D,  // 6
    0x07,  // 7
    0x7F,  // 8
    0x6F,  // 9
    0x77,  // A
    0x7C,  // b
    0x39,  // C
    0x5E,  // d
    0x79,  // E
    0x71,  // F
    0x40,  // -
    0x00   // 空
};

// 数码管显示缓冲区
uint8_t display_digit = 0;  // 当前显示位

// 定时器1中断服务程序 - 数码管动态扫描
void Timer1_ISR(void) interrupt 3 {
    TH1 = (65536 - 2000) / 256;  // 重装初值,2ms
    TL1 = (65536 - 2000) % 256;
    
    // 关闭所有位选
    DIGIT1 = 0;
    DIGIT2 = 0;
    DIGIT3 = 0;
    DIGIT4 = 0;
    
    // 根据当前显示位输出段码
    switch(display_digit) {
        case 0:
            P0 = seg_code[display_buffer[0]];
            DIGIT1 = 1;
            break;
        case 1:
            P0 = seg_code[display_buffer[1]];
            DIGIT2 = 1;
            break;
        case 2:
            P0 = seg_code[display_buffer[2]];
            DIGIT3 = 1;
            break;
        case 3:
            P0 = seg_code[display_buffer[3]];
            DIGIT4 = 1;
            break;
    }
    
    // 更新显示位
    display_digit = (display_digit + 1) & 0x03;
}

// 显示更新函数
void Display_Update(void) {
    static uint8_t display_mode = 0;
    static uint8_t blink_counter = 0;
    
    blink_counter++;
    if(blink_counter > 50) {  // 500ms闪烁
        blink_counter = 0;
    }
    
    // 根据显示模式更新显示缓冲区
    switch(display_mode) {
        case 0:  // 显示速度
            display_buffer[0] = 0x00;  // 空
            display_buffer[1] = motor.speed / 100;
            display_buffer[2] = (motor.speed % 100) / 10;
            display_buffer[3] = motor.speed % 10;
            break;
            
        case 1:  // 显示方向
            display_buffer[0] = 0x00;  // 空
            display_buffer[1] = 0x00;  // 空
            if(motor.state == MOTOR_FORWARD) {
                display_buffer[2] = 0x0F;  // F
                display_buffer[3] = 0x00;  // 空
            } else if(motor.state == MOTOR_REVERSE) {
                display_buffer[2] = 0x50;  // r
                display_buffer[3] = 0x00;  // 空
            } else {
                display_buffer[2] = 0x00;  // 空
                display_buffer[3] = 0x00;  // 空
            }
            break;
            
        case 2:  // 显示故障代码
            if(fault_flag) {
                display_buffer[0] = 0x0F;  // F
                display_buffer[1] = 0x00;  // 空
                display_buffer[2] = fault_flag / 10;
                display_buffer[3] = fault_flag % 10;
            }
            break;
    }
    
    // 每3秒切换显示模式
    static uint16_t mode_timer = 0;
    mode_timer++;
    if(mode_timer > 300) {  // 3秒
        mode_timer = 0;
        display_mode = (display_mode + 1) % 3;
    }
    
    // 运行状态闪烁
    if(motor.state != MOTOR_STOP) {
        if(blink_counter < 25) {
            display_buffer[0] = 0x00;  // 空
        } else {
            display_buffer[0] = 0x40;  // -
        }
    }
}

7. 延时函数

// 微秒级延时
void Delay_us(uint16_t us) {
    while(us--) {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    }
}

// 毫秒级延时
void Delay_ms(uint16_t ms) {
    uint16_t i, j;
    for(i = 0; i < ms; i++) {
        for(j = 0; j < 114; j++) {
            _nop_();
        }
    }
}

参考代码 51单片机的直流电机驱动系统设计以及Proteus仿 www.youwenfan.com/contentcnt/183160.html

系统测试与调试

1. 测试程序

// 系统测试函数
void System_Test(void) {
    uint8_t i;
    
    // 1. LED测试
    LED_RUN = 1;
    LED_DIR = 1;
    LED_FAULT = 1;
    Delay_ms(1000);
    LED_RUN = 0;
    LED_DIR = 0;
    LED_FAULT = 0;
    Delay_ms(1000);
    
    // 2. 数码管测试
    for(i = 0; i < 10; i++) {
        display_buffer[0] = i;
        display_buffer[1] = i;
        display_buffer[2] = i;
        display_buffer[3] = i;
        Delay_ms(500);
    }
    
    // 3. 电机测试
    // 正转测试
    Motor_Control(MOTOR_FORWARD, 30);
    Delay_ms(2000);
    
    // 加速测试
    for(i = 30; i <= 80; i += 10) {
        Motor_Accelerate(i);
        Delay_ms(1000);
    }
    
    // 减速测试
    for(i = 80; i >= 30; i -= 10) {
        Motor_Accelerate(i);
        Delay_ms(1000);
    }
    
    // 反转测试
    Motor_Control(MOTOR_REVERSE, 50);
    Delay_ms(2000);
    
    // 停止测试
    Motor_Control(MOTOR_STOP, 0);
    Delay_ms(1000);
    
    // 4. 按键测试
    display_buffer[0] = 0x0B;  // 显示"H"
    display_buffer[1] = 0x0E;  // 显示"E"
    display_buffer[2] = 0x0C;  // 显示"L"
    display_buffer[3] = 0x0C;  // 显示"L"
    Delay_ms(2000);
    
    // 5. ADC测试
    adc_value = ADC_ReadValue();
    display_buffer[0] = adc_value / 1000;
    display_buffer[1] = (adc_value % 1000) / 100;
    display_buffer[2] = (adc_value % 100) / 10;
    display_buffer[3] = adc_value % 10;
    Delay_ms(2000);
    
    // 测试完成,显示"PASS"
    display_buffer[0] = 0x73;  // 显示"P"
    display_buffer[1] = 0x77;  // 显示"A"
    display_buffer[2] = 0x6D;  // 显示"S"
    display_buffer[3] = 0x6D;  // 显示"S"
}

2. 调试技巧

// 串口调试函数(如果使用串口)
void UART_Init(void) {
    SCON = 0x50;        // 8位数据,可变波特率
    TMOD |= 0x20;       // 定时器1工作方式2
    TH1 = 0xFD;         // 波特率9600
    TL1 = 0xFD;
    TR1 = 1;            // 启动定时器1
    ES = 1;             // 允许串口中断
    EA = 1;             // 开启总中断
}

// 串口发送一个字符
void UART_SendChar(char c) {
    SBUF = c;
    while(TI == 0);
    TI = 0;
}

// 串口发送字符串
void UART_SendString(char *str) {
    while(*str != '\0') {
        UART_SendChar(*str);
        str++;
    }
}

// 串口发送数字
void UART_SendNumber(uint16_t num) {
    char buffer[6];
    sprintf(buffer, "%d", num);
    UART_SendString(buffer);
}

// 调试信息输出
void Debug_Info(void) {
    UART_SendString("Motor State: ");
    switch(motor.state) {
        case MOTOR_STOP: UART_SendString("STOP"); break;
        case MOTOR_FORWARD: UART_SendString("FORWARD"); break;
        case MOTOR_REVERSE: UART_SendString("REVERSE"); break;
        case MOTOR_BRAKE: UART_SendString("BRAKE"); break;
    }
    UART_SendString("\r\n");
    
    UART_SendString("Speed: ");
    UART_SendNumber(motor.speed);
    UART_SendString("%\r\n");
    
    UART_SendString("Current: ");
    UART_SendNumber(Current_Read());
    UART_SendString("mA\r\n");
    
    UART_SendString("Temperature: ");
    UART_SendNumber(Temperature_Read());
    UART_SendString("C\r\n");
    
    UART_SendString("Voltage: ");
    UART_SendNumber(Voltage_Read() / 100);
    UART_SendString(".");
    UART_SendNumber(Voltage_Read() % 100);
    UART_SendString("V\r\n");
    
    UART_SendString("Fault Flag: 0x");
    UART_SendNumber(fault_flag);
    UART_SendString("\r\n\r\n");
}

硬件连接清单

元件 型号/规格 数量 备注
单片机 STC89C52RC 1 主控芯片
晶振 11.0592MHz 1 系统时钟
电容 30pF 2 晶振负载电容
电容 10uF 1 复位电容
电容 0.1uF 10 去耦电容
电阻 10K 1 复位电阻
电阻 1K 8 限流电阻
电阻 220Ω 4 数码管限流
电机驱动 L298N 1 双H桥驱动
直流电机 12V/24V 1 负载电机
数码管 4位共阴 1 显示模块
按键 轻触开关 5 控制按键
LED 5mm 3 状态指示
电位器 10K 1 调速旋钮
ADC芯片 ADC0804 1 模数转换
电流传感器 ACS712-05A 1 电流检测
热敏电阻 NTC 10K 1 温度检测
二极管 1N4007 4 续流二极管
稳压芯片 LM7805 1 5V稳压
稳压芯片 LM7812 1 12V稳压
保险丝 2A 1 过流保护
接线端子 2P/3P 若干 电源/电机连接

使用说明

1. 系统上电

  1. 连接12V/24V直流电源
  2. 系统进行自检,LED指示灯依次点亮
  3. 数码管显示系统版本号或测试信息
  4. 自检完成后进入待机状态

2. 基本操作

3. 故障处理

故障代码 含义 处理方法
F01 过流保护 检查电机负载是否过大
F02 过热保护 等待电机冷却
F03 欠压保护 检查电源电压
F04 过压保护 检查电源电压

4. 参数设置

通过修改代码中的宏定义可以调整系统参数:

// 在config.h中修改以下参数
#define CURRENT_LIMIT 3000    // 电流限制(mA)
#define TEMP_LIMIT 80        // 温度限制(°C)
#define VOLTAGE_MIN 10       // 最低电压(V)
#define VOLTAGE_MAX 30       // 最高电压(V)
#define PWM_FREQ 1000        // PWM频率(Hz)
#define ACCEL_TIME 100       // 加速时间(ms)

设计要点总结

1. 关键技术

2. 性能指标

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