搜索
您的当前位置:首页正文

基于at89s52单片机的数控稳压电源设计

来源:知库网
内容摘要:该电源系统以AT89S52单片机为核心控制芯片,实现可预设电压数控直流电源功能的方案。设计采用8位精度的DA转换器DAC0808和LT082运算放大器构成稳压源,实现了输出电压范围为0V~+9.9V,电压步进可调的数控稳压电源,具有较高的精度与稳定性。另外该方案采用通过按键实现输出电压的方便设定,显示部分采用数码管来显示输出电压,通过数字电压表显示实际输出电压值。

关键词:数控 AT89S52 DAC0808 稳压电源

1绪论

电源技术尤其是数控电源技术是一门实践性很强的工程技术,服务于各行各业。电力电子技术是电能的最佳应用技术之一。当今电源技术融合了电气、电子、系统集成、控制理论、材料等诸多学科领域。随着计算机和通讯技术发展而来的现代信息技术革命,给电力电子技术提供了广阔的发展前景,同时也给电源提出了更高的要求。随着数控电源在电子装置中的普遍使用,普通电源在工作时产生的误差,会影响整个系统的精确度。电源在使用时会造成很多不良后果,世界各国纷纷对电源产品提出了不同要求并制定了一系列的产品精度标准。只有满足产品标准,才能够进入市场。随着经济全球化的发展,满足国际标准的产品才能获得进出的通行证。数控电源是从80年代才真正的发展起来的,期间系统的电力电子理论开始建立。这些理论为其后来的发展提供了一个良好的基础。在以后的一段时间里,数控电源技术有了长足的发展。但其产品存在数控程度达不到要求、分辨率不高、功率密度比较低、可靠性较差的缺点。因此数控电源主要的发展方向,是针对上述缺点不断加以改善。单片机技术及电压转换模块的出现为精确数控电源的发展提供了有利的条件。新的变换技术和控制理论的不断发展,各种类型专用集成电路、数字信号处理器件的研制应用,到90年代,己出现了数控精度达到0.05V的数控电源,功率密度达到每立方英寸50W的数控电源。从组成上,数控电源可分成器件、主电路与控制等三

部分。目前在电力电子器件方面,几乎都为旋纽开关调节电压,调节精度不高,而且经常跳变,使用麻烦。

数字化智能电源模块是针对传统智能电源模块的不足提出的,数字化能够减少生产过程中的不确定因素和人为参与的环节数,有效地解决电源模块中诸如可靠性、智能化和产品一致性等工程问题,极大地提高生产效率和产品的可维护性。

电源采用数字控制,具有以下明显优点:

(1)易于采用先进的控制方法和智能控制策略,使电源模块的智能化程度更高,性能更完美;

(2)控制灵活,系统升级方便,甚至可以在线修改控制算法,而不必改动硬件线路;

(3)控制系统的可靠性提高,易于标准化,可以针对不同的系统(或不同型号的产品),采用统一的控制板,而只是对控制软件做一些调整即可;

(4)系统的一致性好,成本低,生产制造方便。由于控制软件不像模拟器件那样存在差异,所以,其一致性很好。由于采用软件控制,控制板的体积将大大减小,生产成本下降。

2 系统设计

2.1 设计任务与要求

2.1.1 设计任务

(1)设计一台微机控制的数控直流电压源,为电子设备供电; (2)在设计过程中,选择1~2个单元电路使用仿真软件(例如Proteus等)进行仿真调试;

(3)用计算机绘制所有的电路图。 2.1.2 设计要求

(1)输出电压范围0-9.9v,步进值可调;

(2)电压调整率Sv<0.1%V; (3)用数字显示输出电压。

2.2 方案的选择与论证

2.2.1 总体设计方案

方案一:采用各类数字电路来组成键盘控制系统,进行信号处理,如选用CPLD等可编程逻辑器件。本方案电路复杂,灵活性不高,效率低,不利于系统的扩展,对信号处理比较困难。

方案二:采用51系列单片机作为整机的控制单元,通过改变输入数字量来改变输出电压值,从而使输出功率管的基极电压发生变化,间接地改变输出电压的大小。

