CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

problem with #int_rb interrupt on 18F26K20 (solved)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Leef_me



Joined: 14 Mar 2006
Posts: 45

View user's profile Send private message

problem with #int_rb interrupt on 18F26K20 (solved)
PostPosted: Tue Jun 16, 2009 2:09 am     Reply with quote

I the RB interrupt on change interrupt doesn't seem to fire.
I have created a small program based on the 'ex_pbutt' but for this uC.

I have two test cases, polled (which works) and interrupt driven (which does not work)

Can anyone help me understand why the interrupt case doesn't work?

Thanks in advance.

Leef_me

Code:
#include <18F26K20.h>
#device ICD=TRUE

#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=1000000)

#define LOWTOHIGH TRUE
#define HIGHTOLOW FALSE

short int dbutton4, dbutton5;
int k,x;

#int_rb
void detect_rb_change() {
   int current;
   static int last=0;

   set_tris_b(0xF0);
   current=input_b();

   #if LOWTOHIGH
   if ((!bit_test(last,4))&&(bit_test(current,4))) {dbutton4=1;}
   if ((!bit_test(last,5))&&(bit_test(current,5))) {dbutton5=1;}
   #elif HIGHTOLOW
   if ((!bit_test(current,4))&&(bit_test(last,4))) {dbutton4=1;}
   if ((!bit_test(current,5))&&(bit_test(last,5))) {dbutton5=1;}
   #endif

   last=current;
}

void clear_delta() {
   dbutton4=0;
   dbutton5=0;
}

void main()
{
   port_b_pullups(TRUE);
   k=input_b();
   clear_delta();

   clear_interrupt(INT_RB);
   enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);

   output_low(PIN_B0);
   x = 0;
   
// test case one:
// enable the first while loop and add breakpoint below
//   result: taking either RB4 or RB5 low causes the x++ instruction
//       to execute and the breakpoint occurs


// test case two:
// disable the first while loop, and add scope probes to
//  RB0, RB4 & RB5
//   result: RB0 is set low initally and is never set high
//      even though both RB4 & RB5 are obeserved to go low

   
   WHILE(0)  // if 0, skip this while and do the next WHILE instead
   {
      k = input_b()& 0b00110000;
      if (k!=0b00110000)
      {
         x++; //   <===== add breakpoint here
         x++;
      }
   }
   
// note the change from 'ex_pbutt', both buttons should set RB0 high
// the original set/reset action is not performed

   while (1) {
      if(dbutton4) {
        output_high(PIN_B0);
        dbutton4=FALSE;
      }
      if(dbutton5) {
        output_high(PIN_B0);
        dbutton5=FALSE;
      }
   }
}


Last edited by Leef_me on Tue Jun 16, 2009 1:56 pm; edited 1 time in total
Ttelmah
Guest







PostPosted: Tue Jun 16, 2009 9:48 am     Reply with quote

It wouldn't.
Use fast_io, otherwise CCS, will set the whole port to input, when you read it. Your TRIS command does nothing, since it is overridden on the next instruction. Just use fast_io, and set the tris once at the start of the main.
Now, on wake up, last, is effectively set incorrectly, since it is set to '0', while the port bits are actually 1. You need to initialise 'last' to match the real state of the port on boot. As it currently stands, the interrupt triggers on the falling edge, but is not seen, since 'last' is set to '0'.
Make 'last' global, and set it at the start of the main, when you clear/enable the interrupts.
More efficient probably, to use:
Code:

#use fast_io(B)

int8 last;

#int_rb
void changed(void) {
   int8 changes;
   int8 current;
   changes = last ^ (current=input_b());
   if (bit_test(changes,4))
   #if LOWTOHIGH
       if (bit_test(current,4)) dbutton4=1;
   #else
       if (bit_test(last,4)) dbutton4=1;
   #endif
   if (bit_test(changes,5))
   #if LOWTOHIGH
       if (bit_test(current,5)) dbutton5=1;
   #else
       if (bit_test(last,5)) dbutton4=1;
   #endif
   last=current;
}

