找回密码
 立即注册

QQ登录

只需一步,快速开始

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

简单数控电源(1.25V~9.99V)

[复制链接]
跳转到指定楼层
楼主
ID:127902 发表于 2016-6-24 23:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近搞到两块DAC0832,一直在考虑干什么用,想想还是做个数控电源吧!

输入是旧的ADSL上的DC14.5V电源,
主电路是由LM317变压的,
控制IC是M8L,
显示用的两组3位数码管,
DAC0832加上LM2904运放实现可调电压基准,供LM317使用,
0.5欧姆电阻加上LM358运放实现电流、电压的采样,送至M8的AD0、AD1,

现在已经实现了电压、电流的测量、显示,并且校准了,
也实现了LM317主电路电压可调,在1.25V~9.99V之间,步进0.06V(如果改变负压基准,精度还可以提高)。

















/*===========================================================================
   由于我是外部+14.5V输入,负压源用的是MC34063产生的,只使用了-5V一路,所以电
   压步进0.06V左右。
   自动修正程序在考虑中,在学习PID,争取运用到程序中。
===========================================================================*/
#include "iom8v.h"
//LED位选 电流
#define LED_I0_R PORTB&=0xfd //PB1
#define LED_I1_R PORTB&=0xfb //PB2
#define LED_I2_R PORTC&=0xfb //PC2
//LED位选 电压
#define LED_U0_R PORTC&=0xf7 //PC3
#define LED_U1_R PORTC&=0xef //PC4
#define LED_U2_R PORTC&=0xdf //PC5
//LED复位
#define LED_PB_S PORTB|=0x06 //PB1 PB2
#define LED_PC_S PORTC|=0x3c //PC2 PC3 PC4 PC5
//DAC0832
#define DAC_CS_S PORTB|=0x01 //DAC0832片选 PB0
#define DAC_CS_R PORTB&=0xfe
//按键
#define KeyA (PINB&0x08) //加 PB3
#define KeyD (PINB&0x10) //减 PB4
#define KeyM (PINB&0x20) //增量 PB5
void _nus(unsigned char); //微秒延时
void _nms(unsigned int);  //n毫秒延时
unsigned char eeprom_rd(unsigned char);       //EEPROM读取函数
void eeprom_wr(unsigned char, unsigned char); //EEPROM写入函数
void init_devices(void);  //硬件初始化

unsigned char ui_var[6] = {10,10,0,0,0,0}; //电流、电压
// 0    1    2    3    4    5    6    7    8    9  _
const unsigned char LED_CODE[11] =
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xf7};
unsigned char led_cs=0; //显示循环变量
//定时器2 3ms循环,CTC模式
#pragma interrupt_handler timer2_comp_isr:4
void timer2_comp_isr(void)
{
LED_PB_S; LED_PC_S;
PORTD = LED_CODE[ui_var[led_cs]];
if(led_cs==3) PORTD&=0x7f;   //小数点
  switch(led_cs){
  case 0: LED_I2_R; break; //电流
  case 1: LED_I1_R; break;
  case 2: LED_I0_R; break;
  case 3: LED_U2_R; break; //电压
  case 4: LED_U1_R; break;
  case 5: LED_U0_R; break;
}
if(led_cs<5) led_cs++;
else led_cs = 0;
}
unsigned int u_var=0; //电压值
unsigned int i_var=0; //电流值
unsigned char ui_flg=0; //AD循环变量
unsigned char ui_cs=0;  //ADC0/1通道选择
unsigned int ad_var=0;  //AD累加值
//定时器1 1.3ms循环,CTC模式 7.5Hz
#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
  unsigned int adc_h;
