View previous topic :: View next topic |
Author |
Message |
sam.mihyar
Joined: 30 Jun 2012 Posts: 4
|
#int_rb problems |
Posted: Sat Jun 30, 2012 11:10 am |
|
|
So I have a simple task of detecting any change on ports RB4-7, and viewing that change by lighting a LED from port c. Sounds simple enough, but I'm failing to do it in Proteus. I will post my code, maybe there's something wrong with it.
Code: |
#include <16f877a.h>
#fuses xt,nowdt
#use delay (clock=4000000)
#int_RB
RB_isr()
{
output_high(PIN_c0);
delay_ms(3000);
output_low(PIN_c0);
}
void main()
{
set_tris_b(1);
set_tris_c(0);
while (1)
{
output_c(0);
enable_interrupts(GLOBAL);
enable_interrupts(int_RB);
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Sat Jun 30, 2012 12:07 pm |
|
|
INT_RB triggers, when the contents of a port latch, disagree with what is coming in on the input pins. The latch is set to match the pins whenever a read operation is performed on the pins.
So two things are immediately wrong. First, you are setting TRIS_B, to '1', this makes all the pins except B0 into output pins. RB only triggers on B4 to B7, and none of these pins are now inputs. From the data sheet:
"12.10.3 PORTB INTCON CHANGE
An input change on PORTB<7:4> sets flag bit RBIF
(INTCON<0>). The interrupt can be enabled/disabled
by setting/clearing enable bit RBIE (INTCON<4>)
(Section 3.2).".
Note the <7:4>, and the 'input change'.
Second though the latch needs to be set, by reading the pin(s) before you enable the interrupt, and then reset by reading the pin(s) in the interrupt.
Finally, you should only set the interrupt _once_.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
sam.mihyar
Joined: 30 Jun 2012 Posts: 4
|
|
Posted: Sat Jun 30, 2012 2:03 pm |
|
|
Gratitude for answering..helpful indeed...I'm a newbie, but correct me if I'm wrong...Doesn't "Set_tris_B(1)" Assign the entire 'B' port with all of its pins into input pins ? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Sat Jun 30, 2012 2:32 pm |
|
|
No.
The port has eight pins. They are represented by the binary bits in the number you feed to the TRIS statement. If you use binary notation:
0b00000000 = whole port is output
0b00000001 = bit 0 is input, rest output
0b00000010 = bit 1 is input, rest output
0b10000001 = bit 7 is input, and bit 0 is input, rest output.
etc. etc.
'1' in decimal, is '1' in binary, so you are setting bit 0 as input, and the rest of the pins as output.
set_tris_b(255);
would be the command to set all the pins as inputs. (0b11111111).
In fact, you can simply get rid of this. There is almost no need to use 'TRIS' with CCS.
If you just perform a _read_ on the port (which will reset the latch), so:
Code: |
void main(void) {
int bval;
bval=input_b();
.......
|
CCS will say 'he wants the port to be an input, I'll set TRIS for all the bits to be input', and handle TRIS automatically.
output_low(PIN_B1);
will _automatically_ set pin B1 to be an output pin (and not change any of the other pins), then output the signal.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
sam.mihyar
Joined: 30 Jun 2012 Posts: 4
|
|
Posted: Sat Jun 30, 2012 3:17 pm |
|
|
Ok...that made sense with the whole tris thing. So to test it out and actually get to my goal, I have a power source with a switch in B4, and the led on C0. Expectations, I open/close the switch, the led should light on and off....reality, the second I simulate the LED stays on during the whole time no matter what I do with the switch. So it defeats the whole purpose of "detecting" any change on B4-7 pins.
I realize this is a trivial stupid problem, but I'm self-teaching myself this and I cant get the hang of it yet.
Here's the current code used in Proteus:
Code: |
# include <16f877a.h>
# fuses xt,nowdt
# use delay (clock=4000000)
#int_RB
RB_isr()
{
int readb;
readb= input_b();
output_high(PIN_c0);
}
void main()
{
int readb;
readb= input_b();
set_tris_c(0);
enable_interrupts(GLOBAL);
enable_interrupts(int_RB);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jun 30, 2012 3:33 pm |
|
|
I don't know if interrupt-on-change even works in Proteus, and I'm not at
a location where I can test this in hardware, but at a minimum, you need
to make all the changes listed below:
Quote: |
void main()
{
int readb;
port_b_pullups(TRUE); // *** Add this line
delay_us(10); // *** Add this line
readb= input_b();
output_low(PIN_C0); // *** Add this line
// set_tris_c(0); // *** Not needed
clear_interrupt(INT_RB); // *** Add this line
enable_interrupts(GLOBAL);
enable_interrupts(int_RB);
while(1); // *** Add this line
}
|
Quote: | output_high(PIN_c0); |
Also, stop changing the case on constants, as you have done in the pin
constant shown above. The CCS compiler is unique in that it doesn't
check the case of variables or constants. (It can be enabled to do so).
This leads to sloppy programming. All other compilers DO care about
the case. It must match the definitions in the .h file for your PIC. |
|
![](templates/subSilver/images/spacer.gif) |
sam.mihyar
Joined: 30 Jun 2012 Posts: 4
|
|
Posted: Sat Jun 30, 2012 4:25 pm |
|
|
Ok it worked...changes in B4-7 ports are lighting up the LED. I'm trying to let it light on and then off after a couple of seconds so it will re-light when I make another change without me having to stop the simulation and redo it..should be done easily :D
Thank you Ttelmah.
Thank you PCM programmer.
Your help was very much appreciated |
|
![](templates/subSilver/images/spacer.gif) |
|