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.

Timer interrupt halts ADC interrupt and kick out PC from the main function

Hi

I am using Msp430 FR6989. I have a simple code which is supposed to read the internal temperature sensor and display the results on the LCD. LCD is updated on timer overflow interrupts. it works fine for a few cycles bu then apparently the program counter is being kicked out of the main routine and ADC does not work anymore. however, timer interrupt keeps running.

I am very new in using the system so I was wondering if anybody has an idea why is this the case. Please find the code below.

thanks a lot in advance

Afshin

#include <msp430.h>

#define CALADC12_12V_30C *((unsigned int *)0x1A1A) // Temperature Sensor Calibration-30 C
//See device datasheet for TLV table memory mapping
#define CALADC12_12V_85C *((unsigned int *)0x1A1C) // Temperature Sensor Calibration-85 C

#define CielCounter 10000

const unsigned char lcd_num[10] = {
0xFC, // 0
0x60, // 1
0xDB, // 2
0xF3, // 3
0x67, // 4
0xB7, // 5
0xBF, // 6
0xE4, // 7
0xFF, // 8
0xF7, // 9
};


unsigned int temp;
volatile float temperatureDegC;
volatile float temperatureDegF;

// Timer A interrupt service routine
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1_ISR( void )
{

_DINT();
int den1, den2, rem1, quot, dummy;
den1=100;
den2=10;
switch(__even_in_range(TA0IV, TA0IV_TAIFG))
{
case TA0IV_NONE: break; // No interrupt
case TA0IV_TACCR1: break; // CCR1 not used
case TA0IV_TACCR2: break; // CCR2 not used
case TA0IV_3: break; // reserved
case TA0IV_4: break; // reserved
case TA0IV_5: break; // reserved
case TA0IV_6: break; // reserved
case TA0IV_TAIFG: // overflow
dummy= (int) (temperatureDegC*10);
quot=dummy/den1; /* Computes quotient */
rem1=dummy%den1;
// Display quot on Segment 36,37
LCDM19 = lcd_num[quot];
quot=rem1/den2;
rem1=rem1%den2;

// Display quot on " on Segment 28,29
LCDM15 = lcd_num[quot];
LCDM16=0x01; // decimal point
// Display rem1 on " on Segment 14,15
LCDM8 = lcd_num[rem1];

P1OUT ^=BIT0;
break;
default: break;
}
TA0CCR0=CielCounter;
_EINT();
}

void Init( void )
{
// init timer A
TA0CCR0=CielCounter;
//TA0CTL = TASSEL__ACLK | MC__CONTINUOUS | ID_1| TACLR | TAIE; // ACLK, contmode, clear TAR
TA0CTL = TASSEL__SMCLK | MC__CONTINUOUS| ID_3 | TACLR | TAIE; // SMCLK, continuous mode
P1DIR |= BIT0;
P1OUT |= BIT0;
// Enable interrupts
//_EINT();
}

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT

// Initialize the shared reference module
// By default, REFMSTR=1 => REFCTL is used to configure the internal reference
while(REFCTL0 & REFGENBUSY); // If ref generator busy, WAIT
REFCTL0 |= REFVSEL_0 + REFON; // Enable internal 1.2V reference

/* Initialize ADC12_A */
ADC12CTL0 &= ~ADC12ENC; // Disable ADC12
ADC12CTL0 = ADC12SHT0_10 + ADC12ON; // Set sample time
ADC12CTL1 = ADC12SHP; // Enable sample timer
ADC12CTL3 = ADC12TCMAP; // Enable internal temperature sensor
ADC12MCTL0 = ADC12VRSEL_1 + ADC12INCH_30; // ADC input ch A30 => temp sense
ADC12IER0 = 0x001; // ADC_IFG upon conv result-ADCMEMO

LCDCPCTL0 = LCDS14 | LCDS15; // Initialize LCD segments
LCDCPCTL1 = LCDS28 | LCDS29 | LCDS30;
LCDCPCTL2 = LCDS36 | LCDS37;

