Jump to content

Combined PWM with interrupt not interrupting

Recommended Posts

Hi All,


I am trying to generate a PWM output using TimerA, which I also want to trigger an interrupt at TACCR0.

There is nothing in the manual that suggests I cant do this, but for some reason the interrupt is not firing, even though PWM is working as expected.


Here is how I set it up, can anyone spot anything obvious?

#define PWMOUT BIT2;
P1OUT &= ~PWMOUT; // output 0 to start with
P1DIR |= PWMOUT; // set as output
P1SEL |= PWMOUT; // select timer OUT
TA0CCTL1 |= OUTMOD_7; // setup pwm output mode 
TA0CCTL0 |= CCIE; // enable interrupt 
TA0CTL |= (TASSEL_2 + MC_1 + TAIE); // start timer, enable interrupts

and the ISR

#pragma vector=TIMER0_A0_VECTOR //Timer A0 CCR0.
__interrupt void PWM_Cycle(void)
Link to post
Share on other sites

If the TA0CTL line you posted isn't actually commented out, then your code may be stuck in the other Timer A interrupt (TIMER0_A1_VECTOR). That interrupt requires reading TA0IV to clear the flag. If you don't read TA0IV, it will get stuck with that ISR repeating endlessly. The fix is to remove TAIE from that line.


TA0CCTL0 |= CCIE; // enable interrupt
TA0CTL |= (TASSEL_2 + MC_1 + TAIE); // start timer, enable interrupts
Link to post
Share on other sites

They are two distinct interrupts, you do not have to enable both.


The TAIE bit in TACTL enables an interrupt that occurs when the timer reaches 0.


The CCIE bit in the TACCTLx registers enables an interrupt that occurs on a match between the compare register or a capture event.


All these interrupt enable bits are completely independent of each other. Enable only those that you are using and have written an ISR for.


The only other interrupt that has to be enabled is the global interrupt flag in the status register. That can be enabled with _enable_interrupts() or a few other methods.

Link to post
Share on other sites

In addition to @@oPossum 's awesome advice, the final point that always confuses people is that each Timer has TWO different ISRs. One (TIMER0_A0_VECTOR) is a special higher priority one just for TA0CCR0, and its interrupt flag is cleared automatically by entering the ISR at all. The other one (TIMER0_A1_VECTOR) is for all of the other TA0CCRx interrupts and TAIE - this is the one that uses TAIV - its highest-priority pending flag is cleared by reading TAIV.


This code example uses both of them, so you can see: http://dev.ti.com/tirex/#/?link=MSPWare%2FDevices%2FMSP430%2FMSP430G2XX%2FMSP430G2553%2FExamples%2FC%2Fmsp430g2xx3_ta_07.c


It's a common point that trips people up. 


If you currently have no ISR defined for TIMER0_A1_VECTOR but have TAIE enabled, if you use CCS for example it defines a trap ISR for all undefined ISRs for just this case (so part doesn't jump off into some random location), so your part is probably hanging out there. 

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...