基于STM32的BUCK变换器闭环控制程序
一、系统架构设计
1.1 硬件配置
BUCK电路参数:
- 输入电压:12V-24V
- 输出电压:5V(可调)
- 最大输出电流:3A
- 开关频率:50kHz
- 电感:47μH
- 输出电容:220μF
STM32F103C8T6配置:
- PWM输出:TIM1_CH1 (PA8) → BUCK MOSFET栅极
- 电压采样:ADC1_IN0 (PA0) → 输出电压分压
- 电流采样:ADC1_IN1 (PA1) → 电流采样电阻
- 保护输入:PB0 → 过流保护
1.2 控制原理
┌─────────────────────────────────────────────┐
│ BUCK闭环控制系统 │
├─────────────────────────────────────────────┤
│ 参考电压Vref ──→ (+) │
│ │ │
│ ↓ │
│ PID控制器 │
│ │ │
│ ↓ │
│ PWM占空比调整 │
│ │ │
│ ↓ │
│ BUCK功率级 │
│ │ │
│ ↓ │
│ 输出电压Vo │
│ │ │
│ └──────→ ADC采样 ←──────┘
└─────────────────────────────────────────────┘
二、完整源码实现
2.1 主程序(main.c)
/**
* @file main.c
* @brief STM32 BUCK变换器闭环控制程序
* @version 2.0
*/
#include "stm32f10x.h"
#include "pid.h"
#include "pwm.h"
#include "adc.h"
#include "voltage.h"
#include "protection.h"
/* 系统参数 */
#define VREF_TARGET 5.0f // 目标输出电压5V
#define VIN_MAX 24.0f // 最大输入电压
#define VOUT_MAX 12.0f // 最大输出电压
#define IOUT_MAX 3.0f // 最大输出电流
#define PWM_FREQ 50000 // PWM频率50kHz
#define ADC_SAMPLE_FREQ 10000 // ADC采样频率10kHz
/* 全局变量 */
BuckSystem buck_sys;
PID_TypeDef voltage_pid;
PID_TypeDef current_pid;
ControlStatus ctrl_status;
/* BUCK系统结构 */
typedef struct {
float vin; // 输入电压
float vout; // 输出电压
float iout; // 输出电流
float duty_cycle; // PWM占空比
float vref; // 参考电压
uint8_t enable; // 使能标志
uint8_t fault; // 故障标志
} BuckSystem;
/* 控制状态 */
typedef struct {
uint32_t sample_count; // 采样计数
uint32_t pwm_period; // PWM周期
uint32_t adc_value_vout; // ADC输出电压值
uint32_t adc_value_iout; // ADC输出电流值
float voltage_error; // 电压误差
float current_error; // 电流误差
} ControlStatus;
int main(void)
{
/* 1. 系统初始化 */
System_Init();
/* 2. 外设初始化 */
Delay_Init();
PWM_Init(PWM_FREQ);
ADC_Init(ADC_SAMPLE_FREQ);
Protection_Init();
/* 3. PID控制器初始化 */
PID_Init(&voltage_pid, 0.5f, 0.1f, 0.05f); // 电压环PID参数
PID_Init(¤t_pid, 1.0f, 0.2f, 0.1f); // 电流环PID参数
/* 4. BUCK系统初始化 */
Buck_Init(&buck_sys);
buck_sys.vref = VREF_TARGET;
buck_sys.enable = 1;
/* 5. 显示初始化信息 */
printf("BUCK Converter Started\r\n");
printf("Target Voltage: %.2fV\r\n", VREF_TARGET);
/* 6. 主循环 */
while(1)
{
/* 6.1 采样电压和电流 */
buck_sys.vin = ADC_GetVoltage(ADC_VIN);
buck_sys.vout = ADC_GetVoltage(ADC_VOUT);
buck_sys.iout = ADC_GetCurrent(ADC_IOUT);
/* 6.2 保护检测 */
if (Protection_Check(&buck_sys))
{
buck_sys.fault = 1;
PWM_Disable();
printf("Fault Detected! System Stopped.\r\n");
continue;
}
/* 6.3 闭环控制 */
if (buck_sys.enable && !buck_sys.fault)
{
/* 电压环控制 */
buck_sys.duty_cycle = PID_Calculate(&voltage_pid,
buck_sys.vref,
buck_sys.vout);
/* 限幅保护 */
if (buck_sys.duty_cycle > 0.9f) buck_sys.duty_cycle = 0.9f;
if (buck_sys.duty_cycle < 0.05f) buck_sys.duty_cycle = 0.05f;
/* 更新PWM占空比 */
PWM_SetDuty(buck_sys.duty_cycle);
/* 电流环控制(可选) */
if (buck_sys.iout > IOUT_MAX)
{
float current_duty = PID_Calculate(¤t_pid,
IOUT_MAX,
buck_sys.iout);
if (current_duty < buck_sys.duty_cycle)
buck_sys.duty_cycle = current_duty;
}
}
/* 6.4 状态显示(每1秒) */
static uint32_t last_display = 0;
if (Get_Tick() - last_display > 1000)
{
printf("Vin: %.2fV, Vout: %.2fV, Iout: %.2fA, Duty: %.1f%%\r\n",
buck_sys.vin, buck_sys.vout, buck_sys.iout,
buck_sys.duty_cycle * 100);
last_display = Get_Tick();
}
/* 6.5 延时控制采样率 */
Delay_Ms(1); // 1kHz控制频率
}
}
/* 系统初始化 */
void System_Init(void)
{
/* 系统时钟配置:72MHz */
SystemClock_Init();
/* 中断优先级分组 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 初始化全局变量 */
memset(&buck_sys, 0, sizeof(BuckSystem));
memset(&ctrl_status, 0, sizeof(ControlStatus));
buck_sys.vref = VREF_TARGET;
buck_sys.enable = 0;
buck_sys.fault = 0;
}
2.2 PID控制器(pid.c)
/**
* @file pid.c
* @brief PID控制器实现
*/
#include "pid.h"
#include "math.h"
/* PID初始化 */
void PID_Init(PID_TypeDef* pid, float kp, float ki, float kd)
{
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->integral = 0.0f;
pid->prev_error = 0.0f;
pid->output = 0.0f;
pid->max_output = 1.0f; // 最大输出1.0(对应100%占空比)
pid->min_output = 0.0f; // 最小输出0.0
pid->integral_limit = 0.5f; // 积分限幅
}
/* PID计算 */
float PID_Calculate(PID_TypeDef* pid, float target, float feedback)
{
float error;
float derivative;
float output;
/* 计算误差 */
error = target - feedback;
/* 比例项 */
output = pid->kp * error;
/* 积分项(带抗积分饱和) */
if (fabs(output) < pid->max_output)
{
pid->integral += error;
/* 积分限幅 */
if (pid->integral > pid->integral_limit)
pid->integral = pid->integral_limit;
if (pid->integral < -pid->integral_limit)
pid->integral = -pid->integral_limit;
}
output += pid->ki * pid->integral;
/* 微分项 */
derivative = error - pid->prev_error;
output += pid->kd * derivative;
pid->prev_error = error;
/* 输出限幅 */
if (output > pid->max_output) output = pid->max_output;
if (output < pid->min_output) output = pid->min_output;
pid->output = output;
return output;
}
/* 增量式PID(适合BUCK控制) */
float PID_Incremental(PID_TypeDef* pid, float target, float feedback)
{
float error;
float delta_output;
error = target - feedback;
/* 增量计算 */
delta_output = pid->kp * (error - pid->prev_error)
+ pid->ki * error
+ pid->kd * (error - 2*pid->prev_error + pid->prev_prev_error);
pid->output += delta_output;
/* 限幅 */
if (pid->output > pid->max_output) pid->output = pid->max_output;
if (pid->output < pid->min_output) pid->output = pid->min_output;
/* 保存历史误差 */
pid->prev_prev_error = pid->prev_error;
pid->prev_error = error;
return pid->output;
}
2.3 PWM驱动(pwm.c)
/**
* @file pwm.c
* @brief PWM驱动 - TIM1高级定时器
*/
#include "pwm.h"
#include "stm32f10x_tim.h"
/* PWM初始化 */
void PWM_Init(uint32_t frequency)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* 使能时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE);
/* 配置PA8为TIM1_CH1输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 时基配置 */
TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / frequency - 1; // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 0; // 预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* PWM模式配置 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* 使能主输出 */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
}
/* 设置PWM占空比 */
void PWM_SetDuty(float duty_cycle)
{
uint16_t pulse;
uint16_t period = TIM1->ARR;
/* 限制占空比范围 */
if (duty_cycle > 0.95f) duty_cycle = 0.95f;
if (duty_cycle < 0.05f) duty_cycle = 0.05f;
/* 计算脉冲宽度 */
pulse = (uint16_t)(period * duty_cycle);
TIM_SetCompare1(TIM1, pulse);
}
/* 使能PWM输出 */
void PWM_Enable(void)
{
TIM_Cmd(TIM1, ENABLE);
}
/* 禁用PWM输出 */
void PWM_Disable(void)
{
TIM_Cmd(TIM1, DISABLE);
TIM_SetCompare1(TIM1, 0); // 占空比设为0
}
2.4 ADC采样(adc.c)
/**
* @file adc.c
* @brief ADC采样 - 电压和电流检测
*/
#include "adc.h"
#include "stm32f10x_adc.h"
/* 电压采样参数 */
#define VOLTAGE_DIVIDER_RATIO 11.0f // 分压比:R1=100K, R2=10K
#define CURRENT_SENSE_RATIO 0.1f // 电流采样电阻0.1Ω,放大倍数20
#define ADC_REF_VOLTAGE 3.3f // ADC参考电压3.3V
#define ADC_RESOLUTION 4095.0f // 12位ADC
/* ADC初始化 */
void ADC_Init(uint32_t sample_freq)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* 使能时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* 配置PA0(ADC_IN0)和PA1(ADC_IN1)为模拟输入 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ADC配置 */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO; // TIM3触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 2;
ADC_Init(ADC1, &ADC_InitStructure);
/* 配置ADC通道 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // VOUT
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); // IOUT
/* 使能ADC */
ADC_Cmd(ADC1, ENABLE);
/* ADC校准 */
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
/* 配置TIM3触发ADC采样 */
TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / sample_freq - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* 选择TIM3的更新事件作为触发输出 */
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
TIM_Cmd(TIM3, ENABLE);
}
/* 获取输出电压 */
float ADC_GetVoltage(uint8_t channel)
{
uint16_t adc_value;
float voltage;
if (channel == ADC_VOUT)
{
adc_value = ADC_GetConversionValue(ADC1);
/* 计算实际电压:ADC值 → 电压值 → 分压前电压 */
voltage = (adc_value * ADC_REF_VOLTAGE / ADC_RESOLUTION) * VOLTAGE_DIVIDER_RATIO;
}
else if (channel == ADC_IOUT)
{
adc_value = ADC_GetConversionValue(ADC1);
/* 计算电流:电压差 → 电流值 */
voltage = (adc_value * ADC_REF_VOLTAGE / ADC_RESOLUTION) / CURRENT_SENSE_RATIO;
}
return voltage;
}
/* 获取输入电压 */
float ADC_GetInputVoltage(void)
{
return ADC_GetVoltage(ADC_VIN);
}
/* 获取输出电流 */
float ADC_GetCurrent(uint8_t channel)
{
return ADC_GetVoltage(ADC_IOUT);
}
2.5 保护功能(protection.c)
/**
* @file protection.c
* @brief BUCK变换器保护功能
*/
#include "protection.h"
#include "pwm.h"
/* 保护阈值 */
#define OVER_VOLTAGE_THRESHOLD 12.0f // 过压保护12V
#define UNDER_VOLTAGE_THRESHOLD 4.0f // 欠压保护4V
#define OVER_CURRENT_THRESHOLD 3.5f // 过流保护3.5A
#define OVER_TEMPERATURE_THRESHOLD 85.0f // 过温保护85°C
/* 保护状态 */
typedef enum {
PROTECTION_NORMAL = 0,
PROTECTION_OVER_VOLTAGE,
PROTECTION_UNDER_VOLTAGE,
PROTECTION_OVER_CURRENT,
PROTECTION_OVER_TEMPERATURE
} ProtectionState;
/* 保护检测 */
uint8_t Protection_Check(BuckSystem* buck)
{
static ProtectionState state = PROTECTION_NORMAL;
/* 1. 过压保护 */
if (buck->vout > OVER_VOLTAGE_THRESHOLD)
{
state = PROTECTION_OVER_VOLTAGE;
printf("Over Voltage Protection! Vout=%.2fV\r\n", buck->vout);
return 1; // 保护触发
}
/* 2. 欠压保护 */
if (buck->vout < UNDER_VOLTAGE_THRESHOLD && buck->enable)
{
state = PROTECTION_UNDER_VOLTAGE;
printf("Under Voltage Protection! Vout=%.2fV\r\n", buck->vout);
return 1;
}
/* 3. 过流保护 */
if (buck->iout > OVER_CURRENT_THRESHOLD)
{
state = PROTECTION_OVER_CURRENT;
printf("Over Current Protection! Iout=%.2fA\r\n", buck->iout);
return 1;
}
/* 4. 输入欠压保护 */
if (buck->vin < 8.0f) // 输入电压低于8V
{
state = PROTECTION_UNDER_VOLTAGE;
printf("Input Under Voltage! Vin=%.2fV\r\n", buck->vin);
return 1;
}
/* 5. 过温保护(如果有温度传感器) */
// if (Temperature_Get() > OVER_TEMPERATURE_THRESHOLD)
// {
// state = PROTECTION_OVER_TEMPERATURE;
// return 1;
// }
state = PROTECTION_NORMAL;
return 0; // 无保护触发
}
/* 保护初始化 */
void Protection_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 配置保护引脚(PB0) */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/* 软启动控制 */
void Soft_Start(BuckSystem* buck)
{
static float startup_duty = 0.0f;
static uint32_t last_time = 0;
if (Get_Tick() - last_time > 10) // 每10ms增加一次占空比
{
if (startup_duty < buck->duty_cycle)
{
startup_duty += 0.01f; // 每次增加1%
PWM_SetDuty(startup_duty);
}
else
{
startup_duty = buck->duty_cycle;
}
last_time = Get_Tick();
}
}
2.6 头文件(buck.h)
/**
* @file buck.h
* @brief BUCK变换器头文件
*/
#ifndef __BUCK_H
#define __BUCK_H
#include "stm32f10x.h"
#include "pid.h"
/* ADC通道定义 */
#define ADC_VIN 0 // 输入电压
#define ADC_VOUT 1 // 输出电压
#define ADC_IOUT 2 // 输出电流
/* 全局变量声明 */
extern BuckSystem buck_sys;
extern PID_TypeDef voltage_pid;
extern PID_TypeDef current_pid;
extern ControlStatus ctrl_status;
/* 函数声明 */
void System_Init(void);
void Buck_Init(BuckSystem* buck);
void PWM_Init(uint32_t frequency);
void PWM_SetDuty(float duty_cycle);
void PWM_Enable(void);
void PWM_Disable(void);
void ADC_Init(uint32_t sample_freq);
float ADC_GetVoltage(uint8_t channel);
float ADC_GetCurrent(uint8_t channel);
float ADC_GetInputVoltage(void);
uint8_t Protection_Check(BuckSystem* buck);
void Protection_Init(void);
void Soft_Start(BuckSystem* buck);
#endif /* __BUCK_H */
三、Keil工程配置
3.1 工程设置
Target:
- Device: STM32F103C8T6
- Clock: 8MHz HSE → 72MHz PLL
- RAM: 20KB
- Flash: 64KB
C/C++:
- Define: USE_STDPERIPH_DRIVER, STM32F103C8T6
- Include Paths:
.\
..\Libraries\CMSIS\Include
..\Libraries\STM32F10x_StdPeriph_Driver\inc
..\User
..\User\drivers
..\User\control
Linker:
- IROM1: 0x08000000, 0x10000 (64KB Flash)
- IRAM1: 0x20000000, 0x5000 (20KB RAM)
四、测试与调试
4.1 测试步骤
/* 测试1:PWM输出测试 */
void Test_PWM_Output(void)
{
printf("Testing PWM Output...\r\n");
PWM_Init(50000); // 50kHz
for (int duty = 10; duty <= 90; duty += 10)
{
PWM_SetDuty(duty / 100.0f);
printf("Duty Cycle: %d%%\r\n", duty);
Delay_Ms(1000);
}
PWM_Disable();
printf("PWM Test Completed!\r\n");
}
/* 测试2:ADC采样测试 */
void Test_ADC_Sampling(void)
{
float vin, vout, iout;
ADC_Init(10000); // 10kHz采样
printf("Testing ADC Sampling...\r\n");
for (int i = 0; i < 10; i++)
{
vin = ADC_GetInputVoltage();
vout = ADC_GetVoltage(ADC_VOUT);
iout = ADC_GetCurrent(ADC_IOUT);
printf("Vin=%.2fV, Vout=%.2fV, Iout=%.2fA\r\n", vin, vout, iout);
Delay_Ms(1000);
}
}
/* 测试3:闭环控制测试 */
void Test_ClosedLoopControl(void)
{
printf("Testing Closed Loop Control...\r\n");
buck_sys.vref = 5.0f; // 目标5V
buck_sys.enable = 1;
for (int i = 0; i < 100; i++)
{
buck_sys.vout = ADC_GetVoltage(ADC_VOUT);
/* 简单比例控制 */
float error = buck_sys.vref - buck_sys.vout;
buck_sys.duty_cycle = 0.5f + error * 0.1f; // 比例控制
/* 限幅 */
if (buck_sys.duty_cycle > 0.9f) buck_sys.duty_cycle = 0.9f;
if (buck_sys.duty_cycle < 0.1f) buck_sys.duty_cycle = 0.1f;
PWM_SetDuty(buck_sys.duty_cycle);
printf("Target: %.2fV, Actual: %.2fV, Duty: %.1f%%\r\n",
buck_sys.vref, buck_sys.vout, buck_sys.duty_cycle * 100);
Delay_Ms(100);
}
}
4.2 调试输出示例
BUCK Converter Started
Target Voltage: 5.00V
Vin: 12.00V, Vout: 4.98V, Iout: 0.15A, Duty: 42.5%
Vin: 12.00V, Vout: 5.01V, Iout: 0.18A, Duty: 41.8%
Vin: 12.00V, Vout: 4.99V, Iout: 0.22A, Duty: 42.1%
Vin: 12.00V, Vout: 5.00V, Iout: 0.20A, Duty: 41.9%
参考代码 简单的BUCK闭环程序 www.youwenfan.com/contentcnu/56424.html
五、优化建议
5.1 性能优化
- 数字PID:使用增量式PID,避免积分饱和
- 前馈控制:加入输入电压前馈,提高动态响应
- 软启动:逐渐增加占空比,避免启动冲击
- 滞环控制:加入电压滞环,减少PWM抖动
5.2 功能扩展
/* 多电压输出 */
typedef struct {
float vout1; // 5V输出
float vout2; // 3.3V输出
float vout3; // 12V输出
} MultiOutput;
/* 同步整流 */
void SyncRect_Enable(void)
{
// 控制同步整流MOSFET
}
/* 负载均流(多相BUCK) */
void Load_Sharing(uint8_t phase_num)
{
// 多相BUCK的负载均流控制
}

浙公网安备 33010602011771号