📄 ch.c
字号:
//***************************************************************************
//* Charger.c
//* By : Anthony Xie
//* Date : June 2004
//* Description : Off-line Li-ion battery charger demo for P89LPC916
//*
//********************Revise History*****************************************
//* By : David Dai
//* Date : July 2004
//* Description : TO port the code into P89LPC916
//***************************************************************************
#include <reg916.h> // SFR definitions for LPC916
#define uchar unsigned char
#define uint unsigned int
//-----------------------------------------------
//Global Variable Definitions
//---------------------------------------------
uchar data RTC_Counter_LED, LED_Flash_Speed; //RTC count for LED delay
uint data RTC_Counter_AD; //RTC count for AD convert
uint data AD_Convert_Speed; //AD convert interval
uint data RTC_Counter; //RTC count for delay
uchar data RTC_Counter_Minute; // minutes counter for dalay
bit data LED_Flag, AD1_Flag, AD_Flag, Battery_On_Socket;
bit data Pre_Charge_Status, Constant_Current_Charge, Constant_Voltage_Charge;
uint data AD1_1,AD1_2,AD1_3; //AD1.1-Battery V+, AD1.2-temp., AD1.3-I detect
uchar data average; // AD average times
//-----------------------------------------------
//Constant Definitions
//-----------------------------------------------
#define LED_FLASH_FAST 10 // define led flash with high fre.
#define LED_FLASH_SLOW 200 // define led flash with low fre.
#define STOP_CHARGE_DELAY 50 // define delay time when charge I <60mA, x Minutes
//***************************************************************************
//* Functions
//***************************************************************************
void main(void); // main loop
void init(void); // part initialization
void ad_convert(void);
//***************************************************************************
//* main()
//* Input(s) : none.
//* Returns : none.
//* Description : main loop
//***************************************************************************
void main ()
{
EA = 0;
init();
EA = 1;
for( RTC_Counter = 1; RTC_Counter < 1700; );
RTC_Counter = 0;
for(;;)
{
if(LED_Flag == 0) // control LED flash
{
KB1 = 0;
}
else
{
KB1 = 1;
}
if( ( AD_Flag == 1 ) && ( Battery_On_Socket == 1 ))
// start AD convert and PWM control, with pre-set AD convert speed
{ // AD_Flag control AD convert speed
ad_convert();
AD_Flag = 0;
}
if( RTC_Counter_Minute == STOP_CHARGE_DELAY ) // If delay ended, stop charge
{
EA = 0; //shut down interrupt, so AD_Flag can not be set
P1 = 0; //Shut down PWM
LED_Flag = 1; //LED stable RED
}
}
}
//***************************************************************************
//* init()
//* Input(s) : none.
//* Returns : none.
//* Description : initialization of P89LPC916
//***************************************************************************
void init(void)
{
//SP = 0x30; //Set SP from 50H to 7FH
//-----------------------------------------------
//Config P0 I/O
//-----------------------------------------------
P0M1 = 0x1C; // Set P0.2/3/4 for Input Only, 0001 1100
P0M2 = 0xE3; // Set P0.1 for PP, ^1 for led drive, 1110 0011, others all pp
//-----------------------------------------------
//Config P1 I/O
//-----------------------------------------------
P1M1 = 0x24; // ^5 Input only 0010 0100
P1M2 = 0xdf; // set ^2 open drain 1101 1111 others all pp
//-----------------------------------------------
//Config P2 I/O (P2 not used)
//-----------------------------------------------
P2M1 = 0x00; // All PP
P2M2 = 0xFF;
KB5 = 0; //set p0.7 = 0 can forfid T1 PWM
P1 = 0x00; //set p1.2 = 0 can forbid TO PWM
P2 = 0x00;
RTC_Counter = 0x00;
RTC_Counter_LED = 0x00;
LED_Flag = 0;
LED_Flash_Speed = LED_FLASH_SLOW;
AD1_1 = 0;
AD1_2 = 0;
AD1_3 = 0;
AD1_Flag = 0;
RTC_Counter_LED= 0;
AD_Flag = 0;
average = 10;
Pre_Charge_Status = 0;
Constant_Current_Charge = 0;
Constant_Voltage_Charge = 0;
RTC_Counter_Minute = 0;
Battery_On_Socket = 1;
AD_Convert_Speed = 10;
//-----------------------------------------------
//Initialize RTC for time delay counter
//-----------------------------------------------
WDCON &=0xE0; //Shut down WDT
RTCH = 0x01; //Set 16bit counter for RTC, about 8.9ms
RTCL = 0xFF;
RTCCON = 0x63; //RTC Enable, CCLK use Internal RC oscillator
EWDRT = 1; //Enable RTC/WD Interrupt
//-----------------------------------------------
//Initialize T0 for PWM
//-----------------------------------------------
TMOD |= 0x02; //Set T0 mode 6
TAMOD |= 0x01; //For PWM, 0x01
TH0 = 255; //Duty cycle = 256 - TH0, for 5v input, set initial charge current very small
AUXR1 |= 0x10; //Enable toggling pin P1.2
TR0 = 1; //Enable T0
//----------------------------------------------------------------------
//Enable the A/D Converter and use the CPU clock as the A/D clock.
//----------------------------------------------------------------------
ADMODA = 0x10; //AD1 single mode no boundary interrupt
ADMODB = 0x40; //AD "40" for CCLK/3, 7.3728/3=2.4576M. "60" for CLK = CCLK/4, 1.8432M, ADC MODE
ADINS = 0xE0; //Enable AD11,AD12,AD13
ADCON1 = 0x04; //Enable AD1 with timer no start occurs mode, no completed & boundary interrupt
}
//***************************************************************************
//* ad_convert()
//* Input(s) :
//* Returns :
//* Description : ad_convert & control action
//***************************************************************************
void ad_convert ()
{
uchar temp = 0;
ADCON1 |= 0x01; //Enable AD convert
while( !(ADCON1 & 0x08) ); //waiting for AD to end
ADCON1 &= ~0x08;
if( average-- == 0) // every x(10) times AD output one result, first judge, second --
{
AD1_1 = AD1_1/10;
AD1_2 = AD1_2/10;
AD1_3 = AD1_3/10;
average = 10;
//-----------------------------------------------
//AD11 for battery voltage detect
//-----------------------------------------------
if( AD1_1 > 176 ) // If Vout > 4.6v
{ // Prevent battery plug out during charging
SCL=0;
Battery_On_Socket = 0; // forbid AD convert, skip <115, <162, <176, until <38
RTC_Counter = 5000; //Delay 15's, then enable AD convert in RTC_Interrupt()
LED_Flash_Speed = LED_FLASH_FAST; // indicate error status-battery not in socket
}
else if( AD1_1 <= 38 ) // If Vout <= 1V, <=(1/3.31*2)*256 = 256/6.66
{
SCL=0; //Set p1.2 = 0, forbid PWM, shut down output
LED_Flash_Speed = LED_FLASH_FAST; // indicate error status
AD1_1 = 0; // digital LED display "000"
} // battery shortage or battery not in socket
else if( AD1_1 <= 115) // If Vout<= 3V, 3 x 256/6.66
{
SCL=1; // Enable P1.2 PWN
TH0 = 250; // preset charge current, for 5v input, about 30-65mA
LED_Flash_Speed = LED_FLASH_SLOW; // indicate charging status
if( Constant_Current_Charge == 0 ) Pre_Charge_Status = 1; // Set Precharge status
}
else if( AD1_1 < 162) // detect Vout = battery voltage + 0.35*0.75
// for fullly charged bat,bat vol=4.24,I limit 20mA, 4.24+0.02*0.75=4.26v
// for protect battery, set Vout = 4.26v (162)
{ // if bat vol=4.2, I will be limited 80mA, 4.2+0.08*0.75=4.26v
// if bat vol=4.15, I will be limited 150mA, 4.15 + 0.15*0.75 = 4.26v
// when cons-current-charging,4.26-0.35*0.75=4.00v, so Vbat>4.00v,enter cons-vol
// when cons-vol-charging, charge I= min 20mA,Vbat= 4.26-0.02*0.75=4.24v
// ( 161-4.252, 162-4.267, 160-4.234 )
SCL=1;
LED_Flash_Speed = LED_FLASH_SLOW; // indicate charging status
if( Constant_Voltage_Charge == 0)
{
Constant_Current_Charge = 1; // Set Constant Current Charge status
Pre_Charge_Status = 0; // forbid Precharge status
}
}
else // If 4.26V < Vout <4.6V
{
SCL=1;
LED_Flash_Speed = LED_FLASH_SLOW; // indicate charging status
Constant_Voltage_Charge = 1; // Set Constant Voltage Charge status
Constant_Current_Charge = 0; // forbid Constant Current Charge status
Pre_Charge_Status = 0; // forbid Precharge status
}
temp = AD1_1;
AD1_1 = 0; // reset AD1_1
//-----------------------------------------------
//AD12 for temperature detect
//-----------------------------------------------
// AD1_2 = AD1_2*83/64; // input x 3.31 x 100 / 256
// First_Bit = AD1_2/100;
// AD1_2 = AD1_2%100;
// Second_Bit = AD1_2/10;
// Third_Bit = AD1_2%10;
// DP_Enable = 0;
AD1_2 = 0; // reset AD1_2
//-----------------------------------------------
//AD13 for charge current detect
//-----------------------------------------------
if( Pre_Charge_Status == 1 )
{
if( ( AD1_3 > 1 ) && ( TH0 < 250 ) ) // ensure Pre-charger current < 65mA
{ TH0++;}
}
else if( Constant_Current_Charge == 1 )
{
if( AD1_3 < 17 ) // 260mv,(I charge = 350mA)
{ // if I charge < 350mA, pwm++
if( TH0 < 2 )
{
TH0 = 1;
if( RTC_Counter == 0 ) //start 20 minutes delay to end charge
{ RTC_Counter = 1; } //this case happened for charged battery,if Vout < 2.6v
//while Ibat can't achieve 350mA, even max PWM
}
else
{ TH0 = TH0 - 1; }
}
else if( AD1_3 > 17)
{ //if I charge > 350mA, pwm--
if( TH0 > 253 )
{ TH0 = 254; }
else
{
TH0 = TH0 + 1;
}
}
}
else if( Constant_Voltage_Charge == 1 )
{
if( AD1_3 <= 1 ) // Charge current is < 60mA
{
if( RTC_Counter == 0 ) { RTC_Counter = 1; } //start 50 minutes delay to end charge
}
if( temp > 160 ) //temp=AD1_1, if Vout is > 4.23v(achieve 4.23v), -- PWM
{
if( TH0 < 255)
{
TH0++;
}
}
else if( temp < 160 ) // if Vout is < 4.21v (achieve 4.21v), ++PWM
{
if( TH0 > 1 )
{
TH0--;
}
}
}
AD1_3 = 0; // reset AD1_3
}
else
{
AD1_1 += AD1DAT1;
AD1_2 += AD1DAT2;
AD1_3 += AD1DAT3;
}
}
//***************************************************************************
//* RTC_Interrupt
//* Input(s) : none.
//* Returns : none.
//* Description : Interrupt from RTC
//***************************************************************************
void RTC_Interrupt (void) interrupt 10 using 1
{
if( RTC_Counter != 0 ) { RTC_Counter++; }
RTC_Counter_LED++;
RTC_Counter_AD++;
if ( RTC_Counter_LED == LED_Flash_Speed)
{
LED_Flag = ~LED_Flag;
RTC_Counter_LED = 0;
}
if ( RTC_Counter_AD == AD_Convert_Speed )
{
AD_Flag = 1;
RTC_Counter_AD = 0;
}
if ( RTC_Counter == 6750) // delay for 1 minute
{
RTC_Counter_Minute++;
RTC_Counter = 1;
if( Battery_On_Socket == 0) // complete 15's delay for battery not in socket
{
Battery_On_Socket = 1;
RTC_Counter = 0;
}
}
RTCCON = 0x63; //Clear RTCCON.7-RTCF
}
/*--------------------------------------------------------------------------
REG916.H
Header file for Philips 89LPC916
--------------------------------------------------------------------------*/
#ifndef __REG916_H__
#define __REG916_H__
/* BYTE Registers */
sfr P0 = 0x80;
sfr P0M1 = 0x84;
sfr P0M2 = 0x85;
sfr P1 = 0x90;
sfr P1M1 = 0x91;
sfr P1M2 = 0x92;
sfr P2 = 0xA0;
sfr P2M1 = 0xA4;
sfr P2M2 = 0xA5;
//------------------
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
//------------------
sfr ADCON1 = 0x97;
sfr ADINS = 0xA3;
sfr ADMODA = 0xC0;
sfr ADMODB = 0xA1;
sfr AD1BH = 0xC4;
sfr AD1BL = 0xBC;
sfr AD1DAT0= 0xD5;
sfr AD1DAT1= 0xD6;
sfr AD1DAT2= 0xD7;
sfr AD1DAT3= 0xF5;
sfr AUXR1 = 0xA2;
sfr BRGR0 = 0xBE;
sfr BRGR1 = 0xBF;
sfr BRGCON = 0xBD;
sfr CMP1 = 0xAC;
sfr CMP2 = 0xAD;
sfr DIVM = 0x95;
sfr FMADRH = 0xE7;
sfr FMADRL = 0xE6;
sfr FMCON = 0xE4;
sfr FMDATA = 0xE5;
sfr I2ADR = 0xDB;
sfr I2CON = 0xD8;
sfr I2DAT = 0xDA;
sfr I2SCLH = 0xDD;
sfr I2SCLL = 0xDC;
sfr I2STAT = 0xD9;
sfr IEN0 = 0xA8;
sfr IEN1 = 0xE8;
sfr IP0 = 0xB8;
sfr IP0H = 0xB7;
sfr IP1 = 0xF8;
sfr IP1H = 0xF7;
sfr KBCON = 0x94;
sfr KBMASK = 0x86;
sfr KBPATN = 0x93;
sfr PCON = 0x87;
sfr PCONA = 0xB5;
sfr PT0AD = 0xF6;
sfr RSTSRC = 0xDF;
sfr RTCCON = 0xD1;
sfr RTCH = 0xD2;
sfr RTCL = 0xD3;
sfr SADDR = 0xA9;
sfr SADEN = 0xB9;
sfr SBUF = 0x99;
sfr SCON = 0x98;
sfr SSTAT = 0xBA;
sfr SPCTL = 0xE2;
sfr SPSTAT = 0xE1;
sfr SPDAT = 0xE3;
sfr TAMOD = 0x8F;
sfr TCON = 0x88;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr TMOD = 0x89;
sfr TRIM = 0x96;
sfr WDCON = 0xA7;
sfr WDL = 0xC1;
sfr WFEED1 = 0xC2;
sfr WFEED2 = 0xC3;
/* BIT Registers */
/* PSW */
sbit CY = PSW^7;
sbit AC = PSW^6;
sbit F0 = PSW^5;
sbit RS1 = PSW^4;
sbit RS0 = PSW^3;
sbit OV = PSW^2;
sbit F1 = PSW^1;
sbit P = PSW^0;
/* TCON */
sbit TF1 = TCON^7;
sbit TR1 = TCON^6;
sbit TF0 = TCON^5;
sbit TR0 = TCON^4;
sbit IE0 = TCON^1;
sbit IT0 = TCON^0;
/* ADMODA */
sbit BNDI1 = ADMODA^7;
sbit BURST1 = ADMODA^6;
sbit SCC1 = ADMODA^5;
sbit SCAN1 = ADMODA^4;
sbit BNDI0 = ADMODA^3;
sbit BURST0 = ADMODA^2;
sbit SCC0 = ADMODA^1;
sbit SCAN0 = ADMODA^0;
/* IEN0 */
sbit EA = IEN0^7;
sbit EWDRT = IEN0^6;
sbit EBO = IEN0^5;
sbit ES = IEN0^4;
sbit ESR = IEN0^4;
sbit ET1 = IEN0^3;
sbit ET0 = IEN0^1;
sbit EX0 = IEN0^0;
/* IEN1 */
sbit EAD = IEN1^7;
sbit EST = IEN1^6;
sbit ESPI = IEN1^3;
sbit EC = IEN1^2;
sbit EKBI = IEN1^1;
sbit EI2C = IEN1^0;
/* IP0 */
sbit PWDRT = IP0^6;
sbit PB0 = IP0^5;
sbit PS = IP0^4;
sbit PSR = IP0^4;
sbit PT1 = IP0^3;
sbit PT0 = IP0^1;
sbit PX0 = IP0^0;
/* P0 */
sbit KB5 = P0^5;
sbit CMPREF = P0^5;
sbit KB4 = P0^4;
sbit CIN1A = P0^4;
sbit KB3 = P0^3;
sbit CIN1B = P0^3;
sbit KB2 = P0^2;
sbit CIN2A = P0^2;
sbit KB1 = P0^1;
sbit CIN2B = P0^1;
/* P1 */
sbit RST = P1^5;
sbit INT0 = P1^3;
sbit SDA = P1^3;
sbit T0 = P1^2;
sbit SCL = P1^2;
sbit RxD = P1^1;
sbit TxD = P1^0;
/* P2 */
sbit SPICLK = P2^5;
sbit SS = P2^4;
sbit MISO = P2^3;
sbit MOSI = P2^2;
/* SCON */
sbit SM0 = SCON^7;
sbit FE = SCON^7;
sbit SM1 = SCON^6;
sbit SM2 = SCON^5;
sbit REN = SCON^4;
sbit TB8 = SCON^3;
sbit RB8 = SCON^2;
sbit TI = SCON^1;
sbit RI = SCON^0;
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -