|
本帖最后由 gaobao_1 于 2012-6-14 10:54 编辑
用m8做的锂电充电器大家发表观点
/***************2012/04/20初写*******************/
/***************2012/05/10调试*******************/
/***********没用中断方式的充电器**************/
/***************2012/05/10试用版*******************/
#include<iom8v.h>
#include "macros.h"
#include"delay.h"
//#include"LCMXX.H"
#define LEDM_1 PORTD|= (1<<PD3) //充满指示
#define LEDM_0 PORTD&=~(1<<PD3)
#define LEDC_1 PORTD|= (1<<PD4) //充电指示
#define LEDC_0 PORTD&=~(1<<PD4)
#define FDKG_1 PORTD|= (1<<PD5) //放电开关
#define FDKG_0 PORTD&=~(1<<PD5)
#define ACKEY_1 PORTC|= (1<<PC5) //交流开关
#define ACKEY_0 PORTC&=~(1<<PC5)
unsigned char hour,cent,second,time_ms;
int Error[4]; //误差值
int vpwm ,pwm,sumError=0;
unsigned char mode; //工作模式
unsigned int vdd_tmp; //ADC_BAT电压
unsigned int vdd_BAT1; //ADC_BAT电压
unsigned int vdd_BAT0; //ADC_BAT电压
unsigned int bat_A; //ADC_电流通渠道
unsigned int ADC_tmp; //ADC_BAT电压
unsigned long ADC_BAT;
unsigned int read_2_56adc(unsigned char ad_chanel)
{ unsigned int ui_AD_data ;
ADMUX=ad_chanel; //外2.56V参考电压
delay_us(100);
ADCSRA=1<<ADEN|1<<ADSC|6<<ADPS0; //启动AD 64分频
while (!(ADCSRA&(1<<ADIF))); //等待A/D完成
ADCSRA|=(1<<ADIF); //写1清除标志位
ui_AD_data=ADC;
return (ui_AD_data);
}
/*
void bit_bcd (unsigned int tmpda) //转换BCD码
{
play_data[3]= SEG7_2[tmpda/1000%10];
play_data[2]= SEG7_2[tmpda/100%10];
play_data[1]= SEG7_2[tmpda/10%10];
play_data[0]= SEG7_2[tmpda%10];
}
void bit_bcd_1 (unsigned int tmpda) //转换BCD码
{
display_data[0]= SEG7_1[tmpda/1000%10];
display_data[1]= SEG7_1[tmpda/100%10];
display_data[2]= SEG7_1[tmpda/10%10];
display_data[3]= SEG7_1[tmpda%10];
}*/
#pragma interrupt_handler timer2:5
//T/C2中断服务
void timer2(void)
{
/***********************************/
time_ms++;
if(time_ms==2)
{time_ms=0;second++;}
if(second==60)
{second=0;
cent++;
}
if(cent==60)
{cent=0;
hour++;
}
if(hour==24)
{hour=0;
}
_SEI();
}
//端口初始化
void port_init(void)
{
PORTB = 0x08; //key_PB3输入
DDRB = 0x07;
PORTC = 0x00;
DDRC = 0x30; //PC5输出
PORTD = 0x00;
DDRD = 0xff;
}
//定时T1初始化
void timer1_init(void)
{
TCCR1B = 0x00;//停止定时器
TIMSK |= 0x00;//中断允许
OCR1A = 0x0000;//匹配A值
//ICR1 = 0x012c;//输入捕捉匹配值
TCCR1A = 0x81; //8位pwm
TCCR1B|=!(1<<WGM12)|1<<CS10; //系统时钟
}
void init_timer2_ocr(void)
{
ASSR=(1<<AS2);
TCCR2=0x04; //64分频
TIMSK=(1<<TOIE2);
TCNT2=0x00;
while (ASSR&(1<<OCR2UB));
}
void init_devices(void)
{
CLI(); //禁止所有中断
MCUCR = 0x00;
MCUCSR = 0x80;//禁止JTAG
GICR = 0x00;
port_init();
timer1_init();
//init_timer2_ocr();
SEI();//开全局中断
}
//主函数
void main(void)
{ unsigned char i;
init_devices();
delay_ms( 200 ) ;
TCCR1A = 0x00;//停止定时器
delay_us(20);
FDKG_1;
delay_ms(6);
vdd_tmp=read_2_56adc(0x00);
vdd_BAT0=(vdd_tmp*17)/10;
FDKG_0;
ADC_tmp=vdd_BAT0/10;
vpwm=250*ADC_tmp/150; //计算PWM值1500是电源电压
OCR1A=vpwm;
if(vdd_BAT0<300){mode=0;
TCCR1A = 0x81;//停止定时器
LEDC_1 ;
LEDM_0 ; //无电池或电池严重欠压
OCR1A=30;
delay_ms(100);
TCCR1A = 0x00;//停止定时器
LEDC_0 ;
delay_ms(60);
}
else if(vdd_BAT0<900){mode=1;
TCCR1A = 0x81;
LEDM_0; //备充电状态
LEDC_1;
for(i=0;i<60;i++)
{
delay_05ms();
vdd_tmp=read_2_56adc(0x01);
vdd_BAT1=vdd_tmp*17;
vdd_tmp=read_2_56adc(0x00);
vdd_BAT0=vdd_tmp*17;
if(vdd_BAT1>vdd_BAT0)
{bat_A=(vdd_BAT1-vdd_BAT0);
Error[0]=70-bat_A;
pwm=vpwm+(Error[0]/12)+(Error[1]/24);//
vpwm=pwm;
Error[1]=Error[0];
OCR1A=pwm;
}
}
}
else if (vdd_BAT0<1259){ mode=2;
TCCR1A = 0x81;
LEDM_0; //恒流充电状态
LEDC_1;
for(i=0;i<60;i++)
{
delay_05ms();
vdd_tmp=read_2_56adc(0x01);
vdd_BAT1=vdd_tmp*17;
vdd_tmp=read_2_56adc(0x00);
vdd_BAT0=vdd_tmp*17;
if(vdd_BAT1>vdd_BAT0)
{bat_A=(vdd_BAT1-vdd_BAT0);
Error[0]=245-bat_A;
pwm=vpwm+(Error[0]/12)+(Error[1]/24);//
vpwm=pwm;
Error[1]=Error[0];
OCR1A=pwm;
}
}
}
else { mode=3;
LEDM_1; //恒压充电状态
LEDC_0;
vpwm=30;
OCR1A=vpwm;
TCCR1A = 0x81;
for(i=0;i<40;i++)
{
delay_ms (2);
vdd_tmp=read_2_56adc(0x01);
vdd_BAT1=vdd_tmp*17;
Error[0]=12600-vdd_BAT1;
pwm=vpwm+(Error[0]/12)+(Error[1]/24);
vpwm=pwm;
Error[1]=Error[0];
OCR1A=pwm;
}
}
while(1)
{ TCCR1A = 0x00;//停止定时器
delay_us(20);
FDKG_1; //放电测量电池电压
delay_ms(6);
vdd_tmp=read_2_56adc(0x00);
ADC_BAT=vdd_tmp;
vdd_BAT0=(unsigned int)((ADC_BAT*171)/100);
//vdd_BAT0=(vdd_tmp*17)/10;
FDKG_0;
if(vdd_BAT0<300){mode=0;
TCCR1A = 0x00;//停止定时器
LEDM_0 ; //无电池或电池严重欠压
LEDC_0 ;
}
else if(vdd_BAT0<900){mode=1;
LEDM_0; //备充电状态
LEDC_1;
TCCR1A = 0x81;
}
else if (vdd_BAT0<1259){mode=2;
LEDM_0; //恒流充电状态
LEDC_1;
TCCR1A = 0x81;
}
else if(vdd_BAT0<1261) { mode=3;
LEDM_1; //恒压充电状态
LEDC_0;
TCCR1A = 0x81;
}
else { mode=4;
LEDM_1; //停止恒压充电状态
LEDC_0;
TCCR1A = 0x00;
}
if((PINB&0x08)==0) //key ac/dc变换
{
PORTC ^= 0x20;
}
if((PINC&0x20)==0x20)
{ mode=0;
}
switch(mode)
{
case 0:TCCR1A = 0x00;//停止定时器
LEDM_0 ; //无电池或电池严重欠压
LEDC_0 ;
delay_ms (120);
break;
case 1: for(i=0;i<240;i++)
{
delay_05ms ();
vdd_tmp=read_2_56adc(0x01);
vdd_BAT1=vdd_tmp*17;
vdd_tmp=read_2_56adc(0x00);
vdd_BAT0=vdd_tmp*17;
if(vdd_BAT1>vdd_BAT0)
{bat_A=(vdd_BAT1-vdd_BAT0);
Error[0]=70-bat_A;
//sumError += Error[0];
Error[2]=Error[0]-Error[1];
pwm=vpwm+(Error[0]/12)+(Error[2]/24);
vpwm=pwm;
Error[1]=Error[0];
OCR1A=pwm;
}
}
break;
case 2:
for(i=0;i<240;i++)
{
delay_05ms();
vdd_tmp=read_2_56adc(0x01);
vdd_BAT1=vdd_tmp*17;
vdd_tmp=read_2_56adc(0x00);
vdd_BAT0=vdd_tmp*17;
if(vdd_BAT1>vdd_BAT0)
{bat_A=(vdd_BAT1-vdd_BAT0);
Error[0]=245-bat_A;
Error[2]=Error[0]-Error[1];
pwm=vpwm+(Error[0]/12)+(Error[2]/24);//+(sumError/20);
vpwm=pwm;
Error[1]=Error[0];
OCR1A=pwm;
}
}
break;
case 3:
for(i=0;i<90;i++)
{
delay_ms (2);
vdd_tmp=read_2_56adc(0x01);
vdd_BAT1=vdd_tmp*17;
Error[0]=12600-vdd_BAT1;
Error[2]=Error[0]-Error[1];
pwm=vpwm+(Error[0]/12)+(Error[2]/24);
vpwm=pwm;
Error[1]=Error[0];
OCR1A=pwm;
}
break;
case 4:
TCCR1A = 0x00;//停止定时器
LEDM_1 ; //无电池或电池严重欠压
LEDC_0 ;
delay_ms (100);
break;
default: break;
}
}
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|