找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5943|回复: 1
打印 上一主题 下一主题
收起左侧

简易数控直流电源设计论文

[复制链接]
跳转到指定楼层
楼主
ID:212598 发表于 2017-6-19 15:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
简易数控直流电源设计
1 设计任务
设计出有一定输出电压范围和功能的数控电源。
2 设计要求
(1)输出电压:范围0~+9.9V,步进0.1V,纹波不大于10mV;
(2)输出电压值由LCD显示;
(3)由“+”、“-”两键分别控制输出电压步进增减;
(4)输出电压可预置在0~9.9V之间的任意一个值;
5)自制键盘设置电压值。
3 设计原理与总体方案
3.1  总体设计方案
鉴于目前数控直流源一般采取运放构成的电流-电压转换电路与单片机结合,设计方案大多为开环系统,主控制器仅用于数字给定及显示,没有对输出电流进行检测和控制。本文在传统电路设计的基础上,利用控制系统中反馈与控制原理,引入电流负反馈,在采样电阻上获取和电流成正比的采样电压,并接人运算放大器的反向输入端,实现负反馈,形成恒流输出的闭环控制系统;
软件方面,将具有全局寻优能力但收敛速度慢的遗传算法和具有收敛速度快且局部寻优能力强的直接搜索法结合在一起,设计基于遗传算法和直接搜索策略的混合优化算法,充分利用了遗传算法的全局搜索能力并以此作为优化过程的“粗调”,同时利用直接搜索法良好的局部搜索能力作为优化过程的“微调”,集中了两者的优点,而克服了两者的弱点,得到的目标函数值较遗传退火策略更优,而且一致性更好,用于PID参数整定是具有整定速度快,调节时间短,稳态误差小等优点。同时结合PID算法,形成软件闭环,实现对输出电流的精确控制。
系统工作原理如下:由键盘预置电压值,输入到单片机;采样电阻采集的电压信号经D/A转换器送入单片机,当两值之差绝对值为零或不大于设定值时,不作任何调整;当两值之差大于设定值时,运用PID算法进行调整,送人D/A转换,调整输出电压,直到差值在允许的范围内。单片机控制液晶显示电流的设定值、实际输出值和电压步进值。
3.2  显示模块选择
LCDLiquid Crystal Display)显示器是利用液晶显示技术来进行图像表现的显示装置,从液晶显示器的结构来看,无论是笔记本电脑还是桌面系统,采用的LCD显示屏都是由不同部分组成的分层结构。LCD显示器按照控制方式不同可分为被动矩阵式LCD及主动矩阵式LCD两种。
LCD由两块玻璃板构成,厚约1mm,其间由包含有液晶材料的5μm均匀间隔隔开。因为液晶材料本身并不发光,所以在显示屏两边都设有作为光源的灯管,而在液晶显示屏背面有一块背光板(或称匀光板)和反光膜,背光板是由荧光物质组成的可以发射光线,其作用主要是提供均匀的背景光源。
背光板发出的光线在穿过第一层偏振过滤层之后进入包含成千上万液晶液滴的液晶层。液晶层中的液滴都被包含在细小的单元格结构中,一个或多个单元格构成屏幕上的一个像素。在玻璃板与液晶材料之间是透明的电极,电极分为行和列,在行与列的交叉点上,通过改变电压而改变液晶的旋光状态,液晶材料的作用类似于一个个小的光阀。在液晶材料周边是控制电路部分和驱动电路部分。当LCD中的电极产生电场时,液晶分子就会产生扭曲,从而将穿越其中的光线进行有规则的折射,然后经过第二层过滤层的过滤在屏幕上显示出来。
3.3键盘选择
键盘实际上是一组开关的集合:当开关按下时,两根导线接通;当开关释放时,两根导线断开。我们通过键盘的输入设置预置值。
3.3.1高低电平翻转矩阵键盘
矩阵键盘又称行列键盘,它是用四条I/O线作为行线,四条I/O线作为列线组成的键盘。在行线和列线的每个交叉点上设置一个按键。这样键盘上按键的个数就为4*4个。这种行列式键盘结构能有效地提高单片机系统中I/O口
最常见的键盘一般由16个按键组成,在单片机中正好可以用一个P口实现16个按键功能。当无按键闭合时,P3.0~P3.3与P3.4~P3.7之间开路。当有键闭合时,与闭合键相连的两条I/O口线之间短路。判断有无按键按下的方法是:第一步,置列线P3.4~P3.7为输入状态,从行线P3.0~P3.3输出低电平,读入列线数据,若某一列线为低电平,则该列线上有键闭合。第二步,行线轮流输出低电平,从列线P3.4~P3.7读入数据,若有某一列为低电平,则对应行线上有键按下。综合一二两步的结果,可确定按键编号。但是键闭合一次只能进行一次键功能操作,因此须等到按键释放后,再进行键功能操作,否则按一次键,有可能会连续多次进行同样的键操作。
识别按键的方法很多其中,最常见的方法是扫描法
按键按下时,与此键相连的行线与列线导通,行线在无按键按下时处在高电平。如果所有的列线都处在高电平,则按键按下与否不会引起行线电平的变化,因此必须使所有列线处在电平。这样,当有按键按下时,改键所在的行电平才回由高变低。才能判断相应的行有键按下。
3.3.2独立按键式键盘
独立按键式直接用I/O口线构成的单个按键电路,其特点式每个按键单独占用一根I/O口线,每个按键的工作不会影响其他I/O口线的状态。独立按键的典型应用如图所示。独立式按键电路配置灵活,软件结构简单,但每个按键必须占用一个I/O口线,因此,在按键较多时,I/O口线浪费较大,不宜采用。
独立按键的软件常采用查询式结构。先逐位查询没跟I/O口线的输入状态,如某一根I/O口线输入为低电平,则可确认该I/O口线所对应的按键已按下,然后,再转向该键的功能处理程序。
独立按键数量少,可根据实际需要灵活编码。矩阵键盘,按键的位置由行号和列号唯一确定,因此可以分别对行号和列号进行二进制编码,然后两值合成一个字节,高4位是行号,低4位是列号。相比较而言高低电平反转矩阵键盘占用的I/O接口少,实现的键数较多,比较符合我们的设计需求。
3.4主控芯片选择
51系列是基本型,包括8051、8751、8031、8951.这四个机种区别,仅在于片内程序储存器。8051为4KBROM,8751为4KBEPROM,8031片内无程序储存器,8951为4KBEEPROM。其他性能结构一样,有片内128B RAM,2个16位定时器/计数器,5个中断源。其中,8031性价比较高,又易于开发,目前应用面广泛。
51系列单片机的特点8位cpu片内带振荡器,频率范围为1.2MHz~12MHz片内带128B的数据存储器片内带4KB的程序存储器程序存储器的寻址空间为64KB片外数据存储器的寻址空间为64KB128个用户位寻址空间21个字节特殊功能寄存器4个8位的I/O并行接口P0、P1、P2、P3两个16位定时、计数器两个优先级别的五个中断源一个全双工的串行I/O接口,可多机通信111条指令,包含乘法指令和除法指令片内采用单总线结构有较强的位处理能力采用单一+5V电源

