This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430F5172: ISR not returning to main

Part Number: MSP430F5172

Hello, 

In the code below, I am trying to use Timer A to trigger ADC conversion every one second. I have multiple sensors in my converter, so I am trying to use the timer for sensing the non-critical signals every one second. There are other sensors that need to be included in the code, but for now I am trying to see if I can execute the main code, trigger ADC signal in the timer ISR every one second and during the rest of the time run the main loop. However, my code is not returning to main. Is just goes into the ADC and timer ISRs. 

I am using single channel ADC conversion and I did try exiting from the ISR in both ADC and timer ISRs but none of them seem to work. The GetADC function sets the input channel and enables the ADC ISR and the timer ISR calls this function every 1 second. How can I make this work or is there a better way of implementing this? Thank you. 

/*
* CSHTEG code
* Firehiwot Gurara - July 2021
* main.c
* used MSP430F51x2_adc10_10.c for configuring ADC and DMA
* Robert Erickson's code for configuring PWM (ecee.colorado.edu/.../main.c)
*/

#include <msp430.h>
#include <stdint.h>
#include <math.h>

//define functions
void SetVcoreUp (unsigned int level);
void SetPWM (unsigned int tbuck, unsigned int tboost);
void SetDuty_Buck (unsigned int dbuckH, unsigned int dbuckL);
void SetDuty_Boost (unsigned int dboost, unsigned int dboostL);
void SetADC ();
void SetDMA();
void OffBuck(unsigned int dH, unsigned int dL);
void OffBoost(unsigned int dH, unsigned int dL);
void OnBattery();
void OffBattery();

#define T_buck 200 // period of buck stage - 200MHz/500kHz (desired freq)=400
#define T_boost 200 // // period of boost stage
unsigned int ADC_Result[6]; // 10-bit ADC conversion result array

unsigned int Iin_temp; // 10-bit ADC conversion result array
unsigned int Vin_temp; // 10-bit ADC conversion result array
unsigned int Vbat_temp; // 10-bit ADC conversion result array
unsigned int Ibat_temp; // 10-bit ADC conversion result array
unsigned int Vout_temp; // 10-bit ADC conversion result array
unsigned int Iout_temp; // 10-bit ADC conversion result array
unsigned int Vbuck_temp;

unsigned int flag;
unsigned int REdge1, FEdge2, FEdge_IN1, FEdge_IN2; // Variables to hold timer capture values
unsigned int F_EDGE, dt;

unsigned int Vin_min=260; // 5V is the minimum input voltage
unsigned int Vin_minABS=180; // ~4V - prevents current flowing back to TEGs (buck stage)

unsigned int i; // Declare counter variable
volatile unsigned int D_buckH,D_buckL ; // buck duty cycle
volatile unsigned int D_boostH,D_boostL; // boost duty cycle
volatile unsigned int bat_State; // battery switch state

