专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

单片机数控电源设计

作者:佚名   来源:本站原创   点击数:  更新时间:2009年10月10日   【字体:
毕业前的最后设计

    即将告别大学,学了几年也没什么拿得出手的作品。由于学校停课,趁着找工作的空闲索性做个一直挂记在心的单片机数控电源。从策划到最后作品成型一共前前后后花了4天。先后经历了两次坐车到电子市场买元器件,调程序到深夜凌晨3点,焊板子,被热熔胶烫破手皮。四天几乎除了吃饭睡觉的几个小时外都在设计。期间也遇到很多问题。例如:做DA时调不出输出电压,反复折腾了一天才解决,原来是单片机管脚有问题,又换了一块。(烧掉一块运放,导致又到电子市场买了一块)。四天下来总算充分完成了设计任务。确实学到了不少,模电这块还是要加强一下。这个作品完成后决定把所有这几年积攒下来的一大麻袋电子垃圾全部扔到无线电协会,从此告别电烙铁,告别大学,开始新生活.

制作过程

完整作品

 

远视图

 

侧视图

 

后视图

 

内部俯视图

 

面板

D/A,A/D数控电源电路板

 


温度,时间部分电路板


变压器和空壳


显示的面板(左上角是温度,中间数码管是时间,液晶是电压)


还未装机

整机

 

俯视图

侧视图

 

正视图

 

 

一,设计任务:

基本部分:

1,输出电压范围0-25V。

2,电流范围0-2.5A。

3,用1602液晶显示电压值。

4,用矩阵键盘实现电压值输入(0-9,清除键,确认键等)。

选设部分:

1, 温度检测显示(可采用4位数码管或在液晶上显示)

2, 时间显示(可采用6位数码管或在液晶上显示)

 

二,系统框图

 

 

三.工作原理:

1.上电复位,读取24C02中的电压,送DA转换输出电压,如24C02中电压为O则设置初始电压为5V;

2.电压控制:通过矩阵键盘控制单片机产生8位数字信号(0-255),通过P3口送至8位数模转换芯片(DAC0832)转换成模拟电流信号,再经运放作I/U转换,得到控制稳压电源输出部分的基准电压;

3.电流取样:采用10位模数转换芯片(TLC1549)作为显示电流的模数转换器件,TLC1549的取样电压由串联在电源输出电路的电流取样电阻(0.1Ω)分压取得,并由运放按一定倍数放大后送至Vin(+),TLC1549把转换结果送至单片机的P2.3口,再由程序将数据处理后送LCD1602显示当前电流;

4.过流保护:当短路或电流超过设定值2.4A时,单片机自动保存当前使用电压并关闭输出;

5.稳压输出:采用传统的串联稳压电路,由运放和功率输出管组成。利用DAC0832控制的基准电压驱动功率管稳压输出,反馈部分是通过电阻R3,VR2将取样电压输入运放的反相端比较,VR2可作小范围调整;

四,源程序 (初稿)

   所有源程序已通过调试,首发于单片机网http://www.51hei.com,有问题可与QQ:125739409联系,注意不得用于商业目的,有两个程序,第一个为数控电源程序,第二个为温度和时间的程序。

程序一
#include <reg52.h> //52系列头文件
#define Disdata P0 //液晶数据端口
#define uchar unsigned char //无符号字符8位
#define uint unsigned int //无符号整数8位
uint data dis[4]={0x00,0x00,0x00,0x00};//4个数据单元和一个
uchar code table[]="OUTPUT: . V "; //定义初始上电液晶默认显示状态
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; //转换结束标志位
sbit da_wr=P2^1;
sbit da_cs=P2^0;
sbit beep=P1^7;//蜂鸣器
data int result;//测量变量暂存地址
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;
//********延时函数************
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) //液晶写命令函数
{
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date) //液晶写数据函数
{
lcdrs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_sg(uchar add,uchar date) //写整数位和小数位函数
{
uint shi,ge;
shi=date/10; //分解出一个2位数的十位
ge=date%10;
write_com(0x80+0x40+add); //设置显示位置
write_data(0x30+shi); //送去液晶显示十位
write_data(0x30+ge); //送去液晶显示个位
}
//void write_da(uchar sps,uchar uru)
//{ uchar yuy,rur;
// yuy=uru;
// rur=0;
// write_com(0x80+sps); //设置显示位置
//if(cvc==8)
// {
// write_data(0x30+yuy); //送去液晶显示十位
// write_data(0x30+rur); //送去液晶显示个位
// }
/// 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); //设置显示初始坐标 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); //设置显示初始坐标
for(num=0;num&lt;16;num++)
{
write_data(table[num]);
delay(5);
}
write_sg(8,shii);
write_sg(11,gei);
 
}
 
