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.

MSP430 Timer B TBIFG Interrupt resets when it enters interrupt

Other Parts Discussed in Thread: MSP430F233

Hi,

I'm trying to run Timer B on my MSP430F233. The MSP receives a variable number from another MSP430 and the MSP should turn on an H-Bridge for that amount of time, then turn it off again. I am using Capture Compare Register 0 to set the timer and then when the interrupt comes it turns off the bridge. TimerB uses the ACLK = VLO/4 = 12kHz/4 = 3kHz.

Because the time to wait may be more than 21.845s (65535/3000 = 21.845) I need to use the timer rollover TBIFG interrupt to subtract the passed time from the time that is yet to be waited. The number passed from the other controller is /150 the number of cycles that need to be waited, so I can wait up to 9830250 timer cycles or ~54 minutes. In other words, only 436.9 are counted off each Timer B rollover of 65535 cycles, so if the number passed was 500, after 1 rollover I still need to wait 63.1 or 9465 Timer B cycles.

I now have 2 problems with the Timer B interrupts.

1. I set TBCTL to 0x122 or Continuous Mode, ACLK, and TBIE.

So when the timer B rolls over after 65535 it should cause a TBIFG interrupt to happen so I can subtract 436.9 from my original wait time. This interrupt does not seem to happen. The timer just rolls over and continues counting. TBIFG also does not set, or is reset somehow. However, when I set TBCTL to 0x120, so the interrupt in NOT enabled, the TBIFG sets but no interrupt is entered. Is there something else I need to set to get this interrupt?

I use this as an interrupt vector handler:

#pragma vector=TIMERB0_VECTOR
__interrupt void TIMERB0_ISR(void)

{

     //Code

}

2. When the number passed is less than 436.9, I set the TBCRR0 to 150* that number and TBCCTL0 |= CCIE; so that an interrupt is generated when the proper time has elapsed. This uses the same interrupt vector as TBIFG. This interrupt works fine. However, TBCCTL0 should have bit 1 set when the interrupt happened. This bit is reset as soon as the interrupt is entered (or is never set). Since I'm using both TBIFG and TBCCR0 CCIFG within the interrupt handler I need to find out what case caused the interrupt. I do this by testing "if(TBCTL & TBIFG)" and "if(TBCCTL0 & CCIFG)". However, if neither flag is set or they are reset, when the interrupt happens it enters neither statement and the interrupt does nothing. Is the CCIFG flag supposed to reset as soon as the interrupt is handled, and if so, how can I test for it?

Right now, the program calls the CC0 interrupt but doesn't enter the if statement since the flag is reset, and it just interrupts again after it's rolled over and counted to TBCCR0 again, and so on infinitely (timer gets turned off in interrupt). If I do not activate the TBCTL interrupt, the TBIFG flag sets and the second time it reached TBCCR0 it enters the TBIFG case.

I've read through the manual on TimerB a few times now and I'm wondering if something is wrong with my understanding or with my MSP430.The manual says "The TBCCR0 CCIFG flag is automatically reset when the TBCCR0 interrupt request is serviced." I am not sure whether that is supposed to mean as soon as the interrupt is entered or after it's left... I need to distinguish between the TBIFG rollover case and TBCCR0IFG case somehow.

I discovered these problems and what is happening using the CCS debugger. I tried it using the TBCCR1. In this case the CCIFG flag is set just fine and not reset until I read TBIV. That doesn't change the fact that I'm not entering an interrupt when TB rolls over.

I am grateful for any help with this!

  • Samuel Boegli said:
    I set TBCTL to 0x122 or Continuous Mode, ACLK, and TBIE.

    And that's the problem. TBIE (intentionally) enables the timer overflow interrupt which triggers the ISR at TIMERB1_VECTOR. Since you don't have a TIMERB1 ISR to handle the overflow event, the processor jumps into the void and eventually resets.

    You'll need both, a TIMERB1 ISR for counting the overflows (the  upper 32 bits of the time) and a TIMERB0 ISR to compare the desired upper 16 bits with the current overflow counter. (or a countdown, however you implement it). Don't forget to clear the TBIFG bit inside the TIMERB1 ISR.

     

    Also, the CCIFG bit in TBCCR0 is cleared by hardware when the TIMERB0 ISR is entered. Ther eis only one IF Gbit that triggers teh TIMERB0 ISR, so to save you some precious time, the bit auto-clears once the interrupt has been accepted. You'll never see this bit set inside the ISR, unless another interrupt occurred while you're still inside the ISR (indicating that your code has a serious problem, or you stopped at a breakpoint inside the ISR without stopping the clocks :) )

  • Thanks! You're right, I used the wrong interrupt vector for TBIFG.

    I'm left with the problem that the CCIFG bit is cleared when I enter the CCR0 interrupt vector. I can say that it's the only case where that vector is entered, but it would still be nice if I could confirm that with "if(TBCCTL0 & CCIFG)". So is that not possible?

  • Samuel Boegli said:
    I can say that it's the only case where that vector is entered

    Yes. That's it. Nothing else (except a forced jump/function call to this funciton) can make the CPU enter this ISR.
    If you don't set CCIE, you can manually check the IFG bit if you want, bu thten of course the ISR is not entered.

    The only reason why the ISR for CCR0 has its own vector, is to allow fastest possible and shortest possible operation on this interrupt.
    Having to manually check (and clear !) this flag would waste time. And then CCR0 interrupt could as well go to the same vector as all other timer interrupts, saving a vector, some hardware and some confusion about these vectors.

  • Alright, thank you very much for your help!

  • Turns out the same is true for Timer A.  I was using   #pragma vector=TIMERA0_VECTOR expecting an interrupt if timer A overflowed, but I need #pragma vector=TIMERA1_VECTOR instead.  Thank you  TI E2E community

**Attention** This is a public forum