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.

LED blinking using TimerA

Other Parts Discussed in Thread: MSP430G2231

Hi,


I'm using msp430g2231 launchpad. I'm trying to blink the LED whenever the TimerA's TACCR0 overflows and sets the CCIFG flag. I'm using ACLK=12Khz clock. CCR0=24,000. This will give me 2s LED blinking rate. Here is the code.


Problem: I'm not getting 2 second blinking rate.

Code:

#include <msp430g2231.h>

/*
 * main.c
 */
int main(void) {
    WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer
    
    P1DIR |= BIT6; // set P1.6 as output
    P1OUT &= ~BIT6;// each time clear the P1.6

    TACTL= TASSEL_1 + MC_2;    // ACLK=12KHz
    CCR0 = 24000;                          //TACCR0 counts to 12000
    // 12000 Hz / 24000 = 0.5Hz = 2s

    while(1)
    {
        if ((TACCTL0 & CCIFG) == 1) // is there any other way to check the flag?
            P1OUT ^= BIT6;
            TACCTL0 &= ~CCIFG;  // is this correct way to reset the flag?
    }
}

Thanks

  • Hello,

    If you implement the timer interrupt you can have an LED that blinks every 2s.  Is there a reason for not using the interrupt?  What I noticed with the above code is that the CCIFG bit is not getting cleared after BIT6 is toggled every time.  The bit is cleared after about 4 seconds.  Here is code using timer interrupt:

    int  main(void){

    WDTCTL = WDTPW + WDTHOLD;  // Stop WDT

    P1DIR |= BIT6;  // P1.6 output

    TA0CCTL0 = CCIE;  // CCR0 interrupt enabled

    TA0CCR0 = 24000;

    TA0CTL= TASSEL_1 + MC_2;

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

    __no_operation();   // For debugger

    }

    // Timer0 A0 interrupt service routine

    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)

    #pragma  vector=TIMER0_A0_VECTOR

    __interrupt  void TIMER0_A0_ISR(void)

    #elif defined(__GNUC__)

    void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR (void)

    #else

    #error Compiler not supported!

    #endif

    {

    P1OUT ^= BIT6;  // Toggle P1.6

    }

  • If you use interrupts as suggested by Arthi Bhat1 you will save power.

    But you can also do it your way with a few changes as shown here:

    #include <msp430g2231.h>
    
    /*
     * main.c
     */
    int main(void) {
        WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer
    
        P1DIR |= BIT6; // set P1.6 as output
        P1OUT &= ~BIT6;// each time clear the P1.6
    
        TACTL= TASSEL_1 + MC_1;    // ACLK=12KHz - You had MC_2 which makes timer count to 0xFFFF
        CCR0 = 24000;              //TACCR0 counts to 12000
        // 12000 Hz / 24000 = 0.5Hz = 2s
    
        while(1)
        {
            if (TACCTL0 & CCIFG) // is there any other way to check the flag? - Don't need ==1
    
            {//Use Brackets here so CCIFG only cleared when set
            	P1OUT ^= BIT6;
                TACCTL0 &= ~CCIFG;  // is this correct way to reset the flag? - Yes
            }//Use Brackets here so CCIFG only cleared when set
    
        }
    }
    

    Edited to highlight in red

  • /*
     * main.c
     */
    int main(void) {
        WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer
        
        P1DIR |= BIT6; // set P1.6 as output
        P1OUT &= ~BIT6;// each time clear the P1.6

        TACTL= TASSEL_1 + MC_2;    // ACLK=12KHz
        CCR0 = 24000;                          //TACCR0 counts to 12000
        // 12000 Hz / 24000 = 0.5Hz = 2s

        while(1)
        {
            if ((TACCTL0 & CCIFG) == 1) // is there any other way to check the flag?
            {
                P1OUT ^= BIT6;
                TACCTL0 &= ~CCIFG;  // is this correct way to reset the flag?
            }
        }
    }

  • Hey Ronak,

    You should use   Insert code using Syntaxhighlighter for code insertion for better look and readability. 

    Ronak Sakaria said:
     if ((TACCTL0 & CCIFG) == 1) // is there any other way to check the flag?
                P1OUT ^= BIT6;
                TACCTL0 &= ~CCIFG;  // is this correct way to reset the flag?

      if ((TACCTL0 & CCIFG) == 1) // is there any other way to check the flag?
    {
                P1OUT ^= BIT6;
                TACCTL0 &= ~CCIFG;  // is this correct way to reset the flag?
    }

    Regards,
    Dharmendra Sharma
    INDIA


    __________________________________
    Do, click "Verify Answer", if any of my replies helps solve your problem.

     

  • Ronak,

    If you’re not getting 2s blink rate, what do you get?
    You don’t have a crystal attached. It seems you try to use VLO. However, you do not select VLO as ACLK source (LFXT1S_2). AFAIK, the default is using the crystal, and there is no fallback if the crystal fails. So your ACLK has 0Hz.
    Also, when using VLO, the frequency is not 12kHz. This is a typical frequency, but from device to device this can vary in the range of 4kHz to 20kHz.

    "Is there any other way to check the flag?"

    First, checking if(TACCTL0&CCIFG) is sufficient, as the result is either CCIFG or 0, which will be interpreted as true or false. No need to do an additional comparison of whether the result is 1. (as a hint, if you use CCIFG here, then use CCIFG there too, instead of a numeric constant - if CCIFG would for some reason not be 1, then your expression would always give false - great chance for typos that are difficult to detect)

    As an alternative to a busy-loop and manual checking, you can set the CCIE bit and write an ISR that gets called as soon (and as long) as CCIFG is set. In case of CCR0, it has its own ISR (TIMER0_A0_VECTOR) and clears CCR0.CCIFG automatically when called. For the other CCRs, there is a common vector and you have to manually clear the CCIFG bits, like you do now.

    The advantage of using an ISR is that main can do other things wihtout ever caring for CCR0.CCIFG - or can enter low-power mode and save some energy while the hardware is waiting for the interrupt.

**Attention** This is a public forum