unsigned char adc_l;
adc_l = ADCL; adc_h = ADCH; adc_h<<=8; adc_h+=adc_l;
ad_var+=adc_h; //累加
if(ui_flg<50) ui_flg++;
else{
  adc_h = ad_var/51;            //求平均
  if(ui_cs==1){ //电压
   //AD->电压V    校准电压时在此修正
   u_var = adc_h-(i_var+10)/20; //输出电压需减去电流采样电阻损耗的压降
   adc_h = u_var;
   ui_var[3] = adc_h/100; adc_h%=100;
   ui_var[4] = adc_h/10; ui_var[5] = adc_h%10;
   //切换到ADC0电流
   ui_cs = 0; ADMUX  = 0xc0;
  }
  else{        //电流
   //AD->电流mA   校准电流时在此修正
   i_var = adc_h;
   if(adc_h>99){
    ui_var[0] = adc_h/100; adc_h%=100; ui_var[1] = adc_h/10;
   }
   else{
    ui_var[0] = 10;
    if(adc_h>9) ui_var[1] = adc_h/10;
    else ui_var[1] = 10;
   }
   ui_var[2] = adc_h%10;
   //切换到ADC1电压
   ui_cs = 1; ADMUX  = 0xc1;
  }
  ui_flg = 0; ad_var = 0;
}
ADCSRA = 0xc1; //重新启动AD
}
unsigned char dac_var=0; //DAC值
//写DAC0832数据,0-3V 0-154
void dac0832_wr(void)
{
  TCCR2 = 0x00; LED_PB_S; LED_PC_S; //关闭LED位选
PORTD = dac_var; DAC_CS_R;        //写DA值
_nus(10); DAC_CS_S; TCCR2 = 0x0b; //恢复
eeprom_wr(0x00,dac_var);          //写入EEPROM数据
}
//主函数
void main(void)
{
init_devices();  //硬件初始化
while(1){
  //KeyA PB3 增加; KeyD PB4 减小; 同时按KeyM PB5 加速
  if(KeyA==0x00){
   _nms(5);
   while((KeyA==0x00)&&(dac_var<148)){
    if(KeyM==0x00){
     if(dac_var<140) dac_var+=8;
     else dac_var = 148;
    }
    else dac_var++;
    dac0832_wr(); _nms(100);
   }
  }
  if(KeyD==0x00){
   _nms(5);
   while((KeyD==0x00)&&(dac_var>0)){
    if(KeyM==0x00){
     if(dac_var>8) dac_var-=8;
     else dac_var = 0;
    }
    else dac_var--;
    dac0832_wr(); _nms(100);
   }
  }
  //上限值148需要根据实际情况定,主要是DAC0832上的负压基准
}
}
//硬件初始化=========================================================
void init_devices(void)
{
  asm("cli");    //禁用全局中断
OSCCAL = 0xa7; //修正内部RC振荡器
ACSR = 0x80;   //1000,0000 关闭模拟比较器电源
//端口设置
PORTB = 0x3f; DDRB = 0x07; //1:2LED位选 0DAC0832
PORTC = 0x7c; DDRC = 0x3c; //2:5LED位选 0电流 1电压
PORTD = 0xff; DDRD = 0xff; //LED段码
//AD初始化 单次 2.56V参考 ADC0 2分频
ADMUX  = 0xc0; //参考源2.56V,ADC0
ADCSRA = 0xc1; //ADC使能,开始,中断关闭,2分频
//T1初始化
  TCCR1A = 0x00; //CTC模式
  TCCR1B = 0x09;
TCNT1  = 0;
OCR1A  = 1300; //1.3ms
//T2初始化
TCCR2 = 0x0b;  //CTC模式,8分频
TCNT2 = 0;
OCR2  = 94;    //3ms
  TIMSK  = 0x90;
//其他
MCUCR = 0x00;
dac_var = eeprom_rd(0x00);   //读取EEPROM的DA值
if(dac_var>148) dac_var = 0; //判断DA值是否超限
dac0832_wr();                //DAC0832初始化
  asm("sei");    //使能全局中断
}
//1M=================================================================
void _nus(unsigned char us){ for(;us>0;us--) asm("nop");} //微秒延时
void _nms(unsigned int ms){ for(;ms>0;ms--) _nus(177);}   //n毫秒延时
//EEPROM读取函数 eaddr地址
unsigned char eeprom_rd(unsigned char eaddr)
{
while(EECR&(1<<EEWE));
EEARH = 0x00; EEARL = eaddr;
EECR|=(1<<EERE);
return EEDR;
}
//EEPROM写入函数 eaddr地址;edata写入数据
void eeprom_wr(unsigned char eaddr, unsigned char edata)
{
while(EECR&(1<<EEWE));
EEARH = 0x00; EEARL = eaddr;
EEDR = edata;
EECR|=(1<<EEMWE);
EECR|=(1<<EEWE);
}
/*-------------END---------------------------------------*/

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

使用道具 举报

沙发
ID:249545 发表于 2017-11-23 22:29 | 只看该作者
感觉手艺好.可是DIY板好乱呀!没计成PCB拿出去制做成板,也不过30元!!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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