基于51单片机的直流电机驱动系统设计
系统总体设计
系统功能要求
- 基本控制:正转、反转、停止、调速
- 速度调节:PWM脉宽调制,多档位速度控制
- 保护功能:过流保护、过热保护
- 显示功能:速度显示、状态指示
- 人机交互:按键控制、旋钮调速
系统组成框图
┌─────────────────────────────────────────────┐
│ 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. 系统上电
- 连接12V/24V直流电源
- 系统进行自检,LED指示灯依次点亮
- 数码管显示系统版本号或测试信息
- 自检完成后进入待机状态
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(可扩展)