EDN首页   博客首页

日志档案

发表于 2007-8-9 19:02:23

1

标签: 数控电源  

一个简易的数控电源DVCS(digital control voltage source)的实现

pdf一个简易的数控电源DVCS(digital control voltage source)的实现。

一、基本功能:

1、输入电压: DC18V,输出电压: 1.3V——16.0V,电压调整精度0.1V

2、负载能力: 400mA

3、动态三位数码管显示输出电压

4、按键调整输出电压,SW1——1V/0.1V步进电压调整键;SW2——递增调整键;SW3——递减调整键

二、功能模块实现:

1、单片机与按键接口部分:

点击看大图

2 单片机与数码管显示接口电路:

采用动态扫描三位数码管,共阳极接法,每段驱动电流约为4mA.

点击看大图

3 DAC与单片机接口电路和DA参考电压电路:

IC6A,IC6B两个运放用来将R-2R DAC 的电路变换为电压并反相放大来驱动LM317的电压调整端,IC1B用来产生一个较为稳定的电压给DAC的转换参考电压来供电.运放选用LM358.

点击看大图

4,电压调整与输出电路:

供电电路采用有中心抽头的变压器双15V,经整流,滤波得到正负18V的电压给LM317供电,Rp1Rp2用来保护LM317,防止输出电流过高而烧坏芯片.运放IC1ALM317一起构成负反馈,使IC1AV-V+电压相等.DAC输出的电压加到运放的输入端,单片机控制DAC的输出电压变化,那么LM317的输出电压由于负反馈的原因而跟随DAC的输出变化.从而实现了数控的作用.Rc用来保证输出电压最小能达到1.3V,如果没有这个下拉电阻分流,LM317adjust current会流进运放使运放输出电压升高,进而导致317输出升高.R25取值是由317load 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;

}

系统分类: 单片机   |   用户分类: 单片机技术   |   来源: 原创   |   【推荐给朋友】   |   【添加到收藏夹】

    阅读(889)    回复(0)  

投一票您将和博主都有获奖机会!