基于STM32F103的数控电源设计方案

数控电源解决方案,包含电路设计、PCB布局、软件控制、保护机制。输出1-30V/3A可调,精度0.1V,效率>85%。


一、系统架构

复制代码
输入电源 → 整流滤波 → Buck变换器 → 输出滤波 → 负载
   ↓           ↓           ↓           ↓
24V AC/DC    EMI滤波   STM32 PWM    LC滤波
   ↓           ↓           ↓           ↓
辅助电源   电压检测   电流检测   电压/电流采样
   ↓           ↓           ↓           ↓
STM32供电   ADC采样   ADC采样   PID控制
   ↓           ↓           ↓           ↓
LCD显示   按键设置   DAC基准   MOSFET驱动

核心特性

  • 输出电压:1-30V 可调
  • 输出电流:0-3A 可调
  • 电压精度:±0.1V
  • 电流精度:±10mA
  • 纹波:<50mV
  • 效率:>85%
  • 保护:过压、过流、过温、短路
  • 通信:UART、USB
  • 显示:LCD/OLED

二、硬件电路设计

1、主电路拓扑

复制代码
采用同步Buck拓扑:
输入24V → MOSFET Q1 → 电感L1 → 输出电容C1 → 负载
         ↓           ↓          ↓
        MOSFET Q2  续流二极管 电压采样

2、核心器件清单

器件 型号 参数 单价
主控 STM32F103C8T6 72MHz, 64KB Flash ¥12
Buck控制器 LM5117 同步Buck控制器 ¥18
功率MOSFET IRF3205 55V/110A ¥8×2
电感 33μH/5A 铁硅铝磁环 ¥15
输出电容 470μF/50V 低ESR电解 ¥5
电流采样 INA282 双向电流检测 ¥6
运放 LM358 双运放 ¥2
ADC基准 REF3030 3.0V基准 ¥5
LCD SSD1306 0.96寸OLED ¥15
编码器 EC11 旋转编码器 ¥3

总成本:约 ¥100


三、原理图设计

1、STM32最小系统

kicad 复制代码
STM32F103C8T6:
  VDD: 3.3V → 100nF+10μF去耦
  NRST: 10k上拉,100nF下拉
  BOOT0: 10k下拉
  OSC: 8MHz晶体 + 20pF×2
  SWD: PA13/PA14调试接口

2、同步Buck主电路

kicad 复制代码
# Power_Section.sch

# 输入滤波
C1, C2: 100μF/50V电解
C3, C4: 100nF陶瓷
L1: 10μH共模电感

# Buck变换器 (LM5117)
U1: LM5117
  VIN: 24V
  HO: 驱动Q1 (高端MOS)
  LO: 驱动Q2 (低端MOS)
  COMP: 误差放大器补偿
  FB: 反馈电压(0.8V)

# 功率MOSFET
Q1: IRF3205 (高端)
Q2: IRF3205 (低端)
R1, R2: 10Ω栅极电阻
D1, D2: 1N4148 栅极钳位

# 输出滤波
L2: 33μH/5A电感
C5: 470μF/50V电解
C6, C7: 100μF陶瓷
C8: 10μF陶瓷

3、电压电流采样

kicad 复制代码
# Sensing_Circuit.sch

# 电压采样 (分压比 1:10)
R3: 90k 1%
R4: 10k 1%
C9: 100nF滤波
-> ADC_IN1 (PA1)

# 电流采样 (INA282)
U2: INA282
  Rsense: 0.05Ω/5W
  Gain: 50V/V
  OUT = (V+ - V-) × 50
  Vref: 1.5V (中间电平)
-> ADC_IN2 (PA2)

# 温度采样
U3: LM35
  Vout = 10mV/°C
-> ADC_IN3 (PA3)

4、控制接口

kicad 复制代码
# Control_Interface.sch

# 编码器
EC11: A→PA6, B→PA7, SW→PB0
# 10k上拉,100nF去抖

# 按键
S1: SET → PB1
S2: UP → PB10
S3: DOWN → PB11
# 10k上拉,100nF去抖

