Jump to content

Interrupts from Timer CCR1

Recommended Posts


Hi All,


Im having a bit of trouble with these interrupts on TimerB2 on the MSP430FR5739.


I am using 3 compare registers, TB2CCR0 = 250, TB2CCR1 = 150 & TB2CCR2 = 50


CCR0 Interrupts are easy enough, but im confused when it comes to the rest.

The Family guide says:


The TBIFG flag and TBxCCRn CCIFG flags (excluding TBxCCR0 CCIFG) are prioritized and combined to
source a single interrupt vector. The interrupt vector register TBxIV is used to determine which flag
requested an interrupt.
Any access, read or write, of the TBxIV register automatically resets the highest-pending interrupt flag. If
another interrupt flag is set, another interrupt is immediately generated after servicing the initial interrupt.
For example, if the TBxCCR1 and TBxCCR2 CCIFG flags are set when the interrupt service routine
accesses the TBxIV register, TBxCCR1 CCIFG is reset automatically.
I was hoping to use the following code, using TB2IV to detemrine which CCRn caused the interrupt but if I read this correctly it will be cleared before I get a chance?
Can someone help? Am I misreading or is there a trick around this?
//=====Interrupt for 40Hz timer pre-sample=====
#pragma vector=TIMER2_B1_VECTOR
__interrupt void Interrupt_40_pre(void)
	switch (TB2IV)
		case 0x02: //Temp
		case 0x04: //Baro
Link to post
Share on other sites

Hi @@basil4j,


Your code is on the right track and should work - in fact this is basically the same way the interrupts are handled in the TI MSP430FR5739 code examples (www.ti.com/lit/zip/slac491 ). You can look at for example MSP430FR57xx_tb0_03.c in that zip file. You can see the ISR looks very similar to yours:

// TimerB Interrupt Vector (TBIV) handler
#pragma vector=TIMER0_B1_VECTOR
__interrupt void TIMER0_B1_ISR(void)
    case  0: break;                          // No interrupt
    case  2: break;                          // CCR1 not used
    case  4: break;                          // CCR2 not used
    case  6: break;                          // reserved
    case  8: break;                          // reserved
    case 10: break;                          // reserved
    case 12: break;                          // reserved
    case 14: P1OUT ^= 0x01;                  // overflow
    default: break; 

I think the confusion is about the part of the user's guide that talks about autoclearing the flags when the TBxIV register is read out. The trick is that it only clears the highest priority flag that is set and leaves the others. This means that it will only clear the one that your switch statement will service in this iteration.


For example, in your ISR above, if you enter the ISR and both the interrupts for 0x02 and 0x04 are already pending, then TBxIV will read as just 0x02 (it only reads as whatever is the highest-priority pending interrupt), though an interrupt flag in the TBxCCTLx register corresponding to the 0x04 interrupt vector is still set, so it will still be pending. From the user's guide:



The highest-priority enabled interrupt (excluding TBxCCR0 CCIFG) generates a number in the TBxIV
register (see register description).


When TBxIV is read, only the highest priority interrupt (the value that you just read out), in this case 0x02, is cleared, and TBxIV will then update to the value of the next highest priority interrupt that is still pending. So after you exit the ISR having serviced 0x02 in your switch statement, you will re-enter your ISR again because 0x04 is still pending, and this time TBxIV will read 0x04.


I hope this helps clear things up - it is pretty useful the way that it works, but can be a bit tricky to understand when you are first starting to use it.




Link to post
Share on other sites

Thanks Katie, my confusion is more around the statment in the manual 'if the TBxCCR1 and TBxCCR2 CFIG flags are set when the interrupt servicr routine accesses the TBxIV register, TBxCCR1 CCIFG is reset automatically. '


This says to me the interrupt routine itself resets the flag once it's decided to use the vector, thus will clear before my switch case even sees it?


Sent from my GT-I9300 using Tapatalk



Link to post
Share on other sites

Not quite - it does actually clear the single TBxCCRn flag that corresponds to the value currently in TBxIV (the highest priority interrupt), as well as clearing TBxIV and setting it to the next priority pending interrupt, but it only does this when your code actually reads out the register TBxIV, not just as soon as the ISR is entered.


You can observe this happening by adding a _no_operation(); before your switch inside your ISR, and put a breakpoint there. Open the register view in your debugger and take note of the state of the CCIFG bits in the TBxCCTLn registers, and the value in TBxIV. You'll see that the CCIFG and TBxIV values are still set on entry to the ISR. Now, single step over the switch statement (where it reads TBxIV) and you'll see that this is the time when the TBxIV and the CCIFG value are cleared. But since your switch is what read TBxIV, it already has the value to jump to the correct case.


I think the easiest way to understand it is probably to run it on a part and step through it and watch what the flags and registers do.




Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...