本设计采用第二种方案。为了能够使系统具备检测实际输出电压值的大小,利用51系列单片机为主控制器,通过键盘来设置直流电源的输出电流,设置步进等级可调,并可由数码管显示预设电压值,数字电压表显示实际输出电压。从数字电压表中读出实际电压值,可直观的看出实际电压与预设电压是否有偏差,并通过键盘更改。通过软件利用单片机程控输出数字信号,经过D/A转换器(DA0808)输出模拟量,再经过运算放大器隔离放大,控制输出功率管的基极,随着功率管基极电电流的变化而输出不同的电压。 2.2.2 显示部分

采用了键盘/显示器接口控制器。不仅简化接口引线,而且减小了软件对键盘/显示器的查询时间,提高了CPU的利用率。采用三位半的数字电压表直接对输出电压采样并显示输出实际电压值,一旦系统工作异常,出现预制值与输出值偏差过大,用户可以根据该信息予以处理。

3 系统硬件设计

本系统由控制器模块、按键模块、LED显示模块和D/A转换模块4个模块组成,系统硬件组成框图如图1所示。系统总体电路原理图如图2所示。

按键模块 电源 控制器 模块 LED显示模块 D/A转换模块

图1系统组成框图

图2 系统电路原理图

3.1 控制器模块

本系统控制器芯片采用AT89S52单片机,其管脚图如图3所示。

图3 AT89S52管脚图

AT89S52是一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash存储器。使用Atmel公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、有效的解决方案。AT89S52的主要特性是:与MCS-51单片机产品兼容;8K字节在系统可编程Flash存储器;1000次擦写周期;三级加密程序存储器;32个可编程I/O口线;三个16位定时器/计数器;8个中断源;全双工UAR串行通道;低功耗空闲和掉电模式;掉电后中断可唤醒;有看门狗定时器;双数据指针。AT89S52具有以下标准功能:8k字节Flash,256字节RAM,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,AT89S52 可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。

3.2 按键模块

采用3x4键盘与单片机的P1口相连,连接电路如图4所示。*设为复位键,按下时,数码管熄灭,电压输出为0。#设为确定键,按下时数码管显示预设电压值,数字电压表显示实际电压值。

图4 按键电路

3.3 D/A转换模块

D/A转换模块如图5所示,由数模转换器DAC0808和运放TL082构成。DAC0808芯片是一个8位D/A转换器,有8个数码输入端,1个模拟输出端,能将控制电路输出的8位二进制数字量转换成模拟量的输出。P2口与DAC0808的输入端相连,通过D/A转换电路将输入的数字量转为模拟量,通过TL082运算放大器输出实际的电压,从数字电压表读出。

图5 D/A转换电路图

DAC0808引脚图如图6所示。DAC0808各引脚功能如表1所示。

图6 DAC0808引脚图

DAC0808的COMP引脚的作用为通过调节外接电阻,以达到改善放大器的性能和输出电压。运放输出电压为

(1)

式中,VREF为外接参考电压,D7~DO为8位输入数字量。当输入数字量在00000000~11111111之间变化时,其对应的输出模拟电压U1在0~-VREF之间,电压分辨率为:△V=5V/(28-1)=19.6mV。

表1 DAC0808的引脚功能

引脚 D7-D0 IO 功能 引脚 功能 补偿端 阈值控制输入端 反相输入端 同相输入端 输出端 8根数据输入线,D7为最高位 COMP 电流输出线(由外向内流) VLC IN- VREF(+)、 VREF(-) 参考电压输入端 VCC、VSS GND VCC-、VCC+ 电源输入端 模拟地 正负电源供应端 IN+ Io TL082是一通用的J-FET双运用算放大器,其引脚图如图7所示,其中2、3管脚分别为正反向输入,对应的6、5管脚为正反向输出,8、4为正负电源。TL0832特点有:较低输入偏置电压和偏移电流;输出没有短路保护;输入级具有较高的输入阻抗;内建频率被子偿电路;较高的压摆率;最大工作电压18V。

图7 TLO82管脚图

3.4数码管显示模块

数码显示模块电路如图8所示。显示部分选用的是7seg-mpx2-cc两片7段共阴数码管。单片机的P00~P07分别接数码管的A~DP口,P20、P21分别接数码管1、2接口,分别控制第一片和第二片的暗亮。外加上拉电阻加强驱动能力,使数码管更亮。

图8 数码管显示电路

3.5硬件元件清单

系统元器件清单见表2。

表2 系统元器件清单

器件 AT89S52 3x4键盘 7seg-mpx2-cc 排阻(4.7k) 电阻(5k) 晶振器 电容(10uF) 数量 1 1 1 1 3 1 1 TL082 DAC0808 电容(220n) 电容(33p) 数字电压表 电阻(1k) 开关 器件 数量 1 1 1 2 1 1 1 4软件设计与仿真

本系统程序包括主程序、键盘扫描子程序、发送键码子程序、发送数据子程序、接收命令子程序等。主程序用于系统初始化,子程序调度等。键盘扫描子程序用于扫描键盘状态,将被按键的位置号存入缓冲器中。发送键码子程序用于将缓冲区键的接通码或断开码发送给单片机接口。发送数据子程序用于将数据发给单片机接口。接收命令子程序用于接收单片机接口发来的键盘命令。

4.1主程序设计

主程序通过键盘扫描子程序进行各行扫描是否有按键,消抖及重键处理:通过软件上延时程序来消除抖动;采用后按键优先处理,即多键同时按下时,只重复发送最后按下键的扫描码。主程序流程图如图9所示。

图9 主程序流程图

4.2 仿真软件简介

Proteus是英国Labcenter公司开发的电路分析与实物仿真软件。它运行于

Windows操作系统上,可以仿真、分析(SPICE)各种模拟器件和集成电路,该软件的特点是:

(1)实现了单片机仿真和SPICE电路仿真相结合。具有模拟电路仿真、数字电路仿真、单片机及其外围电路组成的系统的仿真、RS232动态仿真、I2C调试器、SPI调试器、键盘和LCD系统仿真的功能;有各种虚拟仪器,如示波器、逻辑分析仪、信号发生器等。

(2)支持主流单片机系统的仿真。目前支持的单片机类型有:

ARM7(LPC21xx)、 8051/52系列、AVR系列、PIC10/12/16/18系列、HC11系列以及多种外围芯片。

(3)提供软件调试功能。在硬件仿真系统中具有全速、单步、设置断点等调试功能,同时可以观察各个变量、寄存器等的当前状态,因此在该软件仿真系统中,也必须具有这些功能;同时支持第三方的软件编译和调试环境,如Keil C51 uVision2、MPLAB等软件。

(4)具有强大的原理图绘制功能。

总之,该软件是一款集单片机和SPICE分析于一身的仿真软件,功能极其强大。

Proteus7.5是目前最好的模拟单片机外围器件的工具,可以仿真51系列、AVR、PIC等常用的MCU及其外围电路(如LCD、RAM、ROM、键盘、马达、LED、AD/DA、部分SPI器件、部分IIC器件等)。

软件编译采用KEIL C51软件,Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。用过汇编语言后再使用C来开发,体会更加深刻。

Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。在开发大型软件时更能体现高级语言的优势。

4.3 仿真结果

先按复位键,系统初始化,再输入数字12(预设电压值为1.2V),按下#键(确定键),则数码管显示12,数字电压表显示实际输出电压值。图10、11分别为数码管和电压显示仿真,其中图10中数码管显示1.2V,图11中数字电压表显示1.21V。

图10 预设电压(1.2V)数码管显示仿真图

图11预设电压(1.2V)数字电压表显示仿真图

若需要重新设定,则按下*号键(复位键)。此时数码管熄灭,数字电压表读数为0。此时可重新设定。仿真结果如图12、13所示。

图12 重设定数码管显示仿真图

图13 重设定数字电压表显示仿真图

4.4 系统调试

在调试过程中主要是对程序的修改,特别是延时子程序。开始延时较短时,当按下数字键时,两个数码管同时显示按下的数字。如果延时较长则数字会缓慢的显示出来。通过修改程序,将延时调到适中,系统正常工作。

4.5 误差分析

设定预设值后,读取数字电压表电压值,共记录10组数据如表3所示。通过预设值和实际值的比较进行误差分析。

表3 预设值和实际值的比较(单位:V)

预设值 1.2 2.2 3.2 4.2 5.2 6.2 7.2 8.2 9.2 9.9 实际值 1.21 2.20 3.18 4.17 5.15 6.16 7.15 8.14 9.12 9.78 差值 误差 0.01 0 0.8% 0 0.02 0.03 0.05 0.04 0.05 0.06 0.08 0.12 0.6% 0.7% 0.9% 0.6%. 0.7% 0.7% 0.9% 1.2% 误差平均值=(0.8%+0.6%+0.9%+0.6%+0.7%+0.7%+0.9%+ 1.2%+0.7%)100.78%

从数据中可看出0.78%<<1%,误差较小。 产生误差的因素主要有一下几点: (1)在参数选择的时候没有完全匹配;

(2)数字电压表只能读出3位有效数字; (3)基准电压设定不适中; (4)转换位数不高。

附录:程序清单

#define _PWLOCK_H #define

_PWLOCK_H

#include #include #include

#include

#define uchar unsigned char #define uint unsigned int uchar px; uint a; uint b;

uint c; //uint i;

uchar digbit; // uchar dy;

uchar wordbuf[2]; uchar count; uchar pwbuf[2]; bit enterflag;

bit lh;

// 防止PWLock.h被重复引用

为0XFF 字位 // 字型码缓冲区 // 位计数

// 输入数字存储区

// 确认键按下与否标志

bit pwflag; bit showflag;

sbit P20=P2^0; sbit P21=P2^1;

void display(void); #endif

//#include \"PWLock.h\" /* 键消抖延时函数 */ void delay(void) { uint i;

for (i=12000;i>0;i--);

} /* uchar keyscan(void) { uchar scancode,tmpcode;

P1 = 0xf0;

行扫描码 if ((P1&0xf0)!=0xf0)

{

delay();

抖动

// 密码正确与否标志

// 数码管显示与否标志

// 显示函数

键扫描函数 */

// 发全0

// 若有键按下

// 延时去

if ((P1&0xf0)!=0xf0) // 延时后再判断一次,

去除抖动影响

{

scancode = 0xfe;

while((scancode&0x10)!=0) {

P1 = scancode;

// 输出行

// 逐行扫描

扫描码

if ((P1&0xf0)!=0xf0) {

tmpcode = (P1&0xf0)|0x0f;

// 本行有键按下

/* 返回特征字节码,为1的位即对应于行和列 */ 位 0 }

}

return(0);

// 无键按下,返回值为

}

}

}

return((~scancode)+(~tmpcode));

else scancode = (scancode<<1)|0x01;//行扫描码左移一

/* 定时器0中断服务子程序,2ms定时动态扫描显示 */ void time0_int(void) interrupt 1 { /* 重置2ms定时 */ TH0 = -2000/256;

TL0 = -2000%256;

px++; //片选 if (showflag==1)

display();

// 调用显示函数}

/* 根据共阴极字型编码表获取0~9,A~B字型代码 */ uchar getcode(uchar i) { uchar p; switch (i) { case 0: p=0x3f; break; case 1: p=0x06; break; case 2: p=0x5B; break; case 3: p=0x4F; break;

case 4:

p=0x66;

break;

/* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */

case 5: p=0x6D; break; case 6: p=0x7D; break; case 7: p=0x07; break; case 8: p=0x7F; break; case 9: p=0x67;

break;

default:

break;

}

return(p);

}

void Display(void) //LED数值显示 {

switch (px%2) {

case 0:P20 = 1;P21 = 0; P0 = getcode(wordbuf[0]);break; case 1:P21 = 1;P20 = 0; P0 = getcode(wordbuf[1]);break; default: return; } }

/* 显示函数 */ /*void display(void) {

/* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */

uchar i; switch (digbit) { case 1: i=0; break; case 2:

i=1; break;

default: break;

}

P2 = 0x0;

// P20=0; // P21=0;

P0 = getcode(wordbuf[i]);

P2=digbit; digbit=1;

if(digbit==1)

{ digbit=2; P20 = 1;

P21 = 0;

} digbit=2;

P21 = 1; // 关闭显示// 送字型码// 送字位码

P20 = 0;

if (digbit<0x02)

// 共2位

// 左移一位

digbit = digbit*2;

else

digbit = 0x01;

}

