基于STM32的完整无刷直流电机控制程序,采用6步换相法,支持霍尔传感器和无感FOC两种控制方式。
一、系统架构设计
1.1 控制框图
STM32F103/F4/F7
├── 控制算法(6步换相/FOC)
├── 驱动器接口
│ ├── 高级定时器(TIM1/TIM8)→ PWM输出
│ ├── 比较器/ADC → 电流采样
│ └── 外部中断 → 霍尔传感器
├── 通信接口
│ ├── UART → 上位机调试
│ ├── CAN → 车辆通信
│ └── I2C → 编码器/温度
└── 保护功能
├── 过流保护
├── 过压保护
├── 过温保护
└── 堵转保护
二、硬件连接定义
2.1 电机驱动接口
c
// 6路PWM输出(三相全桥)
// 上桥臂:TIM1_CH1/CH2/CH3
// 下桥臂:TIM1_CH1N/CH2N/CH3N
#define PWM_TIM TIM1
#define PWM_FREQ 20000 // 20kHz PWM频率
// 霍尔传感器接口
#define HALL_U_PIN GPIO_PIN_0
#define HALL_U_PORT GPIOA
#define HALL_V_PIN GPIO_PIN_1
#define HALL_V_PORT GPIOA
#define HALL_W_PIN GPIO_PIN_2
#define HALL_W_PORT GPIOA
// 电流采样(三相下桥臂采样电阻)
#define PHASE_U_CURRENT_ADC ADC1, ADC_CHANNEL_0
#define PHASE_V_CURRENT_ADC ADC1, ADC_CHANNEL_1
#define PHASE_W_CURRENT_ADC ADC1, ADC_CHANNEL_2
#define BUS_VOLTAGE_ADC ADC1, ADC_CHANNEL_3
// 过流保护比较器
#define OCP_COMP COMP1
三、霍尔传感器6步换相控制
3.1 霍尔状态与换相表
c
/* 霍尔传感器状态对应换相表(120°安装) */
typedef struct {
uint8_t hall_state; // 霍尔状态 (UVW二进制)
uint8_t phase_u; // U相状态: 0=关, 1=上管开, 2=下管开
uint8_t phase_v; // V相状态
uint8_t phase_w; // W相状态
} HallCommutationTable;
/* 6步换相表(标准N型MOS驱动) */
const HallCommutationTable commutation_table[6] = {
// Hall=5(101): 位置0°
{0x05, 1, 0, 2}, // U+ W-
// Hall=1(001): 位置60°
{0x01, 1, 2, 0}, // U+ V-
// Hall=3(011): 位置120°
{0x03, 0, 2, 1}, // V+ W-
// Hall=2(010): 位置180°
{0x02, 0, 1, 2}, // V+ U-
// Hall=6(110): 位置240°
{0x06, 2, 1, 0}, // W+ U-
// Hall=4(100): 位置300°
{0x04, 2, 0, 1}, // W+ V-
};
3.2 6步换相核心代码
c
/**
* @file bldc_6step.c
* @brief 无刷直流电机6步换相控制
*/
#include "stm32f1xx_hal.h"
#include "bldc_6step.h"
/* 全局变量 */
volatile uint8_t hall_state = 0;
volatile uint8_t comm_step = 0;
volatile uint16_t speed_rpm = 0;
volatile uint32_t hall_timer = 0;
volatile int32_t electrical_angle = 0;
/* PWM占空比 (0-1000对应0-100%) */
uint16_t pwm_duty = 300; // 初始30%占空比
/* 死区时间 (ns) */
#define DEAD_TIME_NS 1000 // 1μs死区时间
/**
* @brief 初始化PWM输出
*/
void PWM_Init(void)
{
TIM_HandleTypeDef htim1;
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* 时钟使能 */
__HAL_RCC_TIM1_CLK_ENABLE();
/* 定时器配置 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = SystemCoreClock / 1000000 - 1; // 1MHz计数
htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3; // 中央对齐模式
htim1.Init.Period = 1000000 / PWM_FREQ; // 20kHz PWM周期
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_PWM_Init(&htim1);
/* 死区时间配置 */
uint16_t dead_time = DEAD_TIME_NS * (SystemCoreClock / 1000000) / 1000;
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = dead_time;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);
/* PWM通道配置 */
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0; // 初始占空比0
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2);
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3);
/* 启动PWM输出 */
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
/* 使能主输出 */
__HAL_TIM_MOE_ENABLE(&htim1);
}
/**
* @brief 初始化霍尔传感器
*/
void HALL_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* 时钟使能 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* 配置霍尔传感器引脚为输入 */
GPIO_InitStruct.Pin = HALL_U_PIN | HALL_V_PIN | HALL_W_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* 配置外部中断 */
__HAL_RCC_AFIO_CLK_ENABLE();
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
}
/**
* @brief 读取霍尔传感器状态
* @return 霍尔状态 (0-7)
*/
uint8_t HALL_GetState(void)
{
uint8_t state = 0;
state |= (HAL_GPIO_ReadPin(HALL_U_PORT, HALL_U_PIN) ? 1 : 0) << 0;
state |= (HAL_GPIO_ReadPin(HALL_V_PORT, HALL_V_PIN) ? 1 : 0) << 1;
state |= (HAL_GPIO_ReadPin(HALL_W_PORT, HALL_W_PIN) ? 1 : 0) << 2;
return state;
}
/**
* @brief 霍尔传感器中断处理
*/
void EXTI0_IRQHandler(void) // HALL_U
{
if(__HAL_GPIO_EXTI_GET_IT(HALL_U_PIN))
{
__HAL_GPIO_EXTI_CLEAR_IT(HALL_U_PIN);
HALL_Commutation();
}
}
void EXTI1_IRQHandler(void) // HALL_V
{
if(__HAL_GPIO_EXTI_GET_IT(HALL_V_PIN))
{
__HAL_GPIO_EXTI_CLEAR_IT(HALL_V_PIN);
HALL_Commutation();
}
}
void EXTI2_IRQHandler(void) // HALL_W
{
if(__HAL_GPIO_EXTI_GET_IT(HALL_W_PIN))
{
__HAL_GPIO_EXTI_CLEAR_IT(HALL_W_PIN);
HALL_Commutation();
}
}
/**
* @brief 换相处理
*/
void HALL_Commutation(void)
{
static uint32_t last_hall_time = 0;
uint32_t current_time = HAL_GetTick();
uint32_t time_diff;
/* 读取霍尔状态 */
hall_state = HALL_GetState();
/* 计算转速 (RPM) */
if(last_hall_time != 0)
{
time_diff = current_time - last_hall_time;
if(time_diff > 0)
{
// 6步换相 = 1电周期,对于4对极电机,3个霍尔边沿=1机械转
speed_rpm = 60000 / (time_diff * 6); // 简化计算
}
}
last_hall_time = current_time;
/* 查找换相表并执行换相 */
for(int i = 0; i < 6; i++)
{
if(commutation_table[i].hall_state == hall_state)
{
comm_step = i;
BLDC_SetCommutation(i);
break;
}
}
}
/**
* @brief 设置换相状态
* @param step 换相步骤 (0-5)
*/
void BLDC_SetCommutation(uint8_t step)
{
uint16_t pwm_u = 0, pwm_v = 0, pwm_w = 0;
if(step >= 6) return;
/* 根据换相表设置PWM输出 */
switch(commutation_table[step].phase_u)
{
case 0: // 关闭
pwm_u = 0;
break;
case 1: // 上管PWM
pwm_u = pwm_duty;
break;
case 2: // 下管常开
pwm_u = 1000; // 100%占空比
break;
}
switch(commutation_table[step].phase_v)
{
case 0:
pwm_v = 0;
break;
case 1:
pwm_v = pwm_duty;
break;
case 2:
pwm_v = 1000;
break;
}
switch(commutation_table[step].phase_w)
{
case 0:
pwm_w = 0;
break;
case 1:
pwm_w = pwm_duty;
break;
case 2:
pwm_w = 1000;
break;
}
/* 更新PWM占空比 */
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pwm_u);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, pwm_v);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, pwm_w);
}
/**
* @brief 设置PWM占空比
* @param duty 占空比 (0-1000)
*/
void BLDC_SetDuty(uint16_t duty)
{
if(duty > 1000) duty = 1000;
pwm_duty = duty;
}
/**
* @brief 启动电机
*/
void BLDC_Start(void)
{
/* 初始位置检测 */
hall_state = HALL_GetState();
HALL_Commutation();
/* 使能PWM输出 */
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
/* 初始占空比 */
BLDC_SetDuty(100); // 10%启动
}
/**
* @brief 停止电机
*/
void BLDC_Stop(void)
{
/* 关闭所有PWM输出 */
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, 0);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, 0);
/* 禁用PWM输出 */
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
}
四、无感启动与反电动势过零检测
4.1 无感启动算法
c
/**
* @file sensorless_bldc.c
* @brief 无感BLDC控制(反电动势法)
*/
#include "stm32f1xx_hal.h"
/* 反电动势过零检测参数 */
#define BEMF_THRESHOLD 100 // 过零检测阈值 (mV)
#define BEMF_FILTER_COUNT 3 // 滤波次数
/* 启动参数 */
#define ALIGN_TIME_MS 1000 // 预定位时间
#define OPEN_LOOP_STEPS 50 // 开环加速步数
#define MIN_SPEED_RPM 100 // 最小切换速度
/* 状态机 */
typedef enum {
STATE_STOP = 0,
STATE_ALIGN,
STATE_OPENLOOP,
STATE_CLOSEDLOOP
} MotorState;
MotorState motor_state = STATE_STOP;
/**
* @brief 无感启动过程
*/
void Sensorless_Start(void)
{
static uint32_t start_time = 0;
static uint8_t openloop_step = 0;
static uint16_t openloop_speed = 0;
switch(motor_state)
{
case STATE_STOP:
/* 进入预定位状态 */
motor_state = STATE_ALIGN;
start_time = HAL_GetTick();
/* 强制定位到0°位置 */
BLDC_SetCommutation(0);
BLDC_SetDuty(200); // 20%占空比
break;
case STATE_ALIGN:
/* 预定位1秒 */
if(HAL_GetTick() - start_time > ALIGN_TIME_MS)
{
motor_state = STATE_OPENLOOP;
openloop_step = 0;
openloop_speed = 50; // 初始低速
}
break;
case STATE_OPENLOOP:
/* 开环加速 */
if(openloop_step < OPEN_LOOP_STEPS)
{
/* 逐步增加速度和提前换相角 */
openloop_speed += 5;
BLDC_SetDuty(openloop_speed);
/* 强制换相(固定频率) */
static uint32_t last_comm_time = 0;
uint32_t period = 60000 / (openloop_speed * 6); // 计算换相周期
if(HAL_GetTick() - last_comm_time > period)
{
last_comm_time = HAL_GetTick();
comm_step = (comm_step + 1) % 6;
BLDC_SetCommutation(comm_step);
}
openloop_step++;
}
else
{
/* 切换到闭环运行 */
motor_state = STATE_CLOSEDLOOP;
}
break;
case STATE_CLOSEDLOOP:
/* 正常闭环运行 */
BEMF_ZeroCrossing_Detection();
break;
}
}
/**
* @brief 反电动势过零检测
*/
void BEMF_ZeroCrossing_Detection(void)
{
static uint8_t zc_count = 0;
static uint32_t last_zc_time = 0;
int16_t bemf_u, bemf_v, bemf_w;
/* 读取反电动势电压(通过ADC) */
bemf_u = ADC_ReadBEMF(PHASE_U_ADC);
bemf_v = ADC_ReadBEMF(PHASE_V_ADC);
bemf_w = ADC_ReadBEMF(PHASE_W_ADC);
/* 根据当前通电相选择检测相 */
int16_t bemf_det = 0;
uint8_t detect_phase = 0;
switch(comm_step)
{
case 0: // U+ W-,检测V相
bemf_det = bemf_v;
detect_phase = 1;
break;
case 1: // U+ V-,检测W相
bemf_det = bemf_w;
detect_phase = 2;
break;
case 2: // V+ W-,检测U相
bemf_det = bemf_u;
detect_phase = 0;
break;
case 3: // V+ U-,检测W相
bemf_det = bemf_w;
detect_phase = 2;
break;
case 4: // W+ U-,检测V相
bemf_det = bemf_v;
detect_phase = 1;
break;
case 5: // W+ V-,检测U相
bemf_det = bemf_u;
detect_phase = 0;
break;
}
/* 过零检测 */
if(abs(bemf_det) < BEMF_THRESHOLD)
{
zc_count++;
if(zc_count >= BEMF_FILTER_COUNT)
{
zc_count = 0;
/* 计算换相时机(延迟30°电角度) */
uint32_t current_time = HAL_GetTick();
uint32_t half_period = (current_time - last_zc_time) / 2;
/* 设置换相定时器 */
if(half_period > 0)
{
// 30°电角度延迟 = 1/12电周期
uint32_t comm_delay = half_period / 6;
/* 启动延迟换相定时器 */
BEMF_CommutationDelay(comm_delay);
}
last_zc_time = current_time;
}
}
else
{
zc_count = 0;
}
}
/**
* @brief 延迟换相
*/
void BEMF_CommutationDelay(uint32_t delay_ms)
{
/* 使用定时器实现精确延迟 */
static uint32_t comm_timer = 0;
if(delay_ms > 0)
{
comm_timer = HAL_GetTick() + delay_ms;
}
else if(HAL_GetTick() >= comm_timer)
{
/* 执行换相 */
comm_step = (comm_step + 1) % 6;
BLDC_SetCommutation(comm_step);
}
}
五、PID速度控制
5.1 速度PID控制器
c
/**
* @file pid_controller.c
* @brief PID速度控制器
*/
typedef struct {
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float target; // 目标值
float feedback; // 反馈值
float output; // 输出值
float error; // 当前误差
float last_error; // 上次误差
float integral; // 积分项
float derivative; // 微分项
float integral_max; // 积分限幅
float output_max; // 输出限幅
float output_min; // 输出下限
} PID_Controller;
PID_Controller speed_pid = {
.Kp = 0.5f,
.Ki = 0.1f,
.Kd = 0.01f,
.integral_max = 1000.0f,
.output_max = 1000.0f,
.output_min = 0.0f
};
/**
* @brief PID计算
*/
float PID_Calculate(PID_Controller *pid, float target, float feedback)
{
/* 计算误差 */
pid->target = target;
pid->feedback = feedback;
pid->error = target - feedback;
/* 比例项 */
float P_out = pid->Kp * pid->error;
/* 积分项 */
pid->integral += pid->error;
/* 积分限幅 */
if(pid->integral > pid->integral_max)
pid->integral = pid->integral_max;
else if(pid->integral < -pid->integral_max)
pid->integral = -pid->integral_max;
float I_out = pid->Ki * pid->integral;
/* 微分项 */
pid->derivative = pid->error - pid->last_error;
float D_out = pid->Kd * pid->derivative;
pid->last_error = pid->error;
/* 输出计算 */
pid->output = P_out + I_out + D_out;
/* 输出限幅 */
if(pid->output > pid->output_max)
pid->output = pid->output_max;
else if(pid->output < pid->output_min)
pid->output = pid->output_min;
return pid->output;
}
/**
* @brief 速度控制任务
*/
void Speed_Control_Task(void)
{
static uint32_t last_ctrl_time = 0;
uint32_t current_time = HAL_GetTick();
/* 100ms控制周期 */
if(current_time - last_ctrl_time >= 100)
{
last_ctrl_time = current_time;
/* 获取当前转速 */
float current_speed = (float)speed_rpm;
/* PID计算(目标转速1000RPM) */
float duty_out = PID_Calculate(&speed_pid, 1000.0f, current_speed);
/* 更新PWM占空比 */
BLDC_SetDuty((uint16_t)duty_out);
/* 调试输出 */
printf("Target: 1000, Current: %.0f, Duty: %.0f\r\n",
current_speed, duty_out);
}
}
六、保护功能实现
6.1 多重保护机制
c
/**
* @file protection.c
* @brief 电机保护功能
*/
/* 保护阈值 */
#define OVER_CURRENT_THRESHOLD 10.0f // 10A过流保护
#define OVER_VOLTAGE_THRESHOLD 60.0f // 60V过压保护
#define UNDER_VOLTAGE_THRESHOLD 20.0f // 20V欠压保护
#define OVER_TEMP_THRESHOLD 85.0f // 85°C过温保护
#define STALL_TIMEOUT_MS 2000 // 堵转超时2秒
/* 保护状态 */
typedef struct {
uint8_t over_current : 1;
uint8_t over_voltage : 1;
uint8_t under_voltage : 1;
uint8_t over_temp : 1;
uint8_t stall : 1;
uint8_t reserved : 3;
} ProtectionFlags;
ProtectionFlags fault_flags = {0};
uint32_t last_hall_change_time = 0;
/**
* @brief 电流保护检测
*/
void Current_Protection_Check(void)
{
float phase_currents[3];
float bus_current;
/* 读取三相电流 */
phase_currents[0] = ADC_GetCurrent(PHASE_U_CURRENT_ADC);
phase_currents[1] = ADC_GetCurrent(PHASE_V_CURRENT_ADC);
phase_currents[2] = ADC_GetCurrent(PHASE_W_CURRENT_ADC);
/* 计算总线电流(最大值法) */
bus_current = fmaxf(fabsf(phase_currents[0]),
fmaxf(fabsf(phase_currents[1]),
fabsf(phase_currents[2])));
/* 过流检测 */
if(bus_current > OVER_CURRENT_THRESHOLD)
{
fault_flags.over_current = 1;
BLDC_Fault_Handler();
}
}
/**
* @brief 电压保护检测
*/
void Voltage_Protection_Check(void)
{
float bus_voltage = ADC_GetVoltage(BUS_VOLTAGE_ADC);
if(bus_voltage > OVER_VOLTAGE_THRESHOLD)
{
fault_flags.over_voltage = 1;
BLDC_Fault_Handler();
}
else if(bus_voltage < UNDER_VOLTAGE_THRESHOLD)
{
fault_flags.under_voltage = 1;
BLDC_Fault_Handler();
}
}
/**
* @brief 堵转检测
*/
void Stall_Detection(void)
{
static uint8_t last_hall_state = 0;
static uint32_t stall_timer = 0;
uint8_t current_hall_state = HALL_GetState();
if(current_hall_state != last_hall_state)
{
/* 霍尔状态变化,重置定时器 */
last_hall_change_time = HAL_GetTick();
stall_timer = 0;
last_hall_state = current_hall_state;
}
else
{
/* 检查是否超时 */
if(HAL_GetTick() - last_hall_change_time > STALL_TIMEOUT_MS)
{
fault_flags.stall = 1;
BLDC_Fault_Handler();
}
}
}
/**
* @brief 温度保护检测
*/
void Temperature_Protection_Check(void)
{
float mosfet_temp = ADC_GetTemperature(MOSFET_TEMP_ADC);
float motor_temp = ADC_GetTemperature(MOTOR_TEMP_ADC);
if(mosfet_temp > OVER_TEMP_THRESHOLD || motor_temp > OVER_TEMP_THRESHOLD)
{
fault_flags.over_temp = 1;
BLDC_Fault_Handler();
}
}
/**
* @brief 故障处理
*/
void BLDC_Fault_Handler(void)
{
/* 立即关闭所有PWM输出 */
BLDC_Stop();
/* 记录故障代码 */
uint8_t fault_code = 0;
fault_code |= fault_flags.over_current << 0;
fault_code |= fault_flags.over_voltage << 1;
fault_code |= fault_flags.under_voltage << 2;
fault_code |= fault_flags.over_temp << 3;
fault_code |= fault_flags.stall << 4;
printf("FAULT! Code: 0x%02X\r\n", fault_code);
/* 根据故障类型处理 */
if(fault_flags.over_current)
{
printf("Over Current Protection!\r\n");
}
if(fault_flags.stall)
{
printf("Motor Stall Protection!\r\n");
}
/* 进入保护状态,等待复位 */
while(1)
{
/* 故障指示灯闪烁 */
HAL_GPIO_TogglePin(FAULT_LED_PORT, FAULT_LED_PIN);
HAL_Delay(200);
/* 检查故障是否清除 */
if(Check_Fault_Clear())
{
Reset_Fault_Flags();
break;
}
}
}
/**
* @brief 检查故障是否清除
*/
uint8_t Check_Fault_Clear(void)
{
/* 重新检测所有保护条件 */
Voltage_Protection_Check();
Temperature_Protection_Check();
/* 如果有故障标志,返回0 */
if(fault_flags.over_current || fault_flags.over_voltage ||
fault_flags.under_voltage || fault_flags.over_temp)
{
return 0;
}
return 1;
}
七、主程序框架
7.1 主循环与任务调度
c
/**
* @file main.c
* @brief 主程序
*/
#include "main.h"
/* 任务周期定义 */
#define TASK_1MS 1
#define TASK_10MS 10
#define TASK_100MS 100
#define TASK_1000MS 1000
int main(void)
{
/* 硬件初始化 */
HAL_Init();
SystemClock_Config();
/* 外设初始化 */
PWM_Init();
HALL_Init();
ADC_Init();
UART_Init(115200);
/* 初始化PID控制器 */
PID_Init(&speed_pid);
printf("BLDC Motor Controller Ready!\r\n");
/* 主循环 */
while(1)
{
uint32_t tick = HAL_GetTick();
/* 1ms任务 */
if(tick % TASK_1MS == 0)
{
Current_Protection_Check(); // 快速电流保护
}
/* 10ms任务 */
if(tick % TASK_10MS == 0)
{
Voltage_Protection_Check();
Temperature_Protection_Check();
Stall_Detection();
}
/* 100ms任务 */
if(tick % TASK_100MS == 0)
{
Speed_Control_Task(); // 速度控制
}
/* 1000ms任务 */
if(tick % TASK_1000MS == 0)
{
// 状态上报
printf("Speed: %d RPM, Duty: %d%%, Temp: %.1fC\r\n",
speed_rpm, pwm_duty/10, Get_Temperature());
}
/* 空闲任务 */
if(motor_state == STATE_STOP)
{
// 低功耗模式
__WFI();
}
}
}
/**
* @brief 系统时钟配置
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/* 配置HSE 8MHz外部晶振 */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 8MHz * 9 = 72MHz
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/* 配置系统时钟 */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // HCLK = 72MHz
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // PCLK1 = 36MHz
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // PCLK2 = 72MHz
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
}
八、调试与参数整定
8.1 调试接口
c
/**
* @file debug.c
* @brief 调试功能
*/
/* 调试命令 */
typedef enum {
CMD_START = 0x01,
CMD_STOP = 0x02,
CMD_SET_SPEED = 0x03,
CMD_SET_DUTY = 0x04,
CMD_SET_KP = 0x05,
CMD_SET_KI = 0x06,
CMD_SET_KD = 0x07,
CMD_GET_STATUS = 0x08,
CMD_CLEAR_FAULT = 0x09
} DebugCommand;
/**
* @brief 处理调试命令
*/
void Debug_Command_Handler(uint8_t *data, uint8_t len)
{
if(len < 2) return;
uint8_t cmd = data[0];
uint16_t value = (data[1] << 8) | data[2];
switch(cmd)
{
case CMD_START:
BLDC_Start();
printf("Motor Started\r\n");
break;
case CMD_STOP:
BLDC_Stop();
printf("Motor Stopped\r\n");
break;
case CMD_SET_SPEED:
speed_pid.target = (float)value;
printf("Target Speed: %d RPM\r\n", value);
break;
case CMD_SET_DUTY:
BLDC_SetDuty(value);
printf("Duty: %d%%\r\n", value/10);
break;
case CMD_SET_KP:
speed_pid.Kp = (float)value / 1000.0f;
printf("Kp: %.3f\r\n", speed_pid.Kp);
break;
case CMD_SET_KI:
speed_pid.Ki = (float)value / 1000.0f;
printf("Ki: %.3f\r\n", speed_pid.Ki);
break;
case CMD_SET_KD:
speed_pid.Kd = (float)value / 1000.0f;
printf("Kd: %.3f\r\n", speed_pid.Kd);
break;
case CMD_GET_STATUS:
printf("Status: Speed=%d, Duty=%d, State=%d\r\n",
speed_rpm, pwm_duty, motor_state);
break;
case CMD_CLEAR_FAULT:
Reset_Fault_Flags();
printf("Fault Cleared\r\n");
break;
}
}
参考代码 无刷直流电机控制程序 www.youwenfan.com/contentcsu/70601.html
九、工程优化建议
9.1 性能优化
c
/* 使用查表法优化三角函数计算 */
const float sin_table[360] = {
// 预计算的sin值 (0-359度)
};
/* 使用DMA传输ADC数据 */
void ADC_DMA_Init(void)
{
/* 配置ADC DMA传输 */
__HAL_RCC_DMA1_CLK_ENABLE();
hdma_adc.Instance = DMA1_Channel1;
hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc.Init.Mode = DMA_CIRCULAR; // 循环模式
hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;
HAL_DMA_Init(&hdma_adc);
/* 关联ADC到DMA */
__HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc);
}
9.2 参数整定表
| 参数 | 范围 | 建议值 | 说明 |
|---|---|---|---|
| PWM频率 | 8-20kHz | 16kHz | 兼顾效率和噪声 |
| 死区时间 | 500-2000ns | 1000ns | 防止上下管直通 |
| 启动占空比 | 5-20% | 10% | 避免启动冲击 |
| 速度环Kp | 0.1-2.0 | 0.5 | 根据电机调整 |
| 速度环Ki | 0.01-0.5 | 0.1 | 积分系数 |
| 过流阈值 | 5-20A | 10A | 根据电机额定 |
| 堵转时间 | 1-5s | 2s | 检测堵转 |
十、总结
这个完整的无刷直流电机控制程序包含了:
- 6步换相控制 - 支持霍尔传感器
- 无感启动 - 反电动势过零检测
- PID速度控制 - 闭环调速
- 多重保护 - 过流、过压、过温、堵转保护
- 调试接口 - 方便参数调整
实际应用中需要根据具体硬件调整引脚定义和保护阈值。对于高性能应用,可以考虑升级到FOC(磁场定向控制)算法以获得更好的效率和性能。