当前位置: 首页 > news >正文

基于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,工作方式1TH0 = (65536 - 100) / 256;  // 100us中断TL0 = (65536 - 100) % 256;ET0 = 1;            // 允许定时器0中断TR0 = 1;            // 启动定时器0// 定时器1:用于数码管动态扫描TMOD |= 0x10;       // 定时器1,工作方式1TH1 = (65536 - 2000) / 256;  // 2ms中断TL1 = (65536 - 2000) % 256;ET1 = 1;            // 允许定时器1中断TR1 = 1;            // 启动定时器1EA = 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;  // 重装初值,100usTL0 = (65536 - 100) % 256;pwm_counter++;if(pwm_counter >= pwm_period) {pwm_counter = 0;}// 比较计数值和占空比,输出PWMif(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.4if(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-102if(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 * Iadc_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值3950adc_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:1adc_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,  // 00x06,  // 10x5B,  // 20x4F,  // 30x66,  // 40x6D,  // 50x7D,  // 60x07,  // 70x7F,  // 80x6F,  // 90x77,  // A0x7C,  // b0x39,  // C0x5E,  // d0x79,  // E0x71,  // F0x40,  // -0x00   // 空
};// 数码管显示缓冲区
uint8_t display_digit = 0;  // 当前显示位// 定时器1中断服务程序 - 数码管动态扫描
void Timer1_ISR(void) interrupt 3 {TH1 = (65536 - 2000) / 256;  // 重装初值,2msTL1 = (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;  // Fdisplay_buffer[3] = 0x00;  // 空} else if(motor.state == MOTOR_REVERSE) {display_buffer[2] = 0x50;  // rdisplay_buffer[3] = 0x00;  // 空} else {display_buffer[2] = 0x00;  // 空display_buffer[3] = 0x00;  // 空}break;case 2:  // 显示故障代码if(fault_flag) {display_buffer[0] = 0x0F;  // Fdisplay_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工作方式2TH1 = 0xFD;         // 波特率9600TL1 = 0xFD;TR1 = 1;            // 启动定时器1ES = 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. 关键技术

  • PWM调速:通过定时器中断实现精确的PWM控制
  • 软启动/软停止:平滑的速度变化,减少机械冲击
  • 多重保护:过流、过热、过压、欠压保护
  • 人机交互:按键+数码管+LED的状态显示

2. 性能指标

  • 调速范围:10%-100%连续可调
  • 调速精度:1%
  • 响应时间:<100ms
  • 保护响应:<10ms
  • 工作电压:12V-24V DC
  • 最大电流:3A(可扩展)
http://www.jsqmd.com/news/666700/

相关文章:

  • 别再纠结致远、比邻、如翼了!一张图看懂中国电信5G定制网三种模式怎么选
  • 2026 年美发人注意!美发会员管理系统避坑指南在此 - 记络会员管理软件
  • 别再只用Days和Hours了!Java8 ChronoUnit枚举类里这些隐藏的时间单位,让你的代码更专业
  • Android视频压缩的高效方案:基于硬件编解码的MediaCodec实践
  • Ryujinx:在PC上畅玩Switch游戏的终极完整指南
  • Barrier终极指南:一套键鼠控制多台电脑的免费开源解决方案
  • RV1126视频驱动全景解析:从Sensor到ISP的模块化架构与数据流
  • 示波器上那个神秘的‘Escape Mode’是啥?手把手拆解MIPI DSI的低功耗逃生通道
  • 2026 理发店速进!挑收银软件这些坑躲远点别中招 - 记络会员管理软件
  • IDR工具完全指南:从零开始掌握Delphi程序逆向工程
  • 当Windows遇见macOS:用OSX-Hyper-V在虚拟机中打造苹果体验
  • 树莓派4B上Miniconda3保姆级安装教程(含清华源配置与常见SSL报错解决)
  • 手把手教你用UC3843A升压模块点亮IN-12辉光管(附MOS管/二极管替换指南)
  • 别再瞎测了!手把手教你给矢量网络分析仪做一次靠谱的校准(从误差到实操)
  • 抖音无水印批量下载工具:免费高效的视频保存方案
  • 新质谱仪炸场!蛋白代谢天都亮了?
  • Snap Hutao原神工具箱:如何高效管理你的游戏数据体验
  • 2026 年开理发店必避坑!收银系统挑选要点全解析 - 记络会员管理软件
  • 新手避坑指南:用nvm安装Node.js时,90%的人会踩的这几个雷(附解决方案)
  • 智能机器人中的运动规划与任务执行
  • 如何免费生成专业条码:Libre Barcode开源字体完整指南
  • 告别玄学调参:用Cubemx HAL库+MPU6050 DMP,给你的STM32平衡小车一个‘出厂设置’
  • 别再让亚稳态搞崩你的FPGA设计:从异步复位到跨时钟域的实战避坑指南
  • WeMod Patcher终极指南:三步免费解锁Pro高级功能完整教程
  • 2026年重庆变速箱进水维修厂家推荐及选购参考/变速箱阀体修复,变速箱高温维修,变速箱循环换油维修 - 品牌策略师
  • Input Leap:三步实现跨设备键鼠共享的高效方案
  • Physics.Raycast的layerMask进阶玩法:从按位运算到LayerMask.GetMask()的优雅写法
  • Stable Diffusion图片参数全解析:从查看到保护隐私的完整指南(附ExifCleaner使用技巧)
  • 手把手教你用STM32驱动DS1302 RTC模块(附完整代码与避坑指南)
  • FPGA图像处理入门:手把手教你用FIFO实现3x3滑动窗口(附Verilog代码)