Part Number: MSP430F5132
Other Parts Discussed in Thread: PMP
Hi,
We are using PMP 7647 reference design for our solar street light application.
We have been doing testing with the break point and to complete, Can you please support us to clarify the following?
------------------------------------------------------------ Code ------------------------------------------------------------------------------------------
#pragma vector = DMA_VECTOR
__interrupt void DMA0_ISR (void)
{
switch(__even_in_range(DMAIV,16))
{
case 0: break; // No interrupt (No conversion)
case 2:
// Sequence of conversions complete, Interrupt due to channel 0
ADC10CTL0 &= ~ADC10ENC; // Disabled Conversion
Panel_Voltage_Buffer += ADC_Readings [P_V];
Battery_Voltage_Buffer += ADC_Readings [B_V];
Battery_Charging_Current_Buffer += ADC_Readings [B_I];
Load_Voltage_Buffer += ADC_Readings [L_V];
Load_Current_Buffer += ADC_Readings [L_I];
Avg_LOAD_Counter++;
Avg_MPPT_Counter++;
-----------------------------------------------------------------------------------------------------------------------------------------------------------
- When this interrupt DMA0_ISR will occur?
- Functions of this interrupt?
Source code attached for your inputs.
Thanks in advance.
Regards,
Rajesh.
/* PMP7647
*MSP430F5132 - 12A MPPT CHARGER AND LED DRIVER(12 LEDS,700mA)*/
/* Formulae to calculate ADC readings of different system parameters :
* Panel Voltage = 36.83 * PV - 63 ,
* Battery Voltage = BV * 52.44 ,
* Battery Current = BI * 82
* Load Current = LI * 278.25
* Load Voltage = LV * 13.61 */
//Header Files//
#include "msp430f5132.h"
#include "hal_tlv.h"
#define CALTDH0CTL1_256 *((unsigned int *)0x1A36)
#define TURN_OFF_BUCK_STAGE TD0CCTL1 = TD0CCTL2 = OUTMOD_0
#define TURN_ON_BUCK_STAGE TD0CCTL1 = OUTMOD_3; \
TD0CCTL2 = OUTMOD_7;
#define TURN_ON_BOOST_STAGE TD1CCTL1 = OUTMOD_7
#define TURN_OFF_BOOST_STAGE TD1CCTL1 = OUTMOD_0
#define TURN_OFF_TIMER_A TA0CTL &= ~MC_1
#define TURN_ON_TIMER_A TA0CTL |= MC_1 ;\
ms = sec = min = 0;
#define CC_LIMIT 615 // 984 for 12A of 7647 board, 615 for 6A of 7646 board
#define CC_TO_CV_LIMIT 745 // boost voltage 14.2V
#define FLOAT_VOLTAGE 724 //float voltage 13.8v
//Definitions//
#define PANEL_ENABLE P3OUT &= ~BIT3 //RESET TO ENABLE PANEL***P3.3
#define PANEL_DISABLE P3OUT |= BIT3 //SET TO DISABLE PANEL
#define LOAD_ENABLE P3OUT &= ~BIT2 //RESET TO ENABLE LOAD***P3.2
#define LOAD_DISABLE P3OUT |= BIT2 //SET TO DISABLE LOAD
#define GATE_DRIVE_ENABLE PJOUT |= BIT6 //SET TO ENABLE OTHER IC'S***PJ.6
#define GATE_DRIVE_DISABLE PJOUT &= ~BIT6 //RESET TO DISABLE OTHER IC'S
//Index of respective elements in adc output array
#define P_V 4
#define B_V 3
#define B_I 2
#define L_V 1
#define L_I 0
#define REF_AVG_LOAD_COUNTER 4
#define REF_AVG_MPPT_COUNTER 64
#define REF_AVG_STANDBY_COUNTER 32 // 8 seconds in standby mode
#define MPPT_LOOP_EXIT_LIMIT 200 // 1 second
#define MINUTES 1 //MINUTES to provide more flexibility in terms of durations
#define REF_LOAD_CURRENT_FULL_BRIGHTNESS 143 // (195 for 700mA , 5 offset for 7647 board) ,143 for 350mA 7646 board
#define REF_LOAD_CURRENT_HALF_BRIGHTNESS 75 //( 97 for 350mA , 5 offset for 7647 board) , 75 for 170mA 7646 board
#define REF_LOAD_CURRENT_LOW_BRIGHTNESS 10 // 30 for 100mA
#define SUFFICIENT_PANEL_VOLTAGE 490 //15V; To turn off the load; charge battery
#define PANEL_UPPER_LIMIT 842 // 24.6V to turn off the PWM to buck stage mosfet; protection purpose
#define DUTY_BUCK_LOWER_THRESHOLD 50 //97.5%
#define DUTY_BUCK_UPPER_THRESHOLD 1600
#define OC_TRIGGERED_COUNTER_THRESHOLD 1000 // 5 seconds delay , 5.2ms per average
#define OV_TRIGGERED_COUNTER_THRESHOLD 1000 // 5 seconds delay ,5.2ms per average
#define MPPT_STATE 0
#define STAND_BY_STATE 1
#define LOAD_MANAGEMENT_STATE 2
#define START_MPPT_STATE 3
#define START_STANDBY_STATE 4
#define START_LOAD_MANAGEMENT_STATE 5
//Variable declaration//
unsigned int ADC_Readings [5],
System_reset_Mode_ON, Load_Monitor_Mode_ON, // Flags for comparator ISR
OC_Triggered = 0, OC_Triggered_Counter = 0,// Flags for over load current protection
OV_Triggered = 0, OV_Triggered_Counter = 0,// Flags for over load voltage protection
Load_On = 0,
Charge_On = 0,
CV_Mode = 0,
cc_to_cv = 0,
Wait_State=0,
Wait_Counter=0,
Battery_Low_Current_Counter=0;
int MPPT_Direction=1,LPM3_On = 0;
// counters to count for 5hours (Programmable for any time), TIMER A
unsigned long Panel_Voltage,
Battery_Voltage,
Load_Voltage,
Battery_Charging_Current=0,
Load_Current, //inputs to the microcontroller
Prev_Battery_Charging_Current=0, //comparison purpose
Prev_Load_Voltage,
Duty_Buck = 400, // 80% duty cycle
Ref_Load_Current = 0, // to be initialised according to the output current
Panel_Voltage_Buffer = 0,
Battery_Voltage_Buffer = 0,
Load_Voltage_Buffer = 0,
Battery_Charging_Current_Buffer = 0,
Load_Current_Buffer = 0,
Duty_Boost = 100,
MPPT_Loop=1,
MPP_Loop_Exit_Counter=0,
CC_Loop_Exit_Counter=0;
//Average counter and reference counter
unsigned int Avg_MPPT_Counter = 0,
Avg_LOAD_Counter = 0;
int Present_State;
int ms=0,sec=0,min=0;
void Init_Clocks (void);
void SetVcoreUp (unsigned int level);
void init_IO (void);
void init_WDT (void);
void init_ADC (void);
void MPPT (void);
void init_TimerD_BUCK (void);
void init_TimerD_BOOST (void);
void init_TimerA (void);
void Load_Management (void);
void PI_Control (void);
void init_Comparator_LoadMonitor (void);
void init_Comparator_System_Reset (void);
void Battery_Charge_Profiling(void);
void init_WDTLowpowermode3 (void);
void Average_LOAD_ADC_Values(void);
void Average_MPPT_ADC_Values(void);
void Average_STANDBY_ADC_Values();
void main (void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
_delay_cycles(2000000);
Init_Clocks (); // Initialize clocks for 25 MHz
__bis_SR_register(GIE); // Enable Interrupts
init_IO ();
init_ADC ();
init_TimerD_BUCK ();
init_TimerD_BOOST ();
init_TimerA ();
// just for testing
P3DIR |=BIT6;
P3OUT |= BIT6;
P2DIR |=BIT5;
P2OUT |= BIT5;
init_WDT ();// set the ADC sampling interval to 1.3ms
GATE_DRIVE_DISABLE;
TURN_OFF_BUCK_STAGE;
TURN_OFF_BOOST_STAGE;
LOAD_DISABLE;
// Present_State = START_LOAD_MANAGEMENT_STATE;
Present_State = START_MPPT_STATE;
while(1)
{
switch(Present_State)
{
case MPPT_STATE :
if(Avg_MPPT_Counter == REF_AVG_MPPT_COUNTER)
{
Average_MPPT_ADC_Values();
// Battery_Voltage = 512 corresponds to approximately 10.2v
// (((panel_voltage+63)/36.83) > ((Battery_Voltage/ 50.25))) => this expression is to get actual values of BV and PV
if(/*(Panel_Voltage > SUFFICIENT_PANEL_VOLTAGE) && (((Panel_Voltage+63)/36.83) > ((Battery_Voltage/ 50.25))) &&*/(Battery_Voltage > 512)&&(Panel_Voltage < PANEL_UPPER_LIMIT)&&(!Wait_State))
{
PANEL_ENABLE;
TURN_ON_BUCK_STAGE;
if(MPPT_Loop == 1)
MPPT();
else
Battery_Charge_Profiling();
// update timers
TD0CCTL0 &= ~CCIFG; // wait till the timer completes its current cycle
while(!(TD0CCTL0 & CCIFG));
TD0CCR1 = Duty_Buck;
TD0CCR2 = Duty_Buck - 60;
}//end if
// value 10 corresponds to approximately .12A
if (((Battery_Charging_Current < 10)&&(!Wait_State))||(Panel_Voltage > PANEL_UPPER_LIMIT))
{
Battery_Low_Current_Counter++;
if((Battery_Low_Current_Counter>10)||(Panel_Voltage > PANEL_UPPER_LIMIT))
{
TURN_OFF_BUCK_STAGE;
PANEL_DISABLE;
Duty_Buck=400; // 80%
Wait_State =1;
Wait_Counter =0;
// if PV<upper limit , then BI is low bcz PV<15
if(Panel_Voltage < PANEL_UPPER_LIMIT)
{
Present_State = START_STANDBY_STATE;
}
}
}
else if((Battery_Charging_Current > 9))
{
// reset counter once the battery current comes up
Battery_Low_Current_Counter=0;
}
/* This block generates approximately 5 seconds delay
* Whenever battery current goes below a threshold value or panel voltage goes above upper limit
* panel is switched off and restarted after 5 seconds*/
if(Wait_State==1)
{
Wait_Counter++;
if(Wait_Counter > 100)
{
Wait_State =0;
Wait_Counter =0;
Battery_Low_Current_Counter=0;
}
}
}// end of MPPT state
break;
case STAND_BY_STATE :
if(Avg_MPPT_Counter == REF_AVG_STANDBY_COUNTER)
{
Average_STANDBY_ADC_Values();
if(Panel_Voltage > 490) // PV>15v
{
// GATE_DRIVE_ENABLE;
// Present_State = START_MPPT_STATE;
//system reset
PMMCTL0 |=PMMSWBOR; // Brown out reset by software
}
else if(Panel_Voltage < 125) // PV<5v
{
//enable timer D for buck and boost
TD0CTL0 |= MC_1;TD1CTL0 |= MC_1;
LOAD_DISABLE;
PANEL_DISABLE;
GATE_DRIVE_ENABLE;
Present_State = START_LOAD_MANAGEMENT_STATE;
Load_On=0;
}
else
{
Present_State =STAND_BY_STATE;
LPM3_On=1;
__bis_SR_register(LPM3);
}
}// end of stand-by state block
break;
case START_MPPT_STATE :
{
//testing to indicate state change
P2OUT |=BIT5;
init_WDT(); // set the ADC sampling interval to 1.3ms
// try to estimate initial duty cycle
// ratio =(((float)Battery_Voltage/ 52.44)/(((float)Panel_Voltage+63)/36.83));
// Duty_Buck=(1-ratio)*2000;
Duty_Buck=400;
MPPT_Direction=1;
GATE_DRIVE_ENABLE;
Present_State =MPPT_STATE;
} // end of start mppt state
break;
case START_STANDBY_STATE :
{
//testing to indicate state change
P2OUT &= ~BIT5;
init_WDTLowpowermode3(); // change the ADC sampling interval from 1.3ms to .25s
GATE_DRIVE_DISABLE;
//for low standby current
PANEL_ENABLE;
LOAD_ENABLE;
CBCTL1 &= ~CBON; // switch off the comparator to save power
//disable timer D to save power
TD0CTL0 &= ~MC_1;TD1CTL0 &= ~MC_1;
Present_State = STAND_BY_STATE;
}// end of start standby state
break;
case LOAD_MANAGEMENT_STATE :
if(Avg_MPPT_Counter == REF_AVG_MPPT_COUNTER)
Average_MPPT_ADC_Values();
if(Avg_LOAD_Counter == REF_AVG_LOAD_COUNTER)
{
Average_LOAD_ADC_Values();
// first check all the exit conditions
if (Panel_Voltage > 490) // PV>15v
{
//system reset
PMMCTL0 |=PMMSWBOR; // Brown out reset by software
}
else if(Panel_Voltage > 125) // PV>5v
{
GATE_DRIVE_DISABLE;
Present_State = START_STANDBY_STATE;
TURN_OFF_BOOST_STAGE;
TURN_OFF_TIMER_A;
Load_On=0;
LOAD_DISABLE;
}
else
{
if (Battery_Voltage < 525) // BV < 10v
{
GATE_DRIVE_DISABLE;
init_Comparator_System_Reset();
__bis_SR_register(LPM4);
}
else if(Battery_Voltage < 545) // BV < 11v
{
Ref_Load_Current = REF_LOAD_CURRENT_LOW_BRIGHTNESS;
TURN_OFF_TIMER_A;
}
if(OC_Triggered) // if over current has triggered wait for approximately 10s
{
OC_Triggered_Counter++;
if(OC_Triggered_Counter == OC_TRIGGERED_COUNTER_THRESHOLD)
{
Duty_Boost = 100;
TURN_ON_BOOST_STAGE;
LOAD_ENABLE;
Load_On=1;
OC_Triggered=0;
OC_Triggered_Counter=0;
}
}
if(OV_Triggered) // if over voltage has triggered wait for approximately 10s
{
OV_Triggered_Counter++;
if(OV_Triggered_Counter == OV_TRIGGERED_COUNTER_THRESHOLD)
{
Duty_Boost = 100;
TURN_ON_BOOST_STAGE;
LOAD_ENABLE;
Load_On=1;
OV_Triggered=0;
OV_Triggered_Counter=0;
}
}
if(Load_On)
Load_Management();
}
}// end of load management state block
break;
case START_LOAD_MANAGEMENT_STATE :
{
//testing to indicate state change
P2OUT |=BIT5;
if(Battery_Voltage > 603)// BV>12v
{
GATE_DRIVE_ENABLE;
PANEL_DISABLE;
init_WDT(); // initialize ADC sampling interval to 1.3m
init_Comparator_LoadMonitor();
TURN_ON_TIMER_A;
// Ref_Load_Current = REF_LOAD_CURRENT_HALF_BRIGHTNESS;
Ref_Load_Current = REF_LOAD_CURRENT_FULL_BRIGHTNESS;
Load_On=1;
Duty_Boost=100;
TURN_ON_BOOST_STAGE;
LOAD_ENABLE;
Present_State = LOAD_MANAGEMENT_STATE;
}
}
break;
default : break;
}//end of switch block
}//end of while
}//end main
void MPPT (void)
{
if(Battery_Charging_Current<Prev_Battery_Charging_Current)
{
MPPT_Direction = MPPT_Direction * -1;
}
if(MPPT_Direction == 1)
{
Duty_Buck ++;
if(Duty_Buck>DUTY_BUCK_UPPER_THRESHOLD)
{
Duty_Buck=DUTY_BUCK_UPPER_THRESHOLD;
}
}
else
{
Duty_Buck --;
if(Duty_Buck<DUTY_BUCK_LOWER_THRESHOLD)
{
Duty_Buck=DUTY_BUCK_LOWER_THRESHOLD;
}
}
Prev_Battery_Charging_Current = Battery_Charging_Current;
if(Battery_Charging_Current >= CC_LIMIT ||(Battery_Voltage >= CC_TO_CV_LIMIT))
{
MPP_Loop_Exit_Counter ++;
if (MPP_Loop_Exit_Counter > MPPT_LOOP_EXIT_LIMIT)
{
MPPT_Loop = 0;
MPP_Loop_Exit_Counter = 0;
CC_Loop_Exit_Counter=0;
if (Battery_Voltage > CC_TO_CV_LIMIT)
CV_Mode = 1;
else
CV_Mode = 0;
}
}
else
MPP_Loop_Exit_Counter = 0;
}
void Battery_Charge_Profiling(void)
{
if ((Battery_Voltage <= CC_TO_CV_LIMIT)&& (!CV_Mode))
{
if (Battery_Charging_Current < CC_LIMIT)
{
Duty_Buck--;
if (Duty_Buck < DUTY_BUCK_LOWER_THRESHOLD)
{
Duty_Buck = DUTY_BUCK_LOWER_THRESHOLD;
CC_Loop_Exit_Counter ++;
if (CC_Loop_Exit_Counter > MPPT_LOOP_EXIT_LIMIT)
{
MPPT_Loop = 1;
MPP_Loop_Exit_Counter = 0;
CC_Loop_Exit_Counter = 0;
Present_State = START_MPPT_STATE;
}
}
}
else
{
Duty_Buck ++;
if (Duty_Buck > DUTY_BUCK_UPPER_THRESHOLD)
Duty_Buck = DUTY_BUCK_UPPER_THRESHOLD;
CC_Loop_Exit_Counter = 0;
}
}
else
{
CV_Mode = 1;
if (Battery_Voltage < CC_TO_CV_LIMIT)
{
Duty_Buck--;
if (Duty_Buck < DUTY_BUCK_LOWER_THRESHOLD)
Duty_Buck = DUTY_BUCK_LOWER_THRESHOLD;
}
else
{
Duty_Buck ++;
if (Duty_Buck > DUTY_BUCK_UPPER_THRESHOLD)
Duty_Buck = DUTY_BUCK_UPPER_THRESHOLD;
}
if (Battery_Voltage < FLOAT_VOLTAGE - 20)
{
CC_Loop_Exit_Counter ++;
if (CC_Loop_Exit_Counter > MPPT_LOOP_EXIT_LIMIT)
{
MPPT_Loop = 1;
MPP_Loop_Exit_Counter = 0;
CC_Loop_Exit_Counter = 0;
Present_State = START_MPPT_STATE;
}
}
}
}
void Load_Management (void)
{
if (Load_Current > (Ref_Load_Current + 1) )
{
Duty_Boost --;
if (Duty_Boost < 3) Duty_Boost = 3;
}
else if(Load_Current < (Ref_Load_Current - 1))
{
Duty_Boost ++;
if (Duty_Boost > 1600) Duty_Boost = 1600; // max of 50v out
}
TD1CCR1 = Duty_Boost;
}
void Average_MPPT_ADC_Values()
{
Avg_MPPT_Counter = 0;
Panel_Voltage = Panel_Voltage_Buffer/REF_AVG_MPPT_COUNTER;
Battery_Voltage = Battery_Voltage_Buffer/REF_AVG_MPPT_COUNTER;
Load_Voltage = Load_Voltage_Buffer/REF_AVG_MPPT_COUNTER;
Battery_Charging_Current = Battery_Charging_Current_Buffer/REF_AVG_MPPT_COUNTER;
Load_Voltage_Buffer = 0;
Panel_Voltage_Buffer = 0;
Battery_Voltage_Buffer = 0;
Battery_Charging_Current_Buffer = 0;
}
void Average_STANDBY_ADC_Values()
{
Avg_MPPT_Counter = 0;
Panel_Voltage = Panel_Voltage_Buffer/REF_AVG_STANDBY_COUNTER;
Battery_Voltage = Battery_Voltage_Buffer/REF_AVG_STANDBY_COUNTER;
Load_Voltage = Load_Voltage_Buffer/REF_AVG_STANDBY_COUNTER;
Battery_Charging_Current = Battery_Charging_Current_Buffer/REF_AVG_STANDBY_COUNTER;
Load_Voltage_Buffer = 0;
Panel_Voltage_Buffer = 0;
Battery_Voltage_Buffer = 0;
Battery_Charging_Current_Buffer = 0;
}
void Average_LOAD_ADC_Values()
{
Avg_LOAD_Counter = 0;
Load_Current = Load_Current_Buffer/REF_AVG_LOAD_COUNTER; // Copy ADC Readings for use
Load_Current_Buffer = 0;
}
//WDT to restart ADC
void init_WDT (void)
{
WDTCTL = WDT_MDLY_32; // WDT 32ms from 1MHz, SMCLK, interval timer
SFRIE1 |= WDTIE; // Enable WDT interrupt
}
void init_WDTLowpowermode3 (void)
{
WDTCTL = WDT_ADLY_250; // WDT 250ms, ACLK, interval timer
SFRIE1 |= WDTIE; // Enable WDT interrupt
}
// Watchdog Timer interrupt service routine
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
__data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &ADC_Readings[0]);
ADC10CTL0 |= ADC10ENC + ADC10SC+ ADC10ON; // Sampling and conversion start
}
void init_TimerD_BUCK (void)
{
struct s_TLV_Timer_D_Cal_Data * pTD0CAL; // Structure initialized in tlv.h
unsigned char bTD0CAL_bytes;
//Configure TimerD in Hi-Res Free Running Mode
Get_TLV_Info(TLV_TIMER_D_CAL, 0, &bTD0CAL_bytes, (unsigned int **) &pTD0CAL);
//Get TimerD0 Cal Values (instance 0)
if(bTD0CAL_bytes == 0x0)
{
// No TimerD free running cal data found
while(1); // Loop here
}
TD0CTL0 = TDSSEL_2; // TDCLK = SMCLK = 25MHz = Hi-Res input clk select
TD0HCTL1 = pTD0CAL->TDH0CTL1_200; // Read the 200Mhz TimerD TLV Data
TD0CTL1 |= TDCLKM_1;
TD0HCTL0 = TDHEN + TDHM_0; // CALEN=0 => free running mode; High-resolution clock 8x Timer_D clock; High-resolution mode enable
// TDHM_0 => clk = 200 * 1 = 200 Mhz, TDHM_1 => clk = 200 * 2 = 400 Mhz
P2SEL |= BIT0;
P2DIR |= BIT0;
TD0CCR0 = 2000; //TERMINAL COUNT for T0; 1137 FOR 180kHz FROM 200MHz; 2000 for 100kHz from 200MHz
// TD0CCTL1 |= OUTMOD_3; //SET-RESET
// TD0CCTL2 |= OUTMOD_7; //RESET-SET(delayed start)
TD0CCR1 = Duty_Buck;
TD0CCR2 = Duty_Buck - 60;
TD0CTL0 |= MC_1 + TDCLR;
__delay_cycles(6000000); //Delayed start of TD0.2
//increasing duty buck will actually decrease overall dutycycle
}
void init_TimerD_BOOST (void)
{
struct s_TLV_Timer_D_Cal_Data * pTD1CAL; // Structure initialized in tlv.h
unsigned char bTD1CAL_bytes;
P2SEL |= BIT2;
P2DIR |= BIT2;
TD1CTL0 |= MC_1; // SMCLK , up mode
TD1CTL1 |= TDCLKM_1;
TD1HCTL0 |=TDHEN + TDHM_0;
// TDHM_0 => clk = 200 * 1 = 200 Mhz, TDHM_1 => clk = 200 * 2 = 400 Mhz
Get_TLV_Info(TLV_TIMER_D_CAL, 0, &bTD1CAL_bytes, (unsigned int **) &pTD1CAL);
//Get TimerD0 Cal Values (instance 0)
if(bTD1CAL_bytes == 0x0)
{
while(1); // Loop here
}
TD1HCTL1 = pTD1CAL->TDH0CTL1_200;
TD1HCTL0 |=TDHRON; // HR ON
TD1CTL0 |= TDCLR;
//TD1CCTL1 = OUTMOD_7;
TD1CCR0 = 2000;
TD1CCR1 = Duty_Boost; // start from very low duty cycle
TD1CTL0 |= MC_1 + TDCLR;
}
void init_TimerA (void)
{
TA0CCR0 = 25000; // To count 1ms
TA0CTL |= TASSEL_2 + TAIE;
TA0CCTL0 |= CCIE;
}
// Timer0 A0 interrupt service routine; count for any hours, specified in minutes
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
ms++;
if(ms == 1000)
{
sec++;
ms = 0;
}
if(sec == 60)
{
min++;
ms = sec = 0;
}
if(min == MINUTES)
{
ms = sec = min = 0;
if (Ref_Load_Current == REF_LOAD_CURRENT_FULL_BRIGHTNESS)
Ref_Load_Current = REF_LOAD_CURRENT_HALF_BRIGHTNESS;
else
Ref_Load_Current = REF_LOAD_CURRENT_FULL_BRIGHTNESS;
}
TA0CCTL0 &= ~CCIFG;
TA0CTL &= ~TAIFG;
}
void PI_Control (void)
{
}
/*Comparator generates interrupt when +ve terminal is higher than -ve one
* So here ref voltage is given to -ve terminal and Panel voltage is given to +ve terminal
*Configured to detect over current.
* Generates interrupt when load current goes above approximately 800mA */
void init_Comparator_LoadMonitor (void)
{
System_reset_Mode_ON=0;
Load_Monitor_Mode_ON=1;
// clear all registers
CBCTL0 = CBCTL1 =CBCTL2 = CBCTL3 = CBINT =0;
CBCTL0 |= CBIPEN + CBIPSEL_4; // Enable V+, input channel CB4
CBCTL1 |= CBPWRMD_1; // normal power mode
CBCTL2 |= CBRSEL; // VREF is applied to -terminal
CBCTL3 |= BIT4; // Input Buffer Disable @P1.4/CB4
CBCTL2 |= CBRS_1 + CBREF1_4 + CBREF0_4; // VCC applied to R-ladder; to be set after calculation
__delay_cycles(7500); // delay for the reference to settle
CBINT &= ~(CBIFG + CBIIFG); // Clear any errant interrupts
CBINT |= CBIE; // Enable CompB Interrupt on rising edge of CBIFG (CBIES=0)
CBCTL1 |= CBON; // Turn On ComparatorB
}
void init_Comparator_System_Reset (void)
{
System_reset_Mode_ON=1;
Load_Monitor_Mode_ON=0;
// clear all registers
CBCTL0 = CBCTL1 =CBCTL2 = CBCTL3 = CBINT =0;
CBCTL0 |= CBIPEN + CBIPSEL_0; // Enable V+, input channel CB0
CBCTL1 |= CBPWRMD_1; // normal power mode
CBCTL2 |= CBRSEL; // VREF is applied to -terminal
CBCTL3 |= BIT0; // Input Buffer Disable @P1.4/CB4
CBCTL2 |= CBRS_1 + CBREF1_10 + CBREF0_10; // VCC applied to R-ladder; to be set after calculation
__delay_cycles(7500); // delay for the reference to settle
CBINT &= ~(CBIFG + CBIIFG); // Clear any errant interrupts
CBINT |= CBIE; // Enable CompB Interrupt on rising edge of CBIFG (CBIES=0)
CBCTL1 |= CBON; // Turn On ComparatorB
}
// Comp_B ISR - FOR SYSTEM RESET AND OVERCURRENT PROTECTION
#pragma vector=COMP_B_VECTOR
__interrupt void Comp_B_ISR (void)
{
if(Load_Monitor_Mode_ON)
{
TURN_OFF_BOOST_STAGE;
LOAD_DISABLE;
Load_On = 0;
CBINT &= ~CBIFG; // Clear Interrupt flag
OC_Triggered = 1;
OC_Triggered_Counter = 0; //Take action for over current protection by setting a flag
}
else if(System_reset_Mode_ON)
{
CBINT &= ~CBIFG;
PMMCTL0 |=PMMSWBOR; // Brown out reset by software
}
}
// Clocks And Vcore
void Init_Clocks (void)
{
SetVcoreUp (0x01);
SetVcoreUp (0x02);
SetVcoreUp (0x03);
// Configure DCO = 25Mhz
UCSCTL3 = SELREF_2; // Set DCO FLL reference = REFO
UCSCTL4 |= SELA_2; // Set ACLK = REFO
__bis_SR_register(SCG0); // Disable the FLL control loop
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
UCSCTL1 = DCORSEL_7; // Select DCO range 50MHz operation
UCSCTL2 = FLLD_1 + 762; // Set DCO Multiplier for 25MHz
// (N + 1) * FLLRef = Fdco
// (762 + 1) * 32768 = 25MHz
// Set FLL Div = fDCOCLK/2
__bic_SR_register(SCG0); // Enable the FLL control loop
// Worst-case settling time for the DCO when the DCO range bits have been
// changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
// UG for optimization.
// 32 x 32 x 25 MHz / 32,768 Hz ~ 780k MCLK cycles for DCO to settle
__delay_cycles(782000);
// Loop until Xt1 & DCO stabilizes - In this case only DCO has to stabilize
do
{
UCSCTL7 &= ~(XT1LFOFFG + XT1HFOFFG + DCOFFG);
// Clear XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag
}
void SetVcoreUp (unsigned int level)
{
// Open PMM registers for write
PMMCTL0_H = PMMPW_H;
// Set SVS/SVM high side new level
SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
// Set SVM low side to new level
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
// Wait till SVM is settled
while ((PMMIFG & SVSMLDLYIFG) == 0);
// Clear already set flags
PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
// Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
// Wait till new level reached
if ((PMMIFG & SVMLIFG))
while ((PMMIFG & SVMLVLRIFG) == 0);
// Set SVS/SVM low side to new level
SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
// Lock PMM registers for write access
PMMCTL0_H = 0x00;
}
//IO INITIALISATION//
void init_IO (void)
{
P1SEL |= BIT7; //CONFIGURE TD0.1 , PW_H
P1DIR |= BIT7; //OUTPUT HIGH SIDE MOSFET
P2SEL |= BIT0 + BIT2; //CONFIGURE TD0.2 , TD1.1 FOR PW_L , PW_B
P2DIR |= BIT0 + BIT2 + BIT4 + BIT5; //OUTPUT LOW SIDE MOSFET , BOOST STAGE MOSFET
P3DIR |= BIT2 + BIT3;
PJDIR |= BIT6; //CONFIGURE OUTPUT PORTS FOR ENABLE SIGNALS
PMAPPWD = 0x02D52; // Enable Write-access to modify port mapping registers
PMAPCTL = PMAPRECFG; // Allow reconfiguration during runtime
P1MAP0|= PM_ANALOG; // Modify all PxMAPy registers
P1MAP1|= PM_ANALOG; // Modify all PxMAPy registers
P1MAP2|= PM_ANALOG; // Modify all PxMAPy registers
P1MAP3|= PM_ANALOG; // Modify all PxMAPy registers
P1MAP4|= PM_ANALOG; // Modify all PxMAPy registers
PMAPPWD = 0; // Disable Write-Access to modify port mapping registers by writing incorrect key
P1SEL |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4; // setting the port mapping register PxMAPy to PM_ANALOG together with PxSEL.y=1 when applying analog signals
//PANEL_DISABLE;
//LOAD_DISABLE;
_BIS_SR(GIE); // enable global interrupts
}
//ADC INITIALISATION//
void init_ADC (void)
{
ADC10CTL0 = ADC10SHT_2 + ADC10MSC + ADC10ON; // 8clk cycles, Single trigger, conversion disabled
ADC10CTL1 = ADC10SHP + ADC10CONSEQ_1; // Sampling timer, Sequence of channels
ADC10CTL2 |= ADC10RES; // 10-bit conversion results
ADC10MCTL0 = ADC10INCH_4 + ADC10SREF_1; // A4,A3,A2,A1,A0(EoS), Vref+ = Vref, Vref- = gnd
REFCTL0 |= REFVSEL_2+REFON; // Select internal ref = 2.5V
//CONFIGURE DMA
DMACTL0 = DMA0TSEL_24; // ADC10IFG trigger
__data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC10MEM0);
// Source single address
__data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &ADC_Readings[0]);
// Destination array address
DMA0SZ = 0x05; // 5 WORDS(Conversion Results) transferred
DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAEN + DMAIE; // Source unchanged, Destination increments, enabled, interrupts enabled
}
#pragma vector=DMA_VECTOR
__interrupt void DMA0_ISR (void)
{
switch(__even_in_range(DMAIV,16))
{
case 0: break; // No interrupt (No conversion)
case 2:
// Sequence of conversions complete, Interrupt due to channel 0
ADC10CTL0 &= ~ADC10ENC; // Disabled Conversion
Panel_Voltage_Buffer += ADC_Readings [P_V];
Battery_Voltage_Buffer += ADC_Readings [B_V];
Battery_Charging_Current_Buffer += ADC_Readings [B_I];
Load_Voltage_Buffer += ADC_Readings [L_V];
Load_Current_Buffer += ADC_Readings [L_I];
Avg_LOAD_Counter++;
Avg_MPPT_Counter++;
if(ADC_Readings [L_V] > 680) // load voltage > 50v => disable load
{
TURN_OFF_BOOST_STAGE;
LOAD_DISABLE;
Load_On = 0;
OV_Triggered = 1;
OV_Triggered_Counter = 0; //Take action for over current protection by setting a flag
}
// to prevent boosting
if(ADC_Readings [P_V] > PANEL_UPPER_LIMIT)
{
TURN_OFF_BUCK_STAGE;
PANEL_DISABLE;
Duty_Buck=400; // 80%
Wait_State =1;
Wait_Counter =0;
}
//reset counter if these are overflowing.This can happen when MCU is in LPM
if(Avg_LOAD_Counter>REF_AVG_LOAD_COUNTER)
{
Avg_LOAD_Counter=0;
Load_Current_Buffer =0;
}
if((Avg_MPPT_Counter==REF_AVG_STANDBY_COUNTER)&&(LPM3_On==1))
{
LPM3_On=0;
ADC10CTL0 &= ~ADC10ON; // turn off ADC core to save power
LPM3_EXIT;
}
break; // DMA0IFG
case 4: break; // DMA1IFG
case 6: break; // DMA2IFG
case 8: break; // Reserved
case 10: break; // Reserved
case 12: break; // Reserved
case 14: break; // Reserved
case 16: break; // Reserved
default: break;
}
}