# LCD (I2C)
U4: SSD1306
  SCL → PB8
  SDA → PB9
  VCC: 3.3V

5、辅助电源

kicad 复制代码
# Aux_Power.sch

# 24V转5V (Buck)
U5: LM2596-5.0
  IN: 24V
  OUT: 5V/1A
  L3: 100μH
  C10: 100μF/50V

# 5V转3.3V (LDO)
U6: AMS1117-3.3
  IN: 5V
  OUT: 3.3V/500mA
  C11, C12: 10μF陶瓷

四、PCB布局要点

kicad 复制代码
PCB布局要求:
1. 功率路径最短
2. 信号与功率分离
3. 大电流路径加宽
4. 散热处理

层叠结构:
Top: 信号+少量功率
Mid1: GND平面
Mid2: 3.3V平面
Bottom: 功率路径

布线规则:
- 功率线:2mm宽/1A
- 反馈线:远离噪声源
- 地平面:完整,多点接地

五、STM32软件设计

1、项目结构

复制代码
Digital_Power_Supply/
├── Core/
│   ├── main.c
│   └── stm32f1xx_it.c
├── Drivers/
│   ├── pwm.c
│   ├── adc.c
│   ├── dac.c
│   ├── pid.c
│   ├── encoder.c
│   └── lcd.c
├── Middlewares/
│   └── FreeRTOS/
└── Application/
    ├── power_control.c
    ├── user_interface.c
    ├── protection.c
    └── calibration.c

2、主控制头文件

c 复制代码
// power_supply.h
#ifndef POWER_SUPPLY_H
#define POWER_SUPPLY_H

#include "stm32f1xx_hal.h"

// 电源状态
typedef enum {
    STATE_OFF = 0,
    STATE_STANDBY,
    STATE_RUNNING,
    STATE_CV,       // 恒压模式
    STATE_CC,       // 恒流模式
    STATE_ERROR
} Power_State_t;

// 保护状态
typedef enum {
    PROTECT_NONE = 0,
    PROTECT_OVP,    // 过压
    PROTECT_OCP,    // 过流
    PROTECT_OTP,    // 过温
    PROTECT_SCP,    // 短路
} Protect_State_t;

// 电源参数
typedef struct {
    float voltage_set;      // 设定电压
    float voltage_actual;   // 实际电压
    float current_set;      // 设定电流
    float current_actual;   // 实际电流
    float power;           // 输出功率
    float temperature;     // 温度
    uint8_t enable;        // 输出使能
} Power_Params_t;

// PID参数
typedef struct {
    float kp;
    float ki;
    float kd;
    float integral_max;
    float output_max;
    float output_min;
} PID_Params_t;

// 全局实例
extern Power_Params_t power;
extern PID_Params_t pid_voltage;
extern PID_Params_t pid_current;

// 函数声明
void Power_Init(void);
void Power_Set_Voltage(float voltage);
void Power_Set_Current(float current);
void Power_Enable(uint8_t enable);
void Power_Protection_Check(void);
void Power_Update_Display(void);
float Read_Voltage(void);
float Read_Current(void);
float Read_Temperature(void);

#endif

3、主程序

c 复制代码
// main.c
#include "power_supply.h"
#include "lcd.h"
#include "encoder.h"

// 全局变量
Power_Params_t power = {0};
TIM_HandleTypeDef htim1;
ADC_HandleTypeDef hadc1;
DAC_HandleTypeDef hdac;

int main(void)
{
    // 1. HAL初始化
    HAL_Init();
    SystemClock_Config();
    
    // 2. 外设初始化
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_TIM1_Init();  // PWM
    MX_ADC1_Init();  // ADC
    MX_DAC_Init();   // DAC
    MX_USART1_Init(); // 串口
    MX_I2C1_Init();   // I2C (LCD)
    
    // 3. 驱动初始化
    PWM_Init();
    ADC_Init();
    DAC_Init();
    Encoder_Init();
    LCD_Init();
    
    // 4. 电源初始化
    Power_Init();
    
    // 5. 启动FreeRTOS
    osKernelInitialize();
    
    // 创建任务
    xTaskCreate(Power_Control_Task, "Power", 256, NULL, 5, NULL);
    xTaskCreate(UI_Task, "UI", 256, NULL, 4, NULL);
    xTaskCreate(Protection_Task, "Protect", 128, NULL, 6, NULL);
    
    osKernelStart();
    
    while(1) { }
}

