專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

單片機(jī)數(shù)控電源設(shè)計(jì)

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2009年10月10日   【字體:
畢業(yè)前的最后設(shè)計(jì)

    即將告別大學(xué),學(xué)了幾年也沒什么拿得出手的作品。由于學(xué)校停課,趁著找工作的空閑索性做個(gè)一直掛記在心的單片機(jī)數(shù)控電源。從策劃到最后作品成型一共前前后后花了4天。先后經(jīng)歷了兩次坐車到電子市場(chǎng)買元器件,調(diào)程序到深夜凌晨3點(diǎn),焊板子,被熱熔膠燙破手皮。四天幾乎除了吃飯睡覺的幾個(gè)小時(shí)外都在設(shè)計(jì)。期間也遇到很多問題。例如:做DA時(shí)調(diào)不出輸出電壓,反復(fù)折騰了一天才解決,原來是單片機(jī)管腳有問題,又換了一塊。(燒掉一塊運(yùn)放,導(dǎo)致又到電子市場(chǎng)買了一塊)。四天下來總算充分完成了設(shè)計(jì)任務(wù)。確實(shí)學(xué)到了不少,模電這塊還是要加強(qiáng)一下。這個(gè)作品完成后決定把所有這幾年積攢下來的一大麻袋電子垃圾全部扔到無線電協(xié)會(huì),從此告別電烙鐵,告別大學(xué),開始新生活.

制作過程

完整作品

 

遠(yuǎn)視圖

 

側(cè)視圖

 

后視圖

 

內(nèi)部俯視圖

 

面板

D/A,A/D數(shù)控電源電路板

 


溫度,時(shí)間部分電路板


變壓器和空殼


顯示的面板(左上角是溫度,中間數(shù)碼管是時(shí)間,液晶是電壓)


還未裝機(jī)

整機(jī)

 

俯視圖

側(cè)視圖

 

正視圖

 

 

一,設(shè)計(jì)任務(wù):

基本部分:

1,輸出電壓范圍0-25V。

2,電流范圍0-2.5A。

3,用1602液晶顯示電壓值。

4,用矩陣鍵盤實(shí)現(xiàn)電壓值輸入(0-9,清除鍵,確認(rèn)鍵等)。

選設(shè)部分:

1, 溫度檢測(cè)顯示(可采用4位數(shù)碼管或在液晶上顯示)

2, 時(shí)間顯示(可采用6位數(shù)碼管或在液晶上顯示)

 

二,系統(tǒng)框圖

 

 

三.工作原理:

1.上電復(fù)位,讀取24C02中的電壓,送DA轉(zhuǎn)換輸出電壓,如24C02中電壓為O則設(shè)置初始電壓為5V;

2.電壓控制:通過矩陣鍵盤控制單片機(jī)產(chǎn)生8位數(shù)字信號(hào)(0-255),通過P3口送至8位數(shù)模轉(zhuǎn)換芯片(DAC0832)轉(zhuǎn)換成模擬電流信號(hào),再經(jīng)運(yùn)放作I/U轉(zhuǎn)換,得到控制穩(wěn)壓電源輸出部分的基準(zhǔn)電壓;

3.電流取樣:采用10位模數(shù)轉(zhuǎn)換芯片(TLC1549)作為顯示電流的模數(shù)轉(zhuǎn)換器件,TLC1549的取樣電壓由串聯(lián)在電源輸出電路的電流取樣電阻(0.1Ω)分壓取得,并由運(yùn)放按一定倍數(shù)放大后送至Vin(+),TLC1549把轉(zhuǎn)換結(jié)果送至單片機(jī)的P2.3口,再由程序?qū)?shù)據(jù)處理后送LCD1602顯示當(dāng)前電流;

4.過流保護(hù):當(dāng)短路或電流超過設(shè)定值2.4A時(shí),單片機(jī)自動(dòng)保存當(dāng)前使用電壓并關(guān)閉輸出;

5.穩(wěn)壓輸出:采用傳統(tǒng)的串聯(lián)穩(wěn)壓電路,由運(yùn)放和功率輸出管組成。利用DAC0832控制的基準(zhǔn)電壓驅(qū)動(dòng)功率管穩(wěn)壓輸出,反饋部分是通過電阻R3,VR2將取樣電壓輸入運(yùn)放的反相端比較,VR2可作小范圍調(diào)整;

