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.

IR TX / RX with 16F628

Status
Not open for further replies.

NST

New Member
Hi everybody,

I am working on a project for controlling some devices with a remote controller which use NEC protocol. I have written RX codes in CCS using the timers. I have tried to catch fall and rise points to generate two data column and a checksum. After I setup and execute the timer, I wait for signal go to low with while(IR_PIN). But pic doesn't response until this line. It always stays in eternal loop in spite of it's logic value becomes zero.

I confused up. :confused:
 
Have you turned off the comparators CMCON=7;?
Is the pin set to input?
Is IR_PIN defined as a single bit?

A bit more information and some code would be useful.

Mike.
 
Thank you Mike.

Yes I turned the comparators off. Here is my code;

Code:
#include <16f628a.h>
#fuses NOWDT, INTRC_IO, PUT, NOPROTECT, MCLR

#use delay (clock=4000000) //4 MHZ
#byte CMCON=0x07;

#define  IR_PIN  PIN_B0

unsigned char bitcount;

int32 ir_tempbyte_hi;
int16 ir_tempbyte_lo;
int16 headp,heads,rise,fall;

void ir_read(void);
void ir_get_rise(void);
void ir_get_fall(void);
void ir_build_bytes(void);


#int_ext
void  ext_int ()
{
   ir_read();
}


void ir_read(void)
{
   ir_tempbyte_hi=0;
   ir_tempbyte_lo=0;

   while(IR_PIN); // //Wait for minimal pre which stays low 
   
   ir_get_rise(); // Get headp & heads to see what protocol it is
   headp=rise;
   ir_get_fall();
   heads=fall;

   if ((headp>8800)&&(headp<9090)&&(heads>4200)&&(heads<4570)) // We got NEC Start Sequence
   {
      output_high(PIN_A2);
      ir_build_bytes(); // Now trying to read data bits
   }
   else
   {
      output_high(PIN_A2);
   }
}

void ir_get_rise(void)
{
   output_high(PIN_A7);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_1);    // Get high
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   set_timer1(0);
   while(!IR_PIN); // Wait for signal to go high
   rise = get_timer1();
   delay_ms(1000);
   output_low(PIN_A7);   
}

void ir_get_fall(void)
{
   output_high(PIN_A6);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_1);   // Get low
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   set_timer1(0);
   while(IR_PIN);          // Wait for signal to go low 
   fall = get_timer1();
   delay_ms(1000);
   output_low(PIN_A6);
}
void ir_build_bytes(void)
{
   for (bitcount=0;bitcount!=32;bitcount++)
   {
      ir_get_rise();
      ir_get_fall();
      
      if ((rise>450)&&(rise<650)&&(fall>1400)&&(fall<1655))
      {
         ir_tempbyte_hi|=1; // bit=1
      }
      else if ((rise>450)&&(rise<650)&&(fall>390)&&(fall<600)){;} // bit=0
      else return; // Byte Check Fault 
   }

   if (bitcount<31){ir_tempbyte_hi<<=1;}  // Don't shift last bit
   if (bitcount==32){output_high(PIN_A2);} // reception is valid
}

void main ()
{
   setup_CCP1(CCP_OFF);            // CCP1 unit outbound
   ext_int_edge(H_TO_L);           // INT_EXT is High to Low
   
   setup_timer_0(t1_disabled);
   setup_timer_1(t2_disabled);

   enable_interrupts(INT_EXT);     // INT_EXT interrupt inbound
   enable_interrupts(GLOBAL);      // All interrupts inbound
   
   while(1); //Stand by
}
 
I'm afraid I'm not familiar with the compiler you are using. I assume it is the CCS compiler as it appears to clear the interrupt flags for you.

One thing I notice from your code is your ISR calls ir_read which calls ir_get_rise which has a 1 second delay in it!

If it helps, here is some code I wrote in C18 which reads a sony code
Code:
#define IR_in   PORTAbits.RA6
#define IR_tris TRISAbits.TRISA6

unsigned char GetPulse(void){
unsigned char count;
    count=0;
    IR_tris=1;
    while(IR_in==1); 
    while(IR_in==0){
        count++;
        Delay100TCYx(1);   //50uS assumes 8MHz
    }
    return count;
}

void GetIR(char *cmd,char *dev){
char i;
    *cmd=0;
    *dev=0;
    while(GetPulse()<40);    //wait for start pulse
    for(i=0;i<7;i++){
        *cmd=*cmd>>1;
        if(GetPulse()>18)
            *cmd|=0x40;
    }
    for(i=0;i<5;i++){
        *dev=*dev>>1;
        if(GetPulse()>18)
            *dev|=0x10;
    }
}

Mike.
 
One thing I notice is that you haven't disabled Low Voltage Programming in your config, add NOLVP to your fuses statement.

Also as Pommie points out, interrupts should be short and sweet. Perhaps a better method is to set a flag in the isr, then in your main check to see if the flag is set and if so, go to your subroutine from there.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top