//****TLC1549转换处理子函数********void test()
{
 
data uchar i;
 
cs_ad=1; //禁止i/o clock
cs_ad=0; //开启控制电路,使能data out和i/o clock
result=0; //清转换变量
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 返回到高阻状态而终止序列
//****数据转换处理**********
result=result*2;
dis[2]=result/205; //计算整数位
dis[3]=result%205; //余数暂存
dis[3]=dis[3]*10; //计算小数第一位
dis[1]=dis[3]/205;
dis[3]=dis[3]%205;
dis[3]=dis[3]*10; //计算小数第二位
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;
}
 
}
}
}
 
 
//*******主函数*****
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; //数据传输线接单片机的相应的引脚
sbit beep=P1^3;
sbit s1=P1^2;
sbit s2=P1^0;
sbit s3=P1^1;
/*********************************定义全局变量******************************/
unsigned char tempL=0; //临时变量低位
unsigned char tempH=0; //临时变量高位
float temperature;
//温度值/****************************************************************************

函数功能:延时子程序
入口参数:k
出口参数:
****************************************************************************/

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

函数功能:数码管扫描延时子程序
入口参数:
出口参数:
****************************************************************************/

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;
}/****************************************************************************

函数功能:数码管显示子程序
入口参数:k
出口参数:
****************************************************************************/

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)//确认功能键被按下
{ s1num++;//功能键按下次数记录
while(!s1);//释放确认
di();//每当有按键释放蜂鸣器发出滴声
if(s1num==1)//第一次被按下时
{
TR0=0; //关闭定时器
 
 
}
if(s1num==2)//第二次按下光标闪烁定位到分钟位置
{
 
}
if(s1num==3)//第三次按下光标闪烁定位到小时位置
{
 
}
if(s1num==4)//第四次按下
{
s1num=0;//记录按键数清零
 
TR0=1; //启动定时器使时钟开始走
}
}
}
if(s1num!=0)//只有功能键被按下后,增加和减小键才有效
{
if(s2==0)
{
delay1(5);
if(s2==0)//增加键确认被按下
{
while(!s2);//按键释放
di();//每当有按键释放蜂鸣器发出滴声
if(s1num==1)//若功能键第一次按下
{
miao++; //则调整秒加1
if(miao==60)//若满60后将清零
miao=0;
 
 
}
if(s1num==2)//若功能键第二次按下
{
fen++;//则调整分钟加1
if(fen==60)//若满60后将清零
fen=0;
 
 
}
if(s1num==3)//若功能键第三次按下
{
shi++;//则调整小时加1
if(shi==24)//若满24后将清零
shi=0;
 
}
}
}
if(s3==0)
{
delay1(5);
if(s3==0)//确认减小键被按下
{
while(!s3);//按键释放
di();//每当有按键释放蜂鸣器发出滴声
if(s1num==1)//若功能键第一次按下
{
miao--;//则调整秒减1
if(miao==-1)//若减到负数则将其重新设置为59
miao=59; // write_add(1,miao);//数据改变立即存入24C02
}
if(s1num==2)//若功能键第二次按下
{
fen--;//则调整分钟减1
if(fen==-1)//若减到负数则将其重新设置为59
fen=59;
 
}
if(s1num==3)//若功能键第二次按下
{
shi--;//则调整小时减1
if(shi==-1)//若减到负数则将其重新设置为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;
}/****************************************************************************

函数功能:DS18B20初始化子程序
入口参数:
出口参数:
****************************************************************************/

Init_DS18B20(void)
{
unsigned char x=0;
DQ=1; //DQ先置高
delay(8); //延时
DQ=0; //发送复位脉冲
delay(85); //延时(&gt;480ms)
DQ=1; //拉高数据线
delay(14); //等待(15~60ms)
}/****************************************************************************

函数功能:向DS18B20读一字节数据
入口参数:
出口参数: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);
}/****************************************************************************

函数功能:向DS18B20写一字节数据
入口参数:dat
出口参数:
****************************************************************************/

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);
}/****************************************************************************

函数功能:向DS18B20读温度值
入口参数:
出口参数:temperature
****************************************************************************/

ReadTemperature(void)
{
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0x44); //启动温度转换
delay(125); //转换需要一点时间,延时
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)
tempL=ReadOneChar(); //读出温度的低位LSB
tempH=ReadOneChar(); //读出温度的高位MSB
//温度转换,把高低位做相应的运算转化为实际温度
temperature=((tempH*256)+tempL)*0.0625;
delay(200);
return(temperature);
}/****************************************************************************

函数功能:主程序
入口参数:
出口参数:
****************************************************************************/

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;
}
 
}
 
}
 
}
}

关闭窗口