View previous topic :: View next topic |
Author |
Message |
Knifii
Joined: 22 Sep 2014 Posts: 3
|
Multiple interrupts on Port B - 16F887 |
Posted: Mon Sep 22, 2014 4:40 pm |
|
|
Hello!
I'm trying to make my code work. I'm using a PIC16F887 and want to use 3 pushbuttons to generate interrupts. I've tried to put it into a simple program just to clarify how to handle the interrupt routine but it acts unpredictable...
The code below:
Code: | #include <16f887.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#byte TRISB_REG = 0x86
#byte OPTION_REG = 0x81
#bit RBPU = OPTION_REG.7 // option register RBPUbit - enables pullup resistors on port B if is clear
#byte WPUB_REG = 0x95 // WPUB register, each bit enables the correspondung pullup resistor on port B if is set
#byte IOCB_REG = 0x96 //defines which pin of port B may cause an interrupt if is set and if is enabled.
#byte INTCON_REG = 0x8B
#bit RBIE = INTCON_REG.3 //RB Port Change Interrupt Enable bit. Enables port B interrupts if is set.
#bit RBIF = INTCON_REG.0 //RB Port Change Interrupt Flag bit. It is set if interrupt occured.
#bit GIE = INTCON_REG.7 //Global Interrupt Enable interrupts are enabled if is set.
int x;
#INT_RB
void int_rb_isr()
{
swap(x);
}
void init(){
disable_interrupts(GLOBAL);
x = 0x0F;
setup_adc_ports( NO_ANALOGS );
output_b(0);
TRISB_REG = 0x04; //portB pin3 configured as input
RBPU = 0; // Pull-up resistors are enabled
WPUB_REG = 0x04; //portb pin3 pullup enabled
IOCB_REG = 0x04; //portb pin3 may cause interrupt
INTCON_REG = 0x00;
RBIE = 1; //B port interrupts are enabled
RBIF = 0; //flag cleared
GIE = 1;
}
void main()
{
init();
while(1){
output_d(x);
}
} |
I was debugging and saw that for example when i tried to write 04h to TRIS B it gets 84h. First I used the functions like "set_tris_b(0x04);" but it didn't worked that way, so i started to reach the registers directly. I hope It's me who don't see the problem and the task is easy. I would need a simple program that makes my portD leds swap when the main program is interrupted. Also the interrupts should come from B0,B1 and B2. (In this program I just tried to make it work only B2.)
The behavior: It sometimes work for a time and a little later it stops responding. Debugging is horrible
The circuit is simple. I use the built in pullups so i soldered pushbuttons between he pins and GND. (De-bouncing also under development)
I would appreciate any idea or solution!
Thank You in advance!
Knifii |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 22, 2014 5:57 pm |
|
|
You have to read PortB inside the #int_rb routine to clear the "change
condition". This is stated in the PIC data sheet. If you don't do that,
you will get the same interrupt over and over.
This PIC does not have edge selection registers for PortB interrupt-on-change.
That means it will interrupt on both edges. You have to put code in the
#int_rb routine to detect what edge of input signal caused the interrupt.
ie., either the button press, or the button release.
See this CCS example. In this file, you are given two #define statements,
one for each edge. You pick the edge that you want to detect and set
that #define to TRUE and the other one to FALSE.
Quote: | c:\program files\picc\examples\ex_pbutt.c |
More explanation:
http://www.ccsinfo.com/forum/viewtopic.php?t=51383&start=3
Also, the CCS routines should work. It's best to use them.
Post your compiler version. |
|
|
Knifii
Joined: 22 Sep 2014 Posts: 3
|
|
Posted: Tue Sep 23, 2014 4:05 am |
|
|
Dear PCM programmer!
I know what you are saying. Of course I need to read the port B to get the info where does the interrupt came from. And i know that there is no edge selection register in this case for me. Yet this "simpler" program isn't working properly. (I was testing with pressing the button and hold it there to generate 1 interrupt per time). I wish to understand what did i do wrong that this code doesn't work..
Maybe could you give me a hint about that?
Thank you! |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Sep 23, 2014 5:12 am |
|
|
Read PCM's post again. You have to read the portB register inside the interrupt handler to clear the condition that caused the interrupt. Because you don't do this the program now loops forever in the interrupt routine (leaves the interrupt and is triggered immediately again).
Also, you were asked to post your compiler version number. Your TRIS register changing might be a known bug (personally I think you had #ICD defined in your original program which enables the debugger on port B7).
Some background info on TRIS: the CCS compiler is being a bit smart in that it will set the TRIS register for you automatically on every I/O operation. A great feature that comes at the small cost of few extra instructions at every I/O operation. If you want to manage TRIS yourself then add '#USE FAST_IO' to the start of your code.
I hate the code where you access registers directly. It is not portable to other PIC processors and difficult to read, one of the reasons I like the CCS compiler is that alternative functions are supplied resulting in just as compact code. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9250 Location: Greensville,Ontario
|
|
Posted: Tue Sep 23, 2014 5:31 am |
|
|
another point is that unless the 'button' you're pressing is a solidstate device, it WILL give you multiple 'bounces'. That's why you'll need a 'debounce' method. Gold plated switch contacts are better and reed switches are real good but it is something you should be aware of.
It's worth tossing a scope on the switch and seeing what happens !!
jay |
|
|
Knifii
Joined: 22 Sep 2014 Posts: 3
|
|
Posted: Tue Sep 23, 2014 4:21 pm |
|
|
Thank you for your replies.
I'm using compiler version 5.008. I used the FAST_IO directive to set trisB manually, it helped that problem. Now i applied a capacity between the button and the pin to the ground. It is now waiting for the button release always. I set the leds blinking to see that i came back from the routine. When i push the button it stops blinking and wait for the release, than it goes to the routine and comes back from it. Sometimes it doesn't but i guess i have to use schmitt-trigger on the pins to be accurate.
Anyway thank you for your ideas!
Knifii |
|
|
|