?? liion_bc_main.c
字號:
// voltage in mV, and temperature in C, 2% accurate.
//
int Monitor_Battery(unsigned char value)
{
char i;
unsigned long av =0;
long signed result;
ADC0CF = (SYSCLK/5000000) << 3; // ADC conversion clock = 5.0MHz
ADC0CF &= 0xF8; // Clear any Previous Gain Settings
switch (value)
{
case TEMPERATURE:
Turn_PWM_Off(); // Turn PWM Off
AMX0SL = TBAT; // Select appropriate input for AMUX
ADC0CF |= 0x02; // Set PGA gain = 2
break;
case VOLTAGE:
AMX0SL = VBAT; // Select appropriate input for AMUX
ADC0CF |= 0x01; // Set PGA gain = 1
break;
case VOLTAGE_PWM_OFF:
Turn_PWM_Off(); // Turn PWM Off
AMX0SL = VBAT; // Select appropriate input for AMUX
ADC0CF |= 0x01; // Set PGA gain = 1
break;
case CURRENT:
AMX0SL = IBAT; // Select appropriate input for AMUX
ADC0CF |= 0x03; // Set PGA gain = 4
break;
}
//Compute average of next 10 A/D conversions
for(av=0,i=10;i;--i){
AD0INT = 0; // clear end-of-conversion indicator
AD0BUSY = 1; // initiate conversion
while(!AD0INT); // wait for conversion to complete
av = av+ADC0;
}
av = av/10; // Compute the average
av = av<<8; // Convert to 16-bit conversion
// ...to account for 16-bit cal.
// coefficients
PCA0CPM0 = 0x42; // Turn on PWM
switch (value)
{ case TEMPERATURE:
result = (long) av * 1000/TEMP_SLOPE;
break;
case VOLTAGE:
case VOLTAGE_PWM_OFF:
result = (av - VOLT_OFFSET.l); // Account for System Errors
result /= VOLT_SLOPE.l; // Convert to Voltage in Millivolts
result *= 100; // Account for Math Truncation Error
result *= RESAB; // Account for Divide Resistors
result /= RESB;
break;
case CURRENT:
result = av*2; // Account for Differential Mode
result -= I_NOAMP_OFFSET.l; // Account for System Errors
result /= I_NOAMP_SLOPE.l; // Convert to Milliamps
result *= 100; // Account for Math Truncation Error
result /= RSENSE; // Account for Sense Resistor
result *= RESAB; // Account for Divide Resistors
result /= RESB;
result /= CURRENT_GAIN;
break;
}
return (int) result;
}
//-----------------------------------------------------------------------------
// Bulk_Charge Function
//-----------------------------------------------------------------------------
void Bulk_Charge(void)
{
unsigned int temp = 0;
unsigned int bulk_finish_hour = 0;
unsigned int bulk_finish_min = 0;
unsigned int delay_hour = 0;
unsigned int delay_min = 0;
unsigned int last_min = 0;
Reset_Time_Base(); // Reset Time Base to zero
// Calculate BULK charge finish time
bulk_finish_min = (TIME.min + MAX_TIME_BULK);
bulk_finish_hour = TIME.hour;
while (bulk_finish_min > 60)
{
bulk_finish_min = bulk_finish_min - 60;
bulk_finish_hour++;
}
CONST_C = 1; // Start in constant current charge mode
DELAY = 0; // Reset timer DELAY
temp = Monitor_Battery(TEMPERATURE); // Monitor Temperature
// Is temperature within range?
if ((temp > MIN_TEMP_ABS) && (temp < MAX_TEMP_ABS))
{
temp = Monitor_Battery(VOLTAGE); // Monitor Voltage
// Is Voltage within range?
if ((temp <= (MAX_VOLT_ABS + VOLT_TOLERANCE)) && temp > MIN_VOLT_BULK)
{
PCA0CPM0 = 0x42; // Configure CCM0 to 8-bit PWM mode
// Enter main loop in Bulk_Charge()
while ((BULK == 1) && (ERROR == 0))
{
if (CONST_C == 1)
Regulate_Current(I_BULK); // Charge with Constant Current
else if (CONST_V == 1)
Regulate_Voltage(); // Charge with Constant Voltage
// Now, Check for error and charge termination conditions
// If above max charge time, flag error
// Test for BULK Charge Time Out
// Monitor Time
if ((TIME.hour == bulk_finish_hour) && (TIME.min == bulk_finish_min)
&& (DELAY == 0))
{
Turn_PWM_Off(); // Turn Off PWM
TIME_MAX = 1; // Set Time max error flag
ERROR = 1; // Set general error flag
}
// Monitor Temperature
temp = Monitor_Battery(TEMPERATURE);
if ((temp < MIN_TEMP_ABS) && (temp > MAX_TEMP_ABS))
{
Turn_PWM_Off(); // Turn Off PWM
if (temp < MIN_TEMP_ABS)
TEMP_MIN = 1; // Set Temperature below minimum flag
else
TEMP_MAX = 1; // Set Temperature exceeds maximum flag
ERROR = 1; // Set general error flag
}
// Minute elapsed?
// Check for minimum current
// if reached, enter last DELAY charge
if (TIME.min != last_min)
{
last_min = TIME.min;
if ((CONST_V == 1) && (DELAY == 0) && (Monitor_Battery(CURRENT)
<= MIN_I_BULK))
{
// Calculate TOP OFF Battery Time finish time
delay_min = (TIME.min + BULK_TIME_DELAY);
delay_hour = TIME.hour;
while (delay_min > 60)
{
delay_min = delay_min - 60;
delay_hour++;
}
DELAY = 1; // Set Delay Flag
}
// Monitor Delay time, time up?
if ((TIME.hour == delay_hour)&&(TIME.min == delay_min) &&
(DELAY == 1))
{
Turn_PWM_Off(); // Turn Off PWM
CONST_V = 0; // Exit CONST_V
CONST_C = 1; // Prepare to enter CONST_C
BULK = 0; // Prepare to exit BULK mode
LOWCURRENT = 1; // Prepare to enter LOWCURRENT Mode
}
}
} // End Main While loop
}
else if(ERROR == 0)
{
if (temp > (MAX_VOLT_ABS + VOLT_TOLERANCE))
{ VOLT_MAX = 1; // Set Max Voltage error flag
ERROR = 1; // Set general error flag
}
else if(temp < MIN_VOLT_BULK)
{ VOLT_MIN = 1; // Set Minimum bulk voltage error flag
LOWCURRENT = 1; // Switch to LOWCURRENT mode
BULK = 0; // Exit Bulk Charge mode
} // battery's voltage very low
}
}
else if(ERROR == 0) // Absolute temperature out of range?
{
if (temp < MIN_TEMP_ABS)
TEMP_MIN = 1; // Set Temperature below minimum flag
else
TEMP_MAX = 1; // Set Temperature exceeds maximum flag
ERROR = 1; // Set general error flag
}
}
//-----------------------------------------------------------------------------
// Lowcurrent_Charge
//-----------------------------------------------------------------------------
void Lowcurrent_Charge(void)
{
unsigned int temp = 0;
unsigned int lowcurrent_finish_min = 0;
unsigned int lowcurrent_finish_hour = 0;
Reset_Time_Base(); // Reset Time base to zero
// Calculate LOWCURRENT finish time
lowcurrent_finish_min = (TIME.min + MAX_TIME_LOWCURRENT);
lowcurrent_finish_hour = TIME.hour;
while (lowcurrent_finish_min > 60)
{
lowcurrent_finish_min = lowcurrent_finish_min - 60;
lowcurrent_finish_hour++;
}
// Enter Main Lowcurrent Loop.
// Only exits are upon error and full charge
while ((LOWCURRENT == 1) && (ERROR == 0))
{
temp = Monitor_Battery(TEMPERATURE);// Get Temperature Reading
// Is TEMPERATURE within limits
if ((temp > MIN_TEMP_ABS) && (temp < MAX_TEMP_ABS))
{
// Is Battery's Charge Voltage below max charge voltage
temp = Monitor_Battery(VOLTAGE); // Get Voltage Reading
if (temp <= (VOLT_LOWCURRENT + VOLT_TOLERANCE))
{
if (CONST_C == 1) // CONST_C ?, charge w/ constant current
Regulate_Current(I_LOWCURRENT);
if (CONST_V == 1) // CONST_V?, charge w/ constant voltage
Regulate_Voltage();
if ((temp >= MIN_VOLT_BULK) && (DELAY == 0))// Bulk Threshold voltage met?
{ LOWCURRENT = 0; // Exit LOWCURRENT mode
BULK = 1; // Switch to Bulk Charge mode
}
// Check elapsed time
if ((TIME.hour == lowcurrent_finish_hour) &&
( TIME.min == lowcurrent_finish_min))
{
TIME_MAX = 1; // Set Time MAX error flag
ERROR = 1; // Set general error flag
}
}
else if(ERROR == 0) // Voltage to high?
{
VOLT_MAX = 1; // Set Max voltage error flag
ERROR = 1; // Set general error flag
}
}
else if(ERROR == 0) // Absolute temperature out of range?
{
if (temp < MIN_TEMP_ABS)
TEMP_MIN = 1; // Set Temperature below minimum flag
else
TEMP_MAX = 1; // Set Temperature exceeds maximum flag
ERROR = 1; // Set general error flag
}
}
}
//-----------------------------------------------------------------------------
// Main Function
//-----------------------------------------------------------------------------
void main(void)
{
EA = 0; // Disable All Interrupts
Reset_Time_Base();
Config_F300(); // Config F300
CalibrateADCforMeasurement(); // Calibrate F300
EA = 1; // Enable All Active Interrupts
while(1)
{
LED0 = 0; // Turn LED0 off
TERMINATION = 0x00; // Reset Termination Flags
CHARGE_STATUS = 0x00; // Reset Charge Status Flags
BULK = 1; // Start in LOWCURRENT Charge mode
CONST_C = 1;
while (SW0 == 1); // Wait until SW0 pushed
Delay_Loop(); // Wait for Switch Bounce
while (ERROR == 0)
{
if (BULK == 1)
{
LED0 = 1; // Turn LED0,indicates Bulk Mode
Bulk_Charge(); // Enter Bulk Charge Mode
}
if (LOWCURRENT == 1)
Lowcurrent_Charge(); // Enter Lowcurrent_Charge function
// Toggle LED0 at 1 Hz rate via ISR
}
if (ERROR == 1)
{
Turn_PWM_Off();; // Turn PWM Off
LED0 = 0; // Turn OFF LED0 to indicate "ERROR".
EA = 0; // Disable All Interrupts
while (1); // Enter a eternal loop
// No recovery except "reset-button"
}
}
}
//-----------------------------------------------------------------------------
// PCA_ISR
//-----------------------------------------------------------------------------
// This routine counts the elapsed time in seconds, minutes, hours.
// It also toggles LED0 every second when in Lowcurrent Charge Mode.
// This routine interrupts every time the PCA counter overflows, every 256
// SYSCLK cycles. After SYSCLK/256 interrupts, one second has elapsed.
//
void PCA_OVERFLOW_ISR (void) interrupt 9
{
PCA0CN = 0x40; // Reset all PCA Interrupt Flags
PCA0H = 0x00; // Reset High Byte of PCA Counter
// of 8-bit PWM we are using Module1
if (0x0000 == --TIME.t_count)
{
TIME.t_count = PWM_CLOCK; // Reset 1 Second Clock
if ( 60 == ++TIME.sec ) // Account for elapsed seconds
{ // Reset second counter every minute
TIME.sec = 0x00;
if ( 60 == ++TIME.min ) // Account for elapsed minutes
{ // Reset minute counter every hour
TIME.min = 0x00;
if ( 24 == ++TIME.hour ) // Account for elapsed hours
TIME.hour = 0x00; // Reset hour counter every day
}
}
if ((LOWCURRENT == 1) && (ERROR == 0))
{ // Blink LED0 at 1 Hz if in Lowcurrent
if (TIME.sec % 2)
LED0 = 0; // Turn on LED every odd second
else
LED0 = 1; // Turn on LED every even second
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -