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.

Problem Entering Interrupt for Timer A

Other Parts Discussed in Thread: MSP430G2553

Hi-

I've been playing around with my launchpad and am trying to use TimerA0 to read the ADC and timerA1 to run an LED PWM (with another interrupt to deal with switches).  I've been using the code below, and while there is no problem with TimerA0 interrupt, the code never enters the TimerA1 interrupt service routine.  When debugging, I pause the system and can see that the TA1IV register shows '0x0002', suggesting that the interrupt flag has be tripped.

What could I be missing?  Thanks a ton!

Dave

#include <msp430g2553.h>

#ifndef TIMER0_A1_VECTOR
#define TIMER0_A1_VECTOR TIMERA1_VECTOR
#define TIMER0_A0_VECTOR TIMERA0_VECTOR
#endif

volatile long voltageRaw; //Declared for ADC
volatile unsigned int i; //for main loop code
volatile unsigned int t_on; //Peltier time on
volatile unsigned int t_off; //Peltier time off

void FaultRoutine(void);
void ConfigWDT(void);
void ConfigClocks(void);
void ConfigIO(void);
void ConfigADC10(void);
void ConfigTimerA(void);

void main(void)
{
ConfigWDT();
ConfigClocks();
ConfigIO();
ConfigADC10();
ConfigTimerA();

_BIS_SR(GIE); //Enable global interrupts

while(1)
{
}


}

void ConfigWDT(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
}

void ConfigClocks(void)
{
if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
FaultRoutine(); // If calibration data is erased run FaultRoutine()
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO
IFG1 &= ~OFIFG; // Clear OSCFault flag
BCSCTL2 |= SELM_0 + DIVM_3 + DIVS_3; // MCLK = DCO/8, SMCLK = DCO/8
}

void FaultRoutine(void)
{
P1OUT = BIT0; // P1.0 on (red LED)
while(1); // TRAP
}

void ConfigIO(void)
{
P1DIR = BIT6 + BIT0; // P1.6 and P1.0 outputs
P1OUT = 0; // LEDs off
P1IE |= BIT3 + BIT4; //P1.3 and P1.4 interrupt enabled.
P1IES |= BIT3 + BIT4; // Set interrupts for a rising edge

}

void ConfigADC10(void)
{
ADC10CTL1 = INCH_1 + ADC10DIV_0; // INCH1 means P1.1 (pin3), and ADC10 clock divider of 1
}

void ConfigTimerA(void)
{

CCTL0 = CCIE; //enable the counter compare reg 0 interrupt
CCR0 = 12000; //12000 represents 1 second at 12kHz
TA1CCTL0 = CCIE;
TA1CCTL1 = CCIE;
TA1CCR1 = 1000;
TA1CCR2 = 2000;
TA1CTL = TASSEL_1 + MC_2;
TACTL = TASSEL_1 + MC_2;

}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
{
ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON; //config ADC for Vref+, Max sample and hold, turn on ref, turn on ADC
_delay_cycles(5); // Wait for ADC Ref to settle (at least 30uS)
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
P1OUT |= BIT6; // P1.6 on (green LED)
_delay_cycles(100); //delay for 13 ADC cycles (2.6uS with a 5MHZ ADC10CLK)
ADC10CTL0 &= ~ENC; // Disable ADC conversion
ADC10CTL0 &= ~(REFON + ADC10ON); // Ref and ADC10 off
voltageRaw = ADC10MEM; // Read conversion value
P1OUT &= ~BIT6; // green LED off
CCR0 +=12000; // add 1 second to the timer
}


#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1(void)
{
switch( TAIV )
{
case 2:
P1OUT |= BIT0;
TA1CCR1 += 1000; // Add offset to CCR1
break;
case 4:
P1OUT &= ~BIT0;
TA1CCR2 += 1000;
break;
}
}


#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
if(P1IFG & BIT3)
{
P1OUT |= BIT0; //Turn on Red LED
P1IFG &= ~BIT3; //P1.3 IFG Cleared
}

if(P1IFG & BIT4)
{
P1OUT &= ~BIT0; //Turn off Red LED
P1IFG &= ~BIT4; //P1.4 IFG Cleared
}

}

  • Hi-

    I further simplified the code to try and find the problem with my launchpad.  Basically, I made the simplest TimerA1 interrupt that I could, but it still doesn't work.  Anyone have an idea on what might be wrong?  Here is the simpler code that still won't turn on the red LED.  What's strange, is occasionally when I halt the debugger, I can see that the TAIFG bit of the TA1CTL register goes high, and the CCIFG bit of the TA1CCTL0 register goes high, but the TA1IV register remains at 0x0.  I'm at a loss!

    Thanks, Dave

    #include <msp430g2553.h>

    #ifndef TIMER0_A1_VECTOR
    #define TIMER0_A1_VECTOR TIMERA1_VECTOR
    #define TIMER0_A0_VECTOR TIMERA0_VECTOR
    #endif

    volatile long voltageRaw; //Declared for ADC
    volatile unsigned int i; //for main loop code

    void ConfigWDT(void);
    void ConfigClocks(void);
    void ConfigIO(void);
    void ConfigTimerA(void);

    void main(void)
    {
    ConfigWDT();
    ConfigClocks();
    ConfigIO();
    ConfigTimerA();

    _BIS_SR(GIE); //Enable global interrupts

    while(1)
    {

    }
    }

    void ConfigWDT(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    }

    void ConfigClocks(void)
    {
    BCSCTL1 = CALBC1_1MHZ; // Set range
    DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation
    BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO
    IFG1 &= ~OFIFG; // Clear OSCFault flag
    BCSCTL2 |= SELM_0 + DIVM_3 + DIVS_3; // MCLK = DCO/8, SMCLK = DCO/8
    }

    void ConfigIO(void)
    {
    P1DIR = BIT6 + BIT0; // P1.6 and P1.0 outputs
    P1OUT = 0; // LEDs off
    }

    void ConfigTimerA(void)
    {

    TA1CCTL0 = CCIE;
    TA1CCR0 = 10000;
    TA1CTL = TASSEL_1 + MC_2;

    }

    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void Timer_A1(void)
    {
    P1OUT |= BIT0;
    TA1CCR0 = 10000;
    }

  • It looks like you're mixing up TIMER0_A1_VECTOR with TIMER1_A0_VECTOR (which is understandable, given the naming convention).

    Each TimerA block has two interrupt vectors, one that's triggered by TAxCCR0 CCIFG and another to handle all other interrupts for that particular timer block. TIMER0_A1_VECTOR is the "other" interrupt for TimerA0, not the TAxCCR0 CCIFG interrupt for TimerA1.

    Since ConfigTimerA sets up TimerA1 to interrupt on TA1CCR0 CCIFG, the MSP is trying to jump into the TIMER1_A0_VECTOR (which doesn't exist). If you replace TIMER0_A1_VECTOR with TIMER1_A0_VECTOR it should work as expected.

  • Thanks!  You're totally right.  I knew there was something that I was missing.  Thanks for your help!  Corrected code below:

    Dave

    #include <msp430g2553.h>

    #ifndef TIMER0_A1_VECTOR
    #define TIMER0_A1_VECTOR TIMERA1_VECTOR
    #define TIMER0_A0_VECTOR TIMERA0_VECTOR
    #endif
    /*
    #ifndef TIMER1_A1_VECTOR
    #define TIMER1_A1_VECTOR TIMERA1_VECTOR
    #define TIMER1_A0_VECTOR TIMERA0_VECTOR
    #endif
    */
    volatile long voltageRaw; //Declared for ADC
    volatile unsigned int i; //for main loop code

    void ConfigWDT(void);
    void ConfigClocks(void);
    void ConfigIO(void);
    void ConfigTimerA(void);

    void main(void)
    {
    ConfigWDT();
    ConfigClocks();
    ConfigIO();
    ConfigTimerA();

    _BIS_SR(GIE); //Enable global interrupts

    while(1)
    {

    }
    }

    void ConfigWDT(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    }

    void ConfigClocks(void)
    {
    BCSCTL1 = CALBC1_1MHZ; // Set range
    DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation
    BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO
    IFG1 &= ~OFIFG; // Clear OSCFault flag
    BCSCTL2 |= SELM_0 + DIVM_3 + DIVS_3; // MCLK = DCO/8, SMCLK = DCO/8
    }

    void ConfigIO(void)
    {
    P1DIR = BIT6 + BIT0; // P1.6 and P1.0 outputs
    P1OUT = 0; // LEDs off
    }

    void ConfigTimerA(void)
    {

    TA0CCTL0 = CCIE;
    TA0CCR0 = 10000;
    TA0CTL = TASSEL_1 + MC_2;


    }

    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A0(void)
    {
    P1OUT |= BIT0;
    TA1CCR0 = 10000;
    }

  • Exactly what i was looking for as well, thanks!

**Attention** This is a public forum