四,源程序 (初稿)

   所有源程序已通過調(diào)試,首發(fā)于單片機(jī)網(wǎng)http://www.torrancerestoration.com,有問題可與QQ:125739409聯(lián)系,注意不得用于商業(yè)目的,有兩個(gè)程序,第一個(gè)為數(shù)控電源程序,第二個(gè)為溫度和時(shí)間的程序。

程序一
#include <reg52.h> //52系列頭文件
#define Disdata P0 //液晶數(shù)據(jù)端口
#define uchar unsigned char //無符號(hào)字符8位
#define uint unsigned int //無符號(hào)整數(shù)8位
uint data dis[4]={0x00,0x00,0x00,0x00};//4個(gè)數(shù)據(jù)單元和一個(gè)
uchar code table[]="OUTPUT: . V "; //定義初始上電液晶默認(rèn)顯示狀態(tài)
uchar code table1[]="designed by :";
uchar code table3[]=" Li Xiaojun";
uchar code table2[]="INPUT: . V ";
sbit lcden=P2^7; //定義液晶使能端
sbit lcdrs=P2^5; //定義液晶RS端
sbit rw=P2 ^6; //定義液晶RW端
sbit cs_ad=P2^4;
sbit dout=P2^3;
sbit clk=P2^2; //轉(zhuǎn)換結(jié)束標(biāo)志位
sbit da_wr=P2^1;
sbit da_cs=P2^0;
sbit beep=P1^7;//蜂鳴器
data int result;//測(cè)量變量暫存地址
uchar num,num1,num2,num3,num4,num5;
uchar shii,gei;
uchar shuru;
uchar dagg,dass;
uchar key,temp;
uchar cvc,mma,mmb;
uchar ddf;
uint ddt;
//********延時(shí)函數(shù)************
void delay(uint z)
{
uint x,y;
for(x=z;x&gt;0;x--)
for(y=110;y&gt;0;y--);
}
 
//*************
void di()
{
beep=0;
delay(100);
beep=1;
}void write_com(uchar com) //液晶寫命令函數(shù)
{
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date) //液晶寫數(shù)據(jù)函數(shù)
{
lcdrs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_sg(uchar add,uchar date) //寫整數(shù)位和小數(shù)位函數(shù)
{
uint shi,ge;
shi=date/10; //分解出一個(gè)2位數(shù)的十位
ge=date%10;
write_com(0x80+0x40+add); //設(shè)置顯示位置
write_data(0x30+shi); //送去液晶顯示十位
write_data(0x30+ge); //送去液晶顯示個(gè)位
}
//void write_da(uchar sps,uchar uru)
//{ uchar yuy,rur;
// yuy=uru;
// rur=0;
// write_com(0x80+sps); //設(shè)置顯示位置
//if(cvc==8)
// {
// write_data(0x30+yuy); //送去液晶顯示十位
// write_data(0x30+rur); //送去液晶顯示個(gè)位
// }
/// else
// write_data(0x30+rur); //送去液晶顯示十位
// write_data(0x30+yuy);
//}void init()
{
shuru=0;
rw=0;
lcden=0;
shii=0;
gei=0;
dagg=0;
dass=0;
write_com(0x38); //初始化1602液晶
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80); //設(shè)置顯示初始坐標(biāo) for(num2=0;num2&lt;13;num2++)
{
write_data(table1[num2]);
delay(5);
}
write_com(0x80+40);
for(num3;num3&lt;16;num3++)
{
write_data(table3[num3]);
delay(5);
}
delay(3000);
 
} //*******************************
void scan1()
{
write_com(0x80);
for(num1;num1&lt;16;num1++)
{
write_data(table2[num1]);
delay(5);
}
// write_da(8,dass);
//write_da(11,dagg); write_com(0x80+0x40); //設(shè)置顯示初始坐標(biāo)
for(num=0;num&lt;16;num++)
{
write_data(table[num]);
delay(5);
}
write_sg(8,shii);
write_sg(11,gei);
 
}
 
