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.

MSP430FR5994: MSP430FR5994: Timer not working using inbuilt functions

Part Number: MSP430FR5994


Hi,team
I'm using MSP430FR5994 Launchpad kit. I'm trying to Initialize timer using function "timer_delay(delay);" but i'm not getting any interrupt.
I was able to blink LEDs and access switch inputs using another code. For accessing switch, i had to update MSP430FR5994.h file as per given in E2E forum.
The code i used is attached below. Please review.

//***************************************************************************************
//  Blink the LED Demo - Software Toggle P1.0
//
//  Description; Toggle P1.0 inside of a software loop.
//  ACLK = n/a, MCLK = SMCLK = default DCO
//
//                MSP430x5xx
//             -----------------
//         /|\|              XIN|-
//          | |                 |
//          --|RST          XOUT|-
//            |                 |
//            |             P1.0|-->LED
//
//  E. Chen
//  Texas Instruments, Inc
//  March 2016
//  Built with Code Composer Studio v6
//***************************************************************************************

#include "./MSP430FR5xx_6xx/driverlib.h"
#include <stdio.h>
//#include <driverlib.h>


void initClock(void);
void timer_delay(uint32_t);

 int flag1 = 0,flag2 = 0;
 int delay_flag = 0;
 int count = 0;
 volatile int SW1_state=1,SW2_state=1;

int main(void)
{

    volatile uint32_t i;
    volatile uint8_t SW1,SW2;
    volatile uint16_t SW1_interrupt=1,SW2_interrupt=1,SW1_interrupt_pre,SW2_interrupt_pre;

    volatile uint32_t delay = 0;



    // Stop watchdog timer
    WDT_A_hold(WDT_A_BASE);

    //initClock();

    GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);         // Set Red LED output
    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);      // Red LED off
    GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN1);         // Set Green LED output
    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN1);      // Green LED off

    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN6);                      // S1 P5.6: PxDIR, PxOUT and PxREN registers
    GPIO_selectInterruptEdge(GPIO_PORT_P5, GPIO_PIN6,GPIO_HIGH_TO_LOW_TRANSITION);      // S1 P5.6: PxIES register

    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN5);                      // S2 P5.5: PxDIR, PxOUT and PxREN registers
    GPIO_selectInterruptEdge(GPIO_PORT_P5, GPIO_PIN5,GPIO_HIGH_TO_LOW_TRANSITION);      // S2 P5.5: PxIES register


    SW1 = GPIO_getInputPinValue(GPIO_PORT_P5,GPIO_PIN6);

    SW2 = GPIO_getInputPinValue(GPIO_PORT_P5,GPIO_PIN5);





    //SW1_state = SW1 & 0x08;

    // Disable the GPIO power-on default high-impedance mode to activate previously configured port settings
    PMM_unlockLPM5();

    // Set all P5IFG to zero
    P5IFG = 0x00;


    GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN5);
    GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN6);

    __bis_SR_register(GIE);  // Enable all interrupts

    //*
    // Enable Switch interrupt
    GPIO_clearInterrupt(GPIO_PORT_P5, GPIO_PIN5);
    GPIO_clearInterrupt(GPIO_PORT_P5, GPIO_PIN6);

    //*/

    SW1_interrupt_pre= GPIO_getInterruptStatus(GPIO_PORT_P5, GPIO_PIN6);
    SW2_interrupt_pre= GPIO_getInterruptStatus(GPIO_PORT_P5, GPIO_PIN5);

    while(1)
    {


        if (SW1_interrupt_pre != GPIO_getInterruptStatus(GPIO_PORT_P5, GPIO_PIN6))
        {
            if (SW1_interrupt == 1)
            {
                SW1_interrupt = 0 ;
            }
            else
            {
                SW1_interrupt = 1 ;
            }

            GPIO_clearInterrupt(GPIO_PORT_P5, GPIO_PIN6);
        }
        if (SW2_interrupt_pre != GPIO_getInterruptStatus(GPIO_PORT_P5, GPIO_PIN5))
        {
            if (SW2_interrupt == 1)
            {
                SW2_interrupt = 0 ;
            }
            else
            {
                SW2_interrupt = 1 ;
            }
            GPIO_clearInterrupt(GPIO_PORT_P5, GPIO_PIN5);
        }

        SW1 = GPIO_getInputPinValue(GPIO_PORT_P5,
                              GPIO_PIN6);

        SW2 = GPIO_getInputPinValue(GPIO_PORT_P5,
                                  GPIO_PIN5);

        //if  (GPIO_getInputPinValue(GPIO_PORT_P5,GPIO_PIN6) == GPIO_INPUT_PIN_HIGH)
        if (SW2_state == 1)
        {
            if (flag1 == 0)
            {
                flag1 = 10;
                GPIO_toggleOutputOnPin( GPIO_PORT_P1,GPIO_PIN1);
            }
            else
            {
                flag1 = flag1--;

            }
        }


        if  (GPIO_getInputPinValue(GPIO_PORT_P5,GPIO_PIN6) == GPIO_INPUT_PIN_HIGH)
        {
            if (flag2 == 0)
            {
                flag2 = 4;
                GPIO_toggleOutputOnPin(GPIO_PORT_P1,GPIO_PIN0);
            }
            else
            {
                flag2 = flag2--;

            }
        }



        // Delay
        //for(i=1000; i>0; i--);
        delay = 0xFFFFFFF;
        timer_delay(delay);
        timer_delay(delay);
        //timer_delay(delay);
        //__delay_cycles(16000000); //Wait 160000 CPU cycles
    }
}








