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.

Timers mess on MSP430G2553 - event on TA1.0 doesn't trigger interrupt vector TIMER1_A0_VECTOR

Expert 1140 points
Other Parts Discussed in Thread: MSP430G2553

Hi,

I've just began working with MSP430G2 launchpad with MSP430G2553 onboard. I've studied the timers topic and got to implementing stuff, but I really got lost with all those Timer0 and Timer1 things.

First of all, I've connected the DHT11 humidity timer on P2.0/T1.0 and do the following:

TACTL = TASSEL_2 + MC_2; //SMCLK + Continuous mode
TACCTL0 = CM_3 + CCIS_0 + SCS + CAP + CCIE;
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer_A (void) {
    P1OUT ^= BIT6;
    TACCTL0 &= ~CCIFG;
}

I watch the P1.6 on the logic analyze to see whether it changes the logic state and it doesn't, although the state on P2.0/T1.0 does change (confirmed on the logic analyzer).

What do I do wrong? What the heck are Timer0 and Timer1? As far as I know MSP430 has Timer_A and/or Timer_B, here we have a mix of Timer numer 0/1 and letter A/B. Moreover, the sheet for MSP430G2 family mentiones Timer0 phrase  just once in the 660 pages long document.

Please give a little hint on that, thanks in advance!