4、PWM控制(LM5117驱动)

c 复制代码
// pwm.c
#include "pwm.h"

// PWM配置
void PWM_Init(void)
{
    TIM_OC_InitTypeDef sConfigOC = {0};
    
    // 定时器1时钟:72MHz
    htim1.Instance = TIM1;
    htim1.Init.Prescaler = 0;      // 不分频
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim1.Init.Period = 7199;      // 10kHz PWM
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim1.Init.RepetitionCounter = 0;
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    HAL_TIM_PWM_Init(&htim1);
    
    // 通道1配置 (PA8)
    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);
    
    // 启动PWM
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}

// 设置PWM占空比
void PWM_Set_Duty(float duty_cycle)
{
    uint16_t compare_value;
    
    // 限制范围 0-100%
    if(duty_cycle < 0) duty_cycle = 0;
    if(duty_cycle > 100) duty_cycle = 100;
    
    // 计算比较值
    compare_value = (uint16_t)(duty_cycle * 7199 / 100.0f);
    
    // 设置比较寄存器
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, compare_value);
}

// 设置输出电压
void PWM_Set_Voltage(float voltage)
{
    float duty_cycle;
    
    // 电压->占空比转换: D = Vout / Vin
    duty_cycle = (voltage / 24.0f) * 100.0f;  // 输入24V
    
    // 限制最大占空比
    if(duty_cycle > 90) duty_cycle = 90;  // 留10%余量
    
    PWM_Set_Duty(duty_cycle);
}

5、ADC采样

c 复制代码
// adc.c
#include "adc.h"

// ADC初始化
void ADC_Init(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};
    
    // ADC1初始化
    hadc1.Instance = ADC1;
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
    hadc1.Init.ContinuousConvMode = ENABLE;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 3;
    HAL_ADC_Init(&hadc1);
    
    // 配置通道0: 电压采样 (PA1)
    sConfig.Channel = ADC_CHANNEL_1;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    // 配置通道1: 电流采样 (PA2)
    sConfig.Channel = ADC_CHANNEL_2;
    sConfig.Rank = ADC_REGULAR_RANK_2;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    // 配置通道2: 温度采样 (PA3)
    sConfig.Channel = ADC_CHANNEL_3;
    sConfig.Rank = ADC_REGULAR_RANK_3;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    // 启动ADC
    HAL_ADC_Start(&hadc1);
}

// 读取电压
float Read_Voltage(void)
{
    uint32_t adc_value;
    float voltage;
    
    // 选择通道1
    ADC1->SQR3 = ADC_CHANNEL_1;
    
    // 启动转换
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);
    adc_value = HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    
    // ADC值转电压
    // 分压比 1:10, ADC基准3.0V
    voltage = (adc_value * 3.0f / 4095.0f) * 10.0f;
    
    return voltage;
}

// 读取电流
float Read_Current(void)
{
    uint32_t adc_value;
    float voltage, current;
    
    // 选择通道2
    ADC1->SQR3 = ADC_CHANNEL_2;
    
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);
    adc_value = HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    
    // INA282: Vout = (V+ - V-) * 50 + 1.5V
    // 采样电阻0.05Ω
    voltage = adc_value * 3.0f / 4095.0f;
    
    // 计算电流
    // (Vout - 1.5V) / 50 = 采样电阻电压
    // 电流 = 采样电阻电压 / 0.05Ω
    current = ((voltage - 1.5f) / 50.0f) / 0.05f;
    
    return current;
}

