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.

Input Capture for MSP430G2553

Other Parts Discussed in Thread: MSP430G2553

Here is my code for Input Capture.

Remember that TACCRx is the register that store the time (TAR) when the capture occur.

#include <msp430g2553.h>
void main(void) {
    WDTCTL = WDTPW + WDTHOLD;    // Stop WDT
    TACTL |= TASSEL_2 + MC_2;    // SMCLK + Continuous mode
    TACCTL0 |= CM_1 + CCIS_0 + SCS + CAP + CCIE ;    // Raising Edge + CCI0A + Sync + Capture Mode + Interrupt enable
    P1OUT = 0x00;
    P1DIR |= BIT0; //RED LED
    P1SEL |= BIT1; //set this bit as Input Capture (TA0.CCI0A)
    _BIS_SR(LPM0_bits + GIE); //SMCLK active + Interrupts
}


#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
    {
        P1OUT ^= 0x01; //Toggle RedLED
    }

  • Your code has the usual flaw of using |= where = should have been used. This is not any better or worse than most other examples that people are copying and propagating.

  • old_cow_yellow said:
    Your code has the usual flaw of using |= where = should have been used.

    Since the initial value is 0x00, it makes no difference (except wasting a clock cycle).
    More dangerous (but also not causing any bug in this specific case) is the use of an arithmetical addition (+) to combine bit values. Also a common mistake. Often, it works, but it may go epically wrong. Combining bits shoudl be done with the binary OR (|) and not with the arithmetical add.

    But the biggest question is: what is the problem? Does the code run as expected (and what is expected)? Or does it not? And if not, what happens (or doesn't happen)?

  • Hello Jens,

    Jens-Michael Gross said:

    More dangerous (but also not causing any bug in this specific case) is the use of an arithmetical addition (+) to combine bit values. Also a common mistake. Often, it works, but it may go epically wrong. Combining bits shoudl be done with the binary OR (|) and not with the arithmetical add.

    Can you please shed some light on this ?

    Thanks,

    Satbir

  • I had no problem, i just posted this because i wanted to share this code, i did this since i couldn't find any good example of how do the Input capture

  • Satbir Sekhon said:
    Can you please shed some light on this ?


    0x01 + 0x01 = 0x02.
    0x01 | 0x01 = 0x01.

    TACTL = TAIE + TAIE; will clear the timer, while
    TACTL = TAIE | TAIE; will set the TAIE bit, as intended.

    There are lots of defines which combine multiple bits. So it happens often that accidentally, a bit is added twice to the expression. In case of an addition, this will result in completely unexpected behavior, while combining them with a binary OR will simply ignore duplicate bits.

    A prominent example is the watchdog controller, where the predefined options already contain the password. Adding it will cause an immediate reset, OR'ing it will do no harm.

    When individual defines are added to a project, chance for duplicates increases, especially if the code is reworked later, when the initial meaning of those defines is gone form the mind.

  • Thanks for the info, JMG.

  • Hi professor, My problem is how to Capture the pulse of Encoder when motors rotating using msp430g2553. Suppose that I have 2 motors encoder with 1 output pulse. The first one output pulse (from the 1 motor)  I put it on P1.6 and the second output pulse (from the second motor) I put it on P1.4. Now I want to capture the output pulse occurring at the same time of both the motor encoder 1 and the motor encoder 2. Here is my code, but I think it 's wrong. Can you help me improve codes below: Thanks so much.


    #include "msp430g2553.h"
    #include "UART.h"

    #define DIR_W1 (P1IN & BIT3) //P1.3 == 0 = DIR_W1
    #define DIR_W2 (P1IN & BIT5) //P1.5 == 0 = DIR_W2

    unsigned int i=0, j=0, ulcap_val1, ulcap_val2, dir1, dir2, ipos_encp1 = 888, ipos_encp2 = 888;


    void ConfigClock();
    void ConfigPin();
    void InterruptTimer();
    void InterruptPort();

    void ConfigClock(void)
    {
    BCSCTL1 = CALBC1_1MHZ; // Set range
    DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation
    }

    void ConfigPin(void)
    {
    P1DIR |= BIT6; // P1.6 output
    P1SEL |= BIT6; // P1.6 TA0.1

    P1DIR &= ~(BIT4); //Chon nhap
    P1REN |= BIT4; //Cho phep tro treo
    P1OUT |= BIT4; //Tro treo len nguon

    P1DIR |= BIT3 + BIT5; // P1.3, P1.5 input/output
    P1SEL &= ~BIT3;
    P1SEL &= ~BIT5;
    }

    void InterruptTimer(void)
    {
    TA0CTL = TASSEL_2 + ID_0 + MC_1; //Up mode - Setup Timer
    TA0CCR0 = 65000;
    TA0CCTL0 = CCIE;

    TA0CCTL1 = CM_2 + CCIS_0 + SCS + CAP; //Initialize Capture
    TA0CCR1 = 0;
    }

    void InterruptPort(void)
    {

    P1IE |= BIT4; //Cho phep ngat o P1.4
    P1IES |= BIT4; //Ngat canh xuong
    //Dien ap o P1.4 tu 1->0 thi xay ra ngat

    P1IFG &=~BIT4; //Xoa co ngat

    }
    int main( void )
    {
    // Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;
    ConfigClock();
    UART_Init();
    UART_Write_String("Chuong trinh Test UART");
    UART_Write_Char(10);

    ConfigPin();
    InterruptTimer();
    InterruptPort();

    _BIS_SR(LPM0_bits + GIE);
    while(1);
    }

    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer0_A0_ISR(void)
    {
    ulcap_val1 = TA0CCR1; //load the captured value to the unsigned variable
    i++;
    UART_Write_String("Motor 1 bat duoc lan thu ");
    UART_Write_Int(i);
    UART_Write_Char(10);
    UART_Write_String("Thoi gian bat tai canh xuong la ");
    UART_Write_Int(ulcap_val1);
    UART_Write_Char(10);

    TA0CTL &= ~TAIFG;
    TA0CCTL1 &= ~CCIFG; //reset the capture compare flag
    }

    #pragma vector = PORT1_VECTOR
    __interrupt void Port_1(void)
    {
    ulcap_val2 = TA0CCR1;
    j++;
    UART_Write_String("Motor 2 bat duoc lan thu ");
    UART_Write_Int(j);
    UART_Write_Char(10);
    UART_Write_String("Thoi gian bat tai canh xuong la ");
    UART_Write_Int(ulcap_val2);
    UART_Write_Char(10);

    TA0CTL &= ~TAIFG;
    TA0CCTL1 &= ~CCIFG; //reset the capture compare flag
    }

  • First thing I noticed is that you make an UART write inside the port ISR. Since an UART write may take a loooong time, and also might need interrupts itself (depends on implementation), this is the totally wrong place to make any outputs. Same for the timer ISR.

    The ISR should fetch the values into global volatile variables and set a global flag that data is ready (or wake main form LPM). Main then should backup the captured values, process them, and go back to sleep for next data.
    Likely, you’re experiencing a lot of port interrupts while main is still busy processing and sending the information about the first.

    Also, all global variables that are used or changed inside an ISR should be declared as volatile.

**Attention** This is a public forum