//陈永飞于2016年3月28号写的数控电源,上电初始电压是3V //采用ATMEGA8芯片做的,四位数码管显示电压值,调节范围是1.8V到12V之间 //采用开关稳压芯片LM2576ADJ做的降压,效率高达77%,电流最大3A,误差电压为正负0.2V #include #include #define uchar unsigned char #define uint unsigned int #define duan PORTD uchar const tab[]={ 0xC0,/*0*/ 0xF9,/*1*/ 0xA4,/*2*/ 0xB0,/*3*/ 0x99,/*4*/ 0x92,/*5*/ 0x82,/*6*/ 0xF8,/*7*/ 0x80,/*8*/ 0x90,/*9*/ }; uint DY=30; //30就是为3.0V电压,用于设定电压 uint AD_shu,tiao_shu; //一个用于保存ADC转换后的数,一个用于运算比较 void delay(uint k) { for(;k>0;k--); } void init() { DDRD=0xff; //D端口全为输出 PORTD=0; DDRC=0xfc; //C端口低两位用于ADC,高四位用于数码管位选 PORTC=0x0; //C端口输出全0 DDRB=0x07; //定义PB口的低三位为输出,PB1为PWM输出信号 PORTB=0xf8; //低三位输出0,高五位加上拉电阻 TCCR1A=0X63; //设置PWM比较匹配器 TCCR1B=0X13; //设置PWM比较匹配器 OCR1A=250; //装PWM寄存器的高位比较值 OCR1B=10; //装PWM寄存器的低位比较值,开启后自加,达到高位时,PB1端口取反 ADMUX=0xc0; //ADC选通道0,并且用内部的2.56V参考电压,数据右对齐 ADCSRA=0xac; //ADC是连续转换,并且16分频,并且开了中断 } void desplay(uint dian_ya) { duan=tab[dian_ya/100]; //显示十位电压 PORTB|=0x04; //PC2为位选 delay(400); PORTB&=0xfb; duan=tab[dian_ya%100/10]&0x7f; //显示个位电压,并点亮小数点 PORTB|=0x08; //PC3为位选 delay(400); PORTB&=0xf7; duan=tab[dian_ya%10]|0x80; //显示小数位电压,并灭小数点 PORTB|0x10; //PC4为位选 delay(400); PORTB&=0xef; duan=tab[11]; //用于设定时点亮 PORTB|=0x20; //PB5为位选 delay(400); PORTB&=0xdf; } void key() { if(!(PINB&0x08)) //PB3为加电压按键 { delay(5000); if(!(PINB&0x08)) { DY++; if(DY>120)DY=120; } } if(!(PINB&0x10)) //PB4为减电压按键 { delay(5000); if(!(PINB&0x10)) { DY--; if(DY<18)DY=18; } } } int main() { uchar i=1; init(); ADCSRA|=0x40; //开始ADC转换 while(1) { key(); tiao_shu=(uint)(((float)AD_shu)/8.5); //计算ADC采样后的数进行电阻分压后的实际数据转换补常 if(tiao_shu>(DY+2)) i--; //如果采样转换后数值大于设定值,就减小PWM脉宽(设定值加2是电压误差值) if(tiao_shu<(DY-2)) i++; //如果采样转换后数值小于设定值,就加大PWM脉宽(设定值减2是电压误差值) delay(20); //延时 OCR1B=i; //装入PWM寄存器 desplay(DY); } } SIGNAL(SIG_ADC) { AD_shu=ADCL; AD_shu|=(uint)(ADCH<<8); } |
更多回帖