一、系统综述: 该项设计的主要目的是设计一种数控稳压电源。它利用单片机STC89C51作为主控芯片,控制数字/模拟转换器(TLC5615)的输出电压的大小,经过运算放大器(OPA2107)与IRF9Z24N构成负反馈系统,从而输出恒定电压。最后通过电位器分压将输出信号反馈到运算放大器(OPA2107)上,使输出准确度可以调节。此设计通过键盘电路与单片机连接,读入控制数据,利用软件进行判断,从而起到控制电源输出的作用。通过LCD1602(或LED数码管)显示数控电源的输出电压,实现简单的人机对话。该项设计具有设计简单,控制灵活,调节方便,携带方便、成本低等优势,具有较强的实用性。 总体电路图(数码管版) 要求有短路保护的才有对应的电路,此图为完整版及带短路保护的。 总体电路图(液晶版) 要求有短路保护的才有对应的电路,此图为完整版及带短路保护的。 图中采用网络标号的方式,标号相同的代表有电气连接! 二、原理讲解: 供电部分: P2为接线柱,是整个系统的输入电压端口,整个数控电源有此输入能量。D1、D2、D3、D4为四个二极管(in4007),起整流的作用,C6为滤波电容。整流滤波电路是使供电可以为交流,同时也可以用直流供电(交流供电不要超过20V,直流不要超过35V)。受电压限制的主要是后级运放耐压、TL431耐压以及7812的耐压值。7812主要为保护7805,7805稳出5V电压共单片机供电使用。但是7805耐压值是15V,所以前级要加7812保护7805。
晶振部分: C2、C3、Y1(12MHZ)与单片机端口构成震荡电路,为51单片机提供时钟。 复位电路: RST连接单片机复位管脚,此电路及有上电复位功能,又有手动复位功能。C1、R2构成上电复位电路,上电瞬间C1导通,则RST为高电平,单片机将复位,电压稳定后C1储存的电能通过R2对地释放掉,单片机将正常运行。同样K2按下时RST为高电平,单片机复位,弹起来时RST为低电平,单片机正常运行。
单片机部分: 单片机默认选用STC89C51,同时兼容STC89C52、AT89S52、AT89S51、AT89C51等51单片机。 按键部分: 按键选用独立按键,扫描时间短,使程序更简单且扫描时间更短,从而提高稳定性。按键弹起时P20、P21、P22、P23为弱上拉状态,所以为高电平。按键按下时对应的I/O口为低电平,可以被程序中的扫描函数检测到。(写文档时没什么写的,可以在此讲解自弹按键与自锁按键区别和原理,在此朱老师省略。)
数码管显示部分: (写文档时,可以在此讲解共阳数码管与共阴数码管的区别和原理,在此朱老师省略。) 数码管显示采用四位一体共阳数码管,这样使电路更为简单,只需四个8550三极管就可以将其驱动。P24、P25、P26、P27分别作为数码管的位选端,控制是否选通哪一位数码管。采用PNP型三极管,低电平导通,高电平截止(写文档时可以在此处讲解8550三极管的参数等信息,朱老师在此省略)。R20、R30、R40、R50为三极管基极限流电阻,此电阻及能保护三极管又能保证三极管导通时处于完全导通状态。R51为限流电阻,此电阻的大小直接决定数码管的亮暗成都,在此选择220欧姆、1/4色环电阻。数码管的阴极端直接接单片机的P0口,而不需上拉电阻。STC89C51的单片机P0口为漏极开路,所以作为输出时必须接上拉电路,而作为输入时相当于数码管作为上拉,所以不再需要上拉电阻,及简化了电路又节省了成本。 数模转换部分:(此为数控电压数控调压关键所在) (写文档时没什么写的,可以在此讲解TLC5615技术参数和原理,特别是转换公式和数据协议,在此朱老师简单介绍。) 数模转换采用德州仪器的TLC5615,此为一片10位串行单5V电源DAC,直接电压输出。单片机P33、P32、P34分别连接TLC5615的时钟端、片选端、数据端即可控制它输出想要的电压。此时TLC5615的6脚及参考电压输入端需接入2.5V的参考电压。根据公式可知,当参考电压为2.5V时,TLC5615将最大输出5V电压。 TL5615(DAC)电压计算公式
Vout为7脚输出电压,Vrefin为6脚参考电压输入端,N为单片机通过1、2、3管脚向TLC5615写入的数据,1024是根据这是一片10位数模转换而计算出来的(210=1024),最后乘以二是因为TLC5615内部有2倍的增益放大器。 TLC5615内部原理图: TLC5615逻辑时序图:
在给TLC输入2.5V参考电压的时候,我们用了TL431芯片。TL431是可控精密稳压源。它的输出电压用两个电阻就可以任意的设置到从Verf(2.5V)到36V范围内的任何值。该器件的典型动态阻抗为0.2Ω,在很多应用中用它代替稳压二极管。 同时用OPA2107作为跟随器,减小2.5V基准电源的阻抗,再送入TLC5615 参考电压端。 (写文档时,可以在此讲解TL41技术参数OPA2107技术参数和原理和跟随器电路原理)
MOS放大部分: 将上述TLC5615输出的可调电压送到误差放大器(OPA2107)的反相端,通过PMOS管(F9Z24N)放大。同时在F9Z24N的输出端用RW1(10K)电位器分压,取一定比例的输出电压反馈到比较器正相端,构成一个负反馈系统(PMOS是反相放大,所以是负反馈)以保证输出电压的稳定。C5作为输出滤波电容,滤掉输出电压纹波。根据反馈系统的稳定原理计算出输出电压的公式,如下: 设:Vo为输出电压,Vin为OPA2107的2脚输入电压,RWH为电位器上部分电阻,RWL为电位器下部分电阻,RW为电位器阻值。 Vo=Vin×(RW/RWL); (写文档时,可以在此讲解F9Z24N技术参数) 过流检测及短路保护: P1为电源输出端,R11为电流检测电阻,此电阻将电流变换成电压。再通过U4A(OPA2107)反相放大一定的倍数。最后通过U4B与2.5V标准电平比较,若电压大于2.5V则输出低电平,送给单片机。单片机则认为过流就会控制TLC5615将输出将为0V。这样就起到了限流与短路保护的作用。 (写文档时,可以在此讲解反相比例运算电路的原理) 报警电路: 此电路可以由单片机控制三极管(8550)的通断来控制蜂鸣器的报警。当P36为高时,三极管不高通,为低时三极管导通蜂鸣器响。当过流或短路时,单片机切断输出,同时蜂鸣器报名。
单片机源程序如下:
- <font color="rgb(0, 0, 0)">#include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- uchar a,miao,shi,fen,ri,yue,nian,week,key1n,key4n,key3n;alarmflag,temp;
- char amiao,afen,ashi;
- bit flag=0;
- #define yh 0x80
- #define er 0x80+0x40
- sbit rw=P3^6;
- sbit rs=P3^5;
- sbit en=P3^4;
- sbit IO=P1^1;
- sbit RST=P1^2;
- sbit SCLK=P1^0;
- sbit ACC0=ACC^0;
- sbit ACC7=ACC^7;
- //sbit key5=P1^3;
- sbit key1=P3^0;
- sbit key2=P3^1;
- sbit key3=P3^2;
- sbit key4=P3^3;
- sbit beep=P2^4;
- uchar code tab1[]={"20 - - "};
- uchar code tab2[]={" : : "};
- uchar code tab3[]={" alarm setting: "};
- uchar code tab4[]={"Now is the time!"};
- uchar code tab5[]={"Get up quickly! "};
- uchar code tab6[]={"HAPPY EVERY DAY!"};
- uchar cnt;
- void delay(uint xms)
- {
- uint x,y;
- for(x=xms;x>0;x--)
- for(y=110;y>0;y--);
- }
- void write_1602com(uchar com)
- {
- rs=0;
- rw=0;
- P0=com;
- delay(1);
- en=1;
- delay(1);
- en=0;
- }
- void write_1602dat(uchar dat)
- {
- rs=1;
- rw=0;
- P0=dat;
- delay(1);
- en=1;
- delay(1);
- en=0;
- }
- void lcd_init()
- {
- write_1602com(0x38);
- write_1602com(0x08);
- write_1602com(0x0c);
- write_1602com(0x06);
- write_1602com(0x01);
- write_1602com(yh+1);
- for(a=0;a<14;a++)
- {
- delay(5);
- write_1602dat(tab1[a]);
- }
- write_1602com(er+2);
- for(a=0;a<8;a++)
- {
- delay(5);
- write_1602dat(tab2[a]);
- }
- }
- void write_byte(uchar dat)
- {
- ACC=dat;
- RST=1;
- for(a=8;a>0;a--)
- {
- IO=ACC0;
- SCLK=0;
- SCLK=1;
- ACC=ACC>>1;
- }
- }
- uchar read_byte()
- {
- RST=1;
- for(a=8;a>0;a--)
- {
- ACC7=IO;
- SCLK=1;
- SCLK=0;
- ACC=ACC>>1;
- }
- return(ACC);
- }
- void write_1302(uchar add,uchar dat)
- {
- RST=0;
- SCLK=0;
- RST=1;
- write_byte(add);
- write_byte(dat);
- SCLK=1;
- RST=0;
- }
- uchar read_1302(uchar add)
- {
- uchar temp;
- RST=0;
- SCLK=0;
- RST=1;
- write_byte(add);
- temp=read_byte();
- SCLK=1;
- RST=0;
- return(temp);
- }
- uchar BCD_Decimal(uchar bcd)
- {
- uchar Decimal;
- Decimal=bcd>>4;
- return(Decimal=Decimal*10+(bcd&=0x0f));
- }
- void ds1302_init()
- {
- RST=0;
- SCLK=0;
- write_1302(0x8e,0x00);
- write_1302(0x8e,0x80);
- }
- void write_sfm(uchar add,uchar dat)
- {
- uchar gw,sw;
- gw=dat%10;
- sw=dat/10;
- write_1602com(er+add);
- write_1602dat(0x30+sw);
- write_1602dat(0x30+gw);
- }
- void write_nyr(uchar add,uchar dat)
- {
- uchar gw,sw;
- gw=dat%10;
- sw=dat/10;
- write_1602com(yh+add);
- write_1602dat(0x30+sw);
- write_1602dat(0x30+gw);
- }
- void write_week(uchar week)
- {
- write_1602com(yh+0x0c);
- switch(week)
- {
- case 1:write_1602dat('M');write_1602dat('O');write_1602dat('N');break;
- case 2:write_1602dat('T');write_1602dat('U'); write_1602dat('E');break;
- case 3:write_1602dat('W');write_1602dat('E');write_1602dat('D');break;
- case 4:write_1602dat('T');write_1602dat('H');write_1602dat('U');break;
- case 5:write_1602dat('F');write_1602dat('R');write_1602dat('T');break;
- case 6:write_1602dat('S');write_1602dat('T');write_1602dat('A');break;
- case 7:write_1602dat('S');write_1602dat('U');write_1602dat('N');break;
- }
- }
- void settime()
- {
- if(key4n==0)
- {
- if(key1==0)
- {
- delay(9);
- if(key1==0)
- {
- beep=0;//蜂鸣器短响一声
- delay(50);
- beep=1;
- alarmflag=0;
- key1n++;
- while(!key1);
- switch(key1n)
- {
- case 1:TR0=0;
- write_1602com(er+0x09);
- write_1602com(0x0f);
- temp=(miao)/10*16+(miao)%10;
- write_1302(0x8e,0x00);
- write_1302(0x80,0x80|temp);//miao
- write_1302(0x8e,0x80);
- break;
- case 2:write_1602com(er+6);
- break;
- case 3:write_1602com(er+3);
- break;
- case 4:write_1602com(yh+0x0e);
- break;
- case 5:write_1602com(yh+0x0a);
- break;
- case 6:write_1602com(yh+0x07);
- break;
- case 7:write_1602com(yh+0x04);
- break;
- case 8:key1n=0;
- write_1602com(0x0c);
- alarmflag=1;
- TR0=1;
- temp=(miao)/10*16+(miao)%10;
- write_1302(0x8e,0x00);
- write_1302(0x80,0x00|temp);
- write_1302(0x8e,0x80);
- break;
- }
- }
-
- }
- if(key1n!=0)
- {
- if(key2==0)
- {
- delay(10);
- if(key2==0)
- {
- beep=0;//蜂鸣器短响一声
- delay(50);
- beep=1;
- while(!key2);
- switch(key1n)
- {
- case 1:miao++;
- if(miao==60)
- miao=0;
- write_sfm(0x08,miao);
- temp=(miao)/10*16+(miao)%10;
- write_1302(0x8e,0x00);
- write_1302(0x80,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+0x09);
- break;
- case 2:fen++;
- if(fen==60)
- fen=0;
- write_sfm(0x05,fen);
- temp=(fen)/10*16+(fen)%10;
- write_1302(0x8e,0x00);
- write_1302(0x82,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+6);
- break;
- case 3:shi++;
- if(shi==24)
- shi=0;
- write_sfm(2,shi);
- temp=(shi)/10*16+(shi)%10;
- write_1302(0x8e,0x00);
- write_1302(0x84,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+3);
- break;
- case 4:week++;
- if(week==8)
- week=1;
- write_1602com(yh+0x0e);
- write_week(week);
- temp=(week)/10*16+(week)%10;
- write_1302(0x8e,0x00);
- write_1302(0x8a,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+0x0e);
- break;
- case 5:ri++;
- if(ri==32)
- ri=1;
- write_nyr(9,ri);
- temp=(ri)/10*16+(ri)%10;
- write_1302(0x8e,0x00);
- write_1302(0x86,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+10);
- break;
- case 6:yue++;
- if(yue==13)
- yue=1;
- write_nyr(6,yue);
- temp=(yue)/10*16+(yue)%10;
- write_1302(0x8e,0x00);
- write_1302(0x88,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+7);
- break;
- case 7:nian++;
- if(nian==100)
- nian=0;
- write_nyr(3,nian);
- temp=(nian)/10*16+(nian)%10;
- write_1302(0x8e,0x00);
- write_1302(0x8c,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+4);
- break;
- }
- }
- }
- if(key3==0)
- {
- delay(10);
- if(key3==0)
- {
- beep=0;//蜂鸣器短响一声
- delay(50);
- beep=1;
- while(!key3);
- switch(key1n)
- {
- case 1:miao--;
- if(miao==-1)
- miao=59;
- write_sfm(0x08,miao);
- temp=(miao)/10*16+(miao)%10;
- write_1302(0x8e,0x00);
- write_1302(0x80,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+0x09);
- break;
- case 2:fen--;
- if(fen==-1)
- fen=59;
- write_sfm(5,fen);
- temp=(fen)/10*16+(fen)%10;
- write_1302(0x8e,0x00);
- write_1302(0x82,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+6);
- break;
- case 3:shi--;
- if(shi==-1)
- shi=23;
- write_sfm(2,shi);
- temp=(shi)/10*16+(shi)%10;
- write_1302(0x8e,0x00);
- write_1302(0x84,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+3);
- break;
- case 4:week--;
- if(week==-0)
- week=7;
- write_1602com(yh+0x0c);
- write_week(week);
- temp=(week)/10*16+(week)%10;
- write_1302(0x8e,0x00);
- write_1302(0x8a,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+0x0e);
- break;
- case 5:ri--;
- if(ri==0)
- ri=31;
- write_nyr(9,ri);
- temp=(ri)/10*16+(ri)%10;
- write_1302(0x8e,0x00);
- write_1302(0x86,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+10);
- break;
- case 6:yue--;
- if(yue==0)
- yue=12;
- write_nyr(6,yue);
- temp=(yue)/10*16+(yue)%10;
- write_1302(0x8e,0x00);
- write_1302(0x88,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+7);
- break;
- case 7:nian--;
- if(nian==-1)
- nian=99;
- write_nyr(3,nian);
- temp=(nian)/10*16+(nian)%10;
- write_1302(0x8e,0x00);
- write_1302(0x8c,temp);
- write_1302(0x8e,0x80);
- write_1602com(yh+4);
- break;
- }
- }
- }
-
- }
- }
- }
- void setalarm()
- { if(flag==0)
- {if(key1n==0)
-
- {if(key4==0)
- {
- delay(10);
- if(key4==0)
- {
- beep=0;
- delay(50);
- beep=1;
- while(!key4);
- write_1602com(0x80);
- for(a=0;a<16;a++)
- {
- write_1602dat(tab3[a]);
- }
- if(key4n==0)
- {
- write_1602com(er+0x09);write_sfm(8,amiao);
- write_1602com(er+6);write_sfm(5,afen);
- write_1602com(er+3);write_sfm(2,ashi);
- }
- beep=0;key4n++;
- switch(key4n)
- {
- case 1:
- write_1602com(er+0x06);
- write_1602com(0x0f);
- temp=(fen)/10*16+(fen)%10;
- write_1302(0x8e,0x00);
- write_1302(0x82,0x82|temp);//miao
- write_1302(0x8e,0x80);
- break;
- case 2:write_1602com(er+3);
- break;
- case 3: key4n=0;
- write_1602com(0x0c);
- alarmflag=1;
- lcd_init();
- temp=(fen)/10*16+(fen)%10;
- write_1302(0x8e,0x00);
- write_1302(0x82,0x00|temp);
- write_1302(0x8e,0x80);
- break;
- }
- }
-
- }
- if(key4n!=0)
- {
- if(key2==0)
- {
- delay(10);
- if(key2==0)
- {
- beep=0;//蜂鸣器短响一声
- delay(50);
- beep=1;
- while(!key2);
- switch(key4n)
- {
- case 1:afen++;
- if(afen==60)
- afen=0;
- write_sfm(0x05,afen);
- temp=(fen)/10*16+(fen)%10;
- write_1302(0x8e,0x00);
- write_1302(0x82,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+6);
- break;
- case 2:ashi++;
- if(ashi==24)
- ashi=0;
- write_sfm(2,ashi);
- temp=(shi)/10*16+(shi)%10;
- write_1302(0x8e,0x00);
- write_1302(0x84,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+3);
- break;
- }
- }
- }
- if(key3==0)
- {
- delay(10);
- if(key3==0)
- {
- beep=0;//蜂鸣器短响一声
- delay(50);
- beep=1;
- while(!key3);
- switch(key4n)
- {
-
- case 1:afen--;
- if(afen==-1)
- afen=59;
- write_sfm(5,afen);
- temp=(fen)/10*16+(fen)%10;
- write_1302(0x8e,0x00);
- write_1302(0x82,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+6);
- break;
- case 2:ashi--;
- if(ashi==-1)
- ashi=23;
- write_sfm(2,ashi);
- temp=(shi)/10*16+(shi)%10;
- write_1302(0x8e,0x00);
- write_1302(0x84,temp);
- write_1302(0x8e,0x80);
- write_1602com(er+3);
- break;
- }
- }
-
- }
- }
- }
- }
- }
- void timealarm()
- {
- if(shi>7)//大于7点才启动报时
- {
- if(alarmflag==1)//不按下设置按键时才有效
- {
- if(fen==0 && miao<2)
- {
- beep=0;//启动蜂鸣器
- }
- else if(fen==30 && miao==5)
- {
- beep=0;
- }
- else beep=1;
- }
- }
- }
- void init()
- {
- TMOD=0X01;
- EA=1;
- TH0=(65536-60000)/256;
- TL0=(65536-60000)%256;
- ET0=1;
- TR0=1;
- }
- void nz()
- {
- beep=0;
- delay(500);
- }
- void alarmoff()//按任意键关闭闹铃函数
- {
- if(flag==1)
- {
- if(key1==0||key2==0||key3==0||key4==0)
- {
- delay(10);
- if(key1==0||key2==0||key3==0||key4==0)
- {
- while(key1==0||key2==0||key3==0||key4==0)
- flag=0;
- lcd_init();
- }
- }
- }
- }
- void main()
- { beep=1;
- alarmflag=1;
- lcd_init();
- flag=0;
- ds1302_init();
- init();
-
- delay(10);
- while(1)
- {
- timealarm();
- settime();
- if(flag==1)
- {
- write_1602com(yh);
- for(a=0;a<16;a++)
- {
- delay(5);
- write_1602dat(tab4[a]);
- }
- write_1602com(er);
- for(a=0;a<16;a++)
- {
- delay(5);
- write_1602dat(tab5[a]);
- }
- }
- else if(flag==0&&key1n==0&&key4n==0)
- {
- miao=BCD_Decimal(read_1302(0x81));
- fen=BCD_Decimal(read_1302(0x83));
- shi=BCD_Decimal(read_1302(0x85));
- ri=BCD_Decimal(read_1302(0x87));
- yue=BCD_Decimal(read_1302(0x89));
- week=BCD_Decimal(read_1302(0x8b));
- nian=BCD_Decimal(read_1302(0x8d));
- write_sfm(8,miao);
- write_sfm(5,fen);
- write_sfm(2,shi);
- write_nyr(9,ri);
- write_nyr(6,yue);
- write_nyr(3,nian);
- write_week(week);
- }
- if((shi==ashi)&&(fen==afen))
- {
- if(0<miao&&miao<2)
- { nz();
- flag=1;
- }
-
- } else flag=0;beep=1;
- setalarm();
- alarmoff();
- }
- }
复制代码
仅供参考
|