file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3001.tmp.png
1  MCS-51基本结构图
4 硬件电路设计
总体设计图:

file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3002.tmp.jpg
2  电路设计图
4.1 DAC电路
一个8位D/A转换器有8个输入端(其中每个输入端是8位二进制数的一位),有一个模拟输出端。输入可有2^8=256个不同的二进制组态,输出为256个电压之一,即输出电压不是整个电压范围内任意值,而只能是256个可能值。下图DAC0832的逻辑框图和引脚排列。
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3012.tmp.jpg
3  DAC0832的逻辑框图和引脚排列
D0~D7:数字信号输入端。
ILE:输入寄存器允许,高电平有效。
CS:片选信号,低电平有效。
XFER:传送控制信号,低电平有效。
WR1:写信号1,低电平有效。
WR2:写信号2,低电平有效。
IOUT1、IOUT2:DAC电流输出端。
Rfb:是集成在片内的外接运放的反馈电阻。
Vref:基准电压(-10~10V)。
Vcc:是源电压(+5~+15V)。
DAC0832输出的是电流,所以须经过一个外接的运算放大器转换成电压。
AGND:模拟地 NGND:数字地,可与AGND接在一起使用。
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3013.tmp.jpg
4  DAC电路
4.2矩阵键盘模块
在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,如图4所示。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3024.tmp.jpg
5  矩阵式键盘