//****TLC1549轉(zhuǎn)換處理子函數(shù)********void test()
{
 
data uchar i;
 
cs_ad=1; //禁止i/o clock
cs_ad=0; //開啟控制電路,使能data out和i/o clock
result=0; //清轉(zhuǎn)換變量
for(i=0;i&lt;10;i++) //采集10次 ,即10bit
{
clk=0;
result*=2;
if(dout) result++;
clk=1;
}
delay(590);
cs_ad=1; ;;;; //data out 返回到高阻狀態(tài)而終止序列
//****數(shù)據(jù)轉(zhuǎn)換處理**********
result=result*2;
dis[2]=result/205; //計(jì)算整數(shù)位
dis[3]=result%205; //余數(shù)暫存
dis[3]=dis[3]*10; //計(jì)算小數(shù)第一位
dis[1]=dis[3]/205;
dis[3]=dis[3]%205;
dis[3]=dis[3]*10; //計(jì)算小數(shù)第二位
dis[0]=dis[3]/205;
shii=dis[2];
gei=dis[1]*10+dis[0];
write_sg(8,shii);
write_sg(11,gei);
 
}
//***********************
void test_da()
{
 
 
ddf=mma+mmb*0.1-0.7;
ddf=ddf*25.6;
ddt=ddf;
da_wr=0;
da_cs=0;
P3=ddt;
delay(1);
}//*************************
void markey()
{
 
P1=0xfe;
temp=P1;
temp=temp&amp;0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&amp;0xf0;
if(temp!=0xf0);
{
temp=P1;
switch(temp)
{
case 0xee:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+1);
di();
cvc++;
key=1;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+1);
write_data(0x30+0);
key=1;
cvc=0;
di();
mmb=key;
test_da();
break;
case 0xde:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+2);
di();
cvc++;
key=2;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+2);
write_data(0x30+0);
key=2;
cvc=0;
di();
mmb=key;
test_da();
break;
 
 
case 0xbe:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+3);
di();
cvc++;
key=3;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+3);
write_data(0x30+0);
key=3;
cvc=0;
di();
mmb=key;
test_da();
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&amp;0xf0;
}
 
}
 
 
} P1=0xfd;
temp=P1;
temp=temp&amp;0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&amp;0xf0;
if(temp!=0xf0);
{
temp=P1;
switch(temp)
{
case 0xed:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+4);
di();
cvc++;
key=4;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+4);
write_data(0x30+0);
key=4;
cvc=0;
di();
mmb=key;
test_da();
break;
case 0xdd:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+5);
di();
cvc++;
key=5;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+5);
write_data(0x30+0);
key=5;
cvc=0;
di();
mmb=key;
test_da();
break;
case 0xbd:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+6);
di();
cvc++;
key=6;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+6);
write_data(0x30+0);
key=6;
cvc=0;
di();
mmb=key;
test_da();
break;
 
 
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&amp;0xf0;
}
 
}
} P1=0xfb;
temp=P1;
temp=temp&amp;0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&amp;0xf0;
if(temp!=0xf0);
{
temp=P1;
switch(temp)
{
case 0xeb:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+7);
di();
cvc++;
key=7;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+7);
write_data(0x30+0);
key=7;
cvc=0;
di();
mmb=key;
test_da();
break;
case 0xdb:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+8);
di();
cvc++;
key=8;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+8);
write_data(0x30+0);
key=8;
cvc=0;
di();
mmb=key;
test_da();
break;
case 0xbb:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+9);
di();
cvc++;
key=9;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+9);
write_data(0x30+0);
key=9;
cvc=0;
di();
mmb=key;
test_da();
break;
 
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&amp;0xf0;
}
 
}
 
}
 
