51单片机+Proteus仿真:0-15V数控直流稳压电源设计与PID闭环实现

发布时间:2026/9/16 2:24:55
51单片机+Proteus仿真:0-15V数控直流稳压电源设计与PID闭环实现 简介这是一套基于51单片机的0-15V数控直流稳压电源设计方案包含完整仿真与程序代码适合电子爱好者、自动化或电类课程设计者参考。系统以51单片机为核心通过DAC0832实现直流可调输出配合ADC0808采集电位器信号完成数控调节运放电路负责放大输出并由数码管实时显示电压值。资源包共35个文件约325KB主要包含Proteus仿真工程dsn/pdsprj、Keil源程序c/a51/hex、PCB版图lyt/pdsbak以及说明文档txt/png等便于从原理仿真到实物制作逐步跟进。包内文件结构与设计流程对应能帮助学习者快速理解硬件电路与软件控制的协作关系。已有189人学习下载适合想在课程设计或电子制作中快速搭建数控电源方案的读者。1. 为什么用 51 Proteus 做 0-15V 数控直流稳压电源做一块 0-15V 数控直流稳压电源放在十年前是妥妥的硬件设计题现在用 51 单片机加 Proteus 仿真半天就能把主回路、控制逻辑和闭环调通。这个题目的价值不在“焊板子”而在一条非常完整的小信号链单片机输出 PWM滤波后变成直流电压再经运放抬升到 0-15V 输出输出电压分压取样送回 ADC程序里做 PI 修正最终实现“设定 5.4V输出就是 5.4V”。整个过程在 Proteus 里全部可见示波器接上去能直接看到 PWM 波形、滤波后的纹波和负载调整率。适合正在做课程设计、毕业设计或者想把手头的普适 51 开发板玩出模拟味道的读者。整篇文章我会按自己习惯的流程讲先把方案原理掰开再给可复现的仿真电路和 C 程序最后聊调参和排错。2. 数控电源的方案选型为什么是 PWM 滤波而不是 DAC数控直流稳压电源要解决的第一件事是让单片机输出一个“数值可控”的模拟电压。51 单片机本身没有内置 DAC常见做法有两类外挂串行 DAC 芯片如 TLC5615或者用 PWM 加 RC 低通滤波。前者硬件贵一点但纹波好控制后者成本几乎为零而且原理更直观。Proteus 仿真的场景下我优先选 PWM 滤波方案原因有三个元件库中电位器和可变电阻虽多但真正需要的是“能在运行中变化”的源PWM 不需要额外芯片仿真中观察滤波效果特别直观而且这套架构搬到真实硬件上只需要换一级 LDO 或加扩流管没有原理性改动。DAC 方案适合对纹波有严格要求的场景比如电源后面还要接音频电路但做课设和验证数控逻辑PWM 滤波足够。2.1 先把关键公式写出来占空比、截止频率和纹波PWM 滤波的核心思想是高频方波经过低通滤波后平均值等于方波在一个周期内的积分平均。若 PWM 高电平为 VH占空比为 D理想滤波后输出直流分量 Vdc D × VH。这里 VH 在 51 输出高电平场景下约等于 5V所以占空比为 50% 时输出约 2.5V100% 时接近 5V。0-5V 范围显然不够题目要求的 0-15V因此后面必须加放大级这个放到下一章细说。RC 低通滤波器的截止频率 fc 1 / (2πRC)。设计原则很简单截止频率必须远低于 PWM 频率通常取 fc ≤ Fpwm / 10否则输出纹波太大但又不能太低否则动态响应慢设定电压后要几百毫秒才稳定。举个例子PWM 频率定在 10kHzRC 截止频率取 500Hz 左右即 RC ≈ 318μs可以选 R10kΩ、C33nF实际调的时候 C 可以往上加到 100nF纹波会更小但响应变慢。如果希望输出更平滑可以在一级 RC 后级联一组相同的 RC构成二阶滤波。Proteus 中可以直接用示波器观察 V(out) 波形纹波目测就能判断参数是否合理。2.2 一阶 RC 滤波的纹波估算别让仿真骗了你仿真最大的陷阱是放大波形看纹波时发现“干净得不像真实电路”。Proteus 里电压源是理想源开关噪声、寄生电容都没有所以实际做硬件时纹波会大于仿真值。但仿真仍然有参考意义用公式估算一下理论纹波幅值再跟仿真测量值对比能反过来验证模型是否正确。一阶 RC 滤波的纹波峰峰值近似为 Vpp ≈ VH × D × (1-D) / (R × C × Fpwm)。注意这个公式只在 RC 时间常数远大于 PWM 周期时成立当 R10k、C100nF、Fpwm10kHz、D0.5 时Vpp ≈ 5 × 0.5 × 0.5 / (10e3 × 100e-9 × 10e3) 0.125V。125mV 的纹波对粗用电源略大所以多数方案中会在 RC 后再接一级运放有源滤波或稳压器仿真中加一个 10uF 电解电容就能把高频残波压得更低。判断标准很简单如果纹波超过输出电压的 1%就加电容或降截止频率。2.3 开环与闭环为什么必须把输出电压采样回单片机如果只需要“设定 PWM 值然后看输出”那就是开环控制。开环的问题在于PWM 占空比和输出电压之间不是绝对的线性关系——放大级有失调电压、滤波电容有吸附效应、负载变化会引起输出电压跌落。一个 5% 偏差的电源在课设答辩时可能被老师一句话问住负载从 100Ω 变到 10Ω你的输出电压跌了多少所以必须闭环把输出电压分压后送 ADC 采样单片机判断“现在电压 vs 目标电压”的差值用 PI 算法修正 PWM 占空比。这套闭环逻辑是本题的核心考点也是仿真中最能看出基本功的部分。后续代码会给出增量式 PI 的完整写法先记住两个参数比例项让响应快积分项消除静差。3. Proteus 仿真电路搭建元件选择与每个连接点的意义Proteus 中搭建电路第一件事不是画原理图而是想清楚每一个功能块的引脚关系。我的 0-15V 数控电源思路如下AT89C51 的 P1.0 输出 PWMP1.1 作为 ADC0832 的时钟P1.2 作为数据输入输出P1.3 接 ADC 片选P2 口接 4×4 矩阵键盘或独立按键P0 口经上拉电阻接两位数码管。仿真中复位电路和晶振可以不画AT89C51 默认会运行但加上更贴近真实板子。整个电路的关键节点只有四个PWM 输出点、RC 滤波输出点、运放输出点、分压采样点。3.1 元件清单一次找齐别来回开搜索栏Protues 元件库搜索名字容易记混直接对照下面这张表在关键字栏输入元件Proteus 关键字数量说明单片机AT89C511兼容 8051 指令集ADCADC083218 位逐次逼近型串行接口运放OP071低失调运放做同相放大电阻RES若干10k、5.6k、4.7k 等电容CAP / CAP-ELEC3-4滤波用 100nF退耦用 10uF按键BUTTON2分别做“”“-”调节数码管7SEG-MPX2-CA1动态扫描显示电压值电压表DC VOLTMETER1接输出端直接读数电源VCC / VEE-运放需要正负电源运放 OP07 在 Proteus 中需要接正负电源V 接 12VV- 接 -12V直接用 VCC 和 VEE 电压源工具放置即可。如果找不到 OP07用 LM324 也是常见替代注意 LM324 的 V 与 V- 引脚号不同接之前双击元件核对引脚功能。单片机电源和 P0 口上拉电阻别漏AT89C51 的 P0 口是开漏输出不加上拉电阻数码管段选无法正常拉高仿真中表现为显示乱码。3.2 主回路连接PWM → 二阶滤波 → 同相放大 → 输出PWM 从 P1.0 引出后第一级 R1C110kΩ/100nF第二级 R210kΩ、C210uF。第二级用大电容是为了进一步压低纹波代价是响应变慢设定电压后大约 0.2-0.3 秒稳定这个速度对电源来说完全可接受。两级滤波输出接到 OP07 的同相输入端引脚 3OP07 的输出引脚 6经电阻分压反馈到反相输入端引脚 2。这里用同相放大电路增益 G 1 Rf / Rg。因为输入是 0-5V需要输出 0-15V所以 G3。选 Rf20kΩ、Rg10kΩ得到 G 1 20/10 3。注意放大后的输出点接一个电压表和一个 100Ω 负载电阻观察带载时的电压跌落。负载电阻不是必须的但加了它才能验证闭环是否真的能稳住电压。3.3 采样网络分压电阻的取值必须让 ADC 满量程匹配OP07 输出 0-15V 不能直接接 ADC0832因为后者输入范围是 0-5V。标准做法是电阻分压将输出按比例缩小到 0-5V。取 R330kΩ 上端接 VoutR410kΩ 下端接 GND分压比 10/(3010) 0.25这样 Vout15V 时ADC 输入 3.75V小于 5V 满量程。或者取 R320kΩ、R45kΩ分压比同样为 0.2满量程时 15V × 0.2 3.0V留出 2V 裕量给过压保护。分压电阻精度直接影响显示值仿真里用理想电阻没有误差但真实场景一定选 1% 精度电阻。ADC0832 的 Vref 引脚接 5V此时 1LSB 5 / 256 ≈ 19.5mV对应实际输出电压分辨率为 19.5 / 0.25 ≈ 78mV也就是说步进 0.1V100mV是能清晰分辨的这正好匹配题目 0-15V 的数控要求。4. C 程序实现按键设定、PWM 生成与增量式 PI 闭环程序部分我用 Keil C51 写目标器件选择 AT89C51 或 AT89C52 均可。工程结构分四个模块定时器产生 PWM、ADC0832 驱动、数码管动态扫描、按键与 PID 逻辑。总代码量约 250 行核心是定时器中断和 PI 计算这两段其他都是辅助。4.1 定时器 PWM8 位分辨率频率取 10kHz 的折中常见做法是用定时器 0 工作在模式 116 位定时中断里对计数器 i 做加法比较 i 与设定阈值 pwm_high 的大小决定 P1.0 输出电平。12MHz 晶振下机器周期为 1μsPWM 频率选择受中断频率限制。若 PWM 分辨率 256 级取 Fpwm10kHz则每级时间为 1/10kHz/256 ≈ 390ns太短定时器装不下。所以我实际的配置是定时器 0 每 50μs 中断一次计数溢出取 200PWM 频率 1 / (50μs × 200) 100Hz。100Hz 对 RC 滤波来说偏低纹波会略大仿真中可以调到 256 级、300Hz 附近折中。若想提高 PWM 频率且保持 8 位分辨率需要改用定时器 1 做时钟分频或者降低分辨率到 6 位。课设场景下 300Hz 完全够用。// PWM 初始化与中断服务函数8位分辨率频率约 1kHz 配置示例 // 定时器0 每 4 次溢出为一个完整 PWM 周期溢出周期 250us // 中断频率 1 / 0.00025s ≈ 4kHzPWM 频率 4kHz / 4 1kHz #define PWM_PIN P1_0 unsigned char pwm_count 0; // 0~255 循环计数 unsigned char pwm_high 128; // 占空比阈值对应 50% void timer0_init(void) { TMOD 0xF0; // 保持定时器1原模式仅清定时器0控制位 TMOD | 0x01; // 定时器0方式116位 TH0 0xFF; // 1us * (65536 - 65506) 30us 中断 TL0 0xE2; ET0 1; // 允许定时器0中断 TR0 1; // 启动定时器 EA 1; // 打开总中断 } void timer0_isr(void) interrupt 1 { TH0 0xFF; // 重新装载初值 TL0 0xE2; pwm_count; if (pwm_count pwm_high) // 前半段输出高 PWM_PIN 1; else PWM_PIN 0; }代码里 pwm_count 每周期从 0 加到 255但中断里实际只到 256 就自然溢出回 0。比较 pwm_high 与 pwm_count 的关系就是标准 PWM 生成逻辑。pwm_high 的取值范围是 0-255对应占空比 0%-100%。注意 TH0/TL0 初值计算机器周期 1us设定中断周期 30us则初始值 65536 - 30 65506即 0xFFE2。此配置 PWM 周期其实由多次中断组合完成严格说不是每中断一次翻转一次而是靠计数比较维持高低电平时间足以满足电源的平滑需求。如果想更精确可以改用 PCA 模块或单片机内部硬件 PWM但仿真中软件定时器已经能跑出不错的结果。4.2 ADC0832 读取代码数据在时钟下降沿一位一位送出来ADC0832 是 8 位串行 ADC时序不复杂但容易把位序搞错。我的驱动函数只做一件事先拉低 CS发送 3 位配置起始位 1、SGL/DIF1、ODD/SIGN0然后连续读 8 个时钟周期在每个时钟下降沿从 DO 引脚读取一位。Proteus 中 ADC0832 的模型可以仿真时序稍微给宽一点时钟周期建议 10us 以上。这里贴出完整代码// ADC0832 读取通道 CH0 电压值 // 引脚定义CSP1.3, CLKP1.1, DIOP1.2 // 输入无返回0~255 无符号数 sbit ADC_CS P1^3; sbit ADC_CLK P1^1; sbit ADC_DIO P1^2; unsigned char adc_read_ch0(void) { unsigned char i, dat 0; ADC_CS 0; // 片选有效开始一次转换 _nop_(); // 发送配置位: START1, SGL1(单通道), ODD0(CH0) for(i 0; i 3; i) { ADC_CLK 0; if(i 0) ADC_DIO 1; // 起始位 else if(i 1) ADC_DIO 1; // SGL/DIF1表示单通道 else ADC_DIO 0; // ODD/SIGN0表示CH0 ADC_CLK 1; _nop_(); } // 读取 8 位数据 for(i 0; i 8; i) { ADC_CLK 1; _nop_(); ADC_CLK 0; _nop_(); dat 1; if(ADC_DIO) dat | 0x01; } ADC_CS 1; return dat; }发送配置位时从左往右依次是 START1、SGL1、ODD0。读取数据时要注意 DIO 引脚此时已经被 ADC 驱动方向是输出单片机把它当输入读即可。Proteus 仿真中如果读回来一直是 0xFF 或 0x00优先检查 CS 引脚是否在读取期间始终保持低电平如果读回来数值跳变可以在读取结束后加 10ms 延时再循环读或者在主循环里连续读 4 次取平均这个我在 4.4 节给出代码。4.3 增量式 PI用 int 运算避开浮点库PID 控制在 51 上建议用整型增量式避免引入浮点运算拖慢主循环。公式是ΔU Kp × (e[n] - e[n-1]) Ki × e[n]。每次把 ΔU 加到占空比变量上同时做上下限幅。这里 Kp 和 Ki 是定点小数实际计算时放大 100 倍再参与运算最后除以 100。举例Kp0.8Ki0.05实际代码写成 Kp80Ki5除以 100 还原。这样做的原因是 C51 对浮点支持比较慢而且增量式本身对微小的占空比修正足够用了。// 增量式 PI 控制输入目标电压led目标值与ADC采样值输出PWM占空比修正量 // 参数set_volt_mv 目标电压(mV)adc_volt_mv 当前采样电压(mV) // 返回无直接修改全局变量 pwm_high int pid_error, pid_last_error 0; int pid_increment; int pwm_high 128; // 初始占空比 50% #define KP 80 // 比例系数 0.8放大100倍 #define KI 5 // 积分系数 0.05放大100倍 #define PWM_MAX 230 // 占空比上限 #define PWM_MIN 20 // 占空比下限 void pid_control(unsigned int set_volt_mv, unsigned int adc_volt_mv) { pid_error (int)set_volt_mv - (int)adc_volt_mv; // 增量Kp * (En - En-1) Ki * En pid_increment (KP * (pid_error - pid_last_error) KI * pid_error) / 100; pwm_high pid_increment; // 限幅防止占空比越界导致失控 if (pwm_high PWM_MAX) pwm_high PWM_MAX; if (pwm_high PWM_MIN) pwm_high PWM_MIN; pid_last_error pid_error; }主循环里每隔 100ms 调用一次 pid_control 即可。这里把 PWM_MAX 设成 230 而非 255目的是给上限留出余量防止占空比饱和后积分继续累积造成“退饱和”慢的问题PWM_MIN 设 20 是避免输出完全关断导致采样显示为 0 时 PI 无法恢复。经过限幅处理后即使设定 15V 输出而负载过重程序也会限制最大占空比仿真中表现为电压达不到设定值但不会失控。响应速度靠调 KP静态误差靠调 KI先给 KI0KP 从 50 往 150 调直到输出稳定且无明显超调再缓慢增加 KI 消除最后 0.1V 的偏差。4.4 主循环与按键处理滤波后的采样值不要直接进 PIADC 采样值直接参与 PID 会导致占空比抖动因为单次采样噪声约 ±1LSB映射到输出电压约 78mV体现在示波器上就是输出毛刺。我一般会在主循环里做中值滤波连续采样 5 次去掉最大最小值取中间 3 次的平均值。这样做不会显著降低响应速度但能大幅度提升稳定性。按键方面用 P2.0 和 P2.1 接两个独立按键一个“电压 ”一个“电压 -”。每次按键调整 0.1V长按时自动连加。目标电压保存在 unsigned int 变量 target_mv 中范围 0-15000代表 0.00-15.00V。数码管显示用动态扫描P0 输出段码P2.7 和 P2.6 控制位选。// 主循环采样、滤波、PID、按键扫描 // 注意此循环中延时函数 delay_ms 需自行实现采用定时器或空循环 void main(void) { unsigned char adc_raw[5]; unsigned char i, mid; unsigned int adc_avg, adc_volt_mv; unsigned int target_mv 5000; // 默认目标电压 5.000V timer0_init(); // 启动 PWM while (1) { // 1. 连续采集 5 次 for(i 0; i 5; i) { adc_raw[i] adc_read_ch0(); delay_ms(2); } // 2. 冒泡排序取中间值此处直接选择第2个元素即为中值 for(i 0; i 4; i) { for(mid 0; mid 4-i; mid) { if(adc_raw[mid] adc_raw[mid1]) { unsigned char tmp adc_raw[mid]; adc_raw[mid] adc_raw[mid1]; adc_raw[mid1] tmp; } } } // 排序后取中间 3 个数平均 adc_avg ((unsigned int)adc_raw[1] adc_raw[2] adc_raw[3]) / 3; // 3. 换算实际电压 ADC值 / 255 * 5V / 分压比0.25 // 即 adc_avg * 20 / 255 * 1000 (mV) adc_volt_mv (unsigned long)adc_avg * 20 * 1000 / 255; // 4. PID 闭环调整占空比 pid_control(target_mv, adc_volt_mv); // 5. 按键处理每按一次 0.1V上限 15.0V if (key_plus_pressed()) { if (target_mv 15000) target_mv 100; } if (key_minus_pressed()) { if (target_mv 0) target_mv - 100; } display_digit(target_mv / 1000, target_mv % 1000 / 100); delay_ms(50); } }主循环的节奏是一圈约 60ms其中 ADC 采集 5 次耗时 10ms剩余时间分给显示和按键这个速度对电源控制足够了。adc_volt_mv 的换算公式值得再拆一下adc_avg 是 0-255 的原始值对应 ADC 输入电压 0-5V由于实物分压比是 0.25所以真实输出电压 ADC电压 / 0.25 adc_avg × 5 / 255 / 0.25 adc_avg × 20 / 255再乘 1000 变毫伏。代码里写成 adc_avg × 20 × 1000 / 255结果因先乘后除而足够精确。注意 51 是 16 位 intadc_avg × 20000 可能溢出所以我把 adc_avg 强制转成 unsigned long这个坑很多初次写的读者会踩到仿真中表现为电压显示乱跳或负数。5. Proteus 调试技巧与闭环验证从“能跑”到“准”程序烧录不是直接把 .hex 拖进单片机要先在 Proteus 的 AT89C51 元件上双击在 Program File 里指定 .hex 路径后点击确定。很多读者第一次仿真没反应90% 是这一步没操作。此后点击左下角运行按钮红色方块是暂停绿色三角是步进对调试中断特别有用。5.1 三个典型问题定位与解决第一类是数字部分工作但输出恒为高或恒为低。用示波器 Probe 接 P1.0观察是否有方波输出。如果没有方波先查定时器配置Proteus 中 AT89C51 默认晶振频率是 12MHz如果你在代码里按 24MHz 的初值写定时就会偏慢一倍现象是电压极低且数码管乱闪。第二类是输出电压上不去比如设定 10V 但实测只有 6V。把示波器接到 OP07 输出引脚若波形已饱和失真说明增益电阻 Rf/Rg 取值有误或者运放正负电源没接导致输出只有正轨电压。第三类是显示电压和万用表电压不一致优先检查分压电阻阻值和 ADC 换算公式常见错误是把分压比代入式中放反位置。5.2 闭环调参三步法调 PID 参数我习惯按“比例先行、积分殿后”的次序。先令 KI0KP 从 50 开始每次增加 20设定 8.0V 目标电压观察数码管或电压表数值。如果电压长时间不接近设定值说明 KP 太小如果接近但持续振荡说明 KP 过大。找到临界振荡点后把 KP 回退 30%再加入 KI5此时静差会慢慢消失。Proteus 中可以用图表仿真模式Graph Mode直接扫描一段时间的输出设置 Time 轴为 5 秒观察阶跃响应曲线比肉眼盯着电压表更准确。一个小技巧是让示波器的 A 通道接运放输出B 通道接 ADC 输入两路波形叠加能直接看到采样电压是否紧紧跟随设定值的分压点。5.3 最后一个小技巧用 Virtual Terminal 打印中间变量调试 PID 时只靠两三位数码管很难判断内部状态Proteus 的 Virtual Terminal 组件可以替代串口调试助手。在单片机 TXD 引脚接一个 VIRTUAL TERMINAL再加一个 COMPIM 或直接连。程序里想打印就调用 printf但注意 C51 重定向串口需要额外处理在初始化时配置 SCON0x50TMOD 里定时器 1 做波特率发生器然后在工程里把 putchar 重定向到 SBUF。写完这步之后你的 PID 误差值、pwm_high、ADC 原始值全部可以实时滚动显示。仿真最终验收时给出这三组数据的初始变化过程比只说“电压稳了”更有说服力。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询