一、系统架构设计
┌─────────────────────────────────────────────────────────────┐
│ BLDC 双闭环控制系统架构 │
├─────────────────────────────────────────────────────────────┤
│ 速度外环 │ 电流内环 │ 功率驱动 │ 电机本体 │
│ │ │ │ │
│ • 速度PID │ • 电流PID │ • 三相逆变 │ • 定子绕组 │
│ • 速度反馈 │ • 电流采样 │ • 栅极驱动 │ • 永磁转子 │
│ • 斜坡给定 │ • 过流保护 │ • 死区插入 │ • 霍尔传感器│
│ • 正反转控 │ • 解耦控制 │ • 故障保护 │ • 反电动势 │
└─────────────────────────────────────────────────────────────┘
二、硬件平台配置
2.1 硬件连接设计
STM32F103 引脚分配:
┌─────────────┬─────────────────────┬──────────────────┐
│ STM32 引脚 │ 功能描述 │ 外部连接 │
├─────────────┼─────────────────────┼──────────────────┤
│ PA8/TIM1_CH1│ PWM_UH (上桥U相) │ DRV8301 INH_A │
│ PA9/TIM1_CH2│ PWM_VH (上桥V相) │ DRV8301 INH_B │
│ PA10/TIM1_CH3│ PWM_WH (上桥W相) │ DRV8301 INH_C │
│ PB13/TIM1_CH1N│ PWM_UL (下桥U相) │ DRV8301 INL_A │
│ PB14/TIM1_CH2N│ PWM_VL (下桥V相) │ DRV8301 INL_B │
│ PB15/TIM1_CH3N│ PWM_WL (下桥W相) │ DRV8301 INL_C │
│ PA0/ADC_IN0 │ 相电流采样 U │ 电流采样电阻 │
│ PA1/ADC_IN1 │ 相电流采样 V │ 电流采样电阻 │
│ PA2/ADC_IN2 │ 母线电压采样 │ 分压电阻网络 │
│ PB6/TIM4_CH1│ 编码器 A 相 │ 编码器信号 │
│ PB7/TIM4_CH2│ 编码器 B 相 │ 编码器信号 │
│ PC6/TIM3_CH1│ 霍尔传感器 U │ BLDC 霍尔输出 │
│ PC7/TIM3_CH2│ 霍尔传感器 V │ BLDC 霍尔输出 │
│ PC8/TIM3_CH3│ 霍尔传感器 W │ BLDC 霍尔输出 │
│ PB0 │ 电机使能 EN │ DRV8301 EN_GATE │
│ PB1 │ 故障保护 nFAULT │ DRV8301 nFAULT │
│ PB10 │ 方向控制 DIR │ 外部输入 │
│ PB11 │ 刹车控制 BRAKE │ 外部输入 │
└─────────────┴─────────────────────┴──────────────────┘
2.2 功率驱动电路
推荐使用 DRV8301/DRV8323 三相栅极驱动器:
• 工作电压:8-60V
• 驱动电流:1.7A 峰值
• 集成电流采样放大器
• 支持 3 种 PWM 模式
• 过流、过温、欠压保护
三、源码实现
3.1 系统头文件 (bldc_control.h)
c
#ifndef __BLDC_CONTROL_H
#define __BLDC_CONTROL_H
#include "stm32f10x.h"
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
// 系统参数定义
#define PWM_FREQUENCY 20000 // PWM频率 20kHz
#define DEAD_TIME_NS 500 // 死区时间 500ns
#define CONTROL_PERIOD_MS 1 // 控制周期 1ms
#define MAX_SPEED_RPM 3000 // 最大转速 3000 RPM
#define MAX_CURRENT_A 10.0f // 最大电流 10A
#define POLE_PAIRS 4 // 电机极对数
// 控制模式枚举
typedef enum {
CONTROL_MODE_STOP = 0,
CONTROL_MODE_SPEED,
CONTROL_MODE_CURRENT,
CONTROL_MODE_TORQUE,
CONTROL_MODE_POSITION
} ControlMode_t;
// 电机状态枚举
typedef enum {
MOTOR_STATE_IDLE = 0,
MOTOR_STATE_ALIGN,
MOTOR_STATE_RUNNING,
MOTOR_STATE_FAULT,
MOTOR_STATE_BRAKE
} MotorState_t;
// PID 控制器结构体
typedef struct {
float kp; // 比例系数
float ki; // 积分系数
float kd; // 微分系数
float integral; // 积分累加
float prev_error; // 上次误差
float output_limit; // 输出限制
float integral_limit; // 积分限制
bool enable; // 使能标志
} PID_Controller_t;
// 电机参数结构体
typedef struct {
float rs; // 定子电阻 (Ω)
float ls; // 定子电感 (H)
float ke; // 反电动势常数 (V/(rad/s))
float kt; // 转矩常数 (Nm/A)
uint8_t pole_pairs; // 极对数
float max_speed; // 最大转速 (RPM)
float max_current; // 最大电流 (A)
float max_voltage; // 最大电压 (V)
} MotorParams_t;
// 电机状态结构体
typedef struct {
float speed_rpm; // 转速 (RPM)
float speed_rad_s; // 角速度 (rad/s)
float current_a; // A相电流 (A)
float current_b; // B相电流 (A)
float current_c; // C相电流 (A)
float voltage_bus; // 母线电压 (V)
float temperature; // 温度 (°C)
float torque; // 输出转矩 (Nm)
uint32_t position; // 位置计数
MotorState_t state; // 电机状态
ControlMode_t mode; // 控制模式
} MotorStatus_t;
// 控制命令结构体
typedef struct {
float target_speed; // 目标转速 (RPM)
float target_current; // 目标电流 (A)
float target_torque; // 目标转矩 (Nm)
float ramp_rate; // 斜坡速率 (RPM/s)
bool direction; // 方向 (0:正转, 1:反转)
bool brake; // 刹车标志
bool enable; // 使能标志
} ControlCommand_t;
// 双闭环控制结构体
typedef struct {
PID_Controller_t speed_pid; // 速度环 PID
PID_Controller_t current_pid; // 电流环 PID
MotorParams_t motor_params; // 电机参数
MotorStatus_t motor_status; // 电机状态
ControlCommand_t command; // 控制命令
float current_setpoint; // 电流设定值
float speed_setpoint; // 速度设定值
float duty_cycle[3]; // PWM占空比 [U, V, W]
uint8_t commutation_sector; // 换相扇区
uint32_t last_commutation_time; // 上次换相时间
} DualLoopController_t;
// 函数声明
void BLDC_Init(void);
void BLDC_ControlLoop(void);
void BLDC_SetSpeed(float speed_rpm);
void BLDC_SetCurrent(float current_a);
void BLDC_Start(void);
void BLDC_Stop(void);
void BLDC_Brake(bool enable);
void BLDC_ChangeDirection(bool reverse);
void BLDC_UpdateMotorStatus(void);
void BLDC_SafetyCheck(void);
void BLDC_Commutation(void);
void BLDC_CurrentControl(void);
void BLDC_SpeedControl(void);
#endif /* __BLDC_CONTROL_H */
3.2 PWM 与定时器配置 (pwm_driver.c)
c
/**
* @file pwm_driver.c
* @brief STM32 BLDC PWM 驱动
*/
#include "bldc_control.h"
#include "tim.h"
static DualLoopController_t bldc_controller;
// PWM 初始化
void PWM_Init(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
// 使能 TIM1 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
// 配置 TIM1 时基
TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / PWM_FREQUENCY - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// 配置 PWM 通道 1, 2, 3
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Low;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Low;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
// 配置死区时间
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM_BDTRInitStructure.TIM_DeadTime = (uint8_t)((DEAD_TIME_NS * SystemCoreClock) / 1000000000);
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
// 使能预装载寄存器
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
// 使能 TIM1 主输出
TIM_CtrlPWMOutputs(TIM1, ENABLE);
// 启动定时器
TIM_Cmd(TIM1, ENABLE);
}
// 设置 PWM 占空比
void PWM_SetDutyCycle(uint8_t phase, float duty_cycle) {
uint16_t period = TIM1->ARR;
uint16_t pulse = (uint16_t)(period * duty_cycle / 100.0f);
switch(phase) {
case 0: // U相
TIM_SetCompare1(TIM1, pulse);
break;
case 1: // V相
TIM_SetCompare2(TIM1, pulse);
break;
case 2: // W相
TIM_SetCompare3(TIM1, pulse);
break;
}
}
// 设置三相 PWM
void PWM_SetThreePhase(float duty_u, float duty_v, float duty_w) {
PWM_SetDutyCycle(0, duty_u);
PWM_SetDutyCycle(1, duty_v);
PWM_SetDutyCycle(2, duty_w);
}
// 紧急关断 PWM
void PWM_EmergencyStop(void) {
TIM_CtrlPWMOutputs(TIM1, DISABLE);
TIM_Cmd(TIM1, DISABLE);
}
3.3 编码器接口 (encoder.c)
c
/**
* @file encoder.c
* @brief 增量式编码器接口
*/
#include "bldc_control.h"
// 编码器初始化
void Encoder_Init(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
// 使能 TIM4 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
// 配置 TIM4 时基
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 最大计数值
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
// 配置编码器接口
TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
// 配置输入捕获
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0F; // 滤波
TIM_ICInit(TIM4, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInit(TIM4, &TIM_ICInitStructure);
// 清零计数器
TIM_SetCounter(TIM4, 0);
// 启动定时器
TIM_Cmd(TIM4, ENABLE);
}
// 读取编码器计数
int32_t Encoder_GetCount(void) {
return (int32_t)TIM_GetCounter(TIM4);
}
// 读取转速 (RPM)
float Encoder_GetSpeedRPM(uint32_t time_interval_ms) {
static int32_t last_count = 0;
int32_t current_count = Encoder_GetCount();
int32_t delta_count = current_count - last_count;
// 处理计数器溢出
if (delta_count > 32767) {
delta_count -= 65536;
} else if (delta_count < -32767) {
delta_count += 65536;
}
last_count = current_count;
// 计算转速:RPM = (delta_count * 60000) / (PPR * time_interval_ms)
// 假设编码器每转 1000 个脉冲
const uint16_t PPR = 1000;
float rpm = (float)(delta_count * 60000) / (PPR * time_interval_ms);
return rpm;
}
3.4 电流采样与 ADC (current_sense.c)
c
/**
* @file current_sense.c
* @brief 相电流采样与 ADC 转换
*/
#include "bldc_control.h"
#define ADC_BUFFER_SIZE 16
static uint16_t adc_buffer[ADC_BUFFER_SIZE];
static float current_offset_u = 0;
static float current_offset_v = 0;
// ADC 初始化
void ADC_Init_CurrentSense(void) {
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 配置 ADC 引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置 DMA
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)adc_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = ADC_BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
// 使能 DMA
DMA_Cmd(DMA1_Channel1, ENABLE);
// 配置 ADC
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 3;
ADC_Init(ADC1, &ADC_InitStructure);
// 配置 ADC 通道
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5);
// 使能 ADC DMA
ADC_DMACmd(ADC1, ENABLE);
// 使能 ADC
ADC_Cmd(ADC1, ENABLE);
// 校准 ADC
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
// 启动 ADC 转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
// 电流零点校准
Current_CalibrateOffset();
}
// 电流零点校准
void Current_CalibrateOffset(void) {
uint32_t sum_u = 0, sum_v = 0;
uint16_t i;
// 等待电机停止
Delay_ms(1000);
// 采样 100 次取平均
for (i = 0; i < 100; i++) {
sum_u += adc_buffer[0];
sum_v += adc_buffer[1];
Delay_ms(1);
}
current_offset_u = (float)sum_u / 100.0f;
current_offset_v = (float)sum_v / 100.0f;
}
// 获取相电流
void Current_GetPhaseCurrents(float *current_u, float *current_v) {
uint16_t adc_u, adc_v;
float voltage_u, voltage_v;
// 读取 ADC 值
adc_u = adc_buffer[0];
adc_v = adc_buffer[1];
// 转换为电压
voltage_u = (float)adc_u * 3.3f / 4096.0f;
voltage_v = (float)adc_v * 3.3f / 4096.0f;
// 转换为电流(假设采样电阻 0.01Ω,放大倍数 20)
const float SHUNT_RESISTOR = 0.01f; // 10mΩ
const float AMP_GAIN = 20.0f; // 放大倍数
*current_u = (voltage_u - current_offset_u * 3.3f / 4096.0f) / (SHUNT_RESISTOR * AMP_GAIN);
*current_v = (voltage_v - current_offset_v * 3.3f / 4096.0f) / (SHUNT_RESISTOR * AMP_GAIN);
// 计算第三相电流
// *current_w = -(*current_u + *current_v);
}
// 获取母线电压
float Current_GetBusVoltage(void) {
uint16_t adc_value = adc_buffer[2];
float voltage = (float)adc_value * 3.3f / 4096.0f;
// 分压系数:10kΩ + 2kΩ,分压比 1/6
const float VOLTAGE_DIVIDER = 6.0f;
return voltage * VOLTAGE_DIVIDER;
}
3.5 PID 控制器 (pid_controller.c)
c
/**
* @file pid_controller.c
* @brief PID 控制器实现
*/
#include "bldc_control.h"
// PID 初始化
void PID_Init(PID_Controller_t *pid, float kp, float ki, float kd, float limit) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->integral = 0.0f;
pid->prev_error = 0.0f;
pid->output_limit = limit;
pid->integral_limit = limit * 0.5f;
pid->enable = true;
}
// PID 计算
float PID_Calculate(PID_Controller_t *pid, float setpoint, float feedback, float dt) {
float error, derivative, output;
if (!pid->enable) {
return 0.0f;
}
// 计算误差
error = setpoint - feedback;
// 积分项
pid->integral += error * dt;
// 积分限幅
if (pid->integral > pid->integral_limit) {
pid->integral = pid->integral_limit;
} else if (pid->integral < -pid->integral_limit) {
pid->integral = -pid->integral_limit;
}
// 微分项
derivative = (error - pid->prev_error) / dt;
pid->prev_error = error;
// PID 输出
output = pid->kp * error + pid->ki * pid->integral + pid->kd * derivative;
// 输出限幅
if (output > pid->output_limit) {
output = pid->output_limit;
} else if (output < -pid->output_limit) {
output = -pid->output_limit;
}
return output;
}
// 抗积分饱和 PID
float PID_CalculateAntiWindup(PID_Controller_t *pid, float setpoint, float feedback,
float dt, float saturation_limit) {
float error, derivative, output, unsaturated_output;
if (!pid->enable) {
return 0.0f;
}
error = setpoint - feedback;
// 积分项
pid->integral += error * dt;
// 微分项
derivative = (error - pid->prev_error) / dt;
pid->prev_error = error;
// 计算未饱和输出
unsaturated_output = pid->kp * error + pid->ki * pid->integral + pid->kd * derivative;
// 输出限幅
if (unsaturated_output > saturation_limit) {
output = saturation_limit;
} else if (unsaturated_output < -saturation_limit) {
output = -saturation_limit;
} else {
output = unsaturated_output;
}
// 抗积分饱和:只有当输出不饱和时才积分
if (fabsf(output - unsaturated_output) < 0.01f) {
// 正常积分
} else {
// 停止积分或反向积分
pid->integral -= error * dt * 0.1f; // 减小积分
}
return output;
}
3.6 双闭环控制核心 (bldc_control.c)
c
/**
* @file bldc_control.c
* @brief BLDC 双闭环控制核心
*/
#include "bldc_control.h"
#include "pwm_driver.h"
#include "encoder.h"
#include "current_sense.h"
#include "pid_controller.h"
// 全局控制器实例
DualLoopController_t g_bldc_controller;
// 初始化 BLDC 控制
void BLDC_Init(void) {
DualLoopController_t *ctrl = &g_bldc_controller;
// 初始化 PID 参数
PID_Init(&ctrl->speed_pid, 0.5f, 0.1f, 0.01f, MAX_SPEED_RPM);
PID_Init(&ctrl->current_pid, 5.0f, 1.0f, 0.1f, MAX_CURRENT_A);
// 初始化电机参数
ctrl->motor_params.rs = 0.1f; // 0.1 Ω
ctrl->motor_params.ls = 0.001f; // 1 mH
ctrl->motor_params.ke = 0.05f; // 0.05 V/(rad/s)
ctrl->motor_params.kt = 0.05f; // 0.05 Nm/A
ctrl->motor_params.pole_pairs = POLE_PAIRS;
ctrl->motor_params.max_speed = MAX_SPEED_RPM;
ctrl->motor_params.max_current = MAX_CURRENT_A;
ctrl->motor_params.max_voltage = 24.0f;
// 初始化控制命令
ctrl->command.target_speed = 0.0f;
ctrl->command.target_current = 0.0f;
ctrl->command.ramp_rate = 1000.0f; // 1000 RPM/s
ctrl->command.direction = 0;
ctrl->command.brake = false;
ctrl->command.enable = false;
// 初始化电机状态
ctrl->motor_status.speed_rpm = 0.0f;
ctrl->motor_status.current_a = 0.0f;
ctrl->motor_status.current_b = 0.0f;
ctrl->motor_status.voltage_bus = 24.0f;
ctrl->motor_status.temperature = 25.0f;
ctrl->motor_status.torque = 0.0f;
ctrl->motor_status.state = MOTOR_STATE_IDLE;
ctrl->motor_status.mode = CONTROL_MODE_STOP;
// 初始化 PWM
PWM_Init();
// 初始化编码器
Encoder_Init();
// 初始化电流采样
ADC_Init_CurrentSense();
// 初始化换相
ctrl->commutation_sector = 0;
ctrl->last_commutation_time = 0;
printf("BLDC Controller Initialized\r\n");
}
// 双闭环控制循环
void BLDC_ControlLoop(void) {
DualLoopController_t *ctrl = &g_bldc_controller;
float dt = CONTROL_PERIOD_MS / 1000.0f; // 转换为秒
// 更新电机状态
BLDC_UpdateMotorStatus();
// 安全检查
BLDC_SafetyCheck();
if (!ctrl->command.enable || ctrl->motor_status.state == MOTOR_STATE_FAULT) {
PWM_SetThreePhase(0, 0, 0);
return;
}
// 根据控制模式执行
switch (ctrl->motor_status.mode) {
case CONTROL_MODE_SPEED:
BLDC_SpeedControl();
break;
case CONTROL_MODE_CURRENT:
BLDC_CurrentControl();
break;
case CONTROL_MODE_TORQUE:
// 转矩控制(电流控制的一种)
BLDC_CurrentControl();
break;
default:
PWM_SetThreePhase(0, 0, 0);
break;
}
// 执行换相
BLDC_Commutation();
}
// 速度控制(外环)
void BLDC_SpeedControl(void) {
DualLoopController_t *ctrl = &g_bldc_controller;
float dt = CONTROL_PERIOD_MS / 1000.0f;
// 斜坡处理
static float ramp_target = 0.0f;
if (fabsf(ctrl->command.target_speed - ramp_target) > ctrl->command.ramp_rate * dt) {
if (ctrl->command.target_speed > ramp_target) {
ramp_target += ctrl->command.ramp_rate * dt;
} else {
ramp_target -= ctrl->command.ramp_rate * dt;
}
} else {
ramp_target = ctrl->command.target_speed;
}
// 速度 PID 计算
float speed_error = ramp_target - ctrl->motor_status.speed_rpm;
float current_setpoint = PID_Calculate(&ctrl->speed_pid, ramp_target,
ctrl->motor_status.speed_rpm, dt);
// 限制电流设定值
if (current_setpoint > MAX_CURRENT_A) current_setpoint = MAX_CURRENT_A;
if (current_setpoint < -MAX_CURRENT_A) current_setpoint = -MAX_CURRENT_A;
ctrl->current_setpoint = current_setpoint;
// 执行电流控制
BLDC_CurrentControl();
}
// 电流控制(内环)
void BLDC_CurrentControl(void) {
DualLoopController_t *ctrl = &g_bldc_controller;
float dt = CONTROL_PERIOD_MS / 1000.0f;
// 获取相电流
float current_u, current_v;
Current_GetPhaseCurrents(¤t_u, ¤t_v);
ctrl->motor_status.current_a = current_u;
ctrl->motor_status.current_b = current_v;
// 计算电流幅值(矢量模)
float current_magnitude = sqrtf(current_u * current_u + current_v * current_v);
// 电流 PID 计算
float voltage_setpoint = PID_Calculate(&ctrl->current_pid, ctrl->current_setpoint,
current_magnitude, dt);
// 转换为 PWM 占空比
float duty_cycle = voltage_setpoint / ctrl->motor_status.voltage_bus * 100.0f;
// 限制占空比
if (duty_cycle > 95.0f) duty_cycle = 95.0f;
if (duty_cycle < -95.0f) duty_cycle = -95.0f;
// 存储占空比用于换相
ctrl->duty_cycle[0] = duty_cycle;
ctrl->duty_cycle[1] = duty_cycle;
ctrl->duty_cycle[2] = duty_cycle;
}
// 换相控制(六步换向)
void BLDC_Commutation(void) {
DualLoopController_t *ctrl = &g_bldc_controller;
// 根据霍尔传感器或反电动势确定换相扇区
uint8_t hall_state = GPIO_ReadInputData(GPIOC) & 0x07; // PC6, PC7, PC8
// 霍尔状态到扇区的映射
uint8_t sector_map[8] = {0, 0, 1, 2, 5, 4, 3, 0}; // 无效状态为0
uint8_t sector = sector_map[hall_state];
if (sector == 0) {
return; // 无效霍尔状态
}
ctrl->commutation_sector = sector;
// 根据扇区和方向设置 PWM
float duty_u = 0, duty_v = 0, duty_w = 0;
bool direction = ctrl->command.direction;
// 六步换向表
if (!direction) { // 正转
switch(sector) {
case 1: duty_u = ctrl->duty_cycle[0]; duty_v = 0; duty_w = -ctrl->duty_cycle[2]; break;
case 2: duty_u = ctrl->duty_cycle[0]; duty_v = ctrl->duty_cycle[1]; duty_w = 0; break;
case 3: duty_u = 0; duty_v = ctrl->duty_cycle[1]; duty_w = -ctrl->duty_cycle[2]; break;
case 4: duty_u = -ctrl->duty_cycle[0]; duty_v = ctrl->duty_cycle[1]; duty_w = 0; break;
case 5: duty_u = -ctrl->duty_cycle[0]; duty_v = 0; duty_w = -ctrl->duty_cycle[2]; break;
case 6: duty_u = 0; duty_v = -ctrl->duty_cycle[1]; duty_w = -ctrl->duty_cycle[2]; break;
}
} else { // 反转
switch(sector) {
case 1: duty_u = -ctrl->duty_cycle[0]; duty_v = 0; duty_w = ctrl->duty_cycle[2]; break;
case 2: duty_u = -ctrl->duty_cycle[0]; duty_v = -ctrl->duty_cycle[1]; duty_w = 0; break;
case 3: duty_u = 0; duty_v = -ctrl->duty_cycle[1]; duty_w = ctrl->duty_cycle[2]; break;
case 4: duty_u = ctrl->duty_cycle[0]; duty_v = -ctrl->duty_cycle[1]; duty_w = 0; break;
case 5: duty_u = ctrl->duty_cycle[0]; duty_v = 0; duty_w = ctrl->duty_cycle[2]; break;
case 6: duty_u = 0; duty_v = ctrl->duty_cycle[1]; duty_w = ctrl->duty_cycle[2]; break;
}
}
// 设置 PWM
PWM_SetThreePhase(duty_u, duty_v, duty_w);
}
// 更新电机状态
void BLDC_UpdateMotorStatus(void) {
DualLoopController_t *ctrl = &g_bldc_controller;
// 更新转速
static uint32_t last_time = 0;
uint32_t current_time = Get_SystemTime();
uint32_t dt_ms = current_time - last_time;
if (dt_ms >= 10) { // 每10ms更新一次速度
ctrl->motor_status.speed_rpm = Encoder_GetSpeedRPM(dt_ms);
ctrl->motor_status.speed_rad_s = ctrl->motor_status.speed_rpm * 2.0f * M_PI / 60.0f;
last_time = current_time;
}
// 更新母线电压
ctrl->motor_status.voltage_bus = Current_GetBusVoltage();
// 计算输出转矩
ctrl->motor_status.torque = ctrl->motor_status.current_a * ctrl->motor_params.kt;
}
// 安全检查
void BLDC_SafetyCheck(void) {
DualLoopController_t *ctrl = &g_bldc_controller;
// 过流保护
if (fabsf(ctrl->motor_status.current_a) > MAX_CURRENT_A * 1.2f ||
fabsf(ctrl->motor_status.current_b) > MAX_CURRENT_A * 1.2f) {
ctrl->motor_status.state = MOTOR_STATE_FAULT;
PWM_EmergencyStop();
printf("Overcurrent Fault!\r\n");
return;
}
// 过压保护
if (ctrl->motor_status.voltage_bus > 30.0f) {
ctrl->motor_status.state = MOTOR_STATE_FAULT;
PWM_EmergencyStop();
printf("Overvoltage Fault!\r\n");
return;
}
// 欠压保护
if (ctrl->motor_status.voltage_bus < 10.0f) {
ctrl->motor_status.state = MOTOR_STATE_FAULT;
PWM_EmergencyStop();
printf("Undervoltage Fault!\r\n");
return;
}
// 过热保护
if (ctrl->motor_status.temperature > 80.0f) {
ctrl->motor_status.state = MOTOR_STATE_FAULT;
PWM_EmergencyStop();
printf("Overtemperature Fault!\r\n");
return;
}
}
// 设置速度
void BLDC_SetSpeed(float speed_rpm) {
DualLoopController_t *ctrl = &g_bldc_controller;
if (speed_rpm > MAX_SPEED_RPM) speed_rpm = MAX_SPEED_RPM;
if (speed_rpm < -MAX_SPEED_RPM) speed_rpm = -MAX_SPEED_RPM;
ctrl->command.target_speed = speed_rpm;
ctrl->motor_status.mode = CONTROL_MODE_SPEED;
ctrl->command.enable = true;
}
// 设置电流
void BLDC_SetCurrent(float current_a) {
DualLoopController_t *ctrl = &g_bldc_controller;
if (current_a > MAX_CURRENT_A) current_a = MAX_CURRENT_A;
if (current_a < -MAX_CURRENT_A) current_a = -MAX_CURRENT_A;
ctrl->command.target_current = current_a;
ctrl->motor_status.mode = CONTROL_MODE_CURRENT;
ctrl->command.enable = true;
}
// 启动电机
void BLDC_Start(void) {
DualLoopController_t *ctrl = &g_bldc_controller;
ctrl->command.enable = true;
ctrl->motor_status.state = MOTOR_STATE_RUNNING;
// 对齐转子
PWM_SetThreePhase(10, 0, 0); // 施加10%占空比对齐
Delay_ms(100);
printf("Motor Started\r\n");
}
// 停止电机
void BLDC_Stop(void) {
DualLoopController_t *ctrl = &g_bldc_controller;
ctrl->command.enable = false;
ctrl->command.target_speed = 0;
ctrl->command.target_current = 0;
ctrl->motor_status.state = MOTOR_STATE_IDLE;
ctrl->motor_status.mode = CONTROL_MODE_STOP;
PWM_SetThreePhase(0, 0, 0);
printf("Motor Stopped\r\n");
}
// 刹车
void BLDC_Brake(bool enable) {
DualLoopController_t *ctrl = &g_bldc_controller;
ctrl->command.brake = enable;
if (enable) {
// 短路三相下桥臂进行能耗制动
PWM_SetThreePhase(-100, -100, -100);
ctrl->motor_status.state = MOTOR_STATE_BRAKE;
printf("Motor Braking\r\n");
} else {
PWM_SetThreePhase(0, 0, 0);
ctrl->motor_status.state = MOTOR_STATE_IDLE;
}
}
// 改变方向
void BLDC_ChangeDirection(bool reverse) {
DualLoopController_t *ctrl = &g_bldc_controller;
ctrl->command.direction = reverse;
if (reverse) {
printf("Direction: Reverse\r\n");
} else {
printf("Direction: Forward\r\n");
}
}
3.7 主程序 (main.c)
c
#include "stm32f10x.h"
#include "bldc_control.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
// 系统状态
typedef enum {
SYS_INIT = 0,
SYS_READY,
SYS_RUNNING,
SYS_FAULT,
SYS_STOP
} SystemState_t;
static SystemState_t system_state = SYS_INIT;
static uint32_t control_counter = 0;
// 按键处理函数
void Key_Process(void) {
if (Key_Scan(KEY_START)) {
if (system_state == SYS_READY || system_state == SYS_STOP) {
BLDC_Start();
system_state = SYS_RUNNING;
}
}
if (Key_Scan(KEY_STOP)) {
BLDC_Stop();
system_state = SYS_STOP;
}
if (Key_Scan(KEY_BRAKE)) {
static bool brake_state = false;
brake_state = !brake_state;
BLDC_Brake(brake_state);
}
if (Key_Scan(KEY_DIR)) {
static bool dir_state = false;
dir_state = !dir_state;
BLDC_ChangeDirection(dir_state);
}
}
// 串口命令处理
void UART_CommandProcess(void) {
if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) {
char cmd = USART_ReceiveData(USART1);
switch(cmd) {
case '1': // 低速
BLDC_SetSpeed(500);
printf("Set Speed: 500 RPM\r\n");
break;
case '2': // 中速
BLDC_SetSpeed(1000);
printf("Set Speed: 1000 RPM\r\n");
break;
case '3': // 高速
BLDC_SetSpeed(2000);
printf("Set Speed: 2000 RPM\r\n");
break;
case 's': // 停止
BLDC_Stop();
system_state = SYS_STOP;
printf("Motor Stopped\r\n");
break;
case 'r': // 反转
BLDC_ChangeDirection(true);
break;
case 'f': // 正转
BLDC_ChangeDirection(false);
break;
case '?': // 状态查询
printf("Speed: %.1f RPM\r\n", g_bldc_controller.motor_status.speed_rpm);
printf("Current: %.2f A\r\n", g_bldc_controller.motor_status.current_a);
printf("Voltage: %.1f V\r\n", g_bldc_controller.motor_status.voltage_bus);
printf("Torque: %.2f Nm\r\n", g_bldc_controller.motor_status.torque);
break;
}
}
}
int main(void) {
// 系统初始化
SystemClock_Init();
Delay_Init();
USART_Init(115200);
LED_Init();
Key_Init();
printf("STM32 BLDC Dual Loop Control System\r\n");
printf("=====================================\r\n");
// 初始化 BLDC 控制器
BLDC_Init();
system_state = SYS_READY;
printf("System Ready. Press START button or send commands.\r\n");
while(1) {
// 按键处理
Key_Process();
// 串口命令处理
UART_CommandProcess();
// 双闭环控制循环(1ms周期)
static uint32_t last_control_time = 0;
uint32_t current_time = Get_SystemTime();
if (current_time - last_control_time >= CONTROL_PERIOD_MS) {
BLDC_ControlLoop();
last_control_time = current_time;
control_counter++;
// 每秒打印一次状态
if (control_counter % 1000 == 0) {
printf("Speed: %.1f RPM, Current: %.2f A, Voltage: %.1f V\r\n",
g_bldc_controller.motor_status.speed_rpm,
g_bldc_controller.motor_status.current_a,
g_bldc_controller.motor_status.voltage_bus);
}
}
// LED 指示系统状态
switch(system_state) {
case SYS_READY:
LED_On(LED_GREEN);
LED_Off(LED_RED);
break;
case SYS_RUNNING:
LED_Toggle(LED_GREEN);
LED_Off(LED_RED);
break;
case SYS_FAULT:
LED_On(LED_RED);
LED_Off(LED_GREEN);
break;
case SYS_STOP:
LED_Off(LED_GREEN);
LED_Off(LED_RED);
break;
default:
break;
}
Delay_ms(1);
}
}
参考代码 基于STM32的双闭控制直流无刷电机BLDC www.youwenfan.com/contentcsu/60618.html
四、工程配置与优化
4.1 编译配置
makefile
# Makefile 配置
TARGET = bldc_dual_loop
MCU = cortex-m3
CFLAGS = -O2 -Wall -Wextra -std=c99
LDFLAGS = -Tlinker.ld
# 源文件
SOURCES = main.c \
bldc_control.c \
pwm_driver.c \
encoder.c \
current_sense.c \
pid_controller.c \
usart.c \
delay.c \
led.c \
key.c
# 包含路径
INCLUDES = -I./Inc -I./Drivers/STM32F10x_StdPeriph_Driver/inc
# 编译规则
all: $(TARGET).bin
$(TARGET).bin: $(TARGET).elf
arm-none-eabi-objcopy -O binary $< $@
$(TARGET).elf: $(SOURCES)
arm-none-eabi-gcc $(CFLAGS) $(INCLUDES) $(SOURCES) $(LDFLAGS) -o $@
4.2 性能优化建议
| 优化项目 | 建议方案 |
|---|---|
| 控制频率 | 电流环 10-20kHz,速度环 1-5kHz |
| 电流采样 | 使用同步采样,减少噪声 |
| 换相策略 | 结合霍尔传感器和反电动势 |
| 启动算法 | 三段式启动(对齐-加速-切换) |
| 参数整定 | 先调电流环,再调速度环 |
4.3 常见问题解决
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 电机抖动 | PID参数不合适 | 减小比例系数,增加积分时间 |
| 启动困难 | 对齐不充分 | 延长对齐时间,增加对齐电流 |
| 过流保护频繁 | 电流采样噪声大 | 增加滤波,检查采样电阻 |
| 速度不稳 | 编码器分辨率低 | 使用更高分辨率编码器 |
| 效率低下 | 换相时机不准 | 优化换相逻辑,考虑超前角 |
这套基于STM32的双闭环BLDC控制方案提供了完整的软硬件实现,包括速度外环和电流内环控制,可直接应用于电动工具、电动车、工业伺服等领域。