📄 charger.c
字号:
///////////////////////////////////////////////////////////////////////////
///
/// name: charger
/// MCU: uPD78F9202
/// version: V1.52+WDT
/// date: 09/03/2007
///
///////////////////////////////////////////////////////////////////////////
#pragma sfr
#pragma nop
#pragma di
#pragma ei
#pragma halt
#pragma access
#pragma interrupt INTTM000 timer_1s
#define current_700mA 1
#define current_changed 2
#define current_100mA 3
#define LED P3.2
#pragma section @@CNST opt at 0x0080
const unsigned char opb = 0x95;
const unsigned char protect = 0b10100111;
const unsigned char U1=1;
const unsigned char U2=2;
sreg unsigned char second_10 = 0;
sreg unsigned char second_100ms = 0;
sreg unsigned char mode=0;
sreg unsigned char testing_counter=0;
sreg unsigned char no_battery_counter=0;
sreg unsigned char constFlag=0;
sreg unsigned char duty_pwm=100;
sreg unsigned int tempAD[3]={0,0,0};
sreg unsigned int tempADCR=0;
sreg unsigned int ADCR_U1=0;
sreg unsigned int ADCR_U2=0;
sreg unsigned int battery_U1=0;
sreg unsigned int V_battery=0;
sreg unsigned int current=0; // unit is mA
sreg unsigned int current1=0; // unit is mA
sreg unsigned int current2=0; // unit is mA
sreg unsigned int need_current=0; // unit is mA
sreg unsigned int second=0;
sreg unsigned int bit_current=0; // unit is 10ma
sreg unsigned int bit_voltage=0; // unit is 0.1mV
bit second_flag;
bit hour_flag;
bit current_check_start;
bit work_flag;
bit testing_finish;
bit mode_change_flag;
bit can_work;
bit second_10_start;
void AD_convert(unsigned char chn);
void no_battery_handle();
void fast_charging_handle();
void variable_charging_handle();
void fix_100mA_handle();
void pwm_start();
void pwm_stop();
void delay(unsigned int delay_number);
void testing();
void normal_work();
extern void learning();
void hardware_init()
{
DI();
PCC = 0x00;
PPCC = 0x00;
MK0 = 0xFF;
WDTE = 0xAC;
WDTM = 0b01100111;
LSRCM = 0x00;
LVIMK = 1;
LVIIF = 0;
LVIM = 0x00;
LVIS = 0x05;
P2.0 = 0;
PM2 = 0b11110110; // setting for pwm and AD, P20 for pwm, P21 and P22 for ADC
PMC2 =0b00000110; // P20 for pwm, P21 and P22 for ADC
TMHMD1 = 0b00001001; // the bit 1 for inversion or not, 0 is not, 1 is yes, 31KHz count clock of PWM
CMP01 = 253;
CMP11 = 200;
CRC00 = 0x00; // timer00 seeting for interval interrupt of 100ms
CR000 = 3126;
PRM00 = 0x02; // count clock is 2MHz for using Ring-OSC
TMC00 = 0b00000000;
TMIF000 = 0;
TMMK000 = 1;
PM4.3 = 0;
P4.3 = 0;
PM4.0 = 0;
P4.0 = 0;
PM3.2 = 0;
P3.2 = 0;
PM2.3 = 0;
P2.3 = 0;
ADM = 0b00100000; // AD mode setting
EI();
}
void main()
{
hardware_init();
second_flag = 0;
second_10_start = 0;
hour_flag = 0;
current_check_start=0;
work_flag = 1;
testing_finish=0;
can_work=0;
mode_change_flag=0;
constFlag=0x11; //peekb(0x0e01);
if(constFlag!=0x11) // self programming
{
learning();
constFlag=peekb(0x0e01);
while(constFlag==0x11) LED = 1;
while(constFlag!=0x11) LED = 0;
}
else if (constFlag==0x11) // normal operation
{
TMIF000 = 0;
TMMK000 = 0;
TMC00 = 0b00001100;
bit_current=50; //peekw(0x0e02); // current of each bit
bit_voltage=41; //peekw(0x0e04); // voltage of each bit, unit is 0.1mV
while(1)
{
LVIIF = 0;
if(!LVION) LVION = 1;
delay(200);
if(LVIIF == 1) { can_work = 0; LVIIF = 0; pwm_stop(); second_flag = 0; }
else can_work = 1;
LVION = 0;
delay(200);
if(second_flag==1 && can_work==1)
{
if(work_flag==1) testing();
else normal_work();
second_flag = 0;
}
}
}
}
/////////////////////////////////////////////////////////////////////////
void AD_convert(unsigned char chn)
{
unsigned char j=0;
unsigned char k=0;
ADS=chn;
ADCE=1;
NOP();
NOP();
while(j<3)
{
ADCS=1;
while(!ADIF);
ADCS=0;
ADIF=0;
tempAD[j]=ADCR;
j++;
}
ADCE=0;
for(j=0; j<2; j++)
for(k=j+1; k<3; k++)
{
if(tempAD[j]>=tempAD[k])
{
tempADCR=tempAD[j];
tempAD[j]=tempAD[k];
tempAD[k]=tempADCR;
}
}
if(ADS==U1)
{
if(current_check_start==1){ ADCR_U1=tempAD[1]; }
else if(current_check_start==0){ battery_U1=tempAD[1]; }
}
else if(ADS==U2) ADCR_U2=tempAD[1];
}
/////////////////////////////////////////////////////////////////////////////////
void no_battery_handle()
{
pwm_stop();
}
////////////////////////////////////////////////////////////////////////////
void fast_charging_handle()
{
if(current<300)
{
if(duty_pwm<250)
{
if(current<250)
{
if(duty_pwm<200){ duty_pwm = duty_pwm + 30; }
else{ duty_pwm = duty_pwm + 2; }
}
else{ duty_pwm++; }
}
}
else if(current>300)
{
if(current>310){ duty_pwm=220; }
if(duty_pwm>40){ duty_pwm=duty_pwm-5; }
if(duty_pwm>4){ duty_pwm--; }
}
CMP11 = duty_pwm ;
NOP();
NOP();
pwm_start();
}
////////////////////////////////////////////////////////////////////////////
void variable_charging_handle()
{
need_current = 500 - (V_battery - 2750)*4;
if(current<need_current)
{
if(duty_pwm<250)
{
if(current<(need_current-30))
{
if(duty_pwm<100){ duty_pwm = duty_pwm + 45; }
else duty_pwm = duty_pwm + 2;
}
else { duty_pwm++; }
}
}
else if(current>need_current)
{
if(duty_pwm>4){ duty_pwm--; }
}
CMP11 = duty_pwm ;
NOP();
pwm_start();
}
////////////////////////////////////////////////////////////////////////////
void fix_100mA_handle() // fix 100mA handle
{
if(current<100)
{
if(duty_pwm<250)
{
if(duty_pwm<20){ duty_pwm = duty_pwm + 45; }
else duty_pwm++;
}
}
else if(current>100)
{
if(current>200){ duty_pwm=180; }
if(duty_pwm>200){ duty_pwm=180; }
if(duty_pwm>4){ duty_pwm--; }
}
CMP11 = duty_pwm ;
NOP();
NOP();
pwm_start();
if(can_work = 0)
{
mode=1;
second=0;
}
}
////////////////////////////////////////////////////////////////////////////
void pwm_start()
{
TMHE1 = 1;
}
////////////////////////////////////////////////////////////////////////////
void pwm_stop()
{
TMHE1 = 0;
}
///////////////////////////////////////////////////////////////////////////
void delay(unsigned int delay_number)
{
unsigned int i=0;
for(i=0; i<delay_number; i++);
}
///////////////////////////////////////////////////////////////////////////
__interrupt void timer_1s()
{
TMIF000 = 0;
second_100ms++;
WDTE = 0xAC;
if(second_100ms>9)
{
second_100ms = 0;
second_flag = 1;
if(second_10_start == 1) second_10++;
if( mode==current_700mA || mode==current_changed )
{
if(second_10_start==0) second++;
}
if(second_10>10)
{
second_10 = 0;
second=0;
second_10_start = 0;
mode_change_flag=0;
duty_pwm=100;
mode = 0;
NOP();
}
if(second>7200)
{
mode_change_flag=1; // 500mA over 120min, change to 100mA
second=0;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
void normal_work()
{
current_check_start=1;
AD_convert(U1);
AD_convert(U2);
if(ADCR_U1 > ADCR_U2)
{
current1 = (ADCR_U1 - ADCR_U2)*bit_current;
current1 = current1/10 ;
}
delay(50);
AD_convert(U1);
AD_convert(U2);
if(ADCR_U1 > ADCR_U2)
{
current2 = (ADCR_U1 - ADCR_U2)*bit_current;
current2 = current2/10 ;
}
current = current1/2 + current2/2 ;
current_check_start=0;
pwm_stop();
delay(5000); // delay for ADC after switch off
AD_convert(U1); // measure battery voltage
V_battery = (1025 - battery_U1)*bit_voltage;
V_battery = V_battery/10 ;
if(ADCR_U1 < 250) // no battery, U1<0.8V, battery removal
{
work_flag = 1;
second_10_start = 1;
}
else
{
if(mode_change_flag==0)
{
if(V_battery<2751) mode = current_700mA; // battery < 2.75V
else if(V_battery<2851) mode = current_changed; // 2.75V < battery < 2.85V
else mode = current_100mA;
}
else mode = current_100mA;
switch(mode)
{
case current_700mA : fast_charging_handle();
break;
case current_changed : variable_charging_handle();
break;
case current_100mA : fix_100mA_handle();
break;
default : NOP();
break;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void testing()
{
CMP11 = 200 ;
NOP();
pwm_start();
current_check_start=1;
delay(5000); // delay for ADC after switch off
AD_convert(U1); // measure battery voltage
current_check_start=0;
if(ADCR_U1 < 250)
{
work_flag = 1; // work_flag = 1, means no battery, U1<0.8V, battery removal
pwm_stop();
}
else {
work_flag = 0; // work_flag = 0, means has battery
second_10_start = 0;
second_10 = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -