?? liion_bc_main.c
字號:
//-----------------------------------------------------------------------------
//
// Copyright 2002 Cygnal Integrated Products, Inc.
//
// Filename: LIION_BC_MAIN.c
// Target Device: 8051F300
// Created: 11 SEP 2002
// Created By: DKC
// Tool chain: KEIL Eval C51
//
// This is a stand alone battery charger for a Lithium ION battery.
// It utilizes a buck converter, controlled by the on-chip 8-bit PWM,
// to provide constant current followed by constant voltage battery charge.
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f300.h>
#include "LIION_BC_MAIN.h" // Battery Hearder File
//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------
void Config_F300(void)
{ RSTSRC = 0x02; // Enable VDD Monitor
XBR0 = 0x70; // Skip P0.4,5,6; they're analog In
XBR1 = 0x44; // Enable SMBus on P0.0, P0.1, and CEX0
XBR2 = 0x40; // as PWM at P0.2
// Enable crossbar and weak pull-ups
P0MDOUT = 0x0C; // Set P0.2 & P0.3 output to push-pull
P0MDIN = 0x8F; // Configure P0.4,5,6 as Analog Inputs
OSCICN = 0x07; // Set SYSCLK to 24.5MHz, internal osc.
ADC0CN = 0xC0; // Turn on the ADC Module;
// enable low power mode for settling
REF0CN = 0x0C; // Configure ADC's to use VDD for
// Voltage Reference,
// Enable On-chip Temperature Sensor
//-----------------------------------------------------------------------------
// PCA Configuration
//-----------------------------------------------------------------------------
PCA0MD = 0x00; // Disable WDT
PCA0MD = 0x08; // Set PWM Time base = SYSCLK
PCA0L = 0x00; // Initialize PCA Counter to Zero
PCA0H = 0x00;
PCA0CN = 0x40; // Enable PCA Counter
// Clear PCA Counter Overflow flag
//Module 0
PCA0CPM0 = 0x00; // Configure CCM0 to 8-bit PWM mode
PCA0CPL0 = 0xF0; // Initialize PCA PWM to small duty cycle
PCA0CPH0 = 0xF0; // 0xF0 Ensures a Soft Initial Charge
//Module 1
PCA0CPM1 = 0x49; // Configure Module 1 as software timer
PCA0CPL1 = 0xFF; // Initialize to 255 so that Interrupt
// is generated when PCA ends
// 8-bit PWM Cycle
PCA0CPH1 = 0x00; // PCA0CPH is the high byte of the
// Output Compare Module
EIE1 = 0x08; // Enable PCA Overflow Interrupt
}
//-----------------------------------------------------------------------------
// Reset_Time_Base - Resets all Time Counting Values
//-----------------------------------------------------------------------------
void Reset_Time_Base()
{
TIME.sec = 0x00;
TIME.min = 0x00;
TIME.hour = 0x00;
TIME.t_count = PWM_CLOCK;
}
//-----------------------------------------------------------------------------
// Delay - This is a Delay to permit time for Switches to Debounce
//-----------------------------------------------------------------------------
void Delay_Loop (void)
{
long i=0;
for (i=0;i<100000;i++);
}
//-----------------------------------------------------------------------------
// Initialize CalibrateADCforVoltageMeasurement
//-----------------------------------------------------------------------------
// This function calibrates the voltage channel and stores the calibration
// coefficients in the parameters volt_slope and volt_offset.
//
void CalibrateADCforMeasurement()
// This calibration routine uses a 2 point cal.
{ unsigned char xdata *pwrite; // FLASH write pointer
EA = 0; // Disable All Interrupts
// Wait until 1st calibration voltage is ready for cal
while (SW0 == 1); // Wait until SW0 pushed
Delay_Loop(); // Wait for Switch Bounce
// Once ready, Get the first calibration voltage
AMX0SL = VBAT; // Select appropriate input for AMUX
ADC0CF = (SYSCLK/5000000) << 3; // ADC conversion clock = 5.0MHz
ADC0CF &=0xF8; // Clear any Previous Gain Settings
ADC0CF |= 0x01; // PGA gain = 1
temp_INT_1.i = Measure();
// Wait until 2nd calibration voltage is ready for cal
while (SW0 == 1); // Wait until SW0 pushed
Delay_Loop(); // Wait for Switch Bounce
// Once ready, Get the 2nd calibration voltage
AMX0SL = VBAT; // Change Mux for second point
temp_INT_2.i = Measure();
// Calculate the SLOPE // V1 and V2 are in tenth of a degree
temp_LONG_1.l = (unsigned)(temp_INT_2.i-temp_INT_1.i);
temp_LONG_1.l *= (unsigned)100; // Account for Math Truncation Error
temp_LONG_1.l /= (unsigned)(V2_CAL - V1_CAL);
// Calculate the OFFSET
temp_LONG_2.l = (unsigned)temp_INT_1.i;
temp_LONG_2.l -= (signed)(temp_LONG_1.l * V1_CAL/100);
temp_LONG_1.l = 2050; // If no cal. use these
temp_LONG_2.l = 0; // as default values
// Erased memory at page 0x1A00
pwrite = (char xdata *)&(CHECK_BYTE.b[0]);
PSCTL = 0x03; // MOVX writes target FLASH memory;
// FLASH erase operations enabled
FLKEY = 0xA5; // FLASH key sequence #1
FLKEY = 0xF1; // FLASH key sequence #2
*pwrite = 0x00; // initiate PAGE erase
// Write the Volt SLOPE and OFFSET to Flash
PSCTL = 1; // MOVX writes to Flash
pwrite = (char xdata *)&(VOLT_SLOPE.b[0]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_1.b[0];
pwrite = (char xdata *)&(VOLT_SLOPE.b[1]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_1.b[1];
pwrite = (char xdata *)&(VOLT_SLOPE.b[2]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_1.b[2];
pwrite = (char xdata *)&(VOLT_SLOPE.b[3]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_1.b[3];
pwrite = (char xdata *)&(VOLT_OFFSET.b[0]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_2.b[0];
pwrite = (char xdata *)&(VOLT_OFFSET.b[1]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_2.b[1];
pwrite = (char xdata *)&(VOLT_OFFSET.b[2]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_2.b[2];
pwrite = (char xdata *)&(VOLT_OFFSET.b[3]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_2.b[3];
PSCTL = 0; // MOVX writes target XRAM
//-----------------------------------------------------------------------------
// Initialize CalibrateADCforCurrentMeasurement_NOAMP
//-----------------------------------------------------------------------------
// This function calibrates the current channel with no external amp
// and stores the calibration coefficients in the
// parameters i_noamp_slope and i_noamp__offset.
//
// This calibration routine uses a 2 point cal.
// Wait until calibration voltage is ready for cal
while (SW0 == 1); // Wait until SW0 pushed
Delay_Loop(); // Wait for Switch Bounce
// Once ready, Get the first calibration voltage
AMX0SL = IBAT; // Select appropriate input for AMUX
ADC0CF = (SYSCLK/5000000) << 3; // ADC conversion clock = 5.0MHz
ADC0CF &=0xF8; // Clear any Previous Gain Settings
ADC0CF |= 0x03; // Set PGA gain = 4
temp_INT_1.i = Measure(); // Acquire 16-bit Conversion
temp_INT_1.i *= 2; // Account for Differential Mode
// Wait until 2nd calibration voltage is ready for cal
while (SW0 == 1); // Wait until SW0 pushed
Delay_Loop(); // Wait for Switch Bounce
// Once ready, Get the 2nd calibration voltage
temp_INT_2.i = Measure(); // Acquire 16-bit Conversion
temp_INT_2.i *=2; // Account for Differential Mode
// Calculate the SLOPE
temp_LONG_1.l = (unsigned)(temp_INT_2.i - temp_INT_1.i);
temp_LONG_1.l *= (unsigned)100; // Account for Math Truncation Error
temp_LONG_1.l /= (unsigned)(I2_CAL - I1_CAL);
temp_LONG_1.l /= (unsigned)CURRENT_GAIN;// Account for Gain
// Calculate the OFFSET
temp_LONG_2.l = (signed)(temp_INT_1.i/CURRENT_GAIN);
temp_LONG_2.l -= (signed)(temp_LONG_1.l * V1_CAL/100);
temp_LONG_1.l = 2050; // If no cal. use these
temp_LONG_2.l = 0; // as default values
// Memory at 0x1A00 is already erased
// Write the Volt SLOPE and OFFSET to Flash
PSCTL = 1; // MOVX writes to Flash
pwrite = (char xdata *)&(I_NOAMP_SLOPE.b[0]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_1.b[0];
pwrite = (char xdata *)&(I_NOAMP_SLOPE.b[1]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_1.b[1];
pwrite = (char xdata *)&(I_NOAMP_SLOPE.b[2]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_1.b[2];
pwrite = (char xdata *)&(I_NOAMP_SLOPE.b[3]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_1.b[3];
pwrite = (char xdata *)&(I_NOAMP_OFFSET.b[0]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_2.b[0];
pwrite = (char xdata *)&(I_NOAMP_OFFSET.b[1]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_2.b[1];
pwrite = (char xdata *)&(I_NOAMP_OFFSET.b[2]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_2.b[2];
pwrite = (char xdata *)&(I_NOAMP_OFFSET.b[3]);
FLKEY = 0xA5;
FLKEY = 0xF1; // enable flash write
*pwrite = temp_LONG_2.b[3];
PSCTL = 0; // MOVX writes target XRAM
}
//-----------------------------------------------------------------------------
// Measure
//-----------------------------------------------------------------------------
//
// This routine averages 65536 ADC samples and returns a 16-bit unsigned
// result.
//
unsigned int Measure (void)
{
unsigned i; // sample counter
unsigned long accumulator=0L; // here's where we integrate the
// ADC samples
// read the ADC value and add to running total
i = 0;
do {
AD0INT = 0; // clear end-of-conversion indicator
AD0BUSY = 1; // initiate conversion
while(!AD0INT); // wait for conversion to complete
accumulator += ADC0; // read adc value and accumulate
i++; // update counter
} while (i != 0x0000);
// the accumulator now contains 16 added bits of which 8 are usable
return (unsigned int) (accumulator >> 8);
}
//-----------------------------------------------------------------------------
// Regulate_Current
//-----------------------------------------------------------------------------
// This routine monitors the battery's current and adjusts
// the PWM (i.e. duty cycle) to keep the current at a known value
//
void Regulate_Current(int passed_current)
{ unsigned int temp = 0;
do{
temp = Monitor_Battery(CURRENT); // Measure Current
if (temp < passed_current)
PCA0CPH0--;
if (temp > passed_current)
PCA0CPH0++;
}while ((temp < (passed_current - CURRENT_TOLERENCE)) ||
(temp > (passed_current + CURRENT_TOLERENCE)));
// I_BULK or I_LOWCURRENT is set now
temp = Monitor_Battery(VOLTAGE_PWM_OFF);
// If VOLTAGE within range,
// change from constant CURRENT charge
// mode to constant VOLTAGE charge mode
if ((temp >= (VOLT_LOWCURRENT - VOLT_TOLERANCE)) &&
(temp <= (VOLT_LOWCURRENT + VOLT_TOLERANCE)))
{
CONST_C = 0;
CONST_V = 1;
}
}
//-----------------------------------------------------------------------------
// Regulate_Voltage
//-----------------------------------------------------------------------------
// This routine monitors the battery's voltage and adjusts
// the PWM (i.e. duty cycle) to keep the voltage at a known value
//
void Regulate_Voltage(void)
{ unsigned int temp = 0;
// set VOLT_BULK (with "soft start")
do{
temp = Monitor_Battery(VOLTAGE);
if (temp < VOLT_BULK)
PCA0CPH0--;
if (temp > VOLT_BULK)
PCA0CPH0++;
}while ((temp < (VOLT_BULK - VOLT_TOLERANCE)) ||
(temp > (VOLT_BULK + VOLT_TOLERANCE)));
// VOLTAGE is set now
}
//-----------------------------------------------------------------------------
// Turn_PWM_Off
//-----------------------------------------------------------------------------
// This routine peforms a soft charge turn off by taking the PWM's
// duty cycle slowly to zero.
//
void Turn_PWM_Off(void)
{
do{
if (PCA0CPH0 < 0xF0)
PCA0CPH0++;
}while (PCA0CPH0 < 0xF0);
// Duty Cycle is now small and safe to turn off.
PCA0CPM0 = 0x00; // Disable PWM
}
//-----------------------------------------------------------------------------
// Monitor_Battery
//-----------------------------------------------------------------------------
// This routine acts as a switch when gathering different conversion types.
// It adjusts the throughput, adjust the AMUX and returns the current in mA,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -