一个简易的数控电源

2019-07-14 00:24发布

一个简易的数控电源DVCS(digital control voltage source)的实现。
一、基本功能:
1、输入电压: DC18V,输出电压: 1.3V——16.0V,电压调整精度0.1V。
2、负载能力: 400mA
3、动态三位数码管显示输出电压
4、按键调整输出电压,SW1——1V/0.1V 步进电压调整键;SW2——递增调整键;
SW3——递减调整键
二、功能模块实现:
1、单片机与按键接口部分:
3 单片机与数码管显示接口电路:
采用动态扫描三位数码管,共阳极接法,每段驱动电流约为4mA.
2 DAC 与单片机接口电路和DA 参考电压电路:
IC6A,IC6B 两个运放用来将R-2R DAC 的电路变换为电压并反相放大来驱动
LM317 的电压调整端,IC1B 用来产生一个较为稳定的电压给DAC 的转换参考电压
来供电.运放选用LM358.
4,电压调整与输出电路:
供电电路采用有中心抽头的变压器双15V,经整流,滤波得到正负18V 的电压给
LM317 供电,Rp1 和Rp2 用来保护LM317,防止输出电流过高而烧坏芯片.运放IC1A
与LM317 一起构成负反馈,使IC1A 的V-和V+电压相等.把DAC 输出的电压加到运
放的输入端,单片机控制DAC 的输出电压变化,那么LM317 的输出电压由于负反馈
的原因而跟随DAC 的输出变化.从而实现了数控的作用.Rc 用来保证输出电压最
小能达到1.3V,如果没有这个下拉电阻分流,LM317 的adjust current 会流进运
放使运放输出电压升高,进而导致317 输出升高.R25 取值是由317 的load
regulation current 决定的,317 必须有一个最小的负载电流来维持内部的
regulation 来实现输出电压的稳定.C3 用来防止震荡,稳定负反馈环,其取值
由调试时确定.
单片机和DAC 的供电电路有LM7805 来产生.
三, 程序原码:
//***************************程序说明*************************************
//1 使用小模式编译时,不可把变量定义在PDATA区,KEIL 默认的是
// 小模式下的编译。因此,如果使用uchar pdata arry[],则必须
// 将编译器设在compact 模式下编译。数码管显示乱码就是因为编译器
// 没有设置好。
//2 处理按键扫描时,一定要去抖动。由于人按键时间较长,为了实现每
// 按一次键,输出电压增加0.1V。在判断到按下键时,先不去刷新DA的
// 寄存器,在程序里仍然调用动态扫描程序,直到按键释放时,在去刷新
// DA的寄存器,刷新后仍然调用显示程序。这样就实现了按一次键"+" 1
// 的动作
//3 动态扫描时间为每位10毫秒比较适宜,再慢的话,屏幕会抖动.
//4 为了防止按一下键,程序被中断了多次,可以把中断设为边沿触发方式,
// 这样每按一下键只中断了一次.(把中断方式 IT0 设置为"1")
//**************************************************************************
#include "reg51.h"
#include "math.h"
#define uint unsigned int
#define uchar unsigned char
//#include "intrins.h"
#define led_sec P1
#define dac_adr 0x7fff //DAC0832的地址
sbit inc_key = P3^0; //"+" 键
sbit dec_key = P3^1; //"-" 键
sbit step_key = P3^2; //调整键
sbit ten = P3^3; //数码管的十位
sbit one = P3^4; //数码管的个位
sbit point = P3^5; //数码管的小数位
char xdata dacreg _at_ dac_adr; //define the dac0832's address
bit flag0 = 0;
uchar arry10[10] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar arry1[10] = { 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
uchar arry0[10] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar * ptr10 = arry10;
uchar * ptr1 = arry1;
uchar * ptr0 = arry0;
//arry10[10] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//arry1[10] = { 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
//arry0[10] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//**************************initial function**********************************
//中断初始化
void ini_int(void)
{
inc_key = 1;
dec_key = 1;
EA = 1;
EX0 = 1;
IT0 = 1; //边沿触发方式
}
//**************************delay function************************************
//延时动态扫描
void delay(uint i) //delay cycle is 20us
{
uint j=0;
for (;j}
//**************************buffer**************************************
//根据地址查表得出要显示的电压值
buffer(uchar led10,uchar led1,uchar led0)
{
ten = 0;
led_sec = *(led10 + ptr10);
delay(500); // delay 10ms
ten = 1;
one = 0;
led_sec = *(led1 + ptr1);
delay(500);
one = 1;
point = 0;
led_sec = *(led0 + ptr0);
delay(500);
point = 1;
}
//**************************display the output voltage******************
//BCD码到十进制的转换
void disp_out(unsigned char dat)
{
uchar dig_10,dig_1,dig_0,temp,temp1;
temp = dat;
dig_10 = temp/100;
temp1 = temp%100;
dig_1 = temp1/10;
dig_0 = temp%10;
buffer(dig_10,dig_1,dig_0);
}
//**********************main function***********************************
void main()
{
unsigned char dac_dat,dac_temp;
uchar inc_key_temp = 1;
uchar dec_key_temp = 1;
dac_dat = 0xd;
//flag0 = 0; // initialising the flag bit
dac_temp = dac_dat;
dacreg = dac_temp; //set the output voltage to 1.3V
ini_int(); //interrupt initialising
disp_out(dac_temp);
while (1 /*~dec_key | ~inc_key*/)
{
//判断有没有键按下
if ( inc_key == 0 )
{
delay(600);
inc_key_temp = (inc_key == 0) ? 0 : 1;
//按键释放前一直扫描显示,如果按键释放则跳出并 "+" 1
do
{
disp_out(dac_temp);
}
while (inc_key == 0);
}
else if( dec_key == 0 )
{
delay(600);
dec_key_temp = (dec_key == 0) ? 0 : 1;
do
{
disp_out(dac_temp);
}
while (dec_key == 0);
}
else
{
;
}
if ( ~flag0 & ~dec_key_temp & (dac_temp>13)) // decrease and step is 0.1V
{
dec_key_temp = 1;
dac_dat = dac_dat - 1;
dac_temp = dac_dat;
dacreg = dac_temp;
disp_out(dac_temp);
}
else if ( ~flag0 & ~inc_key_temp & (dac_dat<161)) // increase and step is 0.1V
{
inc_key_temp = 1;
dac_dat = dac_dat + 1;
dac_temp = dac_dat;
dacreg = dac_temp;
disp_out(dac_temp);
}
else if ( flag0 & ~dec_key_temp & (dac_dat>23)) //decrease and step is 1V
{
dec_key_temp = 1;
dac_dat = dac_dat - 10;
dac_temp = dac_dat;
dacreg = dac_temp;
disp_out(dac_temp);
}
else if (flag0 & ~inc_key_temp & (dac_dat<151)) // increase and step is 1V
{
inc_key_temp = 1;
dac_dat = dac_dat + 10;
dac_temp = dac_dat;
dacreg = dac_temp;
disp_out(dac_temp);
}
else
{
disp_out(dac_temp);
}
}
}
//*************************interrupt function**************************
void int0() interrupt 0 using 1
{
flag0 = ~flag0;
}