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.

TimerA interrupt trouble

Other Parts Discussed in Thread: MSP430F2274

Hi, 

I am making a code with TimerA. On it I encountered a curious thing. 

I made a 1-second-count-up timer with TimerA0 interrupt and TACCR0 = 32768. 

The code below doesn't go well. The valiable 'second ' doesn't increase correctly. It looks like two-beat walking, 0 ->1->2->1->2->...  

But, after uncommenting TimerA1 interrupt codes, which is useless now, the code goes well without a problem. 

Why does it go well after enabling TimerA1 interrupt code? I can't understand it.

Would anybody please give me suggestion? Thank you in advance.

Regards,

 

#include "msp430x22x4.h"

unsigned int second = 0;
unsigned int minute = 0;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop WDT
 
// CLK set DCO = 8MHz, CPUCLK(MCLK) = 4MHz, SMCLK = 4MHz  
  DCOCTL = CALDCO_8MHZ;
  BCSCTL1 = CALBC1_8MHZ; // Set DCO to 8MHz
  BCSCTL2 = DIVM_1 + DIVS_1; // MCLK Divider 1: /2, SMCLK Divider 1: /2
  BCSCTL3 |= (LFXT1S_0 + XCAP_1); // Mode 0 for LFXT1 : Normal operation
   
//// TimerA set
  TACTL = TASSEL_1 + MC_2 + TAIE; // ACLK, contmode
  TACCTL0 = CCIE; // TACCR0 interrupt enabled
// TACCTL1 = CCIE;        // uncomment here  
  TACCR0 = 32768;
// TACCR1 = 100 + 32768;        // uncomment here  

// port set
  P1DIR |= 0x03; // Set P1.0, P1.1 to output
 