P1=0xf7;
temp=P1;
temp=temp&amp;0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&amp;0xf0;
if(temp!=0xf0);
{
temp=P1;
switch(temp)
{
case 0xe7:
if(cvc==0)
{
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+0);
di();
cvc++;
key=0;
mma=key;
break;
}
else
write_com(0x80+11);
write_data(0x30+0);
write_data(0x30+0);
key=0;
cvc=0;
di();
mmb=key;
test_da();
break;
break;
case 0xd7:
key=11;
write_com(0x80+8);
write_data(0x30+0);
write_data(0x30+0);
write_com(0x80+11);
write_data(0x30+0);
write_data(0x30+0);
di();
cvc=0;
mma=0;
mmb=0;
test_da();
break;
case 0xb7:
key=12;
break;
 
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&amp;0xf0;
}
 
}
}
}
 
 
//*******主函數(shù)*****
void main()
{
init();
scan1();
while(1)
{
markey();test_da();
test();
}
}
 
<B>程序二</B>
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code tab[]={ //0-f的極代碼
0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xa7,0xa1,0x86,
0x8e};uchar count,s1num;
uchar miao,shi,fen;
unsigned char code tab1[]={0xc6};
/*********************************端口定義**********************************/

sbit DQ=P2^0; //數(shù)據(jù)傳輸線接單片機(jī)的相應(yīng)的引腳
sbit beep=P1^3;
sbit s1=P1^2;
sbit s2=P1^0;
sbit s3=P1^1;
/*********************************定義全局變量******************************/
unsigned char tempL=0; //臨時(shí)變量低位
unsigned char tempH=0; //臨時(shí)變量高位
float temperature;
//溫度值/****************************************************************************

函數(shù)功能:延時(shí)子程序
入口參數(shù):k
出口參數(shù):
****************************************************************************/

void delay(unsigned int k)
{
unsigned int n;
n=0;
while(n &lt; k)
{n++;}
return;
}
/****************************************************************************

函數(shù)功能:數(shù)碼管掃描延時(shí)子程序
入口參數(shù):
出口參數(shù):
****************************************************************************/

void delay1(uint x)
{
int j,k;
for(j=x;j&gt;0;j--)
for(k=50;k&gt;0;k--);
}void di()
{
beep=0;
delay1(250);
beep=1;
}/****************************************************************************

函數(shù)功能:數(shù)碼管顯示子程序
入口參數(shù):k
出口參數(shù):
****************************************************************************/

