降压DC/DC开关稳压电源的设计过程和感想

计一对降压型直流开关稳压电源,额定输入直流电压36v ,额定输出直流电压10v的稳压电源。输出电流最大3A,额定功率30W.要求具备稳压功能,输出纹波电压最大70mv,负载调整率<5%,电压调整率<0.7%。有过流保护功能并且动作值3.2A左右。可以并联运行俩个稳压电源。

这次我和大家分享的是降压DC/DC开关稳压电源的设计,这次资料全部开源,对,是全部开源。我会陆续更新把电路PCB、主要原理以及程序等全部开源。还有需要PCB的小伙伴,可以在评论区回复邮箱,我看到就会发送的。

先上主要的系统图片:

开始步入主题啦,一开始用TL494做的简易主控电路,方便虽然方便但是后期测试电路发现他在50Khz工作频率时候芯片发烫严重,效率也跟不上最高也是75%,纹波和电压调整率还可以,负载调整率下跌。

而TL494是一种固定频率脉宽调制电路,它包含了开关电源控制所需的全部功能,广泛应用于单端正激双管式、半桥式、全桥式开关电源,振荡频率可以通过外部的一个电阻和一个电容进行调节。输出电容的脉冲其实是通过电容上的正极性锯齿波电压与另外2个控制信号进行比较来实现。功率输出管Q1和Q2受控于或非门。当双稳触压器的 时钟信号为低电平时才会被通过,即只有在锯齿波电压大于控制信号期间才会被选通。当控制信号增大,输出脉冲的宽度将减小。

控制信号由集成电路外部输入,一路送至时间死区时间比较器,一路送往误差放大器的输入端。死区时间比较器具有120mV的输入补偿电压,它限制了最小输出死区时间约等于锯齿波的周期4%,当输出端接地,最大输出占空比为96%,而输出端接参考电平时,占空比为48%。当把死区时间控制输入端接上固定的电压,即能在输出脉冲上产生附加的死区时间。

脉冲宽度调制比较器为误差放大器调节输出脉宽提供了一个手段:当反馈电压从0.5V变化到3.5时,输出的脉冲宽度从被死区确定的最大导通百分比时间中下降为零。2个误差放大器具有从—0.3V到(vcc—2.0)的共模输入范围,这可能从电源的输出电压和电流察觉的到。误差放大器的输出端常处于高电平,它与脉冲宽度调智器的反相输入端进行“或”运算,正是这种电路结构,放大器只需最小的输出即可支配控制电路。

494外围PCB电路如下:

这是系统全局的一张图,纯硬件电路打造。用起来有点不太灵活

现在的直流稳压电源大致有两类,一类是线性直流稳压电源,另一类是开关直流稳压电源,又称高频直流稳压电源。因为开关直流稳压电源与一般的线性及可控硅电源相比体积更小,重量小,节能效果更好等显著的特点,愈来愈受到广大用户的酷爱。

TL494也是大多DIY爱好者和初学者喜欢的一款可以说是万能的芯片了,第一款产品在不懈努力之下终于完成了,只能说算是中规中矩把任务都完成了,显然没有达到预想的完美效果.整流之后输出的直流电压,虽然是直流电,但其中含有一部分的交流成分,所以还需要经过滤波电路,将多余的交流部分过滤,得到成分较少的直流电。电感滤波适用于低电压场合,Π型LC滤波电路由于电阻的存在,电源功率会有所损耗,降低功率,所以滤波电路选用电容滤波电路。整流电路通过电容滤波电路,相比前两者滤波电路,其输出电路更光滑,电压的平均值也有所增加。

电容滤波电路如图:

这个BUCK电路图纸是

在万用板搭建的基础上又进行了电路的pcb绘制,并打出来第一块板子

这是用运放做的负载识别功能电路,恒压输出与负载识别功能的切换即恒压和恒流模式的切换,可以采用数控方法和OP07双运放放大电路。

通过两个OP07组成双运放电路,第一个OP07运放通过调整电压放大倍数让负载阻值以输出电压形式体现,第二个OP07运放调整输出电压方向,再将电压反馈至TL494的2脚,从而实现负载识别功能。该方案具有很好的稳定性,并且硬件电路不复杂。为了实现切换功能,我们选择按键开关进行手动切换,简单实用。通过比较,我们选择此方案。如图所示。

电阻分压检测电路。经过在输出回路中串连采样电阻,将经过电阻的电流转换成两端的电压,经过检测电压值从而获得电流值。

