基于STM32的多功能数控电源设计
一、系统概述与核心功能
1. 系统定位
基于STM32的多功能数控电源是一款高精度、宽范围、智能化的实验室电源,支持恒压(CV)和恒流(CC)两种工作模式,具备过压(OVP)、过流(OCP)、过温(OTP)等多重保护功能。系统采用PID闭环控制算法,通过STM32的PWM和ADC实现精确的电压/电流调节,并配备OLED显示屏和旋转编码器实现便捷的人机交互。
2. 核心功能模块
| 模块 | 功能描述 | 技术指标 |
|---|---|---|
| 电源变换 | 采用同步Buck拓扑,输入电压12-24V DC,输出0-30V/0-5A可调 | 效率≥92%,纹波≤50mVpp |
| 控制核心 | STM32F103C8T6,72MHz Cortex-M3,12位ADC,PWM分辨率1/1000 | 电压调节精度±0.05V,电流调节精度±0.01A |
| 采样反馈 | 高侧电流采样(INA240)+ 分压电阻电压采样,双路ADC同步采样 | 电压采样精度±0.5%,电流采样精度±1% |
| 人机交互 | 0.96寸OLED显示,旋转编码器调节参数,按键切换模式 | 显示分辨率128×64,参数调节步进0.01V/0.001A |
| 保护功能 | 过压保护(OVP)、过流保护(OCP)、过温保护(OTP)、短路保护 | 响应时间<10ms,保护精度±2% |
| 扩展接口 | USB通信(虚拟串口)、电压/电流校准接口、外部控制接口 | 支持PC端软件监控和控制 |
二、硬件设计方案
1. 核心硬件选型
| 模块 | 型号 | 关键参数 | 接口方式 |
|---|---|---|---|
| 主控MCU | STM32F103C8T6 | 72MHz,64KB Flash,20KB RAM,3个ADC,4个定时器 | 核心控制器 |
| 电源变换 | 同步Buck模块 | 输入12-24V,输出0-30V/5A,开关频率200kHz | 外部功率模块 |
| 电流采样 | INA240A2 | 增益50V/V,共模电压-4V至80V,带宽400kHz | ADC1_IN0(电流采样) |
| 电压采样 | 精密分压电阻 | 100kΩ+10kΩ 1%精度,分压比1/11 | ADC1_IN1(电压采样) |
| 显示模块 | OLED 12864(I2C) | 0.96寸,128×64像素,自发光 | I2C1(PB6/PB7) |
| 交互模块 | EC11旋转编码器+按键 | 20脉冲/圈,带按键功能 | PB0-PB2(编码器A/B/Z相) |
| 保护模块 | NTC热敏电阻+比较器 | 过温检测阈值85℃,硬件快速关断 | ADC1_IN2(温度采样) |
2. 硬件电路设计要点
2.1 电源变换电路(同步Buck)
输入电压Vin (12-24V)
│
├── 输入滤波电容(100μF+0.1μF)
│
├── 同步Buck控制器(如LM5176)
│ ├── PWM输入:STM32 PB1(TIM3_CH4)
│ ├── 反馈电压:来自输出电压分压
│ └── 使能控制:STM32 PB3
│
├── 功率电感(33μH,饱和电流≥8A)
├── 同步整流MOSFET(IRF540N×2)
├── 输出滤波电容(470μF+10μF)
│
└── 输出电压Vout (0-30V)
2.2 采样电路设计
电压采样:
Vout ──[100kΩ]──┬──[10kΩ]── GND
└── ADC1_IN1(电压采样点)
电流采样:
Vout ──[采样电阻0.01Ω]──负载
│
└── INA240A2(增益50V/V)
├── 输入+:采样电阻高端
├── 输入-:采样电阻低端
└── 输出:ADC1_IN0(电流采样点)
2.3 保护电路设计
过压保护(硬件):
Vout ──[分压电阻]──比较器+输入端
参考电压──比较器-输入端
比较器输出──STM32 PB4(外部中断)
当Vout > 设定阈值时,比较器输出低电平,触发中断关断PWM
过温保护:
NTC热敏电阻──ADC1_IN2
STM32实时监测温度,超过85℃时降低输出或关断
三、软件设计与核心代码
1. 系统架构(前后台系统)
采用前后台系统,以定时器中断为后台,主循环为前台:
-
TIM2定时器中断(1ms):执行PID控制算法,更新PWM输出
-
主循环:
- 读取旋转编码器和按键状态
- 更新OLED显示
- 检查保护条件并执行保护动作
- 处理USB通信命令
2. 核心代码实现(基于标准库)
2.1 PID控制算法
#include "pid.h"
// PID参数结构体
typedef struct {
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float setpoint; // 设定值
float feedback; // 反馈值
float integral; // 积分项
float prev_error; // 上次误差
float output; // 输出值
float output_min; // 输出最小值
float output_max; // 输出最大值
} PID_Controller_t;
// PID计算函数
float PID_Calculate(PID_Controller_t *pid) {
float error = pid->setpoint - pid->feedback;
// 比例项
float P = pid->Kp * error;
// 积分项(带抗饱和)
pid->integral += error;
if (pid->integral > pid->output_max) pid->integral = pid->output_max;
if (pid->integral < pid->output_min) pid->integral = pid->output_min;
float I = pid->Ki * pid->integral;
// 微分项
float D = pid->Kd * (error - pid->prev_error);
pid->prev_error = error;
// 计算输出并限幅
pid->output = P + I + D;
if (pid->output > pid->output_max) pid->output = pid->output_max;
if (pid->output < pid->output_min) pid->output = pid->output_min;
return pid->output;
}
// 电压PID控制器
PID_Controller_t voltage_pid = {
.Kp = 2.5f, // 比例系数
.Ki = 0.8f, // 积分系数
.Kd = 0.1f, // 微分系数
.setpoint = 12.0f, // 设定电压12V
.feedback = 0.0f, // 实际电压
.integral = 0.0f,
.prev_error = 0.0f,
.output = 0.0f,
.output_min = 0.0f,
.output_max = 1000.0f // PWM最大占空比
};
// 电流PID控制器
PID_Controller_t current_pid = {
.Kp = 1.5f,
.Ki = 0.5f,
.Kd = 0.05f,
.setpoint = 1.0f, // 设定电流1A
.feedback = 0.0f,
.integral = 0.0f,
.prev_error = 0.0f,
.output = 0.0f,
.output_min = 0.0f,
.output_max = 1000.0f
};
2.2 ADC采样与转换
#include "adc.h"
// ADC采样值转实际电压/电流
float ADC_ToVoltage(uint16_t adc_value) {
// ADC参考电压3.3V,12位分辨率
float voltage_adc = (float)adc_value * 3.3f / 4095.0f;
// 分压比1/11,实际电压 = 采样电压 × 11
return voltage_adc * 11.0f;
}
float ADC_ToCurrent(uint16_t adc_value) {
// INA240增益50V/V,采样电阻0.01Ω
// 电流 = (ADC电压 / 增益) / 采样电阻
float voltage_adc = (float)adc_value * 3.3f / 4095.0f;
return (voltage_adc / 50.0f) / 0.01f; // 单位:安培
}
// 读取电压和电流
void Read_Voltage_Current(float *voltage, float *current) {
// 启动ADC转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
uint16_t adc_voltage = ADC_GetConversionValue(ADC1);
ADC_SoftwareStartConvCmd(ADC2, ENABLE);
while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC));
uint16_t adc_current = ADC_GetConversionValue(ADC2);
*voltage = ADC_ToVoltage(adc_voltage);
*current = ADC_ToCurrent(adc_current);
}
2.3 PWM输出控制
#include "pwm.h"
// 初始化PWM(TIM3_CH4,PB1)
void PWM_Init(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 时基配置:72MHz / (71+1) = 1MHz
TIM_TimeBaseStructure.TIM_Period = 999; // ARR=999,PWM频率1kHz
TIM_TimeBaseStructure.TIM_Prescaler = 71; // PSC=71
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// PWM通道配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
// 设置PWM占空比(0-1000对应0-100%)
void PWM_SetDuty(uint16_t duty) {
if (duty > 1000) duty = 1000;
TIM_SetCompare4(TIM3, duty);
}
2.4 主控制逻辑
#include "main.h"
// 系统状态
typedef enum {
MODE_CV = 0, // 恒压模式
MODE_CC = 1 // 恒流模式
} PowerMode_t;
PowerMode_t system_mode = MODE_CV;
float set_voltage = 12.0f; // 设定电压
float set_current = 1.0f; // 设定电流
float actual_voltage = 0.0f; // 实际电压
float actual_current = 0.0f; // 实际电流
// TIM2中断服务函数(1ms执行一次PID控制)
void TIM2_IRQHandler(void) {
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
// 读取实际电压和电流
Read_Voltage_Current(&actual_voltage, &actual_current);
if (system_mode == MODE_CV) {
// 恒压模式:电压PID控制
voltage_pid.setpoint = set_voltage;
voltage_pid.feedback = actual_voltage;
float pid_output = PID_Calculate(&voltage_pid);
PWM_SetDuty((uint16_t)pid_output);
// 如果电流超过设定值,切换到恒流模式
if (actual_current > set_current * 1.05f) {
system_mode = MODE_CC;
}
} else {
// 恒流模式:电流PID控制
current_pid.setpoint = set_current;
current_pid.feedback = actual_current;
float pid_output = PID_Calculate(¤t_pid);
PWM_SetDuty((uint16_t)pid_output);
// 如果电压低于设定值,切换到恒压模式
if (actual_voltage < set_voltage * 0.95f) {
system_mode = MODE_CV;
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
int main(void) {
// 系统初始化
SystemClock_Config();
GPIO_Init();
ADC_Init();
PWM_Init();
OLED_Init();
Encoder_Init();
// 启动TIM2中断(1ms)
TIM2_Init();
while (1) {
// 扫描旋转编码器
Encoder_Scan();
// 更新OLED显示
OLED_ShowVoltage(set_voltage, actual_voltage);
OLED_ShowCurrent(set_current, actual_current);
OLED_ShowMode(system_mode);
// 检查保护条件
Protection_Check();
// 处理USB通信
USB_Process();
}
}
四、系统调试与优化
1. PID参数整定
| 参数 | 调整方法 | 现象 | 解决方案 |
|---|---|---|---|
| Kp过小 | 逐步增大Kp | 响应慢,稳态误差大 | 增大Kp直到出现小幅震荡 |
| Kp过大 | 逐步减小Kp | 震荡剧烈,不稳定 | 减小Kp直到稳定 |
| Ki过小 | 逐步增大Ki | 稳态误差消除慢 | 增大Ki加快消除静差 |
| Ki过大 | 逐步减小Ki | 积分饱和,超调量大 | 减小Ki,增加积分限幅 |
| Kd过小 | 逐步增大Kd | 超调量大,震荡 | 增大Kd抑制超调 |
| Kd过大 | 逐步减小Kd | 响应迟缓,高频噪声敏感 | 减小Kd |
2. 系统校准
// 电压校准函数
void Voltage_Calibration(void) {
float measured_voltage;
float actual_voltage;
// 设置输出电压为10.00V
set_voltage = 10.00f;
Delay_ms(2000); // 等待稳定
// 读取实际电压(用高精度万用表测量)
actual_voltage = 10.00f; // 假设实际测量值为10.00V
measured_voltage = actual_voltage;
// 计算校准系数
float calibration_factor = actual_voltage / measured_voltage;
// 保存校准系数到EEPROM
EEPROM_WriteFloat(CALIB_VOLTAGE_ADDR, calibration_factor);
}
3. 保护功能测试
| 测试项目 | 测试方法 | 预期结果 |
|---|---|---|
| 过压保护 | 逐步增加设定电压,超过30V | 电源自动关断,显示"OVP" |
| 过流保护 | 输出端短路 | 电流限制在5A以内,显示"OCP" |
| 过温保护 | 加热散热片至85℃ | 降低输出功率或关断,显示"OTP" |
| 短路恢复 | 短路后移除短路 | 自动恢复正常输出 |
参考代码 基于STM32的多功能数控电源设计(原理图、PCB、程序源码等) www.youwenfan.com/contentcnt/123512.html
五、扩展功能
1. 高级功能扩展
- 预置参数存储:存储常用的电压/电流组合,一键调用
- 定时开关机:设置定时开启/关闭电源,适合长时间实验
- 软启动功能:输出电压缓慢上升,避免冲击负载
- 远程控制:通过USB/蓝牙/WiFi实现远程监控和控制
- 数据记录:记录电压、电流、功率随时间的变化曲线
2. 安全增强设计
- 双重保护:硬件比较器+软件PID双重过压过流保护
- 故障自检:开机自检关键电路,异常时禁止输出
- 输出使能:增加物理使能开关,防止误操作
- 散热管理:智能温控风扇,温度过高时强制散热
六、总结
基于STM32的多功能数控电源通过PID闭环控制实现高精度稳压稳流,同步Buck拓扑保证高效率,多重保护机制确保使用安全。