无刷直流电机(BLDC)控制程序 - STM32实现方案

基于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 检测堵转

十、总结

这个完整的无刷直流电机控制程序包含了:

  1. 6步换相控制 - 支持霍尔传感器
  2. 无感启动 - 反电动势过零检测
  3. PID速度控制 - 闭环调速
  4. 多重保护 - 过流、过压、过温、堵转保护
  5. 调试接口 - 方便参数调整

实际应用中需要根据具体硬件调整引脚定义和保护阈值。对于高性能应用,可以考虑升级到FOC(磁场定向控制)算法以获得更好的效率和性能。

相关推荐
LCG元1 小时前
STM32实战:基于STM32F103的智能鹌鹑孵化箱(温湿度+翻蛋控制)
stm32·单片机·嵌入式硬件
黑猫学长呀15 小时前
存储宝典第2篇:盲封TT wafer是什么意思?
linux·嵌入式硬件·项目·芯片·ufs·晶圆·产测
都在酒里15 小时前
STM32标准库驱动HC-SR04超声波测距模块(定时器输入捕获,附完整工程代码)
stm32·嵌入式硬件·mongodb
qq_3707730919 小时前
梁山派GD32F470ZGT6 FreeRTOS CMake 模板适配指南
单片机·嵌入式硬件·gd32·梁山派
嵌入式小站20 小时前
STM32 零基础可移植教程 03:蜂鸣器响一声,LED 跟着翻转一次
stm32·单片机·嵌入式硬件
星夜夏空9921 小时前
STM32单片机学习(15) —— PC串口通信实验
stm32·单片机·学习
星夜夏空9921 小时前
STM32单片机学习(14) —— STM32的串口外设
stm32·单片机·学习
都在酒里21 小时前
STM32标准库驱动L298N双H桥电机驱动模块(调速/正反转/多模式实战,附完整工程代码)
stm32·单片机·嵌入式硬件
Hello_Embed1 天前
USB 学习指南+软硬件框架
网络·笔记·stm32·嵌入式·ai编程