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 support@ccsinfo.com

12F675 Interrupt problems

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







12F675 Interrupt problems
PostPosted: Wed Nov 19, 2003 11:31 am     Reply with quote

I have tried a whole day now to get the PIC12F675 to wake up from sleep using an external interrupt. The interrupt appears to be working but not in a way it is supposed to. What i want to do is to execute a code to do some calculations and then go into sleep mode. And then do the same thing whwn woken up with the ext.int. However the interrupt appears to be generated two times internally everytime I generate one externaly.

Heres the (non working) code so far:

Code:
#include <12F675.h>

#fuses INTRC_IO,PUT,NOWDT,NOPROTECT,NOMCLR, BROWNOUT
#use delay(clock = 4000000)

// IO pins
#bit gpio5 =0x05.5
#bit gpio4 =0x05.4
#bit gpio3 =0x05.3
#bit gpio2 =0x05.2
#bit gpio1 =0x05.1
#bit gpio0 =0x05.0

#use fast_io(a)

#byte ADCON0    = 0x1F // A/D
#byte ANSEL    = 0x9F // A/D config
#byte CMCON    = 0x19 // Comparators

main()
{
     ADCON0    = 0;   // ADC off
     ANSEL    = 0;      // GPIO pins 0,1,2 and 4 set to all digital
     CMCON    = 7;      // Comparators off

     // Setup i/o
     set_tris_a(0b001100); //GP0,1,4,5 output; 2,3 input

     gpio5 = 0;
     gpio4 = 1;  //turn on LED on gp4
     gpio1 = 0;
     gpio0 = 0; 

   delay_ms(1000);
   gpio4 = 0;

     // Set timer0 not to use GP2
   setup_counters(rtcc_internal, rtcc_div_2);

   ext_int_edge(L_TO_H);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);;

   while(true)
   { 
   
      delay_ms(1000);

        gpio5 = !gpio5;   //toggle LEDs just to test that program is running
      delay_cycles(5);

                                delay_ms(1000);
   
      sleep();   
   }// main loop
}// main

#int_ext
void ext_isr(void)
{
   //-- Wake up from sleep --
   gpio1 = !gpio1;      // Test to see if isr is executed
   delay_ms(100);
   
}// ext_isr


The ext_int_edge appear to have no effect what so ever. The interrupt is triggered on any edge. On startup the gpio4 led is blinking. And then the gpio5 led is lit. On interrupt the gpio1 led is blinking and then gpio4 also. Then gpio5 led is lit. As if the cpu is restarted.

If i cause an ext interrupt and keep the input low the cpu will flash the leds gpio1 and gpio4 in a toggling mode, until the ext input is put high. Then the gpio5 led is lit.

What i want is that the the ext.int is only triggered on a L_TO_H edge and only to execute to code until sleep(), and not restarting completley. This ofcourse could be done in a polling mode, but I need the cpu to be in a low power mode between interrupts.

What to do? What is wrong with the code? Please help!
/Fredrik
Ttelmah
Guest







Re: 12F675 Interrupt problems
PostPosted: Wed Nov 19, 2003 12:02 pm     Reply with quote

Fredrik wrote:
I have tried a whole day now to get the PIC12F675 to wake up from sleep using an external interrupt. The interrupt appears to be working but not in a way it is supposed to. What i want to do is to execute a code to do some calculations and then go into sleep mode. And then do the same thing whwn woken up with the ext.int. However the interrupt appears to be generated two times internally everytime I generate one externaly.

Heres the (non working) code so far:

Code:
#include <12F675.h>

#fuses INTRC_IO,PUT,NOWDT,NOPROTECT,NOMCLR, BROWNOUT
#use delay(clock = 4000000)

// IO pins
#bit gpio5 =0x05.5
#bit gpio4 =0x05.4
#bit gpio3 =0x05.3
#bit gpio2 =0x05.2
#bit gpio1 =0x05.1
#bit gpio0 =0x05.0

#use fast_io(a)