void main()
{
   port_b_pullups(TRUE);
   set_tris_b(0xF0);
   delay_us(10); //ensure line has time to settle
   last=input_b();

   clear_delta();
   clear_interrupt(INT_RB);
   enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);

   //etc.


Best Wishes
Leef_me



Joined: 14 Mar 2006
Posts: 45

View user's profile Send private message

PostPosted: Tue Jun 16, 2009 11:25 am     Reply with quote

Hi Ttelmah, thanks for your reply.

>>>But no improvement Crying or Very sad

Quote:
9.11 PORTB Interrupt-on-Change
An input change on PORTB<7:4> sets flag bit, RBIF of the INTCON register.
The interrupt can be enabled/ disabled by setting/clearing enable bit, RBIE of the INTCON register.
Arrow Pins must also be individually enabled with the IOCB register.


Correction: the following code works. Very Happy

Leef_me
Code:
#include <18F26K20.h>
#device ICD=TRUE

#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=1000000)

#define LOWTOHIGH TRUE

#BYTE INTCON = 0xff2    //INTCON: INTERRUPT CONTROL REGISTER
#BYTE IOCB = 0xf7d      // interrupt on change bit  control

#use fast_io(B)

short int dbutton4, dbutton5;
int k,x;
int8 last;

#int_rb
void changed(void) {
   int8 changes;
   int8 current;
   changes = last ^ (current=input_b());
   if (bit_test(changes,4))
   #if LOWTOHIGH
       if (bit_test(current,4)) dbutton4=1;
   #else
       if (bit_test(last,4)) dbutton4=1;
   #endif
   if (bit_test(changes,5))
   #if LOWTOHIGH
       if (bit_test(current,5)) dbutton5=1;
   #else
       if (bit_test(last,5)) dbutton4=1;
   #endif
   last=current;
}



void clear_delta() {
   dbutton4=0;
   dbutton5=0;
}

void main()
{

  port_b_pullups(TRUE);
   set_tris_b(0xF0);
   delay_us(10); //ensure line has time to settle
   IOCB = 0x30;
   clear_delta();
   last=input_b();

   clear_interrupt(INT_RB);
   enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);

   output_low(PIN_B0);
   x = 0;
   
// test case one:
// enable the first while loop and add breakpoint below
//   result: taking either RB4 or RB5 low causes the x++ instruction
//       to execute and the breakpoint occurs


// test case two:
// disable the first while loop, and add scope probes to
//  RB0, RB4 & RB5
//   result: RB0 is set low initally and is never set high
//      even though both RB4 & RB5 are obeserved to go low

   
   WHILE(0)  // if 0, skip this while and do the next WHILE instead
   {
      k = input_b()& 0b00110000;
      if (k!=0b00110000)
      {
         x++; //   <===== add breakpoint here
         x++;
      }
   }
   
// note the change from 'ex_pbutt', both buttons should set RB0 high
// the original set/reset action is not performed
   while (1) {
      if(dbutton4) {
        output_high(PIN_B0);
       dbutton4=FALSE;
      }
      if(dbutton5) {
        output_low(PIN_B0);
        dbutton5=FALSE;
      }
     
   }
}
krasi



Joined: 17 Jun 2009
Posts: 9
Location: Bulgaria

View user's profile Send private message

PostPosted: Fri Nov 20, 2009 6:26 am     Reply with quote

Hi everybody,
I have the same problem with INT_RB. It works OK on 18f2580, but when changed it to 18f25k20, it doesn't.
I read this topic (and many others with the same issue). With the info from this one (thanks to Leef_me Smile ), I solve my problem, but the answer for me is still missing. Why it doesn't work as expected? Although in the include files everything is similar. The value for INT_RB in 25k20 is 0x1FFF208. In 2580 it is 0xFFF208. I tried to make them equal, but still no effect. 18f25k20 also have additional RB enable flags, but they have no effect too. The interrupt doesn't occur at all. I made all necessary steps before enabling it - read the port, clear INT_RB and then enable for the first time. But nothing changed. Is this a compiler's bug or what?
I'll be glad if somebody can answer me.

Thanks,
Krasi
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group