// 读取温度
float Read_Temperature(void)
{
    uint32_t adc_value;
    float temperature;
    
    // 选择通道3
    ADC1->SQR3 = ADC_CHANNEL_3;
    
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);
    adc_value = HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    
    // LM35: 10mV/°C
    temperature = (adc_value * 3.0f / 4095.0f) * 100.0f;
    
    return temperature;
}

6、PID控制算法

c 复制代码
// pid.c
#include "pid.h"

// PID控制器
typedef struct {
    float kp, ki, kd;
    float integral;
    float prev_error;
    float output;
    float output_max;
    float output_min;
} PID_Controller;

static PID_Controller pid_voltage = {0};
static PID_Controller pid_current = {0};

// PID初始化
void PID_Init(void)
{
    // 电压环PID
    pid_voltage.kp = 0.5f;
    pid_voltage.ki = 0.1f;
    pid_voltage.kd = 0.01f;
    pid_voltage.integral = 0;
    pid_voltage.prev_error = 0;
    pid_voltage.output_max = 90.0f;  // 最大占空比90%
    pid_voltage.output_min = 0.0f;
    
    // 电流环PID
    pid_current.kp = 1.0f;
    pid_current.ki = 0.2f;
    pid_current.kd = 0.0f;
    pid_current.integral = 0;
    pid_current.prev_error = 0;
    pid_current.output_max = 90.0f;
    pid_current.output_min = 0.0f;
}

// PID计算
float PID_Calculate(PID_Controller *pid, float setpoint, float actual, float dt)
{
    float error, derivative, output;
    
    // 计算误差
    error = setpoint - actual;
    
    // 积分项
    pid->integral += error * dt;
    
    // 积分限幅
    if(pid->integral > pid->output_max) pid->integral = pid->output_max;
    if(pid->integral < pid->output_min) pid->integral = pid->output_min;
    
    // 微分项
    derivative = (error - pid->prev_error) / dt;
    
    // PID输出
    output = pid->kp * error + 
             pid->ki * pid->integral + 
             pid->kd * derivative;
    
    // 输出限幅
    if(output > pid->output_max) output = pid->output_max;
    if(output < pid->output_min) output = pid->output_min;
    
    // 保存误差
    pid->prev_error = error;
    
    return output;
}

// 电压环控制
float PID_Voltage_Control(float voltage_set, float voltage_actual, float dt)
{
    return PID_Calculate(&pid_voltage, voltage_set, voltage_actual, dt);
}

// 电流环控制
float PID_Current_Control(float current_set, float current_actual, float dt)
{
    return PID_Calculate(&pid_current, current_set, current_actual, dt);
}

7、电源控制任务

c 复制代码
// power_control.c
#include "power_control.h"

// 电源控制状态机
void Power_Control_Task(void *argument)
{
    static uint32_t last_time = 0;
    float duty_cycle;
    float dt;
    
    while(1)
    {
        // 计算时间间隔
        uint32_t current_time = HAL_GetTick();
        dt = (current_time - last_time) / 1000.0f;  // 秒
        if(dt <= 0) dt = 0.001f;
        last_time = current_time;
        
        // 读取实际值
        power.voltage_actual = Read_Voltage();
        power.current_actual = Read_Current();
        power.temperature = Read_Temperature();
        
        // 计算功率
        power.power = power.voltage_actual * power.current_actual;
        
        if(power.enable)
        {
            // 恒压/恒流模式切换
            if(power.current_actual >= power.current_set)
            {
                // 进入恒流模式
                duty_cycle = PID_Current_Control(power.current_set, 
                                                power.current_actual, dt);
            }
            else
            {
                // 进入恒压模式
                duty_cycle = PID_Voltage_Control(power.voltage_set, 
                                                power.voltage_actual, dt);
            }
            
            // 设置PWM
            PWM_Set_Duty(duty_cycle);
        }
        else
        {
            // 关闭输出
            PWM_Set_Duty(0);
        }
        
        // 任务延时
        osDelay(10);  // 100Hz控制频率
    }
}

8、保护功能

c 复制代码
// protection.c
#include "protection.h"

// 保护状态
static Protect_State_t protect_state = PROTECT_NONE;
static uint32_t fault_timer = 0;

// 保护检查任务
void Protection_Task(void *argument)
{
    static uint8_t ovp_count = 0;
    static uint8_t ocp_count = 0;
    
    while(1)
    {
        // 过压保护 (30.5V)
        if(power.voltage_actual > 30.5f)
        {
            ovp_count++;
            if(ovp_count > 5)  // 连续5次过压
            {
                protect_state = PROTECT_OVP;
                Power_Enable(0);
                fault_timer = HAL_GetTick();
            }
        }
        else
        {
            ovp_count = 0;
        }
        
        // 过流保护 (3.2A)
        if(power.current_actual > 3.2f)
        {
            ocp_count++;
            if(ocp_count > 5)  // 连续5次过流
            {
                protect_state = PROTECT_OCP;
                Power_Enable(0);
                fault_timer = HAL_GetTick();
            }
        }
        else
        {
            ocp_count = 0;
        }
        
        // 过温保护 (80°C)
        if(power.temperature > 80.0f)
        {
            protect_state = PROTECT_OTP;
            Power_Enable(0);
            fault_timer = HAL_GetTick();
        }
        
        // 短路保护
        if(power.voltage_actual < 1.0f && power.current_actual > 2.0f)
        {
            protect_state = PROTECT_SCP;
            Power_Enable(0);
            fault_timer = HAL_GetTick();
        }
        
        // 自动恢复
        if(protect_state != PROTECT_NONE)
        {
            if(HAL_GetTick() - fault_timer > 5000)  // 5秒后自动恢复
            {
                protect_state = PROTECT_NONE;
                Power_Enable(1);
            }
        }
        
        osDelay(100);  // 10Hz保护检查
    }
}

// 获取保护状态
Protect_State_t Get_Protect_State(void)
{
    return protect_state;
}

// 清除保护
void Clear_Protection(void)
{
    protect_state = PROTECT_NONE;
    Power_Enable(1);
}

9、用户界面

c 复制代码
// user_interface.c
#include "user_interface.h"

// 编码器处理
void Encoder_Handler(void)
{
    static int16_t last_count = 0;
    int16_t current_count = Encoder_Get_Count();
    int16_t delta = current_count - last_count;
    
    if(delta != 0)
    {
        if(encoder_mode == MODE_VOLTAGE)
        {
            // 调整电压
            power.voltage_set += delta * 0.1f;  // 0.1V/步
            if(power.voltage_set < 1.0f) power.voltage_set = 1.0f;
            if(power.voltage_set > 30.0f) power.voltage_set = 30.0f;
        }
        else if(encoder_mode == MODE_CURRENT)
        {
            // 调整电流
            power.current_set += delta * 0.01f;  // 10mA/步
            if(power.current_set < 0.1f) power.current_set = 0.1f;
            if(power.current_set > 3.0f) power.current_set = 3.0f;
        }
        
        last_count = current_count;
    }
    
    // 编码器按键
    if(Encoder_Button_Pressed())
    {
        encoder_mode = (encoder_mode + 1) % 2;  // 切换模式
    }
}

// UI任务
void UI_Task(void *argument)
{
    char buffer[32];
    
    while(1)
    {
        // 处理编码器
        Encoder_Handler();
        
        // 更新LCD显示
        LCD_Clear();
        
        // 显示电压
        sprintf(buffer, "Vset: %.1fV", power.voltage_set);
        LCD_Write_String(0, 0, buffer);
        
        sprintf(buffer, "Vout: %.2fV", power.voltage_actual);
        LCD_Write_String(0, 1, buffer);
        
        // 显示电流
        sprintf(buffer, "Iset: %.2fA", power.current_set);
        LCD_Write_String(0, 2, buffer);
        
        sprintf(buffer, "Iout: %.3fA", power.current_actual);
        LCD_Write_String(0, 3, buffer);
        
        // 显示功率和温度
        sprintf(buffer, "P: %.1fW T: %.1fC", power.power, power.temperature);
        LCD_Write_String(0, 4, buffer);
        
        // 显示模式
        if(encoder_mode == MODE_VOLTAGE)
            LCD_Write_String(0, 5, "Mode: Voltage");
        else
            LCD_Write_String(0, 5, "Mode: Current");
        
        // 显示保护状态
        if(protect_state != PROTECT_NONE)
        {
            switch(protect_state)
            {
                case PROTECT_OVP: LCD_Write_String(0, 6, "PROTECT: OVP"); break;
                case PROTECT_OCP: LCD_Write_String(0, 6, "PROTECT: OCP"); break;
                case PROTECT_OTP: LCD_Write_String(0, 6, "PROTECT: OTP"); break;
                case PROTECT_SCP: LCD_Write_String(0, 6, "PROTECT: SCP"); break;
            }
        }
        
        // 任务延时
        osDelay(200);  // 5Hz刷新
    }
}

10、校准功能

c 复制代码
// calibration.c
#include "calibration.h"

// 校准参数
typedef struct {
    float voltage_gain;    // 电压增益
    float voltage_offset;  // 电压偏移
    float current_gain;    // 电流增益
    float current_offset;  // 电流偏移
} Calibration_Params_t;

static Calibration_Params_t calib = {1.0f, 0.0f, 1.0f, 0.0f};

// 电压校准
void Calibrate_Voltage(float actual_voltage)
{
    float measured_voltage = Read_Voltage();
    
    // 计算增益和偏移
    // 假设两点校准:0V和10V
    static uint8_t calib_step = 0;
    
    if(calib_step == 0)
    {
        // 零点校准
        calib.voltage_offset = actual_voltage - measured_voltage;
        calib_step = 1;
    }
    else if(calib_step == 1)
    {
        // 增益校准
        float gain = (actual_voltage - calib.voltage_offset) / measured_voltage;
        calib.voltage_gain = gain;
        calib_step = 0;
    }
}

// 应用校准
float Apply_Voltage_Calibration(float raw_voltage)
{
    return raw_voltage * calib.voltage_gain + calib.voltage_offset;
}

float Apply_Current_Calibration(float raw_current)
{
    return raw_current * calib.current_gain + calib.current_offset;
}

参考代码 基于STM32F103的数控电源电路设计输出电源1-30V可调 www.youwenfan.com/contentcsu/70126.html

六、串口通信协议

c 复制代码
// serial_protocol.c
#include "serial_protocol.h"

// 通信协议
typedef struct {
    uint8_t header[2];      // 0xAA 0x55
    uint8_t cmd;           // 命令
    uint8_t length;        // 数据长度
    uint8_t data[16];      // 数据
    uint8_t checksum;      // 校验和
} Serial_Packet_t;

// 命令定义
#define CMD_SET_VOLTAGE    0x01
#define CMD_SET_CURRENT    0x02
#define CMD_GET_STATUS     0x03
#define CMD_ENABLE_OUTPUT  0x04
#define CMD_CALIBRATE      0x05

// 串口接收处理
void UART_Rx_Handler(uint8_t *data, uint16_t size)
{
    static uint8_t rx_buffer[32];
    static uint8_t rx_index = 0;
    
    for(int i = 0; i < size; i++)
    {
        rx_buffer[rx_index++] = data[i];
        
        // 检查包头
        if(rx_index >= 2 && rx_buffer[0] == 0xAA && rx_buffer[1] == 0x55)
        {
            if(rx_index >= 4)  // 至少4字节
            {
                uint8_t pkt_length = rx_buffer[3];
                if(rx_index >= pkt_length + 5)  // 完整包
                {
                    Process_Packet((Serial_Packet_t*)rx_buffer);
                    rx_index = 0;
                }
            }
        }
        else if(rx_index >= 2)
        {
            // 包头错误,清空缓冲区
            rx_index = 0;
        }
    }
}

