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

How to detect both edges in EXT interrupt

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



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

How to detect both edges in EXT interrupt
PostPosted: Sun Jun 06, 2004 5:12 pm     Reply with quote

I need to detect both edges in an interrupt pin, because I want to add a configurable delay in the comparator output pin.

Once it gets the Low to High interrupt it sets the comparator output pin (PIN_C2) high. When a High to Low interrupt occurs, CCP1 is loaded with the desired delay and timer1 is started.. when timer1=ccp1 PIN_C2 is set low, so the high pulse width (in PIN_C2) is the time between interrupts plus a configurable delay.


Code:
#int_ext fast
void ext_isr(void) {
  if(input(PIN_B0)) {           // rising edge detected
     setup_ccp1(CCP_OFF);  // stop comparator so
     output_high(PIN_C2);    // we can set output high
         } else {
   CCP_1=255;   // here we set the delay time 
                set_timer1(0); // clear timer to start from 0
   setup_ccp1(CCP_COMPARE_CLR_ON_MATCH);  // here we go!
   }
}

In MPLAB simulator I get interrupts in both H_to_L and L_TO_H, but in the real PIC the ELSE section is never executed.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jun 06, 2004 5:22 pm     Reply with quote

You can change the active edge with this CCS function:

ext_int_edge(L_TO_H);

or

ext_int_edge(H_TO_L);
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Sun Jun 06, 2004 5:47 pm     Reply with quote

Already tried before the post but nothing yet.

Code:
#int_ext fast
void ext_isr(void) {
     if(input(PIN_B0)) {         // rising edge detected
     setup_ccp1(CCP_OFF);   // stop comparator so
     output_high(PIN_C2);     // we can set output high
     ext_int_edge(H_TO_L);   // change next edge to High to low
          } else {
   ext_int_edge(L_TO_H);  // return edge to normal
   CCP_1=255;     // here we set the delay time
   set_timer1(0);  // clear timer to start from 0
   setup_ccp1(CCP_COMPARE_CLR_ON_MATCH);  // here we go!
   }
}
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Sun Jun 06, 2004 6:23 pm     Reply with quote

Just found what I was looking for..

http://www.ccsinfo.com/forum/viewtopic.php?t=18914&highlight=interrupt+read

Code:
#int_ext
     void ext_isr(void) {
         if(input(PIN_B0)) {               // rising edge detected
             setup_ccp1(CCP_OFF);     // stop comparator so
             output_high(PIN_C2);       // we can set output high
             ext_int_edge(H_TO_L);
               output_high(pin_d3);  //
               output_low(pin_d2);   ////
            } else {                        ///// alternate leds to show what
               output_high(pin_d2);  ////  is happening
               output_low(pin_d3);   //
             ext_int_edge(L_TO_H);
             CCP_1=255;               // here we set the advance timing
             set_timer1(0);             // clear timer to start from 0
             setup_ccp1(CCP_COMPARE_CLR_ON_MATCH); // here we go!
   }
}


I tracked down the problem and without fast interrupts the code works fine.

But with this I lost the fast interrupt and got a big overhead in context saving.

Any sugestions?
ckielstra



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

View user's profile Send private message

PostPosted: Mon Jun 07, 2004 12:18 pm     Reply with quote

I'm doing something similar in my code and this works perfect. A difference is that for determining which edge caused the interrupt to be calld I test the setting of the interrupt register i.s.o. PIN-B0.

I'm a bit worried about the lack of context saving in your FAST interrupt version. Are you sure the compiler is using no registers at all?
Can you post the assembly listing of your FAST interrupt function? There might be a problem with the BSR settings.
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Mon Jun 07, 2004 12:57 pm     Reply with quote

I´m at work right now and will complete this post tonight with the asm listing.

In your application, do you use fast interrupt for EXT?

In the test, do you use something like if(INTCON2&&MASK) {}

EDIT1: Attached files with and without fast interrupt.

http://future.gotdns.com:8080/ccs