file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3035.tmp.jpg
6  键盘电路设计
4.3 显示部分
1602液晶也叫1602字符型液晶,它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用。1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
1602采用标准的16脚接口,其中:第1引脚:GND为电源地;第2引脚:VCC接5V电源正极;第3引脚:V0为液晶显示器对比度调整端;第4引脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器;第5引脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作;第6引脚:E(或EN)端为使能端,高电平(1)时读取信息,负跳变时执行指令;第7~14引脚:D0~D7为8位双向数据端。第15~16脚:空脚或背灯电源。第15引脚背光正极,第16引脚背光负极。
编号
符号
引脚说明
编号
符号
引脚说明
[size=12.0000pt]1
VSS
电源地
[size=12.0000pt]9
D2
数据
[size=12.0000pt]2
VDD
电源正极
10
D3
数据
[size=12.0000pt]3
VL
液晶显示偏压
11
D4
数据
[size=12.0000pt]4
RS
数据/命令选择
12
D5
数据
[size=12.0000pt]5
R/W
读/写选择
13
D6
数据
[size=12.0000pt]6
[size=12.0000pt]E
使能信号
14
D7
数据
[size=12.0000pt]7
D0
数据
15
BLA
背光源正极
[size=12.0000pt]8
D1
数据
16
BLK
背光源负极
1  液晶1602A各个管脚的介绍
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3045.tmp.jpg
7  LCD电路设计
4.4 自制电源模块
自制电源输出+12V、-12V及+5V的电压
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3046.tmp.jpg
8 自制电源
4.5 主控芯片
AT89C51 提供以下标准功能:4k 字节Flash 闪速存储器128字节内部RAM,32 个I/O 口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89C51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3057.tmp.jpg
9 主控芯片电路
4.6 放大电路
放大电路是增加电信号幅度或功率的电子电路。应用放大电路实现放大的装置称为放大器。它的核心是电子有源器件,如电子管、晶体管等。为了实现放大,必须给放大器提供能量。常用的能源是直流电源,但有的放大器也利用高频电源作为泵浦源。放大作用的实质是把电源的能量转移给输出信号。
放大电路本身的特点:
一、有静态和动态两种工作状态,所以有时往往要画出它的直流通路和交流通路才能进行分析;
二、电路往往加有负反馈,这种反馈有时在本级内,有时是从后级反馈到前级,所以在分析这一级时还要能"瞻前顾后"。在弄通每一级的原理之后就可以把整个电路串通起来进行全面综合。

file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3058.tmp.jpg
10  放大电路





5 软件设计流程
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3068.tmp.jpg
11  软件设计流程图
注:在稳压输出端用万用表的电压档测输出电压,将会基本等于从键盘的输入电压。

6 仿真
6.1 仿真问题及解决
(1)D/A转换电路没有正常工作;
问题原因:D0-D7接口出现错误。
(2)步进0.1的程序出现问题;
问题原因:没有写入浮点型函数。

6.2 仿真结果及分析
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps3069.tmp.jpgfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps307A.tmp.jpg
12  输入3.2V电压时的仿真输出值
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps307B.tmp.jpgfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps308C.tmp.jpg
13  输入5.9V电压时的仿真输出值
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps308D.tmp.jpgfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps309D.tmp.jpg
14  输入6.3V电压时的仿真输出值
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps309E.tmp.jpgfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps309F.tmp.jpg
15  输入8.3V电压时的仿真输出值
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps30B0.tmp.jpgfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps30B1.tmp.jpg
16  输入9.1V电压时的仿真输出值

稳压输出端所测电压(V)
从键盘输入的电压(V)
误差
0
0
0
1.22
1.2
0.02
2.39
2.4
0.01
3.61
3.6
0.01
4.51
4.5
0.01
5.32
5.3
0.02
6.73
6.7
0.03
7.91
7.9
0.01
8.81
8.8
0.1
9.12
9.1
0.02
2  测得的数据和从键盘输入的数据
数据分析:
误差不超过0.03
误差分析:
(1)电路中元器件的影响
(2)外界对输出电压的干扰,导致输出有误差