tml

  • With TI, almost everything is a mess ;)

    The Data-sheet of MSP430G2553 tells you the address of all the peripheral registers. And it gives each of them a symbolic name. But the User's Guide may use a similar but different symbolic name. This is particularly true when there are more than one such peripheral in a chip. The compiler actually only need to know the address of the peripheral register you want to use. It looks up in the header file to find out address of what the symbolic name used in the source code is. And the header file changes depending on which version of which compiler you are using. So you end up with a game of guess what I mean, wink wink nudge nudge.

    Most of the I/O pins have multiple functions. In your case, did you set up P2.0/T1.0 as T1.0 input? Did you set up P1.6 as digital output? See Data-sheet Terminal Schematics Section.

    The code you have shown did not do the above. Also it did not set GIE thus all mask-able interrupt are masked (disabled). Furthermore, after the statement that sets TACCTL0, what is the CPU suppose to do?

  • The core code is below. The humidity sensor's data pin (one-pin bus but not 1wire) is connected to P2.0. Alternatively, I can connect it to P2.4, configured as GPIO input.

    The button triggering the DHT_init() is P1.3, the P1.6 pin is being toggled every time the interrupt is triggered and it works when I trigger the interrupt on P2.4. P1.6 is the main loop toggled LED.

    Can someone please help me understand what's the difference between Timer1 and Timer0, among TIMER0_A0_VECTOR, TIMER0_A1_VECTOR, TIMER1_A0_VECTOR and TIMER1_A1_VECTOR and what trigger these vectors? How come Timer_A became Timer0_A or Timer1_A?

    Do I correctly expect the TIMER0_A0_VECTOR to be triggered with P2.0? 

    #include <msp430.h>
    void DHT_init();
    int main(void)  {
       BCSCTL1 = CALBC1_8MHZ;
       DCOCTL = CALDCO_8MHZ;
       WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
       P1DIR = BIT6;
       P1OUT &= ~ BIT6;
       P1REN |= BIT3;
       P1OUT |= BIT3; //pullup
       P1IES |= BIT3; //hi to low
       P1IFG &= ~BIT3; //clear ifg   P1IE |= BIT3;
       _enable_interrupts();
       for(;;) {
          P1OUT ^= BIT6;
         __delay_cycles(1600000);
       }
    }
    void DHT_init() {
       P1DIR |= BIT6;
       //prepare the ports for DTH
       P2DIR |= BIT0;
       P2OUT |= BIT0;
       __delay_cycles(8000);
       P2OUT &= ~BIT0;
       __delay_cycles(175000);
       //...and get back to high signal on DHT pin for 20-40us...
       P2OUT |= BIT0;
       //set the input direction of this pin to get prepared for DHT data
       P2REN |= BIT0;
       P2DIR &= ~BIT0;
       //Bit = 0: The PxIFGx flag is set with a low-to-high transition
       //Bit = 1: The PxIFGx flag is set with a high-to-low transition
       
       //P2IES |= BIT4; //high to low transition on P2.4 starts the DHT's response
       //P2IE |= BIT4; //enable interrupts on BIT4
       
       //prepare the timer
       TACTL = TASSEL_2 + MC_2; //SMCLK + Continuous mode   
       TACCTL0 = CM_3 + CCIS_0 + SCS + CAP + CCIE;
       //now, in about 20-40us we can expect DHT's response}
    
    // Timer A0 interrupt service routine. TIMERx_Ay_VECTOR.(x being the index of the timer, y of the vector for this timer)
    #pragma vector=TIMER0_A0_VECTOR        // <---- this interrupt is NOT triggered when DHT connected to P2.0
    __interrupt void Timer_A (void) {
       P1OUT ^= BIT6;
       TACCTL0 &= ~CCIFG;
    }
    
    #pragma vector = PORT2_VECTOR        // <---- this interrupt is triggered when DHT connected to P2.4
    __interrupt void Port2DHT_ISR(void) {
       P2IES ^= BIT4; //toggle IES
       P1OUT ^= BIT6;
       P2IFG &= ~BIT4;
    }
    
    #pragma vector = PORT1_VECTOR
    __interrupt void Port1_btn_ISR(void) {
       DHT_init();   
       P1IFG &= ~BIT3;
    }
    
  • Hi,

    tml said:

    The core code is below. The humidity sensor's data pin (one-pin bus but not 1wire) is connected to P2.0. Alternatively, I can connect it to P2.4, configured as GPIO input.

       //prepare the timer
       TACTL = TASSEL_2 + MC_2; //SMCLK + Continuous mode   
       TACCTL0 = CM_3 + CCIS_0 + SCS + CAP + CCIE;
    

    you wanted to use P2.0 (TA1.0) as the capture input, is it right?

    If yes, then you should configure TA1CTL and TA1CCTL register instead TACTL and TACCTL0. Basically the G2553 has two Timer_A modules: TA0 and TA1, and i believe you want to use TA1.

    Looking into the header file of CCS:

    /* Alternate register names */
    #define TAIV TA0IV /* Timer A Interrupt Vector Word */
    #define TACTL TA0CTL /* Timer A Control */
    #define TACCTL0 TA0CCTL0 /* Timer A Capture/Compare Control 0 */
    #define TACCTL1 TA0CCTL1 /* Timer A Capture/Compare Control 1 */
    #define TACCTL2 TA0CCTL2 /* Timer A Capture/Compare Control 2 */
    #define TAR TA0R /* Timer A */
    #define TACCR0 TA0CCR0 /* Timer A Capture/Compare 0 */
    #define TACCR1 TA0CCR1 /* Timer A Capture/Compare 1 */
    #define TACCR2 TA0CCR2 /* Timer A Capture/Compare 2 */
    #define TAIV_ TA0IV_ /* Timer A Interrupt Vector Word */
    #define TACTL_ TA0CTL_ /* Timer A Control */
    #define TACCTL0_ TA0CCTL0_ /* Timer A Capture/Compare Control 0 */
    #define TACCTL1_ TA0CCTL1_ /* Timer A Capture/Compare Control 1 */
    #define TACCTL2_ TA0CCTL2_ /* Timer A Capture/Compare Control 2 */
    #define TAR_ TA0R_ /* Timer A */
    #define TACCR0_ TA0CCR0_ /* Timer A Capture/Compare 0 */
    #define TACCR1_ TA0CCR1_ /* Timer A Capture/Compare 1 */
    #define TACCR2_ TA0CCR2_ /* Timer A Capture/Compare 2 */

    as you can see there if the register is addressed without moudle number, then it will refer to TA0.

    another thing is that i think your P2.0 setup is not really correct. According to the datasheet, you shall set the following register bits to make P2.0 act as TA1.0:

    tml said:

    Can someone please help me understand what's the difference between Timer1 and Timer0, among TIMER0_A0_VECTOR, TIMER0_A1_VECTOR, TIMER1_A0_VECTOR and TIMER1_A1_VECTOR and what trigger these vectors? How come Timer_A became Timer0_A or Timer1_A?

    If you look into the header file of CCS compiler, you see it the comment explains the syntax:

    #define TIMER0_A1_VECTOR ".int08" /* 0xFFF0 Timer0)A CC1, TA0 */

    #define TIMER0_A0_VECTOR ".int09" /* 0xFFF2 Timer0_A CC0 */

    #define TIMER1_A1_VECTOR ".int12" /* 0xFFF8 Timer1_A CC1-4, TA1 */

    #define TIMER1_A0_VECTOR ".int13" /* 0xFFFA Timer1_A CC0 */

    As you might probably understand, each Timer_A has two interrupt vectors: one for CCR0, and another one for TAIFG and the rest of CCRx. 

    so the format is TIMER(X)_A(Y)_VECTOR where X is the module number (0=TA0, 1=TA1 for G2553) and Y is the vector number (0=CCR0, 1=TAIFG&other CCRs).

    So in your case, if you want to capture interrupt at P2.0 (TA1.0), you should use the TIMER1_A0_VECTOR.

    Hope this helps.

  • Thank you Leo, that explains pretty much what I needed to understand!

    Therefore I should try catching the TA1.0 signal on TIMER1_A0_VECTOR, preceded by P2SEL |= BIT0.

  • THANK YOU for clearing that up!!

**Attention** This is a public forum