void main(void) {

WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

// Configure PWM channels
/*
P1SEL |= BIT7; // Set P1.7 to output direction - High BUCK
P1DIR |= BIT7;

P2SEL |= BIT0; // Set P2.0 to output direction - Low BUCK
P2DIR |= BIT0;

P2SEL |= BIT2; // Set P2.2 to output direction - High BOOST
P2DIR |= BIT2;

P2SEL |= BIT3; // Set P2.3 to output direction - Low BOOST
P2DIR |= BIT3;
*/

// configure ADC pins
PMAPPWD = 0x02D52; // Enable Write-access to modify port mapping registers
PMAPCTL = PMAPRECFG; // Allow reconfiguration during runtime
//P1MAP0|= PM_ANALOG; // Modify all PxMAPy registers - A0 - Iin
P1MAP1|= PM_ANALOG; // Modify all PxMAPy registers - A1 - Vout_buck
P1MAP2|= PM_ANALOG; // Modify all PxMAPy registers - A2 - Vout
P1MAP3|= PM_ANALOG; // Modify all PxMAPy registers - A3
P1MAP4|= PM_ANALOG; // Modify all PxMAPy registers - A4 - Vbat
P1MAP5|= PM_ANALOG; // Modify all PxMAPy registers - A5 - Iout
P3MAP5|= PM_ANALOG; // Modify all PxMAPy registers - A8 - Ibat
//P3MAP6|= PM_ANALOG; // Modify all PxMAPy registers - A7 - Vin
P2MAP2|= PM_TD1_1;
P2MAP3|= PM_TD1_2;
P2MAP0|= PM_TD0_2;
P1MAP7|= PM_TD0_1;

P1SEL |=BIT7+BIT5+BIT4+BIT3+BIT2+BIT1; // setting the port mapping register PxMAPy to PM_ANALOG together with PxSEL.y=1 when applying analog signals
//P3SEL |=BIT5+BIT6;

P2SEL |= BIT0+BIT2+BIT3;
P2DIR |= BIT0+BIT2+BIT3;
P1DIR |= BIT7;
P1OUT |= 0x00; // Set P1.0 LED on
P1DIR |= BIT0;

P3SEL &= (~BIT0); // Set P3.0 to GPIO and to output direction - BAT_GD_EN
P3DIR |= BIT0;

P2SEL &= (~BIT6); // Set P2.6 as GPIO and to output direction - Vgate BAT
P2DIR |= BIT6;

P3DIR |= BIT6; // P3.6/TA0.1 output
P3SEL |= BIT6; // Output TA0.1 ADC trigger signal

PMAPPWD = 0; // Disable Write-Access to modify port mapping registers by writing incorrect key

// Increase Vcore setting to level3 to support fsystem=25MHz
// NOTE: Change core voltage one level at a time.

SetVcoreUp (0x01);
SetVcoreUp (0x02);
SetVcoreUp (0x03);

// Initialize DCO to 25MHz
__bis_SR_register(SCG0); // Disable the FLL control loop - set SCG0
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
UCSCTL1 = DCORSEL_7; // Select DCO range 4.6MHz-88MHz 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 - clear SCG0

// 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 = 781250 = MCLK cycles for DCO to settle
//__delay_cycles(781250);
__delay_cycles(782000);


// setup ADC
ADC10CTL1 |= ADC10SHP+ADC10SHS_1; // ADCCLK = MODOSC; sampling SIGNAL is sourced from the sampling timer
ADC10CTL2 |= ADC10RES; // 10-bit conversion results
ADC10MCTL0|= ADC10SREF_1; // Select ADC channel; USE VR+ = VREF and VR- = AVSS
// Configure internal reference
ADC10CTL0 |= ADC10SHT_2 + ADC10ON; // ADC10ON, Sample&Hold=16 ADC clks - ADC10SHT_2=2*256
while(REFCTL0 & REFGENBUSY); // If ref generator busy, WAIT
REFCTL0 |= REFVSEL_2+REFON; // Select internal ref = 2.5V
// Internal Reference ON
__delay_cycles(75); // Delay (~4us) for Ref to settle -ADC10 sample & convert = (32+13)*2/SMCLK = 90/SMCLK = 75us

ADC10IE |= ADC10IE0; // Enable ADC conv complete interrupt

SetPWM(T_buck, T_boost);
D_buckH = 53;
D_buckL = 54;
D_boostH = 148;
D_boostL = 149;


__delay_cycles(100); // Delay between sequence convs

// Configure Timer (TA0.1 - see device specific d/s) -> ADC conversion trigger

TA0CCR0 = 16384-1; // PWM Period
TA0CCR1 = 16384-1; // PWM Period
TA0CCTL1 = OUTMOD_4 + CCIE; // TACCR1 toggle;
TA0CTL = TASSEL_1 + MC_1 + TACLR; // ACLK, up mode

while (1){

if (Vin_temp>=Vin_min){
OffBattery();
__delay_cycles(100); // Delay between sequence convs
SetDuty_Buck (D_buckH, D_buckL);

}

else if(Vin_temp<Vin_min & Vin_temp>=Vin_minABS){
// turn off buck stage
//P1OUT &= ~0x01; // Clear P1.0 LED off
OffBuck(0,0);
__delay_cycles(100); // Delay between sequence convs
OnBattery();
__delay_cycles(100); // Delay between sequence convs
// turn on the boost stage
SetDuty_Boost(D_boostH, D_boostL);
}

else if (Vin_temp<Vin_minABS)
{
//P1OUT |= 0x01; // Set P1.0 LED on
OffBuck(0,0);
__delay_cycles(100); // Delay between sequence convs
OffBoost(0,0);
__delay_cycles(100); // Delay between sequence convs
OffBattery();
}

__bis_SR_register(LPM0_bits + GIE); // Enter LPM3, enable interrupts

}

}

