![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
christietjen
Joined: 05 Aug 2007 Posts: 3
|
Interrupt problem. |
Posted: Sun Aug 05, 2007 7:27 am |
|
|
Code: | #include "12F675.h"
#use delay(4M,int) /*Sets up the internal clock for the DELAY_MS function*/
#use fast_io(A) /*Allows the use of the SET_TRIS_A() function.*/
#fuses mclr /*Allows external Master Clear*/
#int_RA /*Interrupt on Port A Change*/
void flip_flop()
{
SET_TRIS_A(0b00001111); /*Sets Port A for LED D0*/
OUTPUT_A(0X00); /*All pins low*/
OUTPUT_HIGH(PIN_A4); /*Lights LED D0*/
DELAY_MS(500); /*On for 1/2 sec.*/
OUTPUT_LOW(PIN_A4); /*Turns off LED D0*/
DELAY_MS(500); /*Off for 1/2 sec.*/
}
void main(void) /*Program starts here.*/
{
ENABLE_INTERRUPTS(INT_RA); /*Turn on Port A Change interrupt*/
ENABLE_INTERRUPTS(GLOBAL); /*Turn on all interrupts*/
}
I'm new to programming and the code above was written to test the Interrupt on Port Change function using the 12F675 chip running on Microchip's PicKit 1 Flash Starter Kit demo board. The eight installed LED's are multiplexed so it's necessary to set the tris register to get them to function individually. My thought was to write the interrupt function above and then in the body of the program toggle one of the ports on and off to activate the interrupt.
It seems however that just turning on the interrupts is providing the trigger to call the Port Change Interrupt. The D0 LED is toggling as it should but what is triggering the interrupt? Is the compiler inserting something that is causing this or have I missed something in my general understanding of what I'm attempting? The Compiler is PCM 4.045.
Thanks for any suggestions.
Chris |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Aug 05, 2007 8:13 am |
|
|
This is dependant on what happens to the pins on power on.
The 'changed' interrupt, is called, whenever the state of the pins 'disagrees, with the value stored in an internal latch on the chip. This latch is reset, whenever you _read_ the pins. Hence the correct sequence to setup the changed interrupt, is:
Read the pins
Clear the interrupt in case it is already set
enable the interrupt.
This is described in the data sheet for the chip.
Also note, that to prevent the interrupt permanently triggering, you _must_ read the pins, inside the interrupt handler.
As a final comment, in the CCS compiler, you need to prevent the code running off the 'end' of main. If this happens, the processor will go to sleep. In the case shown this won't matter (the interrupt will wake the chip again), but in general, you should always add an infinite loop at the end of the code, to prevent this overrun. This is because, unlike programming on a PC, where when the code completes, there is an OS running, to 'drop back' to, here the code is the only thing running.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
christietjen
Joined: 05 Aug 2007 Posts: 3
|
|
Posted: Sun Aug 05, 2007 11:23 am |
|
|
Ttelmah wrote: | This is dependant on what happens to the pins on power on.
The 'changed' interrupt, is called, whenever the state of the pins 'disagrees, with the value stored in an internal latch on the chip. This latch is reset, whenever you _read_ the pins. Hence the correct sequence to setup the changed interrupt, is:
Read the pins
Clear the interrupt in case it is already set
enable the interrupt.
This is described in the data sheet for the chip.
Also note, that to prevent the interrupt permanently triggering, you _must_ read the pins, inside the interrupt handler.
As a final comment, in the CCS compiler, you need to prevent the code running off the 'end' of main. If this happens, the processor will go to sleep. In the case shown this won't matter (the interrupt will wake the chip again), but in general, you should always add an infinite loop at the end of the code, to prevent this overrun. This is because, unlike programming on a PC, where when the code completes, there is an OS running, to 'drop back' to, here the code is the only thing running.
Best Wishes |
I've added a few lines of code that I think handle what you are proposing. There is no change however in the behavior of the circuit. It's my understanding that the INTERRUPT_ACTIVE() function will test the flag and that if true the INTERRUPT_CLEAR() function will clear it.
Thanks for your comments.
Chris
Code: | #include "12F675.h"
#use delay(4M,int) /*Sets up the internal clock for the DELAY_MS function*/
#use fast_io(A) /*Allows the use of the SET_TRIS_A() function.*/
#fuses mclr /*Allows external Master Clear*/
#int_RA /*Interrupt on Port A Change*/
void flip_flop() /*Interrupt function (ISR)*/
{
SET_TRIS_A(0b00001111); /*Sets Port A for LED D0*/
OUTPUT_A(0X00); /*All pins low*/
OUTPUT_HIGH(PIN_A4); /*Lights LED D0*/
DELAY_MS(500); /*On for 1/2 sec.*/
OUTPUT_LOW(PIN_A4); /*Turns off LED D0*/
DELAY_MS(500); /*Off for 1/2 sec.*/
if (INTERRUPT_ACTIVE(INT_RA)); /*Test to see if INT_RA flag is set*/
CLEAR_INTERRUPT(INT_RA); /*Clear the INT_RA flag*/
}
void main(void) /*Program starts here.*/
{
if (INTERRUPT_ACTIVE(INT_RA)); /*Test to see if INT_RA flag is set*/
CLEAR_INTERRUPT(INT_RA); /*Clear the INT_RA flag*/
ENABLE_INTERRUPTS(INT_RA); /*Turn on Port A Change interrupt*/
ENABLE_INTERRUPTS(GLOBAL); /*Turn on all interrupts*/
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Mon Aug 06, 2007 2:17 am |
|
|
You are missing the key line. You _must_ read the port.
You _cannot_ clear this interrupt, till the port is read. It'll retrigger automatically if this is not done.
You don't need to clear the interrupt in the handler. Te exit from the handler, automatically clears it, but it'll reset again, _because yu have not read the port_.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
christietjen
Joined: 05 Aug 2007 Posts: 3
|
|
Posted: Mon Aug 06, 2007 9:49 pm |
|
|
Ttelmah wrote: | You are missing the key line. You _must_ read the port.
You _cannot_ clear this interrupt, till the port is read. It'll retrigger automatically if this is not done.
You don't need to clear the interrupt in the handler. Te exit from the handler, automatically clears it, but it'll reset again, _because yu have not read the port_.
Best Wishes |
This works. Thanks for the help. To be, or not to be, that IS the question.
Chris
Code: |
#include "12F675.h"
/*Testing the 'Interrupt on Port Change' Interrupt
using a PicKit 1 from Microchip.*/
#use fast_io(A) //Allows the use of the SET_TRIS_A() function.
#fuses mclr //Explicitly sets external Master Clear on PIN_A3 (switched).
#use delay(4M,int) //Sets up the internal clock for the DELAY_MS function
#int_RA //Specifies that the follwing function is an
//'Interrupt on Port A Change'.
void flip_flop() //Define Interrupt function (ISR).
{
int value;
SET_TRIS_A(0b00001111); //Sets Port A for LED D0.
OUTPUT_A(0X00); //All pins low.
OUTPUT_HIGH(PIN_A4); //Lights LED D0.
DELAY_MS(500); //On for 1/2 sec.
OUTPUT_LOW(PIN_A4); //Turns off LED D0.
DELAY_MS(500); //Off for 1/2 sec.
value=input_a();
}
#use delay(4M,int) //Second set up of internal clock prevents
//'Warning 216' from occurring.
//See CCS FAQ-Interrupts.
void main(void) //Program starts here.
{
ENABLE_INTERRUPTS(INT_RA); //Turn on Port A Change interrupt.
ENABLE_INTERRUPTS(GLOBAL); //Turn on all interrupts.
//'Power On' triggers ISR once toggling LED D0 on & off.
DELAY_MS(5000); //Delay for 5 sec. to visually isolate 'Power On' toggle
//from ensuing main program toggles.
while(1) //Infinite loop toggling PIN_A4 causes
//'Port Change Interrupt' to be called repeatedly.
{
OUTPUT_TOGGLE(PIN_A4);
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|