最近搞到兩塊DAC0832,一直在考慮干什么用,想想還是做個數(shù)控電源吧!
輸入是舊的ADSL上的DC14.5V電源,
主電路是由LM317變壓的,
控制IC是M8L,
顯示用的兩組3位數(shù)碼管,
DAC0832加上LM2904運放實現(xiàn)可調電壓基準,供LM317使用,
0.5歐姆電阻加上LM358運放實現(xiàn)電流、電壓的采樣,送至M8的AD0、AD1,
現(xiàn)在已經(jīng)實現(xiàn)了電壓、電流的測量、顯示,并且校準了,
也實現(xiàn)了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讀取函數(shù)
void eeprom_wr(unsigned char, unsigned char); //EEPROM寫入函數(shù)
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; //顯示循環(huán)變量
//定時器2 3ms循環(huán),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; //小數(shù)點
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循環(huán)變量
unsigned char ui_cs=0; //ADC0/1通道選擇
unsigned int ad_var=0; //AD累加值
//定時器1 1.3ms循環(huán),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數(shù)據(jù),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數(shù)據(jù)
}
//主函數(shù)
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需要根據(jù)實際情況定,主要是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讀取函數(shù) eaddr地址
unsigned char eeprom_rd(unsigned char eaddr)
{
while(EECR&(1<<EEWE));
EEARH = 0x00; EEARL = eaddr;
EECR|=(1<<EERE);
return EEDR;
}
//EEPROM寫入函數(shù) eaddr地址;edata寫入數(shù)據(jù)
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---------------------------------------*/
|