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

16F873 Interrupts.
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Paul H
Guest







16F873 Interrupts.
PostPosted: Wed Oct 24, 2001 7:17 pm     Reply with quote

Hi all. Trying to get to grips with using Interrupts for
the first time. ''CCS User manual is about useless'' for
this as there is no real explanition of what the actual
INT-XXX Does. Everything is crammed on to one page with
a cheezy example.

Anyway to my question. I have pins RB0, RB2, RB3 configured
as an input. The logic transition on these pins is High to low.
There is an individual switch connected to each pin, when the switch is pressed the pin goes low.

? What is a good way of implementing a interrupt routine
that will catch if the switch on any of these pins gets closed
assuming that in main there is something else going on such as
shifting out data on a pin such as rb6.

The idea is to stop the shifting of data on rb6 and do something
else based on the actual switch closure, then return to shifting
out the data when the switch is released.

A code snip would be a big help if anyone has got one to help
clue me in.

Also I notice in the help file a reference to #INT_BUTTON.
Any idea of what this pertains to and its intended useage.

Thanks for the help....Paul.
___________________________
This message was ported from CCS's old forum
Original Post ID: 824
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: 16F873 Interrupts.
PostPosted: Wed Oct 24, 2001 7:41 pm     Reply with quote

:=Anyway to my question. I have pins RB0, RB2, RB3 configured
:=as an input. The logic transition on these pins is High to low.
:=There is an individual switch connected to each pin, when the switch is pressed the pin goes low.
:=
:=? What is a good way of implementing a interrupt routine
:=that will catch if the switch on any of these pins gets closed
:=assuming that in main there is something else going on such as
:=shifting out data on a pin such as rb6.
--------------------------------------------------------

In Section 3.2 of the data sheet, it says that the "interrupt
on change" feature is available on pind 4-7 of Port B.
So you'll have to move the switches to those pins.

Here's some code that shows how INT_RB works. This is
really just some demo code. It doesn't do de-bouncing.
I have some real code for an interrupt driven keypad,
where when you press a key, it sets a hardware timer
for the debounce period, and then reads the key.
But you need something a bit more simple. Maybe
someone else has that.

-------------------------------------------------------
// Here is a sample program to test Port B interrupt-on-change.
// If you touch pins B4 to B7 with a ground wire,
// this program will send the value of interrupt_count
// to your RS-232 terminal.
// In fact, it will usually send several counts, because of
// "bounce".


#include "16F877.h"
#fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use Delay(Clock=8000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#zero_ram

// Declare a variable for the hardware Port B.
// Then we can access Port B by reading or writing
// to this variable.

#byte port_b = 6

//------------------------------------------------
// FUNCTION PROTOTYPES
void int_rb_isr(void);

//------------------------------------------------
// GLOBALS
char got_interrupt;
char interrupt_count;

//=====================================================
void main(void)
{
// Make all port B pins be inputs
set_tris_b(0xff);

// Set port B to a known state
port_b = 0;

// Enable pullups on all port B pins.
port_b_pullups(TRUE);

// Wait for them to pull up.
delay_us(10);

interrupt_count = 0;
got_interrupt = FALSE;

enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);

// Wait in this loop, and check if we got an interrupt.
// If so, then display the value of interrupt_count.
while(1)
{
disable_interrupts(INT_RB);
if(got_interrupt == TRUE)
{
printf("\%d\n\r", interrupt_count);
got_interrupt = FALSE;
}
enable_interrupts(INT_RB);

}

}
//======================================================

// This function will clear the RBIF flag automatically.
// The CCS compiler inserts the code to do that.
// You can see this by looking at the .LST file.
//
// However, we have to put in code to clear the
// change condition. CCS does not do that for us.
// We can do it by just reading Port B.

