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

Multiple interrupts on Port B - 16F887

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



Joined: 22 Sep 2014
Posts: 3

View user's profile Send private message

Multiple interrupts on Port B - 16F887
PostPosted: Mon Sep 22, 2014 4:40 pm     Reply with quote

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 Shocked

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

View user's profile Send private message

PostPosted: Mon Sep 22, 2014 5:57 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Sep 23, 2014 4:05 am     Reply with quote

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? Wink

Thank you!
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Sep 23, 2014 5:12 am     Reply with quote

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: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Sep 23, 2014 5:31 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Sep 23, 2014 4:21 pm     Reply with quote

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! Wink

Knifii
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