/* 主程序 */ void main() {

uchar j,key;

uint temp;

P20 = 1; P21 = 1;

TMOD = 0x11;

方式1 TH0 = 2000/256; /* 2ms 定时设置 */ TL0 = 2000%256;

/* 启动计数器0,关闭计数器1 */ TR0 = 1; ET0 = 1;

TR1 = 0;

// 关闭数码管显

// T0,T1工作

ET1 = 1; EA = 1; count = 0;

// 初始计数器设为0 // 没有按下确认键

enterflag = 0; lh = 0; pwflag = 0; digbit = 0x01;

// 标志先置为0

// 从第一位数码管开始动态扫描

/* 刚加电时,不显示*/

for (j=0;j<2;j++)

wordbuf[j] = 17;

// 打开数码管显

showflag = 1; while(1) {

key = keyscan(); // 调用键盘扫描函数

switch(key)

{

case 0x11:

// 1行1

列,数字1 “1”

if (count<2) {

wordbuf[count] = 1;

// 对应位上显示

pwbuf[count] = 1; if(count==0)

{a=1; }

{b=1; }

字3

{a=2; }

{b=2;

if(count==1)

count++;

}

break;

case 0x21:

// 1行2列,数

if (count<2) {

wordbuf[count] = 2; // 对应位上显示“2\"

pwbuf[count] = 2;

if(count==0)

if(count==1)

} count++;

字3

“3\"

{a=3; }

{b=3; }

}

break;

case 0x41:

// 1行3列,数

if (count<2) {

wordbuf[count] = 3;

// 对应位上显示

pwbuf[count] = 3;

if(count==0)

if(count==1)

count++;

}

break;

case 0x12:

// 2行1列,数字4

if (count<2)

“4\"

{a=4; }

{b=4; }

列,数字5

“5\"

{a=5;

{

wordbuf[count] = 4;

pwbuf[count] = 4;

if(count==0)

if(count==1)

count++;

}

break;

case 0x22:

if (count<2) {

wordbuf[count] = 5;

pwbuf[count] = 5;

if(count==0)

// 对应位上显示

// 2行2

// 对应位上显示

}

if(count==1)

{b=5; }

列,数字6

“6\"

{a=6; }

{b=6; }

count++;

}

break;

case 0x42:

if (count<2) {

wordbuf[count] = 6;

pwbuf[count] = 6;

if(count==0)

if(count==1)

count++;

}

// 2行3

// 对应位上显示

break;

// 3行1列,数字7

case 0x14:

“7\"

{a=7; }

{b=7; }

列,数字8

“8\"

if (count<2) {

wordbuf[count] = 7;

pwbuf[count] = 7;

if(count==0)

if(count==1)

count++;

}

break;

case 0x24:

if (count<2) {

wordbuf[count] = 8;

// 对应位上显示

// 3行2

// 对应位上显示

pwbuf[count] = 8; if(count==0)

{a=8; }

{b=8; }

列,数字9

“9\"

{a=9; }

{b=9;

if(count==1)

count++;

}

break;

case 0x44:

if (count<2) {

wordbuf[count] = 9;

pwbuf[count] = 9;

if(count==0)

if(count==1)

// 3行3

// 对应位上显示

}

} break;

// 4行1列,数字*

count++;

case 0x18:

“0\"

count = 0; P3=0; px=0;

// 显示清零

for (j=0;j<2;j++) {

wordbuf[j] = 17;

// 数码管不显示pwbuf[j] = 0; // 用FFFFFF清除已经输入的密码

}

break;

case 0x28: // 4行2列,数字0

if (count<2) {

wordbuf[count] = 0; // 对应位上显示

pwbuf[count] = 0;

if(count==0)

{a=0; }

if(count==1)

{b=0; } count++;

}

break;

case 0x48:

列,数字#

enterflag = 1;

按下

if (count==2)

// 只有输入2个数后按确认键才有效输出 pwflag = 1;

break;

default:break;

}

if (enterflag==1)

{ enterflag = 0;

count = 0; //

// 4行3

// 确认键

// 如果按下确认键

// 标志位置回0

计数器清零

c=0xff/12; if (pwflag==1)

{

P3=a*c+b*c/12+12*c/1000; temp=a*c+b*c/12+12*c/1000; if(temp>=0xff) {

P3=0xff; } } }

因篇幅问题不能全部显示,请点此查看更多更全内容

Top