一、系统总体设计
拓扑:同步 / 非同步 Buck(降压)
控制核心:STM32F103C8T6 / CBT6
控制方式:数字 PID + PWM + ADC 反馈
设定方式:电位器 / 按键 / 串口
显示:OLED / LCD / 串口打印
┌──────────┐
│ STM32 │
│ PWM OUT ├────► MOSFET Driver ──► BUCK
│ ADC IN │◄──── 电压反馈(分压)
│ ADC IN │◄──── 电流采样
└──────────┘
二、硬件关键参数
| 项目 | 推荐 |
|---|---|
| MCU | STM32F103C8T6 |
| PWM 定时器 | TIM1(高级定时器) |
| PWM 频率 | 20–65 kHz(常用 40kHz) |
| ADC | ADC1 |
| 电压采样 | 电阻分压(到 0–3.3V) |
| 电流采样 | 运放 + 采样电阻 |
| MOS 驱动 | IR2104 / TC4427 / AO3400 |
| 输出电感 | 33–100 µH |
| 输出电容 | 220–470 µF |
三、核心控制
目标电压 − 实际电压 → PID → 改变 PWM 占空比
四、关键源码
1、PWM 初始化(TIM1_CH1)
void PWM_Init(void)
{
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 = 999; // 72MHz / (999+1) = 72kHz
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
}
2、ADC 初始化(电压 + 电流)
void ADC_Init_Buck(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; // PA0:电压 PA1:电流
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
uint16_t ADC_Read(uint8_t ch)
{
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_55Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
return ADC_GetConversionValue(ADC1);
}
3、PID 控制器
typedef struct
{
float Kp;
float Ki;
float Kd;
float err;
float last_err;
float integral;
float out;
} PID_TypeDef;
void PID_Init(PID_TypeDef *pid)
{
pid->Kp = 0.8f;
pid->Ki = 0.05f;
pid->Kd = 0.01f;
pid->err = 0;
pid->last_err = 0;
pid->integral = 0;
}
float PID_Calc(PID_TypeDef *pid, float target, float feedback)
{
pid->err = target - feedback;
pid->integral += pid->err;
if(pid->integral > 500) pid->integral = 500;
if(pid->integral < -500) pid->integral = -500;
pid->out = pid->Kp * pid->err +
pid->Ki * pid->integral +
pid->Kd * (pid->err - pid->last_err);
pid->last_err = pid->err;
return pid->out;
}
4、主循环(数控电源核心)
#define VREF 3.3f
#define ADC_MAX 4095.0f
PID_TypeDef pid;
int main(void)
{
float v_set = 12.0f; // 目标电压
float v_fb;
float duty;
SystemInit();
PWM_Init();
ADC_Init_Buck();
PID_Init(&pid);
while(1)
{
uint16_t adc_val = ADC_Read(ADC_Channel_0);
v_fb = adc_val * VREF / ADC_MAX * 11.0f; // 假设 1:10 分压
duty = PID_Calc(&pid, v_set, v_fb);
if(duty < 0) duty = 0;
if(duty > 999) duty = 999;
TIM_SetCompare1(TIM1, (uint16_t)duty);
Delay_ms(10);
}
}
五、保护功能
过压保护
if(v_fb > 24.0f) TIM_SetCompare1(TIM1, 0);
过流保护
if(current > 5.0f) TIM_SetCompare1(TIM1, 0);
软启动
for(i=0;i<v_set;i+=0.1){ v_set_now=i; Delay_ms(5); }
参考代码 基于STM32F103的DCDC数控开关电源源码 www.youwenfan.com/contentcsv/72889.html
六、常见问题
| 问题 | 原因 |
|---|---|
| 输出抖动 | PID 参数过大 |
| 空载不稳 | 没有最小占空比限制 |
| 上电炸管 | 没有软启动 |
| 电压不准 | 没校准分压比 |
| 效率低 | PWM 频率太高 |

1625

被折叠的 条评论
为什么被折叠?



