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

Interrupt problem.

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



Joined: 05 Aug 2007
Posts: 3

View user's profile Send private message

Interrupt problem.
PostPosted: Sun Aug 05, 2007 7:27 am     Reply with quote

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 
Ttelmah
Guest







PostPosted: Sun Aug 05, 2007 8:13 am     Reply with quote

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
christietjen



Joined: 05 Aug 2007
Posts: 3

View user's profile Send private message

PostPosted: Sun Aug 05, 2007 11:23 am     Reply with quote

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*/

   
   
}      
Ttelmah
Guest







PostPosted: Mon Aug 06, 2007 2:17 am     Reply with quote

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
christietjen



Joined: 05 Aug 2007
Posts: 3

View user's profile Send private message

PostPosted: Mon Aug 06, 2007 9:49 pm     Reply with quote

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);
         }
   
   
}
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