#byte ADCON0    = 0x1F // A/D
#byte ANSEL    = 0x9F // A/D config
#byte CMCON    = 0x19 // Comparators

main()
{
     ADCON0    = 0;   // ADC off
     ANSEL    = 0;      // GPIO pins 0,1,2 and 4 set to all digital
     CMCON    = 7;      // Comparators off

     // Setup i/o
     set_tris_a(0b001100); //GP0,1,4,5 output; 2,3 input

     gpio5 = 0;
     gpio4 = 1;  //turn on LED on gp4
     gpio1 = 0;
     gpio0 = 0; 

   delay_ms(1000);
   gpio4 = 0;

     // Set timer0 not to use GP2
   setup_counters(rtcc_internal, rtcc_div_2);

   ext_int_edge(L_TO_H);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);;

   while(true)
   { 
   
      delay_ms(1000);

        gpio5 = !gpio5;   //toggle LEDs just to test that program is running
      delay_cycles(5);

                                delay_ms(1000);
   
      sleep();   
   }// main loop
}// main

#int_ext
void ext_isr(void)
{
   //-- Wake up from sleep --
   gpio1 = !gpio1;      // Test to see if isr is executed
   delay_ms(100);
   
}// ext_isr


The ext_int_edge appear to have no effect what so ever. The interrupt is triggered on any edge. On startup the gpio4 led is blinking. And then the gpio5 led is lit. On interrupt the gpio1 led is blinking and then gpio4 also. Then gpio5 led is lit. As if the cpu is restarted.

If i cause an ext interrupt and keep the input low the cpu will flash the leds gpio1 and gpio4 in a toggling mode, until the ext input is put high. Then the gpio5 led is lit.

What i want is that the the ext.int is only triggered on a L_TO_H edge and only to execute to code until sleep(), and not restarting completley. This ofcourse could be done in a polling mode, but I need the cpu to be in a low power mode between interrupts.

What to do? What is wrong with the code? Please help!
/Fredrik

The first thing to remember, is that the global interrupt enable, does not need to be set to 'wake up' from interrupts. The act of waking up, is independant of the normal interrupt handling. Hence your code will wake up, and execute the next instructions after the sleep, then interrupt, and call your handler. Because there is a significant latency after wake up, and calling the interrupt, the code may allready have entered the 'delay_ms(1000)' routine, which because it is called both inside and outside the interrupt, will have the interrupts disabled. Hence this will execute first, then the handler will toggle bit 1, wait 100mSec (get rid of this, interrupt handlers should be short), then return. It will then carry on executing the rest of the main loop.
So, get rid of the interrupt handler completely, and just have the INTF bit defined, clear it, execute the sleep, then have the code you want executed following this instruction. Loop back to the instruction to clear the INTF bit to wait for the next edge. So:

#bit INTF 0xB.1

Then in the main, loop as:

ext_int_edge(L_TO_H);
INTF=0;
enable_interrupts(INT_EXT);

gpio5 = !gpio5; //toggle LEDs just to prove that program is running
while (true) {
INTF=0;
sleep();
gpio1=!gpio1;
delay_ms(100);
}// main loop

This may give a result closer to what you want.

Best Wishes
Fredrik
Guest







PostPosted: Thu Nov 20, 2003 2:12 am     Reply with quote

Yes now it works much better. In my defense: The delays where only there for debug. Thanks for the help and the explanation!

/ Fredrik
Ttelmah
Guest







PostPosted: Thu Nov 20, 2003 3:15 am     Reply with quote

Fredrik wrote:
Yes now it works much better. In my defense: The delays where only there for debug. Thanks for the help and the explanation!

/ Fredrik

The key thing, is the extremely long latency in an interrupt response when 'waking'. This is only visible in one timing diagram on the chips data sheet, but is about four instruction times. This allows the interrupt response to be in a completely 'unexpected' location (in one of the data sheets for older chips, the latency is only one instruction, and MicroChip recommend adding a 'nop' after the sleep, if you want to call an interrupt handler this way, to avoid this type of problem...).
It is one of those faults, that you have to have 'met yourself'...

Good luck
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