void timer_delay(uint32_t delay)
{

    delay_flag = 0;

    //Stop Timer_A
    Timer_A_stop(TIMER_A1_BASE);
    Timer_A_clearTimerInterrupt(TIMER_A1_BASE);
    Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0 );

    //Start TIMER_A
    Timer_A_initContinuousModeParam initContParam = {0};
    initContParam.clockSource= TIMER_A_CLOCKSOURCE_SMCLK;
    initContParam.clockSourceDivider= TIMER_A_CLOCKSOURCE_DIVIDER_1;
    initContParam.timerInterruptEnable_TAIE= TIMER_A_TAIE_INTERRUPT_DISABLE;
    initContParam.timerClear= TIMER_A_DO_CLEAR;
    initContParam.startTimer=false;

    Timer_A_initContinuousMode(TIMER_A1_BASE, &initContParam);

    //Enable Interrupt
    Timer_A_enableInterrupt(TIMER_A1_BASE);

    //Initialize compare mode
    Timer_A_enableCaptureCompareInterrupt(TIMER_A1_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0 );

    Timer_A_initCompareModeParam initCompParam = {0};
    initCompParam.compareRegister= TIMER_A_CAPTURECOMPARE_REGISTER_0;
    initCompParam.compareInterruptEnable= TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE;
    initCompParam.compareOutputMode= TIMER_A_OUTPUTMODE_OUTBITVALUE;
    initCompParam.compareValue= 0x0C350; //50000 count

    Timer_A_initCompareMode(TIMER_A1_BASE, &initCompParam);

    Timer_A_clear(TIMER_A1_BASE);
    Timer_A_startCounter( TIMER_A1_BASE,TIMER_A_CONTINUOUS_MODE);


     count = 0;

    while(!delay_flag)
    {
        //count=Timer_A_getCounterValue(TIMER_A1_BASE);
    }

    //Enter LPM0
    //__bis_SR_register(LPM0_bits);
    //For debugger
    //__no_operation();


}



//******************************************************************************
//
//This is the Timer A interrupt vector service routine
//
//******************************************************************************
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{

    delay_flag = 1;

}