使用电阻采样法,电阻与电位器串联,获得中间电压返回给单片机,实现采集电压的电流转换成两端的电压,经过检测电压值从而获得电流值。

       过流保护采用TL494内部实现过流保护需要在电路中加采样电阻。利用采样电阻的分压进入芯片内部,实现过流保护。同时该芯片有多种过流保护模式,该方案电路非常简单,但是在3.2A情况下,要实现过流保护,需要加大采样电阻,这会降低整个系统的效率。或者可以采用运放放大电压在进行控制。

这对运放线性要求较高。采样电路如图:

驱动电路由IR2104半桥驱动芯片驱动BUCK型同步整流电路实现系统降压的操作,该芯片采用被动式泵荷升压原理。上电时,电源流过快恢复二极管D向电容C充电,C上的端电压很快升至接近Vcc,这时如果下管导通,C负级被拉低,形成充电回路,会很快充电至接近Vcc,当PWM波形翻转时,芯片输出反向电平,下管截止,上管导通,C负极电位被抬高到接近电源电压,水涨船高,C正极电位这时已超过Vcc电源电压。因有D的存在,该电压不会向电源倒流,C此时开始向芯片内部的高压侧悬浮驱动电路供电,C上的端电压被充至高于电源高压的Vcc,只要上下管一直轮流导通和截止,C就会不断向高压侧悬浮驱动电路供电,使上管打开的时候,高压侧悬浮驱动电路电压一直大于上管的S极。采用该芯片降低了整体电路的设计难道,只要电容C选择恰当,该电路运行稳定。

BUCK型同步整流电路如下:

之前测试在输出端采用Π型滤波大大降低了纹波,但是由于滤波使得公共端地的不稳定造成电路有时的故障不能工作一开始以为是基准电压的浮动就用另一片494的基准作为控制端2脚的基准电压。滤波电路带来的损耗也比较大,而该电路只能实现对系统稳压降压以及带载功能过流和负载识别尚没使用。在经过一系列调试测试参数,发现利用494做的纯硬件的稳压电源可以实现过流保护功能、负载识别功能。并且再通过滤波电路的调整会得到一个满足的纹波值。但是这种电路效率最高只能达到75%,离要求还有很多距离而且负载调整率严重不行,重量也严重超标,因此决定换用覆铜板,利用频率和电路PCB布局走线来降低纹波。

在用TL494主控调试中发现,494虽然设计利用起来简便,但在需要高频环境下以及高效率低纹波都满足不了设计要求。而且负载调整的采样电阻分压补偿,硬件做起来难度大精度不高,过流精度也稍微低一点。因此对电路主控进行重新选择,用stc12单片机作为系统主控通过软件实现过流精度以及负载调整的采样电阻分压补偿,stc12单片机可以提供50khz的工作频率进一步降低纹波电压。第一代覆铜板产品乍一看又丑又大,主要是自己对ADPCB绘制的不熟悉造成的,但是电路实用而且纹波降低的效果明显。

测试调试数控稳压电源时的写照

经过一系列调整这是二代PCB电路,在原有基础上对电路的主控布置进行了大范围调整

测试PWM输出如下:

在二代基础上把控制电路移到了中间在四周通过主回路。更一步集成

当时做的双层板,下层主回路上层控制回路,为了增加滤波的效果延长了输出回路并通过差分走线进一步改善滤波效果。

最终的成品电路如下:

对系统进行全面的调试后,进行了对系统参数的测量,此次的系统全部符合题目要求

电压调整0.1%

负载调整1.1%

效率95%

纹波10%

对系统进行并联测试未发现有环流

测试结果分析如下:

根据上述测试数据,由此可以得出结论:

(1) 额定输出电压下,输出电压偏差为:5.5mV,远小于100mV。说明电路的输出准确。

(2) 额定输入电压下,已测最大输出电流为3.102A,大于3A。说明电路能承受大电流。

(3) 输出噪声纹波电压峰峰值为20.5mV,小于50mV。满足题目要求。

(4) 负载调整率为1.02%,小于5%;以及电压调整率为0.01%,小于0.5%。说明整个电路稳定性好,不易受到外部的干扰。

(5) 满载时效率为90.4%。说明该电路效率极高。

(6) 具备3.2A过流保护。

(7) 整体重量为0.17kg说明该电路具有小体积小重量的优势。

附部分源程序:

#include <STC12C5A60S2.H>

#include <intrins.h> /*use _nop_() function*/

#define uchar unsigned char

#define uint unsigned int

#define ADC_FLAG 0X10

#define S1_S0 0x40       //P_SW1.6

#define S1_S1 0x80      //P_SW1.7

sbit SD1 = P3^3;

sbit LED3 = P1^7;

sbit LED4 = P3^4;

sbit key1 = P0^0;   //ok

sbit key2 = P2^0;    //+

sfr P_SW1 = 0xA2; //外设功能切换寄存器1

uint Vout=0;

uint Iout = 0;      //输出电压

uint V1=0;

uint I1 = 0;

uint sum = 0;

uint Vref = 0;

uchar block = 175;

uchar log = 0;

uchar lag = 0;

uchar snm = 0;

uint get = 0;

uint got = 0;

float R = 9.998;

float Vin = 5.08;

float Vget;

float Rfu;

bit busy;

void delay();

void Key_1_();

void Key_2_();

void init_pca();

void init_timer();

void SendData(uchar dat);

void SendString(char *s); /

**********************************************************

函数说明: 延时程序

**********************************************************/

void delay(uchar t)

{

uint j;

uchar i;

for(i=0;

i<t;

i++) for(j=0;

j<1000;

j++);

}

/**********************************************************

函数说明: pca计数器初始化函数

**********************************************************/

void init_pca(void)

{

CMOD=0x08;//计数器0的溢出为PCA计数器的时钟源,允许pca中断使能,PDF资料上错误

CCON=0x00;

CCAPM0=0x42;//8位PWM输出,无中断

CCAPM1=0x42;//8位PWM输出,无中断

CL=0x00;//清零pca计数器

CH=0x00;

CCAP0L=0; //初始化spwm输出的占空比

CCAP0H=0;

CCAP1L=0; //初始化spwm输出的占空比

CCAP1H=0; CR=1;//运行pca计数器

}

/**********************************************************

函数说明: 读ADC数值

**********************************************************/

uchar GetADC(uchar ch)

{

uint laji;

uint result=0;

ADC_CONTR=0x88|ch; //选择通道 开始AD转换

_nop_();

_nop_();

_nop_();

_nop_();

while(!ADC_FLAG); //查询ADC_FLOG是否置位1 转换结束

~ADC_FLAG; //Clear ADC interrupt flag//1111 0111 结束AD转换

laji=ADC_RESL;

result=ADC_RES;

return(result);

}

/**********************************************************

函数说明: ADC查询法 始化函数

**********************************************************/

void InitADC()

{

uchar a;

P1M1=0x07;

P1M0=0x00;

P1ASF=0X07;

//相应端口当ADC使用时,端口要置位

P10&P11 ADC_RES=0;

ADC_CONTR=0X80; //1000 0000 开电源,最低速

delay(50);

for(a=0;a<5;a++)

{

GetADC(0);

}

}

/**************************************

短延时

**************************************/

void delay5ms()

{

uchar i,v,k;

for(i=1;i>0;i--) for(v=168;v>0;v--) for(k=22;k>0;k--);

}

/**********************************************************

函数说明: 过流保护开启按键

**********************************************************/

void Key_1_()

{

if(key1==0)

{

delay(100);

if(key1==0)

 {

SD1 = 1;

LED4 = 1;

delay(200);

LED4 = 0;

}

delay(100);

}

}

/**********************************************************

函数说明: 模式选择按键

**********************************************************/

void Key_2_()

{

if(key2==0)

{

delay(100);

if(key2==0)

{

if(log<3)log+=1;

else log = 0;

LED4 = 1;

delay(200);

LED4 = 0;

}

delay(100);

}

}

/**********************************************************

函数说明: 调整电压

**********************************************************/

void VAdjust()

{

uchar a,b,c,d;

switch(lag)

{

case 0: I1 = GetADC(1); sum+=1;Iout +=I1;break;

case 1: ADC_CONTR=0X00;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;

case 2: V1 = GetADC(0); sum+=1; Vout +=V1;break;

case 3: ADC_CONTR=0X80;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;

}

if(sum >= 100)

{

sum = 0;

switch(lag)

{

case 0: Iout = Iout/50;

a = 48+Iout/1000;

b = 48+Iout%1000/100;

c = 48+Iout%100/10;

d = 48+Iout%10;

// SendData(e);

SendData(a);

SendData(b);

SendData(c);

SendData(d);

SendData('\n');

 Vref = 119+ Iout/29;

break;

case 1: break;

case 2: Vout = Vout/100;

a = 48+Vout/1000;

b = 48+Vout%1000/100;

c = 48+Vout%100/10;

d = 48+Vout%10;

//               SendData(e);

SendData(a);

SendData(b);

SendData(c);

SendData(d);

SendData('\n');

if(Vout>Vref) //输出电压小于36V

{

if(block==255)

block=255; 

else block++;

}

else //输出电压大于36V

{

 if(block==50)

block= 50;

else block--;

} break;

case 3: break;

} lag+=1;

if(lag>3) lag=0;

Vout = 0;

Iout = 0;

}

}

/**********************************************************

函数说明: 过流保护

**********************************************************/

void IAdjust()

{

uchar a,b,c,d;

switch(lag)

{

case 0: I1 = GetADC(1); sum+=1;Iout +=I1;break;

case 1: ADC_CONTR=0X00;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;

case 2: V1 = GetADC(0); sum+=1; Vout +=V1;break;

case 3: ADC_CONTR=0X80;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;

}

if(sum >= 100)

{

sum = 0;

switch(lag)

{ case 0: Iout = Iout/50;

a = 48+Iout/1000;

b = 48+Iout%1000/100;

c = 48+Iout%100/10;

d = 48+Iout%10;

// SendData(e);

SendData(a);

SendData(b);

SendData(c);

SendData(d);

SendData('\n');

if(Iout>=218)

{

snm+=1;

if(snm >=20) SD1 = 0;

}

Vref = 119+ Iout/29; break;

case 1: break;

case 2: Vout = Vout/100;

a = 48+Vout/1000;

b = 48+Vout%1000/100;

c = 48+Vout%100/10;

d = 48+Vout%10;

// SendData(e);

SendData(a);

SendData(b);

SendData(c);

SendData(d);

SendData('\n');

if(Vout>Vref) //输出电压小于36V

{

if(block==255)

block=255;

else

block++;

}

else //输出电压大于36V

{ if(block==50)

block= 50;

else

block--;

} break;

case 3: break;

}

lag+=1;

if(lag>3)

lag=0;

Vout = 0;

Iout = 0;

}

}

/**********************************************************

函数说明: 负载识别

**********************************************************/

void KnowLoad(void)

{ uchar a,b,c,d;

switch(lag)

{

case 0: get = GetADC(2); sum+=1;got +=get;break;

case 1: ADC_CONTR=0X00;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;

case 2: V1 = GetADC(0); sum+=1; Vout +=V1;break;

case 3: ADC_CONTR=0X80;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;

}

if(sum >= 100)

{

sum = 0;

switch(lag)

{ case 0: got = got/100;

a = 48+got/1000;

b = 48+got%1000/100;

c = 48+got%100/10;

d = 48+got%10;

// SendData(e);

SendData(a);

SendData(b);

SendData(c);

SendData(d);

SendData('\n');

if(got>=240) Vref = 0;

else

{ if(got<=60) {Vget = (got+2)*0.02;

Rfu =Vget*R/Vin/(1-Vget/Vin)/2.0;

Vref = Rfu/0.02-3;

}

if(got>60 && got<100)

{

Vget = (got-3)*0.02;

Rfu =Vget*R/Vin/(1-Vget/Vin)/2.0;

Vref = Rfu/0.02+2;

}

if(got>=100)

{ Vget = (got-6)*0.02;

Rfu =Vget*R/Vin/(1-Vget/Vin)/2.0;

Vref = Rfu/0.02;

}

} break;

case 1: break;

case 2: Vout = Vout/100;

a = 48+Vout/1000;

b = 48+Vout%1000/100;

c = 48+Vout%100/10;

d = 48+Vout%10;

// SendData(e);

/* SendData(a);

SendData(b);

SendData(c);

SendData(d);

SendData('\n');

*/ if(Vout>Vref) //输出电压小于36V

{

if(block==255)

block=255;

else block++;

}

else //输出电压大于36V

{

if(block==50)

block= 50;

else block--;

} break;

case 3: break;

}

lag+=1;

if(lag>3) lag=0;

Vout = 0;

Iout = 0; }

}

/**********************************************************

函数说明: 主函数

**********************************************************/

void main(void)

{ LED1 = LED2 =LED3 =LED4 =0;

delay(255);delay(255);delay(255);

InitADC();

init_pca();

init_timer();

EA=1;//开总中断

while(1)//主循环

{

Key_2_();

// VAdjust();

switch(log)

{

case 1: break;

case 0: VAdjust();LED1 = 1;LED2 = LED3 = 0;break;

case 3: IAdjust();LED2 = 1;LED1 = LED3 = 0;Key_1_();break;

case 2: KnowLoad();LED3 = 1;LED1 = LED2 = 0;break;

}

}

}

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 1
收藏 8
关注 5
成为作者 赚取收益
全部留言
0/200
  • এ゛Yuvin_Shan。 2022-03-17 20:32
    老师发给我18626134488@163.com
    回复
  • 阳光帝国 2020-10-29 09:51
    大开眼界,真是好文
    回复
  • 好学2019 2020-10-10 19:32
    学习学习1240516555@qq.com
    回复