|
|
View previous topic :: View next topic |
Author |
Message |
Leef_me
Joined: 14 Mar 2006 Posts: 45
|
problem with #int_rb interrupt on 18F26K20 (solved) |
Posted: Tue Jun 16, 2009 2:09 am |
|
|
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
|
|
Posted: Tue Jun 16, 2009 9:48 am |
|
|
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
|
|
Posted: Tue Jun 16, 2009 11:25 am |
|
|
Hi Ttelmah, thanks for your reply.
>>>But no improvement
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.
Pins must also be individually enabled with the IOCB register. |
Correction: the following code works.
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
|
|
Posted: Fri Nov 20, 2009 6:26 am |
|
|
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 ), 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 |
|
|
|
|
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
|