//******************************************************************************
//
//This is the PORT5_VECTOR interrupt vector service routine
//
//******************************************************************************
#pragma vector=PORT5_VECTOR //0xFFC6
__interrupt void Port_5(void)
{
//P5.5 = toggle

    switch (P5IFG)
    {
        case 0b01000000: // S1 P5.6 = 64: toggle red LED
        {
            //P1OUT ^= BIT0;          // Toggle P1.0
            //P5IFG &= ~BIT6;         // P5.6 clear interrupt flag
            GPIO_clearInterrupt(GPIO_PORT_P5,GPIO_PIN6);
            if (SW1_state == 1)
            {
                SW1_state = 0;
            }
            else
            {
                SW1_state = 1;
            }

        }
        break;
        case 0b00100000: // S2 P5.5 = 32: toggle green LED
        {
            //P1OUT ^= BIT1;          // Toggle P1.1
            //P5IFG &= ~BIT5;         // P5.5 clear interrupt flag
            GPIO_clearInterrupt(GPIO_PORT_P5,GPIO_PIN5);
            if (SW2_state == 1)
            {
                SW2_state = 0;
            }
            else
            {
                SW2_state = 1;
            }

        }
        break;
        default: // should not be here!
        {
          //printf("Put an error message here. \n");
        }
        break;
    }

//P5.5 IFG cleared
//GPIO_clearInterrupt(GPIO_PORT_P5,GPIO_PIN5);
}


  • 1) 

    > #pragma vector=TIMER0_A0_VECTOR

    You're using TIMER_A1, so this should be:

    > #pragma vector=TIMER1_A0_VECTOR

    2) delay_flag should be declared "volatile"

    3) You should set delay_flag=0 After stopping the timer.

  • Hi

    Updated code as per suggested but it is still not working. I also update the line initContParam.clockSourceDivider= TIMER_A_CLOCKSOURCE_DIVIDER_1;  to initContParam.clockSourceDivider= TIMER_A_CLOCKSOURCE_DIVIDER_16;

    In above case , the clock is initialized using code in

    ie , SMCLK will be 16MHz. So clock source will be set as 1MHz using TIMER_A_CLOCKSOURCE_DIVIDER_16.

    Purpose of the code is to generate a delay of 1 second. So i set initCompParam.compareValue= 0xF4240; Interrupt enabled to detect comparator reach 0xF4240. When reached it should call ISR and delay to be set as 1 and thus loop ends. 

    Delay is assigned 0 when timer_delay() is called.

    Please comment on the code and method used.

  • What is it (precisely) that doesn't work?

    You can't use a compareValue of 0xF4240, since compareValue (and TA1CCR0) is only 16 bits. I'm rather surprised the compiler didn't warn you about this.

    You can divide the input clock by up to 8*8=64, so with SMCLK=16MHz you can obtain a period of (65536/(16MHz/64))=~0.262 seconds. If you want to use SMCLK, I suggest you break up the delay into smaller units, e.g. 250ms or maybe 10ms.

    From the other thread it appears you have a 32kHz crystal on your board. ACLK can count 1 second quite easily (compareValue=CCR0=32768U-1).

    Unsolicited: For doing a delay you'll probably find Up mode more convenient than Continuous mode.

  • Hi

    As suggested i updated code using Upmode and clock source ACLK/64 (32.768KHz) . So to get 1s delay i made initContParam.timerPeriod=0x0200; for period equal to 1 second. I created two functions   timer_init() and  timer_delay(uint32_t delay). Using timer_delay() i want to create start timer , check delay_flag set to 1 when timer reach 0x200 using interrupt routine and then stop timer, go back to main function.

    Currently the code gets stuck in while loop inside timer_delay() and LED stops blinking.

    Please check updated code and let me know what the issue is.

  • Hi

    Code is below.



    #include "./MSP430FR5xx_6xx/driverlib.h"
    #include <stdio.h>
    //#include <driverlib.h>


    void initClock(void);
    void timer_init(void);
    void timer_delay(uint32_t);

    int flag1 = 0,flag2 = 0;
    volatile int delay_flag = 0;
    int count = 0;
    int SW1_state=1,SW2_state=1;

    int main(void)
    {

        volatile uint32_t i;
        volatile uint8_t SW1,SW2;
        volatile uint16_t SW1_interrupt=1,SW2_interrupt=1,SW1_interrupt_pre,SW2_interrupt_pre;
        volatile uint16_t timer_value=0;
        volatile uint32_t delay = 0;

        count = 0;

        // Stop watchdog timer
        WDT_A_hold(WDT_A_BASE);

        //initClock();

        timer_init();

        GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);         // Set Red LED output
        GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);      // Red LED off
        GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN1);         // Set Green LED output
        GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN1);      // Green LED off

        GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN6);                      // S1 P5.6: PxDIR, PxOUT and PxREN registers
        GPIO_selectInterruptEdge(GPIO_PORT_P5, GPIO_PIN6,GPIO_HIGH_TO_LOW_TRANSITION);      // S1 P5.6: PxIES register

        GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN5);                      // S2 P5.5: PxDIR, PxOUT and PxREN registers
        GPIO_selectInterruptEdge(GPIO_PORT_P5, GPIO_PIN5,GPIO_HIGH_TO_LOW_TRANSITION);      // S2 P5.5: PxIES register


        SW1 = GPIO_getInputPinValue(GPIO_PORT_P5,GPIO_PIN6);

        SW2 = GPIO_getInputPinValue(GPIO_PORT_P5,GPIO_PIN5);





        //SW1_state = SW1 & 0x08;

        // Disable the GPIO power-on default high-impedance mode to activate previously configured port settings
        PMM_unlockLPM5();

        // Set all P5IFG to zero
        P5IFG = 0x00;

        // Set all P5IFG to zero
        //TAIFG = 0x00;


        GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN5);
        GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN6);

        __bis_SR_register(GIE);  // Enable all interrupts

        //*
        // Enable Switch interrupt
        GPIO_clearInterrupt(GPIO_PORT_P5, GPIO_PIN5);
        GPIO_clearInterrupt(GPIO_PORT_P5, GPIO_PIN6);

        //*/

        SW1_interrupt_pre= GPIO_getInterruptStatus(GPIO_PORT_P5, GPIO_PIN6);
        SW2_interrupt_pre= GPIO_getInterruptStatus(GPIO_PORT_P5, GPIO_PIN5);

        while(1)
        {


            if (SW1_interrupt_pre != GPIO_getInterruptStatus(GPIO_PORT_P5, GPIO_PIN6))
            {
                if (SW1_interrupt == 1)
                {
                    SW1_interrupt = 0 ;
                }
                else
                {
                    SW1_interrupt = 1 ;
                }

                GPIO_clearInterrupt(GPIO_PORT_P5, GPIO_PIN6);
            }
            if (SW2_interrupt_pre != GPIO_getInterruptStatus(GPIO_PORT_P5, GPIO_PIN5))
            {
                if (SW2_interrupt == 1)
                {
                    SW2_interrupt = 0 ;
                }
                else
                {
                    SW2_interrupt = 1 ;
                }
                GPIO_clearInterrupt(GPIO_PORT_P5, GPIO_PIN5);
            }

            SW1 = GPIO_getInputPinValue(GPIO_PORT_P5,
                                  GPIO_PIN6);

            SW2 = GPIO_getInputPinValue(GPIO_PORT_P5,
                                      GPIO_PIN5);

            //if  (GPIO_getInputPinValue(GPIO_PORT_P5,GPIO_PIN6) == GPIO_INPUT_PIN_HIGH)
            if (SW2_state == 1)
            {
                if (flag1 == 0)
                {
                    flag1 = 10;
                    GPIO_toggleOutputOnPin( GPIO_PORT_P1,GPIO_PIN1);
                }
                else
                {
                    flag1 = flag1--;

                }
            }


            if  (GPIO_getInputPinValue(GPIO_PORT_P5,GPIO_PIN6) == GPIO_INPUT_PIN_HIGH)
            {
                if (flag2 == 0)
                {
                    flag2 = 4;
                    GPIO_toggleOutputOnPin(GPIO_PORT_P1,GPIO_PIN0);
                }
                else
                {
                    flag2 = flag2--;

                }
            }



            // Delay
            for(i=100000; i>0; i--);
            delay = 0xFFFFFFF;
            timer_delay(delay);

            //timer_value = Timer_A_getCounterValue(TIMER_A1_BASE);
            //timer_delay(delay);
            //timer_delay(delay);
            //__delay_cycles(16000000); //Wait 160000 CPU cycles
        }
    }



    void timer_init()
    {

        //Start TIMER_A
        //Timer_A_initContinuousModeParam initContParam = {0};
        Timer_A_initUpModeParam  initContParam = {0};
        initContParam.clockSource= TIMER_A_CLOCKSOURCE_ACLK;
        initContParam.clockSourceDivider= TIMER_A_CLOCKSOURCE_DIVIDER_64;
        initContParam.timerPeriod=0x0200;
        initContParam.timerInterruptEnable_TAIE= TIMER_A_TAIE_INTERRUPT_ENABLE;
        initContParam.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE ;
        initContParam.timerClear= TIMER_A_DO_CLEAR;
        initContParam.startTimer=false;

        Timer_A_initUpMode(TIMER_A1_BASE, &initContParam);    // Timer_A_initContinuousMode

    }




    void timer_delay(uint32_t delay)
    {

        delay_flag = 0;

        Timer_A_clear(TIMER_A1_BASE);
        Timer_A_startCounter( TIMER_A1_BASE,TIMER_A_UP_MODE);


        while(!delay_flag)
        {
            
        }


        Timer_A_stop(TIMER_A1_BASE);
        Timer_A_clearTimerInterrupt(TIMER_A1_BASE);



        //Enter LPM0
        //__bis_SR_register(LPM0_bits);
        //For debugger
        //__no_operation();


    }


    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void TIMER0_A1_ISR(void)
    //void __attribute__((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR(void)
    {

        delay_flag = 1;

    }



  • > #pragma vector=TIMER0_A1_VECTOR

    You're using TIMER_A1_BASE, so this should be:

    > #pragma vector=TIMER1_A1_VECTOR

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

    Somewhere inside the ISR you need to explicitly clear TAIFG , using something like:

    >Timer_A_clearTimerInterrupt(TIMER_A1_BASE);

    Otherwise the interrupt will just keep triggering. (This isn't required for CCR0, i.e. TIMER1_A0_VECTOR.) [Ref User Guide (SLAU367P) Sec 25.2.6]

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

    >    GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN5);
    >    GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN6);

    You're enabling these pin interrupts, but I don't see an ISR (PORT5_VECTOR) for them. The rest of the code seems to be polling the interrupt status, so you probably should just remove these lines.

  • Hi

    1. Is it OK to use Timer_A_clear(TIMER_A1_BASE); to reset the timer so that it will start from zero when timer_delay() is called. Or will Timer_A_startCounter() automatically start timer from zero whenever it is called ?

    2. Is timer A CCR0 called as Timer0_A0_vector, CCR1 as Timer0_A1_vector, ... and timer B CCR0 called as Timer1_A0_vector, CCR1 as Timer1_A1_vector,.... Please confirm.

    Code modified as follows : ISR (PORT5_VECTOR) was added. Also Timer_A_clearTimerInterrupt(TIMER_A1_BASE); added inside ISR.

  • 1) Yes, in fact you should do that. Neither Timer_A_stop nor Timer_A_startCounter clears the counter.

    2) Mostly. UG Sec 25.2.6 describes two different IRQs for each timer -- one for CCR0 and another for all-the-others (including TAIFG). For TA0, these are (as you said) TIMER0_A0_VECTOR and TIMER0_A1_VECTOR. For TA1 they are TIMER1_A0_VECTOR and TIMER1_A1_VECTOR. For TB2, they are TIMER2_B0_VECTOR and TIMER2_B1_VECTOR. It takes a little practice, but there is a system.

    So what does your program do now?

  • Hi Bruce,

    Thanks for the support. Code is working now.

    Regards,

    Bivin

**Attention** This is a public forum