#int_rb
void int_rb_isr(void)
{
// This variable should be declared as static, to hopefully
// prevent a CCS bug, in which memory allocated to isr varibles
// is sometimes reused for other variables. (Known to exist
// in vs. 2.xxx. Not known if still exists in 3.xxx).

static char i;

// Clear the change condition by reading Port B.
i = port_b;

interrupt_count++;

got_interrupt = TRUE;
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 825
Guan Choon Lim
Guest







Interrupt Driven Keypad
PostPosted: Wed Oct 01, 2003 10:25 pm     Reply with quote

Hi. Does anyone have a demo code on interrupt driven keypad? I am trying to understand the theory of design a interrupt driven console program to monitor user inputs from keypad, switches and rotary encoder.

Your help is greatly appreciated!

Regards

Lim Smile
Geps



Joined: 05 Jul 2010
Posts: 129

View user's profile Send private message

PostPosted: Fri Jul 30, 2010 3:20 am     Reply with quote

Sorry to kick up this very old discussion but I'm having trouble getting my interrupt to work.

I've amended the program PCM programmer posted above to this (additon of set/clear LED and updated fuses and header files for my device):

Code:

#include "18F4520.h"
#fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use Delay(Clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#zero_ram

#byte port_b = 6

//------------------------------------------------
// FUNCTION PROTOTYPES
void int_rb_isr(void);

//------------------------------------------------
// GLOBALS
char got_interrupt;
char interrupt_count;

void main(void)
{
// Make all port B pins be inputs
set_tris_b(0xff);

// Set port B to a known state
port_b = 0;

// Enable pullups on all port B pins.
port_b_pullups(TRUE);

// Wait for them to pull up.
delay_us(10);

interrupt_count = 0;
got_interrupt = FALSE;

//enable_interrupts(INT_RB);
//enable_interrupts(GLOBAL);

// Wait in this loop, and check if we got an interrupt.
// If so, then display the value of interrupt_count.
while(TRUE)
{
//disable_interrupts(INT_RB);
printf("Interrupt Count: \%d\n\r", interrupt_count);
if(got_interrupt == TRUE)
{
printf("Interrupt Count: \%d\n\r", interrupt_count);
got_interrupt = FALSE;
}
output_low(PIN_A5);
delay_ms(100);
output_high(PIN_A5);           
delay_ms(100);
enable_interrupts(INT_RB);
}
}

#int_rb
void int_rb_isr(void)
{
static char i;
i = port_b;
interrupt_count++;
got_interrupt = TRUE;
}


I'm finding that with the interupts enabled the software only runs once and then hangs - commenting out the enables allows it to run continously.

I've read through the RB section of the datasheet and nothing strikes as being wrong.

Compiler version: 4.087
Hardware: PIC18F4520 CCS Development Board
Programmer: ICD-U64
Circuit:
Push button switch with pull up resistor on A4
LEDs on A5, B4 and B5 going to 5V rail.
Wire connecting Pins A4 to B5.

Voltage level change on Pin B5 checked with DVM.
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Fri Jul 30, 2010 3:46 am     Reply with quote

One really big problem....

Inside the interrupt on change, you need to read portB, to clear the interrupt. You think you are doing this, reading from a variable called 'port_b', and allocated to address 6. However 'portb', is _not_ at address 6, on a PIC18. You need to read the data sheet, and move the port_b variable to the right location....

Best Wishes
Geps



Joined: 05 Jul 2010
Posts: 129

View user's profile Send private message

PostPosted: Fri Jul 30, 2010 4:34 am     Reply with quote

Thanks, I've amended it but still the same performance:

Datasheet
http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf

Page 65:
Quote:
F81h PORTB


New address:

Code:
int16 port_b = 0xF81;


and updated the interrupt function:

Code:
static int16 i;

// Clear the change condition by reading Port B.
i = port_b;
Geps



Joined: 05 Jul 2010
Posts: 129

View user's profile Send private message

PostPosted: Fri Jul 30, 2010 6:21 am     Reply with quote

I've managed to work out that it never seems to leave the interrupt. Disabling the interrupt inside the interrupt function is the only way I've managed to return it to the main program - which isn't suitable for my program.
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Fri Jul 30, 2010 6:35 am     Reply with quote

Code:

int16 port_b = 0xF81;


This is wrong.
All this does is create a 16 bit int and assign the value 0xF81 to it.

you need to use #BYTE

Code:

#BYTE port_b = 0xF81
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Fri Jul 30, 2010 6:42 am     Reply with quote

That's not going to work.

You are going to need to change this:

Code:
int16 port_b = 0xF81;

to this:

Code:
#byte port_b  = 0xF81


But why do you need to explicitly declare PORTB. The location is already in the header file for your device.

To read the state of PORTB you can just use the CCS function input_x():

Code:
static int8 i;
i = input_b(); //returns the byte representing the input state of PORTB pins


Last edited by mkuang on Fri Jul 30, 2010 6:46 am; edited 2 times in total
Geps



Joined: 05 Jul 2010
Posts: 129

View user's profile Send private message

PostPosted: Fri Jul 30, 2010 6:42 am     Reply with quote

Excellent thanks for that, it's working nicely.

A couple of question if I may so I understand it....

In my device header file it lists:
Code:
#define BYTE int8


How is

#BYTE port_b

different to

int8 port_b?

Also is BYTE is defined as int8 how can you store a 12bit value in it?

Cheers,
Geps



Joined: 05 Jul 2010
Posts: 129

View user's profile Send private message

PostPosted: Fri Jul 30, 2010 6:46 am     Reply with quote

mkuang wrote:
But why do you need to explicitly declare PORTB. The location is already in the header file for your device.

To read the state of PORTB you can just use the CCS function input_x():

Code:
static int8 i;
i = input_b(); //returns the byte representing the input state of PORTB pins


I was just looking at sample code on here to better my understanding of it. Didn't want to go deleting lines until I had the program working.
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Fri Jul 30, 2010 6:50 am     Reply with quote

Please post your working program.
Geps



Joined: 05 Jul 2010
Posts: 129

View user's profile Send private message

PostPosted: Fri Jul 30, 2010 6:53 am     Reply with quote

Code:

#include "18F4520.h"
#fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use Delay(Clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#zero_ram

#use fast_io(B)



#BYTE port_b = 0xF81

// FUNCTION PROTOTYPES
void int_rb_isr(void);

// GLOBALS
char got_interrupt;
char interrupt_count;



void main(void)
{

set_tris_b(0xff);
set_tris_a(0x00);


port_b = 0;

port_b_pullups(TRUE);

delay_us(10);

interrupt_count = 0;
got_interrupt = FALSE;

enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);

while(TRUE)
{
disable_interrupts(INT_RB);

if(got_interrupt == TRUE)
{
printf("\%d\n\r", interrupt_count);
got_interrupt = FALSE;
}

enable_interrupts(INT_RB);

}

}



#int_rb
void int_rb_isr(void)
{
static int16 i;
i = port_b;

interrupt_count++;

got_interrupt = TRUE;

disable_interrupts(INT_RB);
}



mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Fri Jul 30, 2010 7:03 am     Reply with quote

You do not need this actually:

#BYTE port_b = 0xF81

If you look at the file "18F4520.h" (I don't have that compiler installed on this PC) you should see something like:

#BYTE PORTB = 0xF81 already in there.

In your code you can simply omit your port_b declaration and use the PORTB already declared by your compiler.
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Fri Jul 30, 2010 8:41 am     Reply with quote

Geps wrote:
Excellent thanks for that, it's working nicely.

A couple of question if I may so I understand it....

In my device header file it lists:
Code:
#define BYTE int8


How is

#BYTE port_b

different to

int8 port_b?

Also is BYTE is defined as int8 how can you store a 12bit value in it?

Cheers,


Note the difference between BYTE and #BYTE Smile

#BYTE (has a # in front) is a pre-processor directive to tell the compiler to create a variable which has an address of what follows.

#define BYTE int8
This tells the compile to replace all instances of BYTE (no #) with int8

so

Code:

BYTE myvar;

is the same as

int8 myvar;
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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