// Timer A0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void)
#else
#error Compiler not supported!
#endif
{

flag=5;
GetADC(flag);
TA0CTL = 0; // Clear Timer_A control registers
__bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)

}


// ADC10 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC10_VECTOR))) ADC10_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(ADC10IV,12))
{
case 0: break; // No interrupt
case 2: break; // conversion result overflow
case 4: break; // conversion time overflow
case 6: break; // ADC10HI
case 8: break; // ADC10LO
case 10: break; // ADC10IN
case 12:
//ADC10IFG &= ~ADC10INIFG; // Clear interrupt flag
//TD0CTL0 &= ~MC_1; // Turn off Timer
ADC10CTL0 &= ~ADC10ENC;

if (flag==0)
Iin_temp= ADC10MEM0;
else if (flag==1)
Vbuck_temp= ADC10MEM0;
else if (flag==2)
Vout_temp= ADC10MEM0;
else if (flag==4)
Vbat_temp= ADC10MEM0;
else if (flag==5)
Iout_temp= ADC10MEM0;
else if (flag==7)
Vin_temp= ADC10MEM0;
else if (flag==8)
Ibat_temp= ADC10MEM0;
//__bic_SR_register_on_exit(LPM0_bits);
break; // Clear CPUOFF bit from 0(SR)

default: break;
}
}
// functions

