基于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");
}
相关推荐
Zhao136824553911 小时前
DP4330A 与DP4363 测试对比
嵌入式硬件
辛迪聊物业数字化1 小时前
智慧社区小程序落地避坑指南:3类物业方案选型+成本测算,线上服务零翻车
大数据·嵌入式硬件·百度·系统架构
电子科技圈2 小时前
Arm电机控制开发工具哪家强?
arm开发·单片机·嵌入式硬件·设计模式·软件构建
JasmineX-12 小时前
下位机直接控制57步进电机匀速转动
stm32·单片机·嵌入式硬件
聆思科技AI芯片2 小时前
【AI硬件开发上手教程】怎么使用AI编程实现小聆AI语音控制舵机
人工智能·嵌入式硬件·开源·ai编程·智能硬件
abc light3 小时前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发
吠品12 小时前
智谱开源 ZCode 之后,真正的考试才开始
单片机·嵌入式硬件·1024程序员节
Chery114014 小时前
高速ADC与精密DAC怎么选?DP9230D与DP8532D应用解析
嵌入式硬件·物联网·射频工程
小李不想当小白17 小时前
SPI通信外设与W25Q64 (硬件SPI)(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
LCG米17 小时前
STM32驱动W5500以太网模块实测:TCP吞吐瓶颈定位、TX指针回绕陷阱与断线重连保活落地
stm32·单片机·嵌入式硬件·tcp/ip