EDIT2: Lots of edits... Your solution really worked, testing INTCON2.6 instead PORTB.0 did the job.

Thank you for you attention Very Happy
ckielstra



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

View user's profile Send private message

PostPosted: Mon Jun 07, 2004 5:02 pm     Reply with quote

My function is mostly written in assembler because I had an example program to work from that was in assembler and for interrupts I like having total control.

So my assembly code for the test on a PIC18F458 looks like
Code:

        btfss   intcon,intf     ; external interrupt?
        goto    intovfl         ; no, go     
        bcf     intcon,intf     ; yes. Clear external interrupt flag
        btg     intcon2,intedge0 ; trigger on opposite edge
        ; do something usefull
        goto int_exit
intovfl:
        ; handle other interrupts
int_exit:

or the C equivalent
Code:

if bit_test(intcon, intf)
{
  bit_clear(intcon, intf);
  bit_toggle(intcon2, intedg0);
}


Further I think you better read your own thread of a few days ago again http://www.ccsinfo.com/forum/viewtopic.php?t=19498.... Wink
Here Ttelmah explains that using an index in your interrupt handler requires saving several of the table pointer registers and a couple of scratch registers. Then looking at the FAST example I posted there you can see I save the FSROL, FSROH and #3 registers. I'm sure you will see these same registers being used in your code. Not saving these registers will corrupt your main program loop with unpredictable results.

One other small gotcha: Make sure you have set the timer for synchronous clock input as the data sheets say that compare is not guaranteed with the asynchronous counter. Setting this wrong will make you loose an occasional edge change.
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Mon Jun 07, 2004 5:40 pm     Reply with quote

At the time of the other post, I needed only one edge.. When I needed to detect the 2 edges I got the bug, because I was wrong thinking that testing portb.0 would show me what edge it was.

You can see in the links I post that none of the registers are used.

One thing that I dont know is why if(input(PIN_B0)) does not work with fast interrupts. if(INTCON2.6) works in all cases.

What I understand for "synchronous clock input" is when it is derived from the internal crystal/4 clock.. If this is correct, then yes, timer1 is incremented every 4 internal clock ticks.

When was bit_toggle statement added to CCS? I cant see it even in the changes from version 3.000+
ckielstra



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

View user's profile Send private message

PostPosted: Tue Jun 08, 2004 2:17 am     Reply with quote

I don't know why testing port.b is not working, the only reason I can think of is that you have a very fast changing input signal and that the level has changed again before your test.

The function bit_toggle() is my own code, something I think is missing from CCS. The PIC18 provides a single instruction for toggling a bit, trying to do the same with C code will result in at least two instructions.

Code:
#define bit_toggle(byte, bit) { \
  #ASM \
  btg byte,bit \
  #ENDASM}


With the "synchronous clock" the internal clock is mentioned, as opposed to an external clock.
hydrogene



Joined: 23 May 2004
Posts: 11
Location: Montreal

View user's profile Send private message

PostPosted: Sat Jun 12, 2004 3:47 pm     Reply with quote

Hi,
You can do your own edge detector. Here is the code:
Code:

//Global var
int1 btn_state = 0;

#int_ext
void interrupt_B_zero();
{
    btn_state = ~btn_state;    // change 1 for 0 and 0 for 1

    if(btn_state)
       what you want to do on down edge
    else
       what you want to do on up edge

}

Good luck

David
ckielstra



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

View user's profile Send private message

PostPosted: Sat Jun 12, 2004 4:12 pm     Reply with quote

Hydrogene,

Your solution is one way to implement an edge detector and I have thought of doing it like that, but there are a few reasons why I decided otherwise:

1) It is not a real edge detector, but more like a semaphore remembering the last state. A programming error could cause the semaphore to get out of sync and you will be executing code for the wrong edge.
2) It requires an extra variable (RAM) and code to set it (ROM).

Testing for the value of INTCON2.6 doesn't have these disadvantages.
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