// ADC set port- A0, A1, A2, A6, A7
  ADC10AE0 = 0xC7; // P2.0/1/2,P3.6/7 ADC port enable
 
  while (1)
  {
 if (second == 60)
 {
  second = 0;
  minute++;
 }
 __bis_SR_register(LPM3_bits + GIE); // Enter LPM3, enable interrupts
  }
}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void)
{
 P1OUT ^= 0x01; // Set P1.0
 second++;
 TACCR0 += 32768; // Add Offset to TACCR0
 __bic_SR_register_on_exit(LPM3_bits); // Exit LPM
}
//// Timer A1 interrupt service routine
//#pragma vector=TIMERA1_VECTOR        // uncomment below      
//__interrupt void Timer_A1 (void)
//{
// switch (TAIV)
// {
// case 2:
// TACCR1 += 32768;
// break;
// }
//}

 

  • I got it at last. 

    I stuck to to the description of Timer_A Registers, TACTL. 

      '+ TAIE' is not necessary. I removed it then the code runs correct. 

    It is difficult to see what interrupt enable bit to use in the hardware manual.  

    We have CCIE bits for each compare/ capture register and TAIE bit. The relation between CCIE bits and TAIE is not clear in the register description. 

    I saw and compared the sample codes msp430x22x4_ta_01.c, msp430x22x4_ta_04.c and msp430x22x4_ta_06.c. Then I found the system.

    CCR0 -> CCIE only. Not need TAIE.

    CCR1, CCR2 -> either CCIE or TAIE

    overflow -> TAIE only. No CCIE bit.

    Thank you.  

  • Well done for sorting out your problem!  If you prompt an interrupt (the overflow of counting 0xFFFF to 0 sets TAIFG which prompts the interrupt for the TIMERA1_VECTOR) without specifying an ISR for that vector then problems will ensue!

     

    kusanagi said:
    CCR1, CCR2 -> either CCIE or TAIE

    I disagree with you here.  TAIE enables an interrupt when TAIFG is set.  TAIFG is set when the counter counts to 0 (e.g. overflow in up and continuous up modes and when counting down from 1 to 0 in up/down mode).  The CCIE bits are related to the CCR modules and are separate from the TAIE - if you want to have an interrupt for CCR1/2 then you have to set their relevant CCIE bits.

  • Hi,

    do you know Grace? Have a look at it here: http://focus.ti.com/docs/toolsw/folders/print/grace.html?DCMP=Grace&HQS=Other+EM+grace

    It will help you in configuring your MSP430 series peripherals (Value Line and MSP430F2274 at the moment (it is still beta), more to come).

    Rgds
    aBUGSworstnightmare 

  • chris_m said:

    The CCIE bits are related to the CCR modules and are separate from the TAIE - if you want to have an interrupt for CCR1/2 then you have to set their relevant CCIE bits.

    This is important. Then, 

    CCR0 -> CCIE only. Not need TAIE. 

    CCR1, CCR2 -> both CCIE and TAIE

    overflow -> TAIE only. No CCIE bit.

    I didn't know Grace. It looks like Cypress PSoC Designer. It is good for beginners. 

    I tryed to install it but the site--software- dl.ti.com was down. 'Network Connection Problem' occurs. I try later. 

    Thank you. 

     

     

  • kusanagi said:
    CCR1, CCR2 -> both CCIE and TAIE

    No!  If you want an interrupt for CCR1 then just set the CCIE bit in TACCTL1.  Likewise for CCR2 just set the CCIE bit in TACCTL2.  If you want an interrupt for the overflow then set the TAIE bit BUT IF YOU DON'T WANT THE OVERFLOW INTERRUPT THEN DON'T SET THE TAIE BIT!!

  • Allow me to pitch a curve-ball at you.

    Assume that TACCTL1 is almost the way you wanted. Except that its associated interrupt is not enabled yet and you want to enable that.

    ---

    TACCTL1 |= CCIE;

    Will do that nicely.

    ---

    You could also use one of the following instead:

    TACCTL1 |= LOCK;

    TACCTL1 |= NMIIFG;

    TACCTL1 |= LFXT1S0;

    TACCTL1 |= CCI + CCI;

    They sound strange, never the less, the c-compiler will generate exactly the same code as before.

    ---

    But you cannot get the same effect if you use:

    TACCTL1 |= TAIE;

    ---

    Hint: Take a look at the header file and find out how CCIE, LOCK, NMIIFG, LFXT1S0, CCI and TAIE are defined. Also read the User's Guide to find out how TACCTL1 works.

     

     

  • kusanagi said:

    CCR0 -> CCIE only. Not need TAIE. 

    CCR1, CCR2 -> both CCIE and TAIE

    overflow -> TAIE only. No CCIE bit.

    Ah... no!

    TAIE and CCIE are just aliases for a bit value (TAIE = 0x02, CCIE = 0x10) and have only a meaning in the context of a certain hardware register. TAIE is for use with TAxCTL register, while CCIE is only for use with TAxCCTLn register. Setting TAIE in TAxCCTLx causes the COV bit (capture overflow) being set 8which has no meaning fin compare mode)

    Also, the itnerrupts enables by TAIE and CCIE are completely different. TAIE will enable the tiemr overflow interrupt, which is completely independent of the CCRx interrupts. If you use the timer in Up mode, however, the condition CCR===TAR will cause a CCR0 interrupt and also cause the tiemr to roll over to 0, which will in turrn cause a Timer overflow (TAIFG) one tiemr tick later (whcih may, on a slow timer clock, be ages later, but usually is very close to the CCR0 interrupt).

    The interrupts of the other CCR units (CCR1..CCR6) are completely independent, but share the same interrupt vector as the TiemrA overflow interrupt. It's necessary to either check the IFG bits or the TAIV vector to determine which one has caused the interrupt. And if you check the IFG bits, it's necessary to reset them manually.
    The CCR0 interrupt, however, has its own interrupt vector and the CCRIFG bit for CCCR0 is automatically cleared once its ISR is called.

    So setting CCIE is necessary for any CCRx related interrupt (and needs to be set in the CCTLx register) and TAIE is necessary, if you want a timer overflow interrupt (which may or may not be influenced by CCR0, depending on whether you are running the timer in UP mode or not, but still works independent of the use of CCIE in CCTL0)

  • Gentlemen:

    Thank you for your replies.

    Now I agree with you. No! 

    I checked the User's Guide again after I read the reply of Mr. Chris_M. 

    The detail comment of Mr. Jens-Michael Gross is very helpful. Thank you. 

    • My first misunderstanding was that TAIE was necessary to use any TimerA interrupt. 
      The description in the TACTL register page could be read so because of its short expression. 
      • TAIE-- Timer_A interrupt enable. This bit enables the TAIFG interrupt request.
      • TAIFG-- Timer_A interrupt flag 
    • Actually TAIE enables only TAIFG, which means TimerA overflow interrupt.  
    • Next misunderstanding was that TAIE was necessary to use TAIV vector. It is a fault.

    Thank you again.

  • "TAIE" does sound a bit generic so I can understand your confusion with the TAIV.  I agree that the information is a bit spread out in the user guide and not easy to immediately understand.  I found some of the timing diagrams quite helpful when trying to get my head around it.  Once you've set up the timer module a few times it'll seem easy!

     

    Regards,

    Chris.

**Attention** This is a public forum