// Disable the GPIO power-on default high-impedance mode
// to activate previously configured port settings
PM5CTL0 &= ~LOCKLPM5;

Init(); // initialize timer

// Initialize LCD_C
// ACLK, Divider = 1, Pre-divider = 16; 4-pin MUX
LCDCCTL0 = LCDDIV__1 | LCDPRE__16 | LCD4MUX | LCDLP | LCDSSEL;
// Enable charge pump and select internal reference for it
LCDCVCTL = VLCD_1 | VLCDREF_0 | LCDCPEN;

LCDCCPCTL = LCDCPCLKSYNC; // Clock synchronization enabled

LCDCMEMCTL = LCDCLRM; // Clear LCD memory

//Turn LCD on
LCDCCTL0 |= LCDON;


while(!(REFCTL0 & REFGENRDY)); // Wait for reference generator
// to settle
//ADC12CTL0 |= ADC12ENC;

while(1)
{

ADC12CTL0 |= ADC12ENC| ADC12SC; // enable and Sampling and conversion start

__bis_SR_register(LPM0_bits | GIE); // LPM4 with interrupts enabled
// __no_operation();

// Temperature in Celsius. See the Device Descriptor Table section in the
// System Resets, Interrupts, and Operating Modes, System Control Module
// chapter in the device user's guide for background information on the
// used formula.
temperatureDegC = (float)(((long)temp - CALADC12_12V_30C) * (85 - 30)) /
(CALADC12_12V_85C - CALADC12_12V_30C) + 30.0f;

// Temperature in Fahrenheit Tf = (9/5)*Tc + 32
temperatureDegF = temperatureDegC * 9.0f / 5.0f + 32.0f;

__delay_cycles(2000);
__no_operation(); // SET BREAKPOINT HERE

}
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12ISR (void)
#else
#error Compiler not supported!
#endif
{
_DINT();
switch(__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
{
case ADC12IV_NONE: break; // Vector 0: No interrupt
case ADC12IV_ADC12OVIFG: break; // Vector 2: ADC12MEMx Overflow
case ADC12IV_ADC12TOVIFG: break; // Vector 4: Conversion time overflow
case ADC12IV_ADC12HIIFG: break; // Vector 6: ADC12BHI
case ADC12IV_ADC12LOIFG: break; // Vector 8: ADC12BLO
case ADC12IV_ADC12INIFG: break; // Vector 10: ADC12BIN
case ADC12IV_ADC12IFG0: // Vector 12: ADC12MEM0 Interrupt
temp = ADC12MEM0; // Move results, IFG is cleared
__bic_SR_register_on_exit(LPM4_bits); // Exit active CPU
break;
case ADC12IV_ADC12IFG1: break; // Vector 14: ADC12MEM1
case ADC12IV_ADC12IFG2: break; // Vector 16: ADC12MEM2
case ADC12IV_ADC12IFG3: break; // Vector 18: ADC12MEM3
case ADC12IV_ADC12IFG4: break; // Vector 20: ADC12MEM4
case ADC12IV_ADC12IFG5: break; // Vector 22: ADC12MEM5
case ADC12IV_ADC12IFG6: break; // Vector 24: ADC12MEM6
case ADC12IV_ADC12IFG7: break; // Vector 26: ADC12MEM7
case ADC12IV_ADC12IFG8: break; // Vector 28: ADC12MEM8
case ADC12IV_ADC12IFG9: break; // Vector 30: ADC12MEM9
case ADC12IV_ADC12IFG10: break; // Vector 32: ADC12MEM10
case ADC12IV_ADC12IFG11: break; // Vector 34: ADC12MEM11
case ADC12IV_ADC12IFG12: break; // Vector 36: ADC12MEM12
case ADC12IV_ADC12IFG13: break; // Vector 38: ADC12MEM13
case ADC12IV_ADC12IFG14: break; // Vector 40: ADC12MEM14
case ADC12IV_ADC12IFG15: break; // Vector 42: ADC12MEM15
case ADC12IV_ADC12IFG16: break; // Vector 44: ADC12MEM16
case ADC12IV_ADC12IFG17: break; // Vector 46: ADC12MEM17
case ADC12IV_ADC12IFG18: break; // Vector 48: ADC12MEM18
case ADC12IV_ADC12IFG19: break; // Vector 50: ADC12MEM19
case ADC12IV_ADC12IFG20: break; // Vector 52: ADC12MEM20
case ADC12IV_ADC12IFG21: break; // Vector 54: ADC12MEM21
case ADC12IV_ADC12IFG22: break; // Vector 56: ADC12MEM22
case ADC12IV_ADC12IFG23: break; // Vector 58: ADC12MEM23
case ADC12IV_ADC12IFG24: break; // Vector 60: ADC12MEM24
case ADC12IV_ADC12IFG25: break; // Vector 62: ADC12MEM25
case ADC12IV_ADC12IFG26: break; // Vector 64: ADC12MEM26
case ADC12IV_ADC12IFG27: break; // Vector 66: ADC12MEM27
case ADC12IV_ADC12IFG28: break; // Vector 68: ADC12MEM28
case ADC12IV_ADC12IFG29: break; // Vector 70: ADC12MEM29
case ADC12IV_ADC12IFG30: break; // Vector 72: ADC12MEM30
case ADC12IV_ADC12IFG31: break; // Vector 74: ADC12MEM31
case ADC12IV_ADC12RDYIFG: break; // Vector 76: ADC12RDY
default: break;
}
_EINT();
}

  • the program counter is being kicked out of the main routine and ADC does not work anymore

    What specific symptoms lead you to this deduction?

  • Afshin,

    I did not look at all your code, but you're doing a lot in your timer ISR. Maybe this takes too long and the next timer interrupt is already generated when the previous one hasn't finished yet. Since the timer interrupt has a higher priority, the ADC's one will not pop up in between the timer interrupts. Don't do calculations inside an ISR. You should have an array that holds the display content for all digits. And this content is calculated in the main. Inside the ISR you simply start the output. This is just a guess, but you should move all the calculations to the main.

    Dennis

    By the way: temp is modified inside an ISR, so it should be volatile.

  • Thanks for your response.

    I tried to move the calculation out of the timer ISR and put them within the main function but it did not resolve the issue.
    please see the changed code below.

    Best,
    Afshin

    #include <msp430.h>

    #define CALADC12_12V_30C *((unsigned int *)0x1A1A) // Temperature Sensor Calibration-30 C
    //See device datasheet for TLV table memory mapping
    #define CALADC12_12V_85C *((unsigned int *)0x1A1C) // Temperature Sensor Calibration-85 C

    #define CielCounter 50000

    const unsigned char lcd_num[10] = {
    0xFC, // 0
    0x60, // 1
    0xDB, // 2
    0xF3, // 3
    0x67, // 4
    0xB7, // 5
    0xBF, // 6
    0xE4, // 7
    0xFF, // 8
    0xF7, // 9
    };


    unsigned int temp;
    volatile float temperatureDegC;
    volatile float temperatureDegF;
    int TmISROn;

    // Timer A interrupt service routine
    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void Timer_A1_ISR( void )
    {
    ADC12CTL0 &= ~ADC12ENC;
    _DINT();

    switch(__even_in_range(TA0IV, TA0IV_TAIFG))
    {
    case TA0IV_NONE: break; // No interrupt
    case TA0IV_TACCR1: break; // CCR1 not used
    case TA0IV_TACCR2: break; // CCR2 not used
    case TA0IV_3: break; // reserved
    case TA0IV_4: break; // reserved
    case TA0IV_5: break; // reserved
    case TA0IV_6: break; // reserved
    case TA0IV_TAIFG: // overflow
    TmISROn=1;
    P1OUT ^=BIT0;
    break;
    default: break;
    }
    TA0CCR0=CielCounter;
    _EINT();
    }

    void Init( void )
    {
    // init timer A
    TA0CCR0=CielCounter;
    //TA0CTL = TASSEL__ACLK | MC__CONTINUOUS | ID_1| TACLR | TAIE; // ACLK, contmode, clear TAR
    TA0CTL = TASSEL__SMCLK | MC__UP| ID_3 | TACLR | TAIE; // SMCLK, continuous mode
    P1DIR |= BIT0;
    P1OUT |= BIT0;
    // Enable interrupts
    //_EINT();
    }



    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    int den1, den2, rem1, quot, dummy;
    den1=100;
    den2=10;
    // Initialize the shared reference module
    // By default, REFMSTR=1 => REFCTL is used to configure the internal reference
    while(REFCTL0 & REFGENBUSY); // If ref generator busy, WAIT
    REFCTL0 |= REFVSEL_0 + REFON; // Enable internal 1.2V reference
    TmISROn=0;
    /* Initialize ADC12_A */
    ADC12CTL0 &= ~ADC12ENC; // Disable ADC12
    ADC12CTL0 = ADC12SHT0_10 + ADC12ON; // Set sample time
    ADC12CTL1 = ADC12SHP; // Enable sample timer
    ADC12CTL3 = ADC12TCMAP; // Enable internal temperature sensor
    ADC12MCTL0 = ADC12VRSEL_1 + ADC12INCH_30; // ADC input ch A30 => temp sense
    ADC12IER0 = 0x001; // ADC_IFG upon conv result-ADCMEMO

    LCDCPCTL0 = LCDS14 | LCDS15; // Initialize LCD segments
    LCDCPCTL1 = LCDS28 | LCDS29 | LCDS30;
    LCDCPCTL2 = LCDS36 | LCDS37;

    // Disable the GPIO power-on default high-impedance mode
    // to activate previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    Init(); // initialize timer

    // Initialize LCD_C
    // ACLK, Divider = 1, Pre-divider = 16; 4-pin MUX
    LCDCCTL0 = LCDDIV__1 | LCDPRE__16 | LCD4MUX | LCDLP | LCDSSEL;
    // Enable charge pump and select internal reference for it
    LCDCVCTL = VLCD_1 | VLCDREF_0 | LCDCPEN;

    LCDCCPCTL = LCDCPCLKSYNC; // Clock synchronization enabled

    LCDCMEMCTL = LCDCLRM; // Clear LCD memory

    //Turn LCD on
    LCDCCTL0 |= LCDON;


    while(!(REFCTL0 & REFGENRDY)); // Wait for reference generator
    // to settle
    //ADC12CTL0 |= ADC12ENC;

    while(1)
    {

    ADC12CTL0 |= ADC12ENC| ADC12SC; // enable and Sampling and conversion start

    __bis_SR_register(LPM0_bits | GIE); // LPM4 with interrupts enabled
    // __no_operation();

    // Temperature in Celsius. See the Device Descriptor Table section in the
    // System Resets, Interrupts, and Operating Modes, System Control Module
    // chapter in the device user's guide for background information on the
    // used formula.
    temperatureDegC = (float)(((long)temp - CALADC12_12V_30C) * (85 - 30)) /
    (CALADC12_12V_85C - CALADC12_12V_30C) + 30.0f;

    // Temperature in Fahrenheit Tf = (9/5)*Tc + 32
    temperatureDegF = temperatureDegC * 9.0f / 5.0f + 32.0f;

    //__delay_cycles(2000);
    if (TmISROn)
    {
    TmISROn=0;
    dummy= (int) (temperatureDegC*10);
    quot=dummy/den1; /* Computes quotient */
    rem1=dummy%den1;
    // Display quot on Segment 36,37
    LCDM19 = lcd_num[quot];
    quot=rem1/den2;
    rem1=rem1%den2;

    // Display quot on " on Segment 28,29
    LCDM15 = lcd_num[quot];
    LCDM16=0x01; // decimal point
    // Display rem1 on " on Segment 14,15
    LCDM8 = lcd_num[rem1];
    }
    __no_operation(); // SET BREAKPOINT HERE

    }
    }

    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC12_VECTOR
    __interrupt void ADC12ISR (void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    _DINT();
    switch(__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
    {
    case ADC12IV_NONE: break; // Vector 0: No interrupt
    case ADC12IV_ADC12OVIFG: break; // Vector 2: ADC12MEMx Overflow
    case ADC12IV_ADC12TOVIFG: break; // Vector 4: Conversion time overflow
    case ADC12IV_ADC12HIIFG: break; // Vector 6: ADC12BHI
    case ADC12IV_ADC12LOIFG: break; // Vector 8: ADC12BLO
    case ADC12IV_ADC12INIFG: break; // Vector 10: ADC12BIN
    case ADC12IV_ADC12IFG0: // Vector 12: ADC12MEM0 Interrupt
    temp = ADC12MEM0; // Move results, IFG is cleared
    __bic_SR_register_on_exit(LPM4_bits); // Exit active CPU
    break;
    case ADC12IV_ADC12IFG1: break; // Vector 14: ADC12MEM1
    case ADC12IV_ADC12IFG2: break; // Vector 16: ADC12MEM2
    case ADC12IV_ADC12IFG3: break; // Vector 18: ADC12MEM3
    case ADC12IV_ADC12IFG4: break; // Vector 20: ADC12MEM4
    case ADC12IV_ADC12IFG5: break; // Vector 22: ADC12MEM5
    case ADC12IV_ADC12IFG6: break; // Vector 24: ADC12MEM6
    case ADC12IV_ADC12IFG7: break; // Vector 26: ADC12MEM7
    case ADC12IV_ADC12IFG8: break; // Vector 28: ADC12MEM8
    case ADC12IV_ADC12IFG9: break; // Vector 30: ADC12MEM9
    case ADC12IV_ADC12IFG10: break; // Vector 32: ADC12MEM10
    case ADC12IV_ADC12IFG11: break; // Vector 34: ADC12MEM11
    case ADC12IV_ADC12IFG12: break; // Vector 36: ADC12MEM12
    case ADC12IV_ADC12IFG13: break; // Vector 38: ADC12MEM13
    case ADC12IV_ADC12IFG14: break; // Vector 40: ADC12MEM14
    case ADC12IV_ADC12IFG15: break; // Vector 42: ADC12MEM15
    case ADC12IV_ADC12IFG16: break; // Vector 44: ADC12MEM16
    case ADC12IV_ADC12IFG17: break; // Vector 46: ADC12MEM17
    case ADC12IV_ADC12IFG18: break; // Vector 48: ADC12MEM18
    case ADC12IV_ADC12IFG19: break; // Vector 50: ADC12MEM19
    case ADC12IV_ADC12IFG20: break; // Vector 52: ADC12MEM20
    case ADC12IV_ADC12IFG21: break; // Vector 54: ADC12MEM21
    case ADC12IV_ADC12IFG22: break; // Vector 56: ADC12MEM22
    case ADC12IV_ADC12IFG23: break; // Vector 58: ADC12MEM23
    case ADC12IV_ADC12IFG24: break; // Vector 60: ADC12MEM24
    case ADC12IV_ADC12IFG25: break; // Vector 62: ADC12MEM25
    case ADC12IV_ADC12IFG26: break; // Vector 64: ADC12MEM26
    case ADC12IV_ADC12IFG27: break; // Vector 66: ADC12MEM27
    case ADC12IV_ADC12IFG28: break; // Vector 68: ADC12MEM28
    case ADC12IV_ADC12IFG29: break; // Vector 70: ADC12MEM29
    case ADC12IV_ADC12IFG30: break; // Vector 72: ADC12MEM30
    case ADC12IV_ADC12IFG31: break; // Vector 74: ADC12MEM31
    case ADC12IV_ADC12RDYIFG: break; // Vector 76: ADC12RDY
    default: break;
    }
    _EINT();
    }
  • Thanks for your answer.
    The symptoms are:

    the blinking LED continue working. this means that the timer interrupt still works.
    LCD displays freezes which indicates that ADC does not update the input.
    When I put a break point within the main function, the program does not halt at the break point line. This suggest that program counter is kicked out of the main routine.

**Attention** This is a public forum