简介:本资源是一套面向嵌入式电源系统开发者的完整双向DC-DC变换器工程实现方案,聚焦电池储能装置中的能量双向调控需求,适用于高校电力电子课程设计、毕业设计及中小型储能系统原型开发。方案基于dsPICFJ256GP710单片机,采用Buck-Boost拓扑结构,支持Buck模式恒流充电(效率≥94%)与Boost模式恒压放电(效率≥95.5%),集成过压保护与DS18B20温度检测功能,具备工业级可靠性设计特征。压缩包共40个文件,含9个C源码、9个头文件、9个目标文件及PCB原理图(.SchDoc)、PCB布局(.PcbDoc)、论文文档(.doc)、可执行固件(.hex)等核心交付物,总大小7.52MB,结构清晰,便于从控制逻辑、硬件设计到系统验证全流程学习。已有169人下载学习,提供从算法实现(PWM、ADC、定时器驱动)、外设接口(LCD12864、按键、温度传感)到PCB工程落地的全栈参考。 把需求拆开看,这个项目其实包含了几条线:dsPIC单片机的数字控制、Buck-Boost四开关拓扑、双向能量流动、PCB设计,以及一套完整的论文和源码。如果你也卡在“想做数字电源但不知道从哪里下手”,或者已经搭好了硬件但程序调不通,这篇内容可以给你一些参考。
先说结论:四开关Buck-Boost方向做双向DC-DC,是中小功率储能、电池充放电、无人机供电、车载辅助电源这些场景里很实用的方案。用dsPIC做主控,不是因为迷信Microchip,而是因为它的PWM和ADC模块配合度极高,特别适合数字电源这种需要PI环路高速跑的场景。整个项目做完,你手里会有一套能直接改参数重新打样复现的源码、一块功能完整的PCB,以及一份拿得出手的论文底稿。
1. 双向DC-DC的需求来自哪里:拓扑选型背后的四开关Buck-Boost逻辑
1.1 双向变换器的应用场景与设计需求
双向DC-DC变换器,说人话就是同一个变换器既能让能量从A端流向B端,也能让能量从B端流向A端。最常见的需求是电池和直流母线之间做能量管理:电池放电时,把电池电压变换到母线电压;电池充电时,把母线电压降下来给电池充电。光伏配储能、电动车动力电池与回收系统、UPS的充放电模块、机器人电池与伺服母线,都是这类应用。
我的项目需求更具体一些:低压侧电池电压范围10V到16V,高压侧母线电压稳定在24V,功率等级100W,要求四象限运行,也就是既能Buck放电,也能Boost放电;反向就是充电时既能Buck降压,也能Boost升压。这种宽范围的输入输出变化,直接用Buck或者Boost都搞不定,因为Buck只能降压,Boost只能升压。如果低压侧比高压侧低,要用Boost方向;反过来则要Buck方向。两个方向都要有,就需要一个升降压拓扑。
1.2 四开关Buck-Boost拓扑的工作模态
四开关Buck-Boost其实就是两个半桥中间夹一个电感。左边两个开关管构成一个半桥,右边两个开关管构成另一个半桥,电感放在两个开关节点之间。四个开关管通常是两个半桥驱动芯片分别驱动,上下管互补,每个半桥的输出节点就是电感的左端和右端。
这个拓扑的精妙之处在于,它可以看成Buck和Boost的级联,但省掉了中间电容。当左半桥高频开关、右半桥固定开通(或同步整流)时,它是Buck电路;当右半桥高频开关、左半桥固定开通(或同步整流)时,它是Boost电路。因为左右两个半桥都有同步整流能力,所以电流可以双向流动,不管工作在Buck还是Boost模式,窄脉冲那边负责能量传输,宽脉冲那边就做同步整流。
对于双向,关键是不要把它想成“两套独立的单向DC-DC”。双向的核心是控制电感电流的方向。比如高压侧24V,低压侧12V,正向Buck模式下,能量从24V流向12V,电流向右。如果这时候想让能量反向,立刻切换成Boost模式,右半桥开关,左半桥同步整流,电流方向就反过来了。控制逻辑上,只需要根据电压参考变化或者电流指令的正负来判断该跑哪个模式。
1.3 为什么不用普通Buck-Boost电路
传统两开关Buck-Boost电路也能升降压,但是它的输出极性是反的,也就是说输出端与输入端的负端不共地,这带来很多麻烦。很多隔离电源会用它,但在非隔离双向应用里,四开关Buck-Boost才是主流。
四开关还有一个好处:电感两端电压应力可控,占空比不会出现极端的情况,工作范围更宽。同样是12V转24V,如果用传统反极性Buck-Boost,占空比可能要到接近0.7,电感电流应力很大。而四开关Buck-Boost可以让左半桥按Buck模式工作,右半桥同步整流,电感电流波形更好,效率更高。
我在选型的时候,也考虑过Zeta、SEPIC这些拓扑,但它们要么需要耦合电感,要么电容数量多,控制更复杂,而且双向扩展并不方便。四开关Buck-Boost的四个开关管工作在不同组合下,控制自由度大,很适合用数字控制去做模式切换和环路补偿。
2. dsPIC33做主控:PWM与ADC深度配合是数字电源的绝配
2.1 从普通单片机到dsPIC的跳跃
很多人做电源,第一反应是用STM32或者普通的8位单片机。这也不是不行,但一旦开关频率上到100kHz以上,控制环路的延时问题就会非常明显。普通单片机的ADC采样、计算、更新PWM占空比这三个动作如果串行执行,一个控制周期可能做不到10us以内,环路的相位裕度会变得很差。
dsPIC33系列不一样,它好就好在把PWM模块和ADC模块设计成了可以硬件触发的组合。ADC转换周期可以由PWM触发事件同步启动,转换完成之后用DMA直接搬运结果到RAM,然后CPU在下一个PWM周期开始前把新的占空比值写入PWM模块。这个过程大大减少了软件上的等待和调度开销。
我用的是dsPIC33EP64GS502,64KB Flash,主频最高70MIPS,对于数字电源来说完全够用。它自带4路专用PWM模块(支持80ps级的分辨率),以及一个12位ADC,采样率最快到3.5Msps,还有模拟比较器可以直接做快速过流保护,不需要经过CPU。
2.2 PWM模块配置和死区管理
四开关Buck-Boost需要两路互补的PWM:PWM1驱动左半桥,PWM2驱动右半桥。dsPIC的PWM模块可以自动生成互补输出,并且提供可编程的死区插入。死区参数太大会限制最大占空比,太小会直通炸管。我最终设的是180ns死区,用的是250kHz开关频率。
这里有个关键点:死区不是越大越安全。死区期间电感电流会通过MOSFET的体二极管续流,体二极管反向恢复时间长,损耗很大,而且容易产生振铃。所以我选MOSFET的时候特意选了体二极管反向恢复时间短的型号,另外在死区参数上做了权衡,既不能过短导致上下管交叉导通,也不能过长导致效率和EMI变差。
PWM模块还要配合重载周期寄存器。在初始化代码里,要设置PTPER(PWM时基周期寄存器),通过它决定开关频率。例如PLL配置到140MHz,PWM周期寄存器设为559,就能得到250kHz的开关频率。用公式算一下:f_PWM = f_PLL / (2 * (PTPER + 1))。这里每组PWM模块有独立时基,可以方便做相移控制,虽然本设计用不到,但也很重要。
2.3 ADC采样同步与控制环调度
源码设计核心是让ADC采样和PWM周期同步。我采用PWM周期中点采样,也就是在PWM定时器计数归零时触发ADC,这样采样到的电感电流纹波平均值比较接近真实平均值,而不是峰值或者谷值。如果采样点落在开关管开通或关断的边沿附近,很容易采到巨大的开关噪声,导致环路误动作。
ADC的触发源可以直接配置为“PWM模块触发事件”,不需要外部引脚连接。每个PWM周期触发一次ADC,ADC转换完成后产生中断,然后把采样值换算成实际电压和电流,再执行数字PI计算,最后更新PWM占空比。为了减少主循环干扰,整个控制环都在ADC中断里执行,主循环只处理按键、显示、通信这类低速任务。
这里给你一个参考配置顺序:初始化时钟->初始化PWM时基和死区->配置ADC触发源和通道->配置DMA(可选)->使能PWM输出->开ADC中断->进入主循环。
3. 功率级和驱动电路的硬件计算:电感、MOS管、半桥驱动
3.1 主功率电感设计计算
这个环节计算错了,后面调试必炸。根据能量存储和纹波电流公式,电感量L = (Vin * D) / (freq * ΔI_L)。如果高压侧24V升压,低压侧12V降压,假设满载100W,平均输入电流约8.3A(低压侧),设定电感纹波电流峰峰值为平均电流的30%,也就是约2.5A。开关频率250kHz,Boost模式占空比约50%,那么L = (12 * 0.5) / (250k * 2.5) ≈ 9.6uH。我这里最终选了10uH。
注意电感电流的有效值RMS可比平均值大不少,设计时用RMS值去选电感额定电流,而不是简单的直流电流。10uH/12A电感的饱和电流至少要选15A以上,留30%余量。另外磁芯材料别用铁硅铝那种低μ粉芯环,虽然不容易饱和,但损耗在大电流下很明显。我用的是铁硅合金环形磁芯,具体型号不说了,反正绕线时注意别让线圈离外壳太近。
3.2 MOSFET选型考量
四开关Buck-Boost里的四个开关管,每一个在工作和同步整流状态下的应力并不对等。低压侧两个开关管承受的最大电压是高压侧母线电压(24V),高压侧两个开关管承受的最大电压是低压侧电压(12V)加反电动势,也基本在24V以内。所以电压应力不算大,但要特别关注电流应力和Rds(on)。
我选了100V/40A的MOSFET,Rds(on)约9mΩ,Qg约40nC。选大电流主要是为了降低导通损耗,尤其同步整流期间,电流流经MOSFET沟道时损耗是I²R,在小体积下散热不理想,Rds(on)越低越好。高频开关下Qg太大则栅极驱动损耗和驱动芯片的驱动能力都要重新估算。
栅极电阻也很关键。我用的是1Ω到4.7Ω的栅极驱动电阻,用来调节开关速度和抑制振铃。电阻太小,开关速度过慢,开关损耗大;电阻太大,虽然能抑制EMI,但驱动芯片拉不动栅极,容易让MOSFET在开关中途进入线性区,直接导致发热。实际调试时我用示波器看Vgs波形,在保证波形圆润不震荡的前提下尽量减小栅极电阻。
3.3 半桥驱动芯片与自举电路
驱动电路采用半桥驱动芯片,芯片内部集成了上管驱动、下管驱动、自举二极管和欠压锁定。典型型号如IR2104、IRS2186、UCC27714,我用的是IR2104的兼容型号,便宜好用,带硬件关断引脚,方便接保护信号。
需要特别注意自举电容的选型。上管悬浮供电依靠自举电容充放电,电容容量太小导致上管开通瞬间电压跌落太多,会让上管米勒平台期间栅极电压不足。我选的是100nF陶瓷电容并联一颗10uF的电解电容,这是很通用的组合。另外,自举电容的充电路径要经过自举二极管和限流电阻,这个限流电阻太小会冲击自举二极管,太大会导致充电不足。IR2104的数据手册上建议加1Ω到10Ω之间的限流电阻,我最后用4.7Ω,实测Vgs波形正常。
需要注意的是,当PWM占空比接近100%时,上管长时间导通,自举电容得不到有效充电,会造成“自举电容饥饿”。这种情况在Buck模式下如果占空比太高,就会出现上管驱动波形畸变。所以控制算法里我做了最大占空比限制,钳位在95%左右。
3.4 采样与保护电路
电压采样用电阻分压,再经过RC滤波和电压跟随器,送入ADC。分压电阻的精度直接影响测量精度,1%的电阻是底线,最好用0.1%。我实测用0.1%的精度,低压侧12V可以做到±10mV以内。
电流采样这里走了点弯路,最开始用低边检流电阻采样,但是四开关Buck-Boost的PWM地是高低边交替的,低边采样在高端开关导通时无法准确反映电感电流。后来改成高边检流电阻+差分放大器的方式,参考电压浮动比较大,但用差分放大器后效果还行。为了更准确,也可以直接用电流传感器芯片,比如ACS712或霍尔传感器,不过贵一些。我用的是INA240,专门适应高共模电压的电流检测放大器,可以直接接在电感支路上。
保护方面,最重要的就是过流保护。软件过流可以靠ADC检测后做限流,但速度不够快。dsPIC的模拟比较器可以配合PWM的硬件故障引脚,当检测电压超过阈值时,立即关闭PWM输出,响应时间在几十纳秒级。我在源程序里专门做了这段硬件保护配置,并演示过人为短路,能可靠关断。
4. 控制源码怎么搭:状态机、PI调节器与双向切换的实现
4.1 代码结构和工程目录
源码工程用MPLAB X IDE + XC16编译器开发,目录结构尽量分层,避免把一堆函数堆在main.c。我的源码分成模块:
main.c:系统初始化、主循环adc.c:ADC配置和中断服务程序pwm.c:PWM初始化、死区配置control.c:PI调节器、数字滤波、方向判断fault.c:故障检测和状态机peripherals.c:按键、LED、串口显示
每写完一个模块就单独编译,别等全部写完再调试,不然一旦出问题根本不知道是硬件还是软件。
4.2 核心控制算法实现
主控制环我采用的是电压外环和电流内环的双环控制结构。电压外环根据目标电压和当前输出电压之差,计算电流指令;电流内环根据电流指令和实际电感电流之差,更新PWM占空比。
为什么用双环?因为Buck-Boost本质上是一个二阶系统,直接单环电压控制动态响应差,尤其负载突变时电压回落很大。电流内环相当于把一个电流源驱动到了电感路径上,电压外环只需要控制“往电感里”灌多少电流,响应速度会快很多。
PI调节器我用的增量式,代码如下:
typedef struct { float Kp; float Ki; float integral; float out_max; float out_min; } PI_Controller; float PI_Update(PI_Controller* pi, float err) { pi->integral += pi->Ki * err; // 积分限幅 if (pi->integral > pi->out_max) pi->integral = pi->out_max; if (pi->integral < pi->out_min) pi->integral = pi->out_min; float out = pi->Kp * err + pi->integral; if (out > pi->out_max) out = pi->out_max; if (out < pi->out_min) out = pi->out_min; return out; }积分限幅一定要做,不然启动时刻积分疯狂累积,占空比会直接飙到最大,电感电流爆增,轻则炸MOS管,重则烧保险。我这里调Kp和Ki的时候采用的是先调Kp,增大到输出开始震荡,再调Ki,逐步找到响应和稳定性的平衡点。
4.3 双向切换状态机
模式切换是双向DC-DC最容易出bug的地方。我用了四个状态:FORWARD_BUCK、FORWARD_BOOST、REVERSE_BUCK、REVERSE_BOOST。还有一个SOFT_START状态,每次切换都会先进入软启动。
状态切换的核心判断条件是输出电压与目标电压的差值以及方向标志。比如高压侧基准24V,低压侧基准12V,如果检测到高压侧电压低于24V且需要从低压侧取电,就进入正向Boost状态;如果高压侧电压高于24V需要回灌低压侧,就进入反向Buck状态。
切换的时候不能瞬间把PWM占空比跳到目标值,需要斜坡或者按步进变化。我从当前占空比开始,每100us增加1%的占空比步进,直到目标值。实测这个做法能把电流超调控制在设计范围之内。
在源码里还有一段重要的代码是ADC中断里的执行序列:先读电压,再读电流,然后跑模式状态机,再执行电流环PI,最后更新PWM。这里一定要关注执行时间,我实际跑下来,整个中断执行时间约4us,PWM周期4us(250kHz),也就是说CPU有接近一个周期的时间都在跑控制环,留给低速任务的时间很紧张,所以低速任务很少放进中断。
5. PCB设计复盘:功率环路、采样布线与EMI抑制
5.1 功率环路最小化
四开关Buck-Boost的功率回路里有两个开关节点,左边和右边。最忌讳的是把输入电容、MOSFET、输出电容之间的回路拉得很长,环路面积大了,寄生电感就会产生高尖峰电压,直接导致MOSFET过压击穿。
我的做法是先确定输入和输出电容的位置,让它们紧挨着对应的半桥。高压侧半桥的上管漏极接到高压侧正极,低压侧半桥的下管源极接到地,这些回路的铜皮面积要尽可能小。电源地要单点汇接到输入电容的负端,不能乱铺通。
实际我画了四层板,第二层整层当作完整参考地,第4层是电源层,顶层和底层走信号和功率,功率走线尽量加宽。实测相同控制参数下,四层板比双层板的SW节点振铃小了差不多30%。
5.2 采样走线和地线布局
采样的走线是高频开关电路里最容易出错的环节。电感电流检测放大器输出的模拟信号,如果走线穿过功率区域,很容易引入高频噪声。我把采样信号从功率区域拉出来之后,先穿过一个RC低通滤波器(截止频率大约1MHz)再进ADC。这个滤波器是必须的,哪怕dsPIC内部已经有滤波,外部再加一道会更干净。
IGBT或者MOSFET的开关节点(SW节点)旁边不要平行走采样线。我layout的时候特意让采样线远离SW节点至少3mm,如果空间不够,就用地线隔离。
还有一点,ADC的参考电压引脚一定要处理好,我用的是内部Vref,但还是额外在引脚旁放了一个0.1uF+1uF的电容。否则ADC结果会随开关噪声波动,环路稳定性直接受影响。
5.3 散热设计与实际性能
100W功率下,就算效率做到94%,仍然有大约6W的损耗要散发。MOSFET是主要损耗来源,我用的是DPAK封装,在PCB上给漏极铺了一大块铜皮作为散热片。同时加了过孔阵列,把顶层热量导到内层和底层铜皮。
板子实测结果如下:
| 测试条件 | 输入电压 | 输出电压 | 负载功率 | 效率 |
|---|---|---|---|---|
| 正向Boost | 12V | 24V | 50W | 96.5% |
| 正向Boost | 12V | 24V | 100W | 94.8% |
| 反向Buck | 24V | 12V | 50W | 95.9% |
| 反向Buck | 24V | 12V | 100W | 94.1% |
满载工作半小时,MOSFET表面温度在70℃左右,可以接受。如果你们要把功率做到200W以上,建议用TO-220封装并外加散热器,或者直接用同步整流的GaN器件。
6. 调试、实测与论文整理:真正完成一个可复现的电源项目
6.1 调试流程:从空载到满载的递进
我调试这个板子时的顺序很死板,但很有效。第一步,不上电,检查各电源对地阻抗是否有短路。第二步,只给控制板供电,用示波器观察PWM模块是否有输出,且死区时间正确。第三步,输入串接一个电流限制在1A的稳压电源,在空载情况下输出PWM,看输出电压能不能建立,并粗略检查输出电压纹波。第四步,用电子负载从10%负载开始加载,逐步加大负载,同时观察输出波形和电流波形。
这个过程里最容易发现问题的阶段是空载到轻载,因为此时电感电流进入断续模式,控制环路的传递函数会变化。我遇到过用连续模式参数跑断续模式结果出现电压振荡的情况。数字电源里解决这类问题通常有两种思路:一是加入“电流连续与否”的判断,用不同的PI参数;二是简单粗暴地增加一个固定的小负载,或者加入同步整流强制连续模式。我为了减少控制复杂度,在软件里加入了最小电流钳位,让电感电流始终保持在临界连续之上,这样整个负载区间内都是连续模式,控制参数不需要变。
6.2 典型故障和排查思路
我在这个项目里踩过两个值得说的坑。
第一个是上电时烧了一颗MOSFET。排查下来发现是最大占空比限制没做好,软启动功能没有严格执行,启动瞬间PWM占空比直接跳到计算值,电流斜率过大,瞬间超出额定电流。后来加入斜坡软启动,并且用示波器双通道拍Vgs和电感电流,确认启动过程电流没有过冲。
第二个坑是DS电压波形有严重振铃。一开始以为是LC谐振,后来发现是MOSFET的栅极驱动回路环路面积太大,栅极电荷注入产生的米勒平台导致导通瞬间的高频开关噪声。解决方法是把栅极驱动电阻和MOSFET的距离拉近,并且减小驱动回路的面积,同时在驱动芯片的电源引脚旁边多加了100nF+10nF的高频退耦电容。振铃明显减小,EMI也降了。
6.3 论文与附件整理
论文结构我建议按标准毕业设计或者技术报告的惯例来:摘要写清楚你做了个什么变换器、用了什么控制策略、主要的测试性能;第一章绪论介绍双向DC-DC的应用背景和国内外的研究现状,不要写空话;第二章讲系统方案和拓扑选型;第三章详细写硬件电路设计;第四章写软件设计;第五章展示仿真和实测结果,要有波形、效率数据。最后给结论和展望。
源码和PCB附件一定要和论文里的描述对得上。我的论文里提到某个采样滤波器的截止频率,代码里就必须有对应的实现。PCB版图里的器件位号也要和原理图一致,不然评审老师对照起来会一头雾水。我最后交付时把源码、原理图/PCB工程、仿真文件、论文草稿分目录整理,并且写了一份README说明怎么编译和烧录,方便别人复现。
整套源码中有一处值得单独说一下:在MPLAB X的工程文件里,我加了Kconfig式的宏定义注释,方便切换Buck/Boost方向以及改目标电压,这比让用户去代码里搜索数字“24.0”要友好得多。你如果以后要扩展双机通信、远程调压、恒流充电,在这个框架上加模块会方便很多。
最后再分享一个个人体会:数字电源和模拟电源完全是两种思维。模拟电源调环路靠改RC参数,数字电源调环路靠改PID系数,但核心都是反复观察阶跃响应。我建议你每个项目都单独做一块“调试接口板”,用uart和上位机连接,实时显示电流、电压、占空比、PI输出,这样能把你从无限次的示波器读数里解放出来。这个习惯我保留到现在,做任何数字电源项目都会先做通信接口再调主电路。
本文还有配套的精品资源,点击获取