参考文献
1]唐俊瞿,许雷,张群瞻.单片机原理与应用[M].北京:冶金工业出版社,2003
2]李广弟,朱月秀,冷祖祁.单片机基础[M].北京:北京航空航天大学出版社,2007
3]李光飞.单片机课程设计实例指导[M].北京:北京航空航天大学出版社,2004.9
4]张洪润,兰清华.单片机应用技术教程[M].北京:清华大学出版社,1997.11
5]李华.MCS51系列单片机实用接口技术[M]..北京:北京航空航天大学出版社,1993
6]李朝青.单片机原理及接口技术[M]..北京:北京航空航天大学出版社,1998



附录
仿真图
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps30C2.tmp.jpg

源程序
#include<reg51.h>   /*头文件以及变量定义*/
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
sbit rs=P2^4;
sbit rw=P2^5;
sbit ea=P2^6;
uchar num,i,key,j=0;
float a2;
uchar keyscan(void);
uchar code table[6]="Please";
uchar code table1[16]=" enter letter...";
uchar code table2[16]="0123456789abcde.";
float  table3[6];
uchar code table4[8]="volt(v):";
uchar code table5[6]="error!";
uchar  table6[6];
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
  for(y=110;y>0;y--);
}

void write_com(uchar com)
{
rs=0;           
rw=0;         
P0=com;
delay(5);
ea=1;               
delay(5);
ea=0;
}
void write_date(uchar date)
{
rs=1;               
rw=0;
P0=date;
delay(5);
ea=1;
delay(5);
ea=0;
}
void disvol()
{
                write_com(0x80+0x40);                 //写电压
                for(num=0;num<8;num++)         
                   {
                    write_date(table4[num]);
                    delay(10);
                   }               
}

void init()
{
delay(5);
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<6;num++)
  {
   write_date(table[num]);         
   delay(20);
  }
write_com(0x80+0x40);   
for(num=0;num<0x10;num++)         
  {
    write_date(table1[num]);   
    delay(20);
   }
}
void diserr()
{
           write_com(0x80+0x40);        
           for(num=0;num<6;num++)
           {
            write_date(table5[num]);        
                delay(20);
           }
           delay(2000);        
}

void he_zhi()
{
uint a1,a3,c11,c12;
float b1,b2,b3,b4,c1,c2,h;
if(table3[0]!='.')           //整数加点
{
         if(!table3[1])
         {
                 if(j==1)
                {
                         table3[1]='.';
                }
         }

         if(!table3[2])
         {
                 if(j==2)
                {
                        table3[2]='.';
                }
         }

if(table3[1]=='.')
         {         
                 b1=table3[0];
                 b2=table3[2]/10;
                 b3=table3[3]/100;
                 h=b1+b2+b3;
                 a2=h*256/10;
                 a3=a2;
                 a1=a3+1;
                 c1=a2-a3;
                 c2=a1-a2;
                 c11=1000*c1;
                 c12=1000*c2;
                 if(c11>c12)
                 {
                 P1=a1;
                 }
                 else
                 {
                  P1=a3;
                 }
                 //光标显示位
                 if(j==1)
                 {
                         write_com(0x80+0x49);        
                 }                                          
                 if(j==3)
                 {
                         write_com(0x80+0x4b);
                 }
                 if(j==4)
                 {
                         write_com(0x80+0x4c);
                 }

         }

else if(table3[2]=='.')
         {         
                  b1=table3[0]*10;
                  b2=table3[1];
                  b3=table3[3]/10;
                  b4=table3[4]/100;
                  h=b1+b2+b3+b4;
                  if(h<=10)
          {
                                 a2=h*256/10;
                                 a3=a2;
                                 a1=a3+1;
                                 c1=a2-a3;
                                 c2=a1-a2;
                                 c11=1000*c1;
                                 c12=1000*c2;
                                 if(c11>c12)
                                 {
                                         P1=a1;
                                 }
                                 else                 
                                 {
                                         if(a3==256)  
                                         {
                                             P1=255;
                                         }
                                         else                  
                                         {
                                                    P1=a3;
                                         }
                                 }                                 
                 if(j==2)
                 {
                         write_com(0x80+0x4a);        
                 }

        }



                         else
                          {
                                          write_com(0x01);
                                        diserr();               
                          }        
        }
        else
                {
                        write_com(0x01);
                        diserr();        
                }
}

        if(table3[0]=='.')
        {
           write_com(0x01);
           diserr();               
        }

}




