Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
Resource icon

IR remote as mcu input 2015-05-16

So many PIC mcu projects I dream up seem to need a few or lots of switches to allow some program setting or control, so seeing this cheap ir remote key pad , seemed a one size fits all solution. Several code examples out there but none for the NEC ir protocol interfacing with a PIC24Fxxxxx . My method basically waits for the 9ms start burst and checks its length then checks the 4.5ms pause, the following data bits are counted and shifted into the input_data , a ZERO is one count a ONE is two . after 32 bits got_data flag is set.
:- The mcu requires a 16Bit Timer with an interrupt running at 1.125ms. The ir receiver (Detects 38khz ir bursts) drives an mcu INT pin no pull up is required. The C coding here is for a PIC24FV16KA301 running at 16Mhz (8 MIPS).The main routine has to enable the INT0 when ready for ir input and then poll the Got_data flag . This is set when all 32 bits have been received , bit dropouts or errors are ignored . The code result is accumulated as input_data (long int), but I only used the 8 Command bits , the address shown below for this remote is always h’00 so not used (some bit checking could be done if required as the remote transmits inverse data in the bit stream). Keys held down produce repeat codes , but not yet investigated that feature.

Code:
enum {
        Idle,
        Pre_code,
        Start_bit,
        Capture_bit
};


void INT0_SETUP()
{
    TRISBbits.TRISB7 = 1; // INT0 RB7 INPUT FROM ir RECEIVER.
    IPC0bits.INT0IP = 6 ; //INT0 PRIORITY
    INTCON2bits.INT0EP = 1;// INT0 FALLING EDGE
    IFS0bits.INT0IF=0;    // clr flag
     
}

//Set up Timer, 1.125ms interrupts
void T2_init(void)
{

   PR2 = 9000 ;    //   PIC at 8 MIPS comparitor value for 1.125mS
   TMR2= 0 ;   // clear timer
   T2CONbits.TCKPS = 0;     //TIMER 2 pre scale 0 1:1,1 1:8, 2 1:64
   IPC1bits.T2IP  = 5;     //set interrupt priority
   IFS0bits.T2IF = 0;     //reset interrupt flag
   IEC0bits.T2IE = 0;   // DISABLE T2 interrupt
   T2CONbits.TON =0; // timer 2 off
}

// IR LED input to INT0
void __attribute__((__interrupt__, auto_psv))_INT0Interrupt(void)
{
     TMR2=2000;        // PRELOAD T2
     T2CONbits.TON = 1; // timer ON
     IEC0bits.T2IE = 1;   // ENable T2 interrupt
     switch (Current_state){
           case Idle:
               INTCON2bits.INT0EP = 0;//change INT0 rising EDGE
               counter=0;
               Current_state = Pre_code;
               break;
         // found rising edge check length 9ms COUNT 8
       case Pre_code:
           if (counter==8){
              counter=0;
              bit_count=0;
              Current_state = Start_bit;
              INTCON2bits.INT0EP = 1;// INT0 falling EDGE
             }else{
              Current_state=Idle;
              counter=0;
              T2CONbits.TON = 0; // timer off
              IEC0bits.T2IE = 0; // DISABLE T2 interrupt
             }
             break;
         case Start_bit:
          if (counter==4){
              counter=0;
              bit_count=0;
              input_data =0;
              Current_state = Capture_bit;
             }else{
              Current_state=Idle;
              counter=0;
              T2CONbits.TON = 0; // timer off
              IEC0bits.T2IE = 0; // DISABLE T2 interrupt
             }
             break;
         case Capture_bit:
                 if(counter == 1){
                 input_data >>= 1;
                 bit_count++;
                 counter=0;
                 }else{
                 if(counter == 2){
                 input_data >>= 1;
                 input_data |= 0x80000000;
                 bit_count++;
                 counter=0;
                 }else{
                 // error reset to idle
                 INTCON2bits.INT0EP = 1;// INT0 FALLING EDGE
                 Current_state=Idle;
                   }
                    }

if(bit_count == 32){       // RX complete ( ignore last pulse)
                got_data = 1;
                IEC0bits.INT0IE = 0;  //  disable INT0 INTERRUPT.
                T2CONbits.TON =0; // timer off
                IEC0bits.T2IE = 0;   // disable T2 interrupt
                Current_state=Idle;
             }
                        
                 counter=0;
                 break;
           default:  Current_state=Idle;  
          }
     IFS0bits.INT0IF = 0;

}

void __attribute__((__interrupt__, auto_psv))_T2Interrupt(void)
{
    counter++ ;
    if(counter > 10 ){//5
    Current_state=Idle;
    counter=0;
    INTCON2bits.INT0EP = 1;// INT0 FALLING EDGE
    T2CONbits.TON =0; // timer off
    }
    IFS0bits.T2IF = 0;     //cleart T2 interrupt flag
}
  • hx1838-ir-remote-250x250.jpg
    hx1838-ir-remote-250x250.jpg
    35.2 KB · Views: 766
  • NECMessageFrame.jpg
    NECMessageFrame.jpg
    58.7 KB · Views: 774
  • Like
Reactions: ClydeCrashKop
Author
granddad
Views
9,134
First release
Last update
Rating
0.00 star(s) 0 ratings

Latest threads

New Articles From Microcontroller Tips

Back
Top