基于Proteus和STC89C52的Buck可调电源仿真设计详解

发布时间:2026/9/11 10:53:13
基于Proteus和STC89C52的Buck可调电源仿真设计详解 简介面向单片机与电源设计初学者的可调开关电源Buck拓扑仿真设计资源以51单片机为控制核心利用PWM调节占空比实现12V直流输入下0-5V可调输出按键支持大幅度与小幅度步进调节LCD1602实时显示输出电压并涉及ADC0832采样与显示程序。压缩包共48个文件主要包含Proteus仿真工程.pdsprj、C语言源码.c/.h、编译产物.hex/.obj以及演示视频.avi/.rar另有电路截图与工程备份文件整体约16.95MB目录按程序、仿真图、讲解视频归置便于按需查阅学习。该资源已有282人学习下载适合单片机应用、电力电子技术相关课程设计或毕业设计阶段的学生参考使用。通过仿真图、源代码与讲解视频可完整掌握Buck变换器工作原理、PWM占空比调节策略、按键处理与显示程序设计思路同时Proteus工程支持修改电路参数或增添反馈环节为扩展更高电压等级、实现闭环稳压等二次开发提供了便利。1. 从一块可调电源板反推回电路仿真为什么选Buck加单片机做硬件的人几乎都遇到过这种需求要给一个实验板提供 5V、9V、12V 里某一档电压手头又没有可调电源于是开始找 DCDC 方案。最常见的答案是 LM2596 模块淘宝几块钱一个但这东西只给你一个电位器调完是几伏全看电位器手感。换到单片机控制的 Buck 方案好处立刻体现出来——输出电压可以按键设定、数码管显示、甚至可以通过通信接口远程修改。而从原型验证的角度直接用 Proteus 做仿真可以完全不用先焊板子先把 PID 参数和滤波电容试明白。为什么是 Buck 而不是 LDO因为输入 12V 输出 5V 时LDO 的压差 7V 全转成热量100mA 就是 0.7W发热量足以让 LDO 烫手。Buck 是斩波降压开关管导通时电感储能、关断时电感续流器件上的损耗远小于线性调整。Proteus 里仿真的好处更是明显——你可以随意改占空比、换电感量、调电容 ESR甚至故意把参数改错看波形发散的时机这在实体电路上要烧掉几片 MOSFET 才能换来同样的经验。这篇文章适合三类人正在做课程设计需要快速交付仿真图和代码的学生想把 Buck 控制器核心逻辑摸清楚、不想只调模块的入门工程师以及被 Proteus 仿真发散问题折磨过、想搞清楚设置哪个参数才能让闭环跑稳定的开发者。文中的思路会尽量落到可复现的操作从 Buck 的占空比和电感计算、Proteus 元件摆放与示波器接法、到 STC89C52 输出 PWM 调压的全过程最后再说几个仿真必踩的坑。2. Buck拓扑先算再仿占空比、电感值、输出电容的公式与选型2.1 连续导通模式下的占空比与电感公式Buck 电路基础拓扑就是一个开关管、一个续流二极管、一个电感、一个输出电容。开关管导通时输入通过电感给负载供电并充磁关断时电感通过续流二极管继续向负载供电。连续导通模式下稳态电压传输比有一个简单公式Vout Vin × DD 是占空比也就是开关管导通时间与开关周期的比值。这个公式既是原理也是陷阱——它只在连续导通模式下成立而且忽略开关管和二极管的压降。实际设计时导通占空比应该写成D (Vout Vd) / (Vin - Vsw Vd - Vout)Vd 是续流二极管的正向压降Vsw 是开关管导通压降。比如输入 12V、输出 5V、Vd 取 0.5V、Vsw 取 0.2V算出来 D ≈ 0.48而不是直接 5/12 0.42。仿真时如果你发现输出电压与理论值差 5% 以上先检查是不是把二极管压降忽略了。电感的取值决定电路工作在连续还是断续模式。临界电感公式是Lc (1-D) × R / (2 × f)R 是等效负载电阻f 是开关频率。以 12V 输入、5V 输出、500mA 负载、20kHz 开关频率为例等效电阻 R 5V / 0.5A 10ΩD 0.42算得临界电感 Lc (1-0.42)×10 / (2×20000) 0.145mH。实际取临界电感的 3 到 5 倍比较保险也就是 470µH 左右。取值过小会导致电感电流断续输出纹波增大且电压调整率变差取值过大则动态响应变慢负载突变时恢复时间变长。输出电容直接影响纹波电压。纹波主要由电感的纹波电流在电容上充电放电造成近似公式为ΔVout ΔIL / (8 × f × C)ΔIL 是电感纹波电流峰值可以按满载电流的 20% 到 30% 估算。假设满载电流 0.5A、取 25% 即 0.125Af20kHz要求纹波小于 20mV需要的电容 C 0.125 / (8 × 20000 × 0.02) ≈ 39µF。这个公式没有考虑电容 ESR 的贡献为了仿真更贴近实际建议在 Proteus 的电容参数里把 ESR 设为 0.1Ω 到 1Ω 之间的值才能看到纹波不只是锯齿形、而是叠加了一个电压台阶的真实效果。提示仿真时很多人直接把电感、电容值拍脑袋填进去输出电压确实也是对的但一旦换负载或改目标电压就开始振。原因就是电感和电容的搭配不在连续导通模式的设计区间。2.2 同步Buck与异步Buck的仿真选型差异Proteus 里做 Buck 仿真开关管和续流器件的选择关系到电路能不能起振。异步 Buck 用二极管续流优点是结构简单、不用考虑上下管直通问题缺点是大电流下二极管损耗明显。同步 Buck 用 MOSFET 替代二极管续流时下管导通压降看 RDS(on) 与电流的乘积通常比二极管正向压降低很多。同步 Buck 在低压大电流场景效率优势显著但需要额外设计死区时间避免上下管同时导通导致贯穿电流。在 Proteus 仿真中尤其要注意直接用两个反相 PWM 驱动同步 Buck 而不加死区会看到电源电流飙到几安甚至几十安防真结果显示严重发散或电源电压被拉垮。区别对比可以简化成下面这张表类型续流器件典型效率5V/1A 级别控制复杂度Proteus 仿真实测注意点异步 Buck肖特基二极管85%-90%低一个 PWM 即可二极管模型选快恢复或肖特基避免用 1N4007同步 Buck低压 MOSFET 下管90%-95%高需要互补 PWM 死区不写死区会导致直通短路电源电流发散做课程设计或单片机控制这类低压小功率应用老老实实用异步 Buck 就好。Proteus 仿真中续流二极管建议选 BYV29-600 这类快恢复管或者用 Schottky 二极管模型。如果用 1N4007 这种工频整流管反向恢复时间太长开关频率稍高比如 20kHz就可能导致每个开关周期内二极管都要花大段时间泄放效率下降且输出纹波明显增大。2.3 Proteus里Buck电路的5个关键参数设置点在 Proteus 里摆放 Buck 电路跟芯片手册里的参考电路是完全一致的原则。打开设计环境后放置以下器件一个开关管MOSFET 或晶体管、一个电感、一个二极管、一个电解电容加一个小陶瓷电容、一个负载电阻。关键参数集中在这几点开关管选型上推荐直接用 Proteus 元件库里的 IRF540 或 IRLZ44N。注意 IR 系列中带 IRL 前缀的是逻辑电平驱动栅极 5V 就能完全导通适合单片机直接驱动而 IRF540 需要 10V 栅极电压才能进入低导通电阻区用在 5V 单片机电路里如果没有加栅极驱动级导通电阻会偏大、发热明显。仿真时必须按“单片机输出 PWM → 栅极”的接法检查直接在 MOSFET 栅极接 5V PWM 有两个问题一是驱动能力不足导致上升沿变缓二是高电平的 5V 不够让 IRF540 深度导通。电感参数双击后在 Component Properties 里填写 Inductance 值比如 470µH。Proteus 的电感默认无内阻实际情况可以用串联一个小电阻模拟 DCR取值 0.1Ω 到 0.5Ω 效果更真实。输出电容建议并两个不同容值的电容一个大容量电解电容 47µF 负责储能一个小陶瓷电容 100nF 负责滤高频尖峰仿真时能明显看到两种电容对纹波的不同影响。负载建议先用一个简单的电阻负载模拟恒定需求阻值按目标输出电压除以目标电流计算。如果需要观察动态响应用 Proteus 的 SWITCH 配合电阻模拟负载突变在闭环调试阶段很有用。开关频率通过单片机的 PWM 周期设定建议先选 20kHz 而不是更高——Proteus 仿真步长是固定的频率太高会导致每个周期只有几个仿真步进入开关管导通区间瞬态波形看起来毛毛糙糙频率太低则心形磁性元件尺寸大20kHz 是兼顾仿真速度与物理合理性、且刚超音频的平衡值。3. 从零搭出可调Buck仿真元件摆放、PWM接线与电压采样3.1 主电路搭建步骤与器件清单打开 Proteus 新建设计文件建议用 Schematic Capture 视图操作。从左侧设备栏输入关键字并依次放置下表器件放置后检查接地和电源标注序号器件关键字搜索数量用途说明1直流电源POWER1输入电压源12V2N沟道MOSFETIRLZ44N1主开关管逻辑电平可直驱3快恢复二极管BYV29-6001续流二极管4电感INDUCTOR1设置 470µH串联 DCR 小电压源模拟内阻5电解电容CAP-ELEC147µF并 100nF 小电容6负载电阻RESISTOR1按 5V/0.5A 取 10Ω7单片机STC89C52 或 80511产生 PWM读取电压8分压电阻RESISTOR × 22输出电压分压到 ADC 可测范围9示波器OSCILLOSCOPE1观察 PWM、电感电流和输出电压纹波连接顺序是12V 电源正极 → MOSFET 漏极MOSFET 源极 → 电感一端电感另一端 → 输出电容正极和负载输出电容负极接回电源地续流二极管的阴极接在 MOSFET 源极和电感交点阳极接地。这个拓扑里最需要确认的是 MOSFET 源极并不接地而是接在开关节点上所以单片机产生的 PWM 驱动它时要注意参考地是否一致。常见错误是直接把单片机的地接到源极但会引入共模干扰实际做法是让 PWM 通过 10Ω 限流电阻接栅极源极和单片机地之间用一根单独的细线连接形成一个相对明确的回路。电压采样部分输出 3.3V 到 12V 不能直接进 AD否则超量程。用两个电阻分压把电压变成 0 到 5V 区间再送 ADC 输入引脚。比如目标最大输出 10V分压比按 2:1 取上电阻 10kΩ、下电阻 4.7kΩ输出 10V 时 ADC 读取约 3.2V。电阻的值不宜太大否则 ADC 输入阻抗加载会引入误差也不宜太小导致额外功耗10kΩ 级别是个常见折中。3.2 STC89C52定时器模拟PWM输出的代码框架STC89C52 内部没有硬件 PWM 模块常见的做法是用定时器中断翻转 IO 口来生成 PWM。频率 20kHz 对应周期 50µs定时器工作在方式 116 位定时器时间常数 65536 - (晶振频率 × 周期 / 12)。以 12MHz 晶振为例机器周期为 1µs50µs 对应的计数初值是 65536 - 50 65486对应十六进制 0xFFCE。#include reg52.h #define T0_VAL_H 0xFF #define T0_VAL_L 0xCE #define PWM_PERIOD 100 // 占空比 1% 对应一个单位 sbit PWM_PIN P2^0; // PWM 输出到 MOSFET 栅极 static unsigned int pwm_duty 70; // 初始占空比 70% static unsigned int cnt 0; void timer0_isr() interrupt 1 { TH0 T0_VAL_H; TL0 T0_VAL_L; cnt; if (cnt PWM_PERIOD) { cnt 0; PWM_PIN 0; // 周期开始先置低随后在计数值处拉高 } if (cnt pwm_duty) { PWM_PIN 1; } } void main() { TMOD 0x01; // 定时器0方式116位不自动重装 TH0 T0_VAL_H; TL0 T0_VAL_L; EA 1; ET0 1; TR0 1; while (1) { // 后续在此加入按键调整 pwm_duty 的逻辑 } }这个代码的思路是让定时器以 1µs 为单位中断每当计数值小于设定占空比 pwm_duty 时输出高电平计满一个 PWM_PERIOD 后归零重新计数从而形成频率固定、脉宽可调的方波。修改 pwm_duty0 到 100 之间即可改变占空比。注意方式 1 不是自动重装的因此中断服务函数中必须重新写入初值否则定时器计数溢出后从 0 重计定时间隔立刻变成 65536µs频率掉到 15Hz 左右仿真和实物都会出现明显故障。如果手头是 STC15 系列或 STC8 系列可以用内部硬件 PWM 模块代码量更少且可用高级 PWM 输出互补波形做驱动。但在 Proteus 里STC89C52 通常是仿真库中最容易找到且兼容性好的型号所以这里以它为例。能用中断模拟 PWM 后也可以在主循环里通过按键加减 pwm_duty 直接开环调压但开环调压的效果受负载影响极大。负载变重时电感电流上升、导通压降增大即使占空比没变输出电压也会被拉低。所以下一步要加电压闭环。3.3 用ADC0804读取输出电压实现简单的自动反馈STC89C52 内部没有 ADCProteus 里常见的做法是外接一片 ADC0804。ADC0804 是 8 位逐次逼近型 ADC输入电压 0 到 5V转换时间大约 100µs。接线方式是VIN() 接分压电阻的输出点VIN(-) 接地VREF/2 空接或接 2.5V决定满量程是否严格等于 5VCS 接地使能RD 和 WR 接单片机两个 IO 口INTR 接一个 IO 口查询转换完成状态。sbit ADC_CS P1^0; sbit ADC_RD P1^1; sbit ADC_WR P1^2; sbit ADC_INTR P1^3; sbit PWM_PIN P2^0; unsigned char read_adc() { unsigned char value; ADC_CS 0; ADC_WR 0; // 启动转换 ADC_WR 1; while(ADC_INTR); // 等待 INTR 变低表示转换完成 ADC_RD 0; // 读取数据 value P0; // ADC 的 DB0-DB7 接 P0 口 ADC_RD 1; ADC_CS 1; return value; }读到 8 位数字量后换算电压的公式为 V value × (Vref / 255)。如果 Vref 是 5V那么每一级代表 19.6mV。输出电压经分压电阻缩小后进入 ADC所以真实输出电压 value × (Vref/255) × 分压系数。比如分压系数是 (10k4.7k)/4.7k ≈ 3.13读到的数字量 128 对应约 1.961V还原为输出就是 6.14V。这段换算逻辑放在代码里作为测量函数之后才能交给 PID 使用。注意ADC0804 转换需要一点时间在 20kHz PWM 中断里不能直接调用读 ADC 函数——否则中断耗时过长会影响 PWM 波形。常见做法是让 ADC 转换在主循环中执行PID 计算完成后再更新一个全局变量 pwm_dutyPWM 中断里只读取这个变量的当前值。4. 按键设定输出电压PID 闭环让占空比学会自己找位置4.1 增量式PID在Buck调压中的应用与参数含义开环模式下输出 5V 的占空比 42% 是在特定输入和负载条件下算出来的。换一个负载、换一个输入电压同样的占空比不一定能维持 5V。PID 闭环的思路是通过测量输出与目标之间的误差动态修正占空比。数字 PID 常用增量式写法——每次只在上一时刻的占空比基础上加一个 Δu而不是直接计算绝对占空比。这样可以避免积分项累积过大导致的超调也天然适合占空比按步进调整的 PWM 控制场景Δu Kp × (e(k) - e(k-1)) Ki × e(k) Kd × (e(k) - 2×e(k-1) e(k-2))其中 e(k) 是本次误差目标电压减去实际电压e(k-1) 是上次误差。Kp 项决定响应速度Ki 项消除稳态误差Kd 项抑制超调。在 Buck 电源控制里Kp 不能太大因为 PWM 占空比的调整范围只有 0 到 100 而输出电压误差带很小Kp 过大会让占空比在某个点附近来回跳输出表现为低频振荡。Ki 是让最终电压误差趋近于零的关键但 Ki 过大容易积分饱和负载突变时会有一大段占空比被积分项拽住收不回来。增量式 PID 在单片机上的实现不需要用到浮点定点整数处理即可。目标电压换算成与 ADC 数字量同一个量纲例如目标 5V 时经过分压和 ADC 变换后的目标数字量为 target_adc。误差 e target_adc - current_adc。Kp、Ki、Kd 直接用整数表示计算 Δu 后叠加到 pwm_duty 上并做限幅int pwm_duty_int pwm_duty; int e0 target_adc - current_adc; int e1 e_prev; int e2 e_prev2; int delta_u KP*(e0 - e1) KI*e0 KD*(e0 - 2*e1 e2); pwm_duty_int delta_u; if (pwm_duty_int 96) pwm_duty_int 96; // 占空比上限 if (pwm_duty_int 10) pwm_duty_int 10; // 占空比下限 pwm_duty (unsigned int)pwm_duty_int; e_prev2 e_prev; e_prev e0;限幅的上下限取决于 Buck 电路的极限工作范围。下限不能到 0因为二极管和电感的寄生参数决定了占空比很小时电感电流不连续输出会异常上限不能到 100因为开关管需要一点关断时间让电感续流释放能量。在仿真中可以看到如果占空比超过 95输出电压几乎等于输入电压减去一个非常小的压降此时电路已经不是 Buck 而是接近直通失去调整能力。4.2 Proteus中PID参数的工程整定方法PID 参数在 Proteus 里整定比实体板子快很多因为可以暂停仿真、修改代码、重新运行看到的输出波形也是一瞬间的结果。推荐这种试凑路线先用 P 调节Kp 从一个小值开始慢慢加大观察输出电压从启动到稳定是否出现超调。标准做法是让占空比从 0 开始逐步建立P 太小时输出电压上升缓慢、稳态偏离目标值P 太大时输出电压上冲超过目标随后回落表现为一个明显波峰。P 项能稳定的区间找到后加 I 项消去稳态误差。Ki 从小值开始增加每次改完看输出是否在一个合理时间内回到目标电压。如果输出在目标值附近以大概 0.1Hz 到 1Hz 的低频振荡通常是 Ki 太大或 Kp 与 Ki 比例失衡。D 项在 Buck 电路中默认较少使用因为输出电容和电感本身就是一个二阶系统D 项调得过大会把开关噪声放大导致占空比抖动。但若负载切换瞬间超调明显适当加 Kd 可以压制第一个波峰。中断周期也要纳入整定考量ADC 读取和 PID 计算放在主循环中而不是在 PWM 中断里意味着 PID 的执行周期是不精确的这会让参数整定结果难以迁移到实物。更规范的写法是用另一个定时器比如定时器1产生一个 1ms 的时基在这个时基里触发一次 ADC 读取和 PID 更新。这样 PID 的执行频率是稳定的比如 1kHz而 PWM 是 20kHz两者之间相差 20 倍符合“开关频率远高于控制频率”的古典电源设计要求。4.3 按键设定目标电压并显示当前值的完整逻辑实现可调电源的核心功能是在按键中断或主循环轮询中修改 target_adc 的值。按键接 P3.0 和 P3.1一个“增加”、一个“减少”每按一次让目标电压步进 0.1V。与 target_adc 的换算关系为每 0.1V 对应的 ADC 数字量 0.1 × 255 / (Vref / 分压系数)。假设分压系数 3.13、Vref5V那么每 0.1V 对应大约 16 个 ADC 计数单位。用数码管或 LCD1602 显示当前设定值和实测电压可以直观判断闭环是否稳定。显示部分在 Proteus 中常使用 LCD1602需要把 P0 或 P2 接数据位。显示代码本身不复杂关键是在写数据时处理好 P0 口需要上拉电阻的问题——Proteus 中 P0 作为输出必须外接排阻或直接拉高否则 LCD 上的字符会花掉。这个细节是很多 Proteus 单片机仿真翻车的高频原因不是代码写错而是电气模型没搭够。主循环中每 500ms 刷新一次显示这个时间远大于 PID 的 1ms 间隔不会干扰控制回路也足够人眼看到数字滚动变化。按键消抖在仿真里同样要做到位不能用简单的 while 等待松手。仿真中按键没有实体弹片但 Proteus 的交互式按键模型在按下时会产生固定的电平跳变不处理抖动的话一次按键可能触发多次目标电压累加。主循环里采用状态机消抖或 Timeout 确认都可以例如连续两次采样间隔 20ms 仍保持按下才判定有效。5. 从仿真到顺手改造成实体前的最后几个坑5.1 用示波器快速验证三个节点的波形仿真闭环跑稳了之后把 Proteus 的虚拟示波器接到三个位置。第一个位置是开关管栅极观察 PWM 波形是否达到预期频率和占空比第二个位置是 MOS 管漏源之间即开关节点应该看到输入电压和接近零电平之间的方波切换第三个位置是输出电容两端应该看到一个直流电压上叠加少量纹波。三个位置的波形在 Proteus 中使用不同颜色区分设置合适的每格时间档位——20kHz 方波周期 50µs时基应在 10µs/每格附近如果你用的是 50ms/格示波器档位会看到一条糊状的带子误以为电路振荡。示波器在仿真中的位置接错同样会导致测量假象比如把示波器探针的地接到了电感前面而非输出电容负极读取的纹波数值比真实值大一倍。电感电流的观察方式略有不同在 Proteus 中不能直接电流探头测量电流波形通常的做法是给电感串联一个 1mΩ 的采样电阻再把这个电阻上的电压送到示波器第二通道。电流值 电压 / 0.001可以算出峰峰值和平均值。连续导通模式下电感电流波形是三角波峰峰值约为 △IL 的两倍如果发现电流波形不与时间轴交叉即下端点不小于零说明工作在连续导通模式符合设计期望如果电流波形贴地且有一段恒零说明进入了断续导通模式此时需要检查负载电流是否远小于设计值或电感量偏小。5.2 Proteus仿真发散的三类典型原因仿真发散的报错现象各不相同有的直接报错“Simulation failed”有的波形溢出成一条横向直线有的输出电压变成负数。这三类现象对应不同原因。第一类是仿真步长设置过小导致运算时间过长、误差累积失稳。在 Proteus 的仿真设置里把步长从默认值调大一些有时反而能避免数值发散因为过小的步长会让模型在开关瞬间衍生出大量不真实的数值振荡。第二类是 Mosfet 模型选择不当。Proteus 有多种 MOSFET 模型复杂模型包含寄生电容和体二极管仿真精度更高但数值刚性也更强在闭环控制仿真里用简单模型反而更稳定代价是波形毛刺少一些但不会影响验证占空比与闭环逻辑。第三类是 B 类电路广泛存在的数学解发散比如状态空间方程在特定参数组合下出现极点穿越虚轴的情况。Simulation 设置里激活“Gear”积分方式可以改善刚性系统的稳定性而默认的梯形法在某些工作点更精确但更容易振荡。当你发现 PID 参数和电路参数都完全合理、但输出电压就是死活发散时切换积分算法是性价比最高的一步尝试。另外 Proteus 版本也会影响仿真收敛性部分 8.0 早期版本对理想开关管模型的收敛保护不完善升级到后续维护版本或更改 Mosfet 模型库能直接解决。提示仿真发散不一定是你的电路错了。可以先加入一个较大的初始电容电压或者在输出电压节点并一个 1µF 左右的电容来稳定节点电压初值。它还顺手帮你让仿真从启动阶段就建立正确的偏置点。5.3 参数自整定与更近一步的仿真策略PID 参数在仿真中手工试凑已经够用但如果你想观察负载突变下系统如何自动恢复可以加入一个简单的自适应策略。最粗糙的做法是检测误差的大小来切换 PID 的参数组——误差大时使用大 Kp 快速靠近目标误差小时切换小 Kp 加 Ki 消除静差。这种分段式参数切换在 Proteus 中实现简单避免在非线性 Buck 系统中使用单一 Kp 造成的启振或过冲问题也是工程上“实时调整参数必先从分段切控制策略开始”的常规路径。再进一步仿真的目的是替实体板子踩雷。仿真跑稳了下一步转移到实体板前还要做两件事一是计算开关管的开关损耗和导通损耗实物的散热条件不会像仿真那样理想二是检查 Gate 驱动电阻仿真里可以用 0Ω 直连但实物必须加 10Ω 到 22Ω 电阻。如果你在 Proteus 中从一开始就加入这个驱动电阻那么向实体移植时唯一需要改的可能只有接口电平匹配不用重新确认驱动时序。这种把仿真的保守参数设置当作实物的起点策略比“仿真激进、实物回退”更能减少迭代轮次。最后记得在源程序里给 pwm_duty 加上开机软启动——从 0% 缓慢上升到目标值既保护负载又能让你在示波器上看到一列平滑上升的输出电压曲线这比任何对 PID 调节过程的文字描述都直观。本文还有配套的精品资源点击获取