void GetADC(int ADC_chan){
if (ADC_chan==0){ // Iin
ADC10MCTL0|= ADC10INCH_0; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
}
else if (ADC_chan==1){ // Vout_buck
ADC10MCTL0|= ADC10INCH_1; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
}
else if (ADC_chan==2){ // Vout
ADC10MCTL0|= ADC10INCH_2; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
}
else if (ADC_chan==4){ // Vbat
ADC10MCTL0|= ADC10INCH_4; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
}
else if (ADC_chan==5){ // Iout
ADC10MCTL0|= ADC10INCH_5; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
}
else if (ADC_chan==7){ // Vin
ADC10MCTL0|= ADC10INCH_7; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
}
else if (ADC_chan==8){ // Ibat
ADC10MCTL0|= ADC10INCH_8; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
}
else {
//error
}

while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active
ADC10CTL0 |= ADC10ENC + ADC10SC; // Sampling and conversion ready -- triggers the ADC interrupt
}

  • The timer ISR stops the timer.

    Put your code to enter a low power mode inside a while(1) loop so that the program doesn't terminate (enter an infinite loop somewhere in the library code) at the first LPM exit. Or maybe it is, I can't tell because of the lack of formatting since you didn't use the Insert code tool.

  • #include <msp430.h>
    #include <stdint.h>
    #include <math.h>
    
    //define functions
    void SetVcoreUp (unsigned int level);
    void SetPWM (unsigned int tbuck, unsigned int tboost);
    void SetDuty_Buck (unsigned int dbuckH, unsigned int dbuckL);
    void SetDuty_Boost (unsigned int dboost, unsigned int dboostL);
    void SetADC ();
    void SetDMA();
    void OffBuck(unsigned int dH, unsigned int dL);
    void OffBoost(unsigned int dH, unsigned int dL);
    void OnBattery();
    void OffBattery();
    
    #define T_buck 200 // period of buck stage - 200MHz/500kHz (desired freq)=400
    #define T_boost 200 // // period of boost stage
    unsigned int ADC_Result[6]; // 10-bit ADC conversion result array
    
    unsigned int Iin_temp; // 10-bit ADC conversion result array
    unsigned int Vin_temp; // 10-bit ADC conversion result array
    unsigned int Vbat_temp; // 10-bit ADC conversion result array
    unsigned int Ibat_temp; // 10-bit ADC conversion result array
    unsigned int Vout_temp; // 10-bit ADC conversion result array
    unsigned int Iout_temp; // 10-bit ADC conversion result array
    unsigned int Vbuck_temp;
    
    unsigned int flag;
    unsigned int REdge1, FEdge2, FEdge_IN1, FEdge_IN2; // Variables to hold timer capture values
    unsigned int F_EDGE, dt;
    
    unsigned int Vin_min=260; // 5V is the minimum input voltage
    unsigned int Vin_minABS=180; // ~4V - prevents current flowing back to TEGs (buck stage)
    
    unsigned int i; // Declare counter variable
    volatile unsigned int D_buckH,D_buckL ; // buck duty cycle
    volatile unsigned int D_boostH,D_boostL; // boost duty cycle
    volatile unsigned int bat_State; // battery switch state
    
    void main(void) {
    
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    
    // Configure PWM channels
    /*
    P1SEL |= BIT7; // Set P1.7 to output direction - High BUCK
    P1DIR |= BIT7;
    
    P2SEL |= BIT0; // Set P2.0 to output direction - Low BUCK
    P2DIR |= BIT0;
    
    P2SEL |= BIT2; // Set P2.2 to output direction - High BOOST
    P2DIR |= BIT2;
    
    P2SEL |= BIT3; // Set P2.3 to output direction - Low BOOST
    P2DIR |= BIT3;
    */
    
    // configure ADC pins
    PMAPPWD = 0x02D52; // Enable Write-access to modify port mapping registers
    PMAPCTL = PMAPRECFG; // Allow reconfiguration during runtime
    //P1MAP0|= PM_ANALOG; // Modify all PxMAPy registers - A0 - Iin
    P1MAP1|= PM_ANALOG; // Modify all PxMAPy registers - A1 - Vout_buck
    P1MAP2|= PM_ANALOG; // Modify all PxMAPy registers - A2 - Vout
    P1MAP3|= PM_ANALOG; // Modify all PxMAPy registers - A3
    P1MAP4|= PM_ANALOG; // Modify all PxMAPy registers - A4 - Vbat
    P1MAP5|= PM_ANALOG; // Modify all PxMAPy registers - A5 - Iout
    P3MAP5|= PM_ANALOG; // Modify all PxMAPy registers - A8 - Ibat
    //P3MAP6|= PM_ANALOG; // Modify all PxMAPy registers - A7 - Vin
    P2MAP2|= PM_TD1_1;
    P2MAP3|= PM_TD1_2;
    P2MAP0|= PM_TD0_2;
    P1MAP7|= PM_TD0_1;
    
    P1SEL |=BIT7+BIT5+BIT4+BIT3+BIT2+BIT1; // setting the port mapping register PxMAPy to PM_ANALOG together with PxSEL.y=1 when applying analog signals
    //P3SEL |=BIT5+BIT6;
    
    P2SEL |= BIT0+BIT2+BIT3;
    P2DIR |= BIT0+BIT2+BIT3;
    P1DIR |= BIT7;
    P1OUT |= 0x00; // Set P1.0 LED on
    P1DIR |= BIT0;
    
    P3SEL &= (~BIT0); // Set P3.0 to GPIO and to output direction - BAT_GD_EN
    P3DIR |= BIT0;
    
    P2SEL &= (~BIT6); // Set P2.6 as GPIO and to output direction - Vgate BAT
    P2DIR |= BIT6;
    
    P3DIR |= BIT6; // P3.6/TA0.1 output
    P3SEL |= BIT6; // Output TA0.1 ADC trigger signal
    
    PMAPPWD = 0; // Disable Write-Access to modify port mapping registers by writing incorrect key
    
    // Increase Vcore setting to level3 to support fsystem=25MHz
    // NOTE: Change core voltage one level at a time.
    
    SetVcoreUp (0x01);
    SetVcoreUp (0x02);
    SetVcoreUp (0x03);
    
    // Initialize DCO to 25MHz
    __bis_SR_register(SCG0); // Disable the FLL control loop - set SCG0
    UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
    UCSCTL1 = DCORSEL_7; // Select DCO range 4.6MHz-88MHz 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 - clear SCG0
    
    // 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 = 781250 = MCLK cycles for DCO to settle
    //__delay_cycles(781250);
    __delay_cycles(782000);
    
    
    // setup ADC
    ADC10CTL1 |= ADC10SHP+ADC10SHS_1; // ADCCLK = MODOSC; sampling SIGNAL is sourced from the sampling timer
    ADC10CTL2 |= ADC10RES; // 10-bit conversion results
    ADC10MCTL0|= ADC10SREF_1; // Select ADC channel; USE VR+ = VREF and VR- = AVSS
    // Configure internal reference
    ADC10CTL0 |= ADC10SHT_2 + ADC10ON; // ADC10ON, Sample&Hold=16 ADC clks - ADC10SHT_2=2*256
    while(REFCTL0 & REFGENBUSY); // If ref generator busy, WAIT
    REFCTL0 |= REFVSEL_2+REFON; // Select internal ref = 2.5V
    // Internal Reference ON
    __delay_cycles(75); // Delay (~4us) for Ref to settle -ADC10 sample & convert = (32+13)*2/SMCLK = 90/SMCLK = 75us
    
    ADC10IE |= ADC10IE0; // Enable ADC conv complete interrupt
    
    SetPWM(T_buck, T_boost);
    D_buckH = 53;
    D_buckL = 54;
    D_boostH = 148;
    D_boostL = 149;
    
    
    __delay_cycles(100); // Delay between sequence convs
    
    // Configure Timer (TA0.1 - see device specific d/s) -> ADC conversion trigger
    
    TA0CCR0 = 16384-1; // PWM Period
    TA0CCR1 = 16384-1; // PWM Period
    TA0CCTL1 = OUTMOD_4 + CCIE; // TACCR1 toggle;
    TA0CTL = TASSEL_1 + MC_1 + TACLR; // ACLK, up mode
    
    while (1){
    
    if (Vin_temp>=Vin_min){
    OffBattery();
    __delay_cycles(100); // Delay between sequence convs
    SetDuty_Buck (D_buckH, D_buckL);
    
    }
    
    else if(Vin_temp<Vin_min & Vin_temp>=Vin_minABS){
    // turn off buck stage
    //P1OUT &= ~0x01; // Clear P1.0 LED off
    OffBuck(0,0);
    __delay_cycles(100); // Delay between sequence convs
    OnBattery();
    __delay_cycles(100); // Delay between sequence convs
    // turn on the boost stage
    SetDuty_Boost(D_boostH, D_boostL);
    }
    
    else if (Vin_temp<Vin_minABS)
    {
    //P1OUT |= 0x01; // Set P1.0 LED on
    OffBuck(0,0);
    __delay_cycles(100); // Delay between sequence convs
    OffBoost(0,0);
    __delay_cycles(100); // Delay between sequence convs
    OffBattery();
    }
    
    __bis_SR_register(LPM0_bits + GIE); // Enter LPM3, enable interrupts
    
    }
    
    }
    
    // Timer A0 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void Timer_A(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void)
    #else
    #error Compiler not supported!
    #endif
    {
    
    flag=5;
    GetADC(flag);
    TA0CTL = 0; // Clear Timer_A control registers
    __bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
    
    }
    
    
    // ADC10 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC10_VECTOR))) ADC10_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    switch(__even_in_range(ADC10IV,12))
    {
    case 0: break; // No interrupt
    case 2: break; // conversion result overflow
    case 4: break; // conversion time overflow
    case 6: break; // ADC10HI
    case 8: break; // ADC10LO
    case 10: break; // ADC10IN
    case 12:
    //ADC10IFG &= ~ADC10INIFG; // Clear interrupt flag
    //TD0CTL0 &= ~MC_1; // Turn off Timer
    ADC10CTL0 &= ~ADC10ENC;
    
    if (flag==0)
    Iin_temp= ADC10MEM0;
    else if (flag==1)
    Vbuck_temp= ADC10MEM0;
    else if (flag==2)
    Vout_temp= ADC10MEM0;
    else if (flag==4)
    Vbat_temp= ADC10MEM0;
    else if (flag==5)
    Iout_temp= ADC10MEM0;
    else if (flag==7)
    Vin_temp= ADC10MEM0;
    else if (flag==8)
    Ibat_temp= ADC10MEM0;
    //__bic_SR_register_on_exit(LPM0_bits);
    break; // Clear CPUOFF bit from 0(SR)
    
    default: break;
    }
    }
    // functions
    
    void GetADC(int ADC_chan){
    if (ADC_chan==0){ // Iin
    ADC10MCTL0|= ADC10INCH_0; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==1){ // Vout_buck
    ADC10MCTL0|= ADC10INCH_1; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==2){ // Vout
    ADC10MCTL0|= ADC10INCH_2; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==4){ // Vbat
    ADC10MCTL0|= ADC10INCH_4; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==5){ // Iout
    ADC10MCTL0|= ADC10INCH_5; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==7){ // Vin
    ADC10MCTL0|= ADC10INCH_7; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==8){ // Ibat
    ADC10MCTL0|= ADC10INCH_8; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else {
    //error
    }
    
    while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active
    ADC10CTL0 |= ADC10ENC + ADC10SC; // Sampling and conversion ready -- triggers the ADC interrupt
    }

    Thank you for the response, but I enter low power mode in the while loop. 

    I didn't know about insert code tool. I have now copy pasted the previous code using this tool. 

  • Your code is still too difficult to follow. Does anybody read "The Elements of Programming Style"?

  • void main(void) {
    
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    
    // setup ADC
    ADC10CTL1 |= ADC10SHP+ADC10SHS_1; // ADCCLK = MODOSC; sampling SIGNAL is sourced from the sampling timer
    ADC10CTL2 |= ADC10RES; // 10-bit conversion results
    ADC10MCTL0|= ADC10SREF_1; // Select ADC channel; USE VR+ = VREF and VR- = AVSS
    ADC10CTL0 |= ADC10SHT_2 + ADC10ON; // ADC10ON, Sample&Hold=16 ADC clks - ADC10SHT_2=2*256
    while(REFCTL0 & REFGENBUSY); // If ref generator busy, WAIT
    REFCTL0 |= REFVSEL_2+REFON; // Select internal ref = 2.5V
    // Internal Reference ON
    __delay_cycles(75); // Delay (~4us) for Ref to settle -ADC10 sample & convert = (32+13)*2/SMCLK = 90/SMCLK = 75us
    
    ADC10IE |= ADC10IE0; // Enable ADC conv complete interrupt
    
    // Configure Timer (TA0.1 - see device specific d/s) -> ADC conversion trigger
    
    TA0CCR0 = 16384-1; // PWM Period
    TA0CCR1 = 16384-1; // PWM Period
    TA0CCTL1 = OUTMOD_4 + CCIE; // TACCR1 toggle;
    TA0CTL = TASSEL_1 + MC_1 + TACLR; // ACLK, up mode
    
    while (1){
    
    if (Vin_temp>=Vin_min){
    }
    
    else if(Vin_temp<Vin_min & Vin_temp>=Vin_minABS){;
    }
    
    else if (Vin_temp<Vin_minABS)
    {
    }
    
    __bis_SR_register(LPM0_bits + GIE); // Enter LPM3, enable interrupts
    
    }
    }
    
    // Timer A0 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void Timer_A(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void)
    #else
    #error Compiler not supported!
    #endif
    {
    
    flag=5;
    GetADC(flag);
    TA0CTL = 0; // Clear Timer_A control registers
    __bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
    
    }
    
    
    // ADC10 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC10_VECTOR))) ADC10_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    switch(__even_in_range(ADC10IV,12))
    {
    case 0: break; // No interrupt
    case 2: break; // conversion result overflow
    case 4: break; // conversion time overflow
    case 6: break; // ADC10HI
    case 8: break; // ADC10LO
    case 10: break; // ADC10IN
    case 12:
    //ADC10IFG &= ~ADC10INIFG; // Clear interrupt flag
    //TD0CTL0 &= ~MC_1; // Turn off Timer
    ADC10CTL0 &= ~ADC10ENC;
    
    if (flag==0)
    Iin_temp= ADC10MEM0;
    else if (flag==1)
    Vbuck_temp= ADC10MEM0;
    else if (flag==2)
    Vout_temp= ADC10MEM0;
    else if (flag==4)
    Vbat_temp= ADC10MEM0;
    else if (flag==5)
    Iout_temp= ADC10MEM0;
    else if (flag==7)
    Vin_temp= ADC10MEM0;
    else if (flag==8)
    Ibat_temp= ADC10MEM0;
    //__bic_SR_register_on_exit(LPM0_bits);
    break; // Clear CPUOFF bit from 0(SR)
    
    default: break;
    }
    }
    
    // functions
    
    void GetADC(int ADC_chan){
    if (ADC_chan==0){ // Iin
    ADC10MCTL0|= ADC10INCH_0; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==1){ // Vout_buck
    ADC10MCTL0|= ADC10INCH_1; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==2){ // Vout
    ADC10MCTL0|= ADC10INCH_2; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==4){ // Vbat
    ADC10MCTL0|= ADC10INCH_4; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==5){ // Iout
    ADC10MCTL0|= ADC10INCH_5; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==7){ // Vin
    ADC10MCTL0|= ADC10INCH_7; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else if (ADC_chan==8){ // Ibat
    ADC10MCTL0|= ADC10INCH_8; //Select ADC channel; USE VR+ = VREF and VR- = AVSS
    }
    else {
    //error
    }
    
    while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active
    ADC10CTL0 |= ADC10ENC + ADC10SC; // Sampling and conversion ready -- triggers the ADC interrupt
    }

    Sorry for the confusion, I should have put a segment of the code. What I mainly would need help is with understanding the code execution in  the while (1) loop, the ADC ISR and the timer ISR and the GetADC function since it is not returning back to the main loop. 

    Please let me know if anything is unclear. Thank you. 

  • As I said before, you stop the timer in its ISR so it can execute exactly once. Why do you clear TA0CTL?

    If you don't understand what the code is doing, simplify it and get the simple version running. Like getting a timer ISR to blink an LED. Then add.

  • In addition to what David said:

    ----------------------------

    > ADC10CTL1 |= ADC10SHP+ADC10SHS_1; // ADCCLK = MODOSC; sampling SIGNAL is sourced from the sampling timer

    SHS=1 requests a timer trigger (TA0.1) but getADC uses ADC10SC to start a conversion. These two mechanisms will trip over one another. Looking at the rest of the code, I suspect you want SHS=0 here:

    ADC10CTL1 |= ADC10SHP+ADC10SHS_0; // ADCCLK = MODOSC; use ADC10SC to start conversions

    ----------------------------

    > ADC10MCTL0|= ADC10INCH_1;

    These "|=" operations don't set the INCH field,  they alter it, and the alterations will accumulate so INCH will be wrong. One way to do this is:

    > ADC10MCTL0 = (ADC10MCTL0 & ~ADC10INCH) | ADC10INCH_1;

    ----------------------------

    More generally: Keep in mind that if an ISR does a wakeup (clears the LPM0_bits) when main isn't sleeping, that has no effect. If main later sleeps, that wakeup will not wake it up. Working with this can require some planning.

  • Thank you for the reply. The code is working now. It turns out that the timer ISR doesn't return to main if configured using the TACCR1 register. I am not sure why this is happening though, but using TACCR0 register made it work (I also have the configuration wrong in the code I posted yesterday for the timer ISR interrupt vector).  

  • There are two vectors for the timer. (See docs) If you use the wrong one then when the interrupt fires one of two things can happen. The first is that a default interrupt handler is called which obviously will not do what you want. The second is that the vector address is still in its reset state of 0xffff. Nothing good will come of setting the program counter to that value.

  • David makes a good point, though your original vector (TIMER0_A1_VECTOR) appeared to be correct, and I suppose you've made the indicated change (to TIMER0_A0_VECTOR).

    My hypothesis is that switching to CCR0 has separated in time the spurious conversion (from SHS=1) far from the intended conversion (from timer+ADC10SC), and so now they're not interfering with one another. I (still) suggest changing to SHS=0.

**Attention** This is a public forum