void init()
{
 
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void scan(uchar shi,uchar fen,uchar miao)
{
 
 
P2=0xfb;
P0=tab[shi/10];
delay1(1);
 
P0=0xff;
P2=0xf7;
P0=tab[shi%10];
delay1(1); P0=0xff;
P2=0xef;
P0=tab[fen/10];
delay1(1); P0=0xff;
P2=0xdf;
P0=tab[fen%10];
delay1(1); P0=0xff;
P2=0xbf;
P0=tab[miao/10];
delay1(1); P0=0xff;
P2=0x7f;
P0=tab[miao%10];
delay1(1);
P0=0xff;
}
void keyscan()
{
if(s1==0)
{
delay1(5);
if(s1==0)//確認(rèn)功能鍵被按下
{ s1num++;//功能鍵按下次數(shù)記錄
while(!s1);//釋放確認(rèn)
di();//每當(dāng)有按鍵釋放蜂鳴器發(fā)出滴聲
if(s1num==1)//第一次被按下時(shí)
{
TR0=0; //關(guān)閉定時(shí)器
 
 
}
if(s1num==2)//第二次按下光標(biāo)閃爍定位到分鐘位置
{
 
}
if(s1num==3)//第三次按下光標(biāo)閃爍定位到小時(shí)位置
{
 
}
if(s1num==4)//第四次按下
{
s1num=0;//記錄按鍵數(shù)清零
 
TR0=1; //啟動(dòng)定時(shí)器使時(shí)鐘開始走
}
}
}
if(s1num!=0)//只有功能鍵被按下后,增加和減小鍵才有效
{
if(s2==0)
{
delay1(5);
if(s2==0)//增加鍵確認(rèn)被按下
{
while(!s2);//按鍵釋放
di();//每當(dāng)有按鍵釋放蜂鳴器發(fā)出滴聲
if(s1num==1)//若功能鍵第一次按下
{
miao++; //則調(diào)整秒加1
if(miao==60)//若滿60后將清零
miao=0;
 
 
}
if(s1num==2)//若功能鍵第二次按下
{
fen++;//則調(diào)整分鐘加1
if(fen==60)//若滿60后將清零
fen=0;
 
 
}
if(s1num==3)//若功能鍵第三次按下
{
shi++;//則調(diào)整小時(shí)加1
if(shi==24)//若滿24后將清零
shi=0;
 
}
}
}
if(s3==0)
{
delay1(5);
if(s3==0)//確認(rèn)減小鍵被按下
{
while(!s3);//按鍵釋放
di();//每當(dāng)有按鍵釋放蜂鳴器發(fā)出滴聲
if(s1num==1)//若功能鍵第一次按下
{
miao--;//則調(diào)整秒減1
if(miao==-1)//若減到負(fù)數(shù)則將其重新設(shè)置為59
miao=59; // write_add(1,miao);//數(shù)據(jù)改變立即存入24C02
}
if(s1num==2)//若功能鍵第二次按下
{
fen--;//則調(diào)整分鐘減1
if(fen==-1)//若減到負(fù)數(shù)則將其重新設(shè)置為59
fen=59;
 
}
if(s1num==3)//若功能鍵第二次按下
{
shi--;//則調(diào)整小時(shí)減1
if(shi==-1)//若減到負(fù)數(shù)則將其重新設(shè)置為23
shi=23;
 
}
}
}
}
}
 
 
void display(int k)
{
P1=0xef;
P3=tab1[0];
delay1(1);
P3=0xff;
P1=0x7f;
P3=tab[k%100/10];
delay1(1);
P3=0xff;
P1=0xbf;
P3=tab[k%10];
delay1(1);
P3=0xff;
}/****************************************************************************

函數(shù)功能:DS18B20初始化子程序
入口參數(shù):
出口參數(shù):
****************************************************************************/

Init_DS18B20(void)
{
unsigned char x=0;
DQ=1; //DQ先置高
delay(8); //延時(shí)
DQ=0; //發(fā)送復(fù)位脈沖
delay(85); //延時(shí)(&gt;480ms)
DQ=1; //拉高數(shù)據(jù)線
delay(14); //等待(15~60ms)
}/****************************************************************************

函數(shù)功能:向DS18B20讀一字節(jié)數(shù)據(jù)
入口參數(shù):
出口參數(shù):dat
****************************************************************************/

ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat=0;
for (i=8;i&gt;0;i--)
{
DQ=1;
delay(1);
DQ=0;
dat&gt;&gt;=1;
DQ=1;
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}/****************************************************************************

函數(shù)功能:向DS18B20寫一字節(jié)數(shù)據(jù)
入口參數(shù):dat
出口參數(shù):
****************************************************************************/

WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for(i=8;i&gt;0;i--)
{
DQ=0;
DQ=dat&amp;0x01;
delay(5);
DQ=1;
dat&gt;&gt;=1;
}
delay(4);
}/****************************************************************************

函數(shù)功能:向DS18B20讀溫度值
入口參數(shù):
出口參數(shù):temperature
****************************************************************************/

ReadTemperature(void)
{
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳過讀序列號(hào)的操作
WriteOneChar(0x44); //啟動(dòng)溫度轉(zhuǎn)換
delay(125); //轉(zhuǎn)換需要一點(diǎn)時(shí)間,延時(shí)
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳過讀序列號(hào)的操作
WriteOneChar(0xbe); //讀溫度寄存器(頭兩個(gè)值分別為溫度的低位和高位)
tempL=ReadOneChar(); //讀出溫度的低位LSB
tempH=ReadOneChar(); //讀出溫度的高位MSB
//溫度轉(zhuǎn)換,把高低位做相應(yīng)的運(yùn)算轉(zhuǎn)化為實(shí)際溫度
temperature=((tempH*256)+tempL)*0.0625;
delay(200);
return(temperature);
}/****************************************************************************

函數(shù)功能:主程序
入口參數(shù):
出口參數(shù):
****************************************************************************/

void main()
{
 
float i;
init();
while(1)
{
i=ReadTemperature();
display(i);
scan(shi,fen,miao);
keyscan();
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==20)
{
count=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
 
}
 
}
 
}
}

關(guān)閉窗口