void qingchu(uchar p)
{        
        uchar z;
        for(z=0;z<=5;z++)
        {
        table3[z]=p;
        }
}
void jia(uchar dat)    //步进函数
{
         switch(dat)
        {
                case 0:        write_date(table2[1]);
                                break;
                case 1:        write_date(table2[2]);
                                break;
                case 2:        write_date(table2[3]);
                                break;
                case 3:        write_date(table2[4]);
                                break;
                case 4:        write_date(table2[5]);
                                break;
                case 5:        write_date(table2[6]);
                                break;
                case 6:        write_date(table2[7]);
                                break;
                case 7:        write_date(table2[8]);
                                break;
                case 8:        write_date(table2[9]);
                                break;
                case 9:        write_date(table2[0]);
                                break;
        }
        table3[2]++;
        if(table3[2]==10)
        table3[2]=0;
}
void jian(uchar dat)
{
         switch(dat)
        {
                case 0:        write_date(table2[9]);
                                break;
                case 1:        write_date(table2[0]);
                                break;
                case 2:        write_date(table2[1]);
                                break;
                case 3:        write_date(table2[2]);
                                break;
                case 4:        write_date(table2[3]);
                                break;
                case 5:        write_date(table2[4]);
                                break;
                case 6:        write_date(table2[5]);
                                break;
                case 7:        write_date(table2[6]);
                                break;
                case 8:        write_date(table2[7]);
                                break;
                case 9:        write_date(table2[8]);
                                break;
        }
        table3[2]--;
        if(table3[2]==-1)
        table3[2]=9;
}

void main()
{
init();

delay(4500);
write_com(0x01);
write_com(0x80+0x40);
write_com(0x0f);
disvol();
i=0x80+0x48;

while(1)
{
key=keyscan();                          
delay(100);
switch(key)
{         
  case 0xee:write_com(i);
           write_date(table2[0]);table3[j]=0;j++;         //  table2[16]="0123456789abcde."
                        i++;
                        break;//0
  case 0xde:write_com(i);
            write_date(table2[1]);table3[j]=1;j++;
                        i++;
                        break;//1
  case 0xbe:write_com(i);
            write_date(table2[2]);table3[j]=2;j++;
                        i++;break;//2
  case 0x7e:write_com(i);
            write_date(table2[3]);table3[j]=3;j++;
                        i++;break;//3
  case 0xed:write_com(i);
            write_date(table2[4]);table3[j]=4;j++;
                        i++;break;//4
  case 0xdd:write_com(i);
            write_date(table2[5]);table3[j]=5;j++;
                        i++;break;//5
  case 0xbd:write_com(i);
            write_date(table2[6]);table3[j]=6;j++;
                        i++;break;//6
  case 0x7d:write_com(i);
            write_date(table2[7]);table3[j]=7;j++;
                        i++;break;//7
  case 0xeb:write_com(i);
            write_date(table2[8]);table3[j]=8;j++;
                        i++;break;//8
  case 0xdb:write_com(i);
            write_date(table2[9]);table3[j]=9;j++;
                        i++;break;//9
  case 0xe7:write_com(i);
            write_date(table2[15]);table3[j]='.';j++;
                        i++;break;
case 0xbb:write_com(0x80+0x48+2);
                        jia(table3[2]);
                        break;//
  case 0x7b:write_com(0x80+0x48+2);
                        jian(table3[2]);                        
                        break;//        
  case 0xd7:he_zhi();
                         i=0x80+0x48;  
                        j=0;         
                        break;
  case 0xb7:write_com(0x01);
                        qingchu(0);
                        j=0;
                        disvol();
                        write_com(0x80+0x48);
                        i=0x80+0x48;
                        break;

}
}
}
uchar keyscan(void)
{
uchar cord_h,cord_l;
P3=0x0f;            
cord_h=P3&0x0f;     
if(cord_h!=0x0f)   
{
  delay(100);        
  if(cord_h!=0x0f)
  {
    cord_h=P3&0x0f;  
    P3=cord_h|0xf0;
    cord_l=P3&0xf0;  
    return(cord_h+cord_l);
   }
  }return(0xff);   
}


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:298092 发表于 2018-6-30 16:11 | 只看该作者
图全挂了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表