// 处理数据包
void Process_Packet(Serial_Packet_t *packet)
{
    uint8_t checksum = Calculate_Checksum(packet);
    if(checksum != packet->checksum) return;
    
    switch(packet->cmd)
    {
        case CMD_SET_VOLTAGE:
        {
            float voltage = *(float*)packet->data;
            Power_Set_Voltage(voltage);
            break;
        }
            
        case CMD_SET_CURRENT:
        {
            float current = *(float*)packet->data;
            Power_Set_Current(current);
            break;
        }
            
        case CMD_GET_STATUS:
        {
            Send_Status_Packet();
            break;
        }
            
        case CMD_ENABLE_OUTPUT:
        {
            Power_Enable(packet->data[0]);
            break;
        }
    }
}

七、PCB设计注意事项

kicad 复制代码
PCB设计要点:

1. 功率部分:
   - 输入/输出电容靠近MOSFET
   - 大电流路径加宽(2mm/A)
   - 地平面完整
   - 散热焊盘

2. 信号部分:
   - ADC走线远离功率线
   - 模拟地单点连接
   - 反馈线短而粗

3. 布局:
   - 功率在左侧
   - 控制在中部
   - 接口在右侧
   - 散热器在上方

4. 过孔:
   - 功率过孔多打
   - 信号过孔避让
   - 地过孔包围

5. 丝印:
   - 关键测试点
   - 接口定义
   - 警告标识

八、调试与测试

c 复制代码
// 测试程序
void Test_Power_Supply(void)
{
    printf("=== 数控电源测试 ===\n");
    
    // 1. 基本功能测试
    printf("1. 基本功能测试...\n");
    Power_Set_Voltage(5.0f);
    Power_Set_Current(1.0f);
    Power_Enable(1);
    HAL_Delay(1000);
    
    // 2. 电压测试
    printf("2. 电压测试...\n");
    for(float v = 1.0f; v <= 30.0f; v += 1.0f)
    {
        Power_Set_Voltage(v);
        HAL_Delay(100);
        float measured = Read_Voltage();
        printf("Set: %.1fV, Measured: %.2fV\n", v, measured);
    }
    
    // 3. 电流测试
    printf("3. 电流测试...\n");
    for(float i = 0.1f; i <= 3.0f; i += 0.1f)
    {
        Power_Set_Current(i);
        HAL_Delay(100);
        float measured = Read_Current();
        printf("Set: %.1fA, Measured: %.3fA\n", i, measured);
    }
    
    // 4. 保护测试
    printf("4. 保护测试...\n");
    Power_Set_Voltage(31.0f);  // 触发过压
    HAL_Delay(100);
    
    printf("测试完成!\n");
}
相关推荐
LCG元1 小时前
STM32实战:基于STM32F103的智能鱼缸监控投喂系统(水质监测+自动换水)
stm32·单片机·嵌入式硬件
深圳市晨芯阳科技有限公司1 小时前
晨芯阳科技HC358-N双通道运算放大IC
科技·单片机·嵌入式硬件
一路往蓝-Anbo1 小时前
第四章:手撕协议栈 —— 缓冲区与结构体数据的 Mock 技巧
网络·stm32·单片机·嵌入式硬件·软件工程·tdd
jghhh012 小时前
STM32指纹密码锁的程序
stm32·单片机·嵌入式硬件
Achou.Wang2 小时前
从 Atomic 到 Futex:深入解析并发同步的三重境界
单片机·嵌入式硬件
不怕犯错,就怕不做2 小时前
linux的notifier_block内核通知链
linux·驱动开发·嵌入式硬件
时空自由民.2 小时前
Arm Coretex-M核MCU做IAP/OTA升级时候为什么要做中断向量表地址偏移?
arm开发·单片机·嵌入式硬件
不脱发的程序猿2 小时前
MCU升级固件合并和转换工具
单片机·嵌入式硬件
qq_370773093 小时前
OpenOCD 嵌入式调试完全指南:从零开始调试 GD32/STM32 单片机
stm32·单片机·嵌入式硬件·openocd