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.

NEC IR CODE DECODING

Other Parts Discussed in Thread: MSP430G2102

Hello 

I have written following code for decoding NEC IR data.

This code works fine but sometimes it stuck somewhere and I need to reset the msp430g2102.

I have used timer A0 in capture mode and enable interrupts at both edges.

Can any one let me know why is it stuck sometimes?

Complete code is in attached file .

Thanks

manish

8004.ir_code.c

#include<msp430g2102.h>



// IR pulse timing constants in microseconds

#define HP_MIN      8500    // Header pulse minimum duration
#define HP_MAX      9500    // Header pulse maximum duration
#define HPL_MIN     4100    // Header pulse low minimum duration
#define HPL_MAX     4800    // Header pulse low maximum duration
#define RPT_MIN     1900    // Repeat pulse minimum duration
#define RPT_MAX     2500    // Repeat pulse minimum duration
#define BP_MIN      450     // Bit pulse minimum duration
#define BP_MAX      650     // Bit pulse maximum duration
#define ONE_MIN     2000    // Logical one minumum duration
#define ONE_MAX     2500    // Logical one maxumum duration
#define ZERO_MIN    1000    // Logical zero minumum duration
#define ZERO_MAX    1300    // Logical zero maxumum duration

#define FALSE 0
#define TRUE (!FALSE)
#define IR_REPEAT 0xFF00    // Special repeat code
#define MAX_DATA_BITS 32    // NEC protocol provides for 32 bits of data

#define PIN_IR      BIT1    // This must be TA0.0
#define PIN_PS_ON   BIT4    // LED1 on the Launchpad

#define BUTTON_POWER    0X04FB00FF    // This is a code for the button to toggle the LED

static volatile unsigned long data;



void ir_init(void)
{
    _BIC_SR(GIE);                            //DISABLE THE GLOBLE INTERRUTS
    BCSCTL1 = CALBC1_1MHZ;                  // Set DCO to 1MHz to measure pulses in microseconds
    DCOCTL = CALDCO_1MHZ;
    P1DIR &= ~PIN_IR;                       // Set IR detector pin to input
    P1OUT |= PIN_IR;                        // Set resistor to pull-up
    P1REN |= PIN_IR;                        // Enable resistor
    P1SEL |= PIN_IR;                         // set IR detector pin to peripheral function
   TACTL = TASSEL_2 | ID_0 | MC_2;         // SMCLK, Continuous mode, Input divider /1
   TACCTL0 = CM_3 |  CCIS_0 | CAP | CCIE;  // Capture on both edges, Capture Input Select CCI0A, Capture mode, Capture interrupt enable

    _BIS_SR(GIE);                           //ENABLE  THE GLOBLE INTERRUTS
}

 void Re_start_timer()
   
 {
    TACTL |= TACLR;
    TACTL = TASSEL_2 | ID_0 | MC_2;         // SMCLK, Continuous mode, Input divider /1
    TACCTL0 = CM_3 |  CCIS_0 | CAP | CCIE;  // Capture on both edges, Capture Input Select CCI0A, Capture mode, Capture interrupt enable


 }





void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;       // Stop the Watchdog timer
    P1DIR = PIN_PS_ON;               // LED1 to output
    ir_init();                      // Initialize IR detection 
     while(1)
       // Loop forever
    {
       
        // Set a breakpoint on the next line and add a watch for the data variable to see the IR code received 
        if (data == BUTTON_POWER)   // If remote power button is pressed
            
        {
          P1OUT ^= PIN_PS_ON;      // Toggle LED1
           
        }
        
    }
}



#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer0_A0 (void)
{
    static unsigned char hp, hr;                    //header pulse received, header received
    static unsigned char br;                        // bits received
    static unsigned char pulse=FALSE;               // pulse in progress
    static volatile unsigned char ready = FALSE;    // data ready
    static unsigned int pw=0, bw=0;                 // pulse width, bit width
    unsigned int i = TAIV;                          // Read TAIV to clear CCIFG

    // Is this the beginning or the end of the pulse?
    if (!pulse)
    // start of the pulse
    {
        bw=TACCR0;
        // reset Timer
        //TACTL |= TACLR;
       Re_start_timer();
        pulse=TRUE;
        // Has the header pulse just been received?
        if (hp)
        {
            // Is the header duration in range?
            if (bw>HPL_MIN && bw<HPL_MAX)
            {
                hr=TRUE;
                br=0;
                data=0;
                ready=FALSE;
            }
            // is it a repeat code?
            else if (bw>RPT_MIN && bw<RPT_MAX)
            {
                data=IR_REPEAT;
                hr=FALSE;
                ready=TRUE;
            }
        }
        // Was there a bit pulse before, and also has the header been received?
        if(hr && pw>BP_MIN && pw<BP_MAX)
        {
            if (bw>ONE_MIN && bw<ONE_MAX)
            {
                data<<=1;
                data++;
                br++;
            }
            else if (bw>ZERO_MIN && bw<ZERO_MAX)
            {
                data<<=1;
                br++;
            }
            if (br==MAX_DATA_BITS)
            {
                hr=FALSE;
                ready=TRUE;
            }
        }
        hp=FALSE;
    }
    else
    // end of the pulse
    {
        pw=TACCR0;
        pulse=FALSE;
        // Is this a header pulse?
        if (pw>HP_MIN && pw<HP_MAX)
        {
            // set Header Pulse Received flag
            hp=TRUE;
            // Reset timer
            Re_start_timer();
        }
        else
        {
            hp=FALSE;
        }
    }
    if (ready)
    {
        ready = FALSE;
       
    }
}

























 

  • manish bhatt1 said:
    Can any one let me know why is it stuck sometimes?

    Debugger can tell. You would want to run your code using in-circuit debugger and stop code when it's stuck, look where it's stuck. When you determine THE place, you are welcome to come back and consult further

  • Dear Sir,

    I have sen in debugger that sometimes timer value for in first 9ms pulse is incorrect.

    The timer reading should between  8500 to 9500 for first 9ms pulse but sometimes it is incorrect.

    I could' nt find why it is so ?

    Can you pls help?

    Thanks

    Manish

  • You enabled capture for both rising and falling edge of IR detector (this is correct). But inside ISR, you did not check if it is rising or falling (this is not prudent). Occasionally, you may get "out of phase" and keep reading the code "upside-down".

  • Hello

    I have couted number of edges in ISR.

    Normally it gives 68 edges which is correct.

    But when  code is out of phase it gives 73 edges.

    I couldnt understand why there is 5 more edges?

    I have stooped the timer after getting 68 edges so extra edges not form repeat pulse.

    Can any body tell ?

    Thanks

    Manish

  • Lots of things can confuse your observation. Glitches in the IR detector output, ambient noise (IR or EM), bugs in your code, etc.

    Inside your ISR, you can read CCI or SCCI to find out if the current interrupt is caused by what edge. And you can read COV to find out if you have missed an interrupt.

**Attention** This is a public forum