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 Issue

Expert 1175 points

Other Parts Discussed in Thread: MSP430F5418

Hello All,

I am using MSP430F5418 with IAR.

I have 32KHz ACLK. and a button is connected to P1.0

My aim is to swap the state of an LED connected to P5.1 after two seconds from the time of button press.

Below is my code. My problem is, some times the LED is blinking with correct interval and some times not.

Can anybody tell me why is it so??

int main(void)
{
    WDTCTL = WDTPW + WDTHOLD;  
    P1IE |= BIT0;
    P5DIR |= BIT1;
    TBCCR0 = 0xffff - 1;
    TBCTL = TBSSEL__ACLK + MC__UP + TBCLR;          // ACLK, upmode, clear TBR
    __enable_interrupt();
    for(;;);
}

#pragma vector=TIMERB0_VECTOR
__interrupt void TIMERB1_ISR(void)
{
    P5OUT ^= BIT1;
    TB0CCTL0 &= ~CCIE;
}

#pragma vector = PORT1_VECTOR
static __interrupt void keypad_isr (void)
{
    TB0CCTL0 |= CCIE;
    P1IFG = 0;
}

  • Hi Hari,

    you need to debounce your button. You can do it i.e. by disabling it's interrupt once the button is pressed and have it re-enabled in the Timer ISR. 

    Kind regards
    aBUGSworstnightmare 

  • Ya I have done debouncing also.

    But still it doesn't work.

    I also used continious mode, but the same problem exists there too.

     

  • Hari,

    I understand you want to toggle the LED state two seconds after the button press.

    Consider the keypress ISR:

    Hari said:

    #pragma vector = PORT1_VECTOR
    static __interrupt void keypad_isr (void)
    {
        TB0CCTL0 |= CCIE;
        P1IFG = 0;
    }

    When this ISR executes, what is the state of CCIFG in TB0CCTL0?  Also what is the value of TB0R (the counter)?  You should carefully consider these questions as you keep working on this problem.  May I ask you if this is school work?

    Jeff

  • Hello,

    Thanks for your answer

    The timer is configured in up mode. so the CCIFG will set when the timer counts to 0xffe isn't it? From the Timer ISR after toggling the LED the timer interrupt is disabled.

    Even if I write TBCCR0 = TB0R + 0xffff - 1 within port ISR the same result is happening. (Initially it will give correct interval and after some time the interval changes )

    This is not a school work. My Actual intention is to display a screen after last key press. Since it is not working I just checked with a simple LCD.

    Hari

  • Thank you for mentioning abount the CCIFG Flag.

    It was the problem. So I cleard it just after enabling the timer interrupts in port ISR.

    Now the problem is fixed.

    I am wondering why the CCIFG is enable before an interrupt came.

    Can you tell me what are the situations in which the flag is setting??

     

    Thank you Very much...........

    Hari

  • Hari said:
    I am wondering why the CCIFG is enable before an interrupt came.

    CCIFG is set when TAR matches CCR0. Which will happen sooner or later, even if you never touch one of the two. And since nobody cleared it, it is still set. And as soon as the corresponding IE bit is set, the interrupt happens.
    This happens for many other flags too. e.g. on the UARTs: initially, the transmit buffer is empty, so the TXIFG bit is set. As soon as you set TXIE, your ISR will be called to fill the TX buffer.
    This can be really useful - you can trigger on events that were in the past, even before you enabled the interrupt. In my TX function, I write new data to a ring buffer and set TXIE. If TSBUF is empty, this will trigger a TX interrupt immediately and starts sending. If there is a transfer already in progress, it does nothing as TXIE is alreadsy set.
    Inside the TX ISR, when ther eis nothing more to send in the buffer, I simply clear TXIE and whiel TXIFG is still set, the ISR is no longer called. Once I write something to the buffer and set TXIE, the process begins anew. No need to check whether the ISR has stopped and disabled the interrupt on every byte write, Or to do a 'kickstart' write if the transfer stopped.

    All you need to do is to take care of clearing any unwanted events flags when you initialize a module.

  • Hari said:

    ... TBCCR0 = TB0R + 0xffff - 1 ..

    Hi Hari,

    Just as a word of warning, you should probably make a confirmed read of TB0R.  For example, your code might look like this for a two-second delay:

    do {TBCCR0 = TBR;} while (TBCCR0 != TBR);  // "confirmed" read (aka majority vote)

    TBCCTL0 = CCIE;

    P1IFG = 0;

    The confirmed read makes sure you don't accidentally read TBR while it is invalid during an increment operation.  When TBR and the CPU are not clocked by the same clock, you need to read TBR carefully  For slow TBR clocks, a confirmed read works nicely.  For fast TBR clocks, you can use a synchronized software capture into TBCCRn.

    Jeff

**Attention** This is a public forum