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

16f628 clearing INT_RB problem/workaround

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



Joined: 06 Jul 2007
Posts: 15
Location: Montreal Canada

View user's profile Send private message Visit poster's website

16f628 clearing INT_RB problem/workaround
PostPosted: Mon Mar 24, 2008 9:53 am     Reply with quote

Hi,
I have a project using a 16f628. I have a quadrature encoder providing input on PORTB pin 4 and 5. I use INT_RB to catch my encoder signal changes. I also have a couple other pins on PORTB used as inputs. My problem is that INT_RB will execute whenever there is a change on any of the PORTB inputs (this is expected). To handle this, the first step I take in my ISR is to check if it is a valid interrupt (did my encoder inputs change state?). If the interrupt was caused by a different pin, then I exit early. Unfortunately, if one of my encoder signals change while I am handling an invalid interrupt, It will not be 'seen' because the compiler generated ISR code clears the INT_RB flag at then end of the ISR.

So, has anyone else run into this issue? How can I make sure that I don't miss a valid signal change while handling an 'invalid' interrupt?

Any help will be greatly appreciated. I have a couple ideas of using assembly code with a GOTO to circumvent the compiler generated code, but I would really rather not use a hack like that.

-Matt
Ttelmah
Guest







PostPosted: Mon Mar 24, 2008 10:02 am     Reply with quote

You are always going to have some potential problems with this. However you can minimise it, by using:
Code:

#INT_RB noclear
void handler(void) {
   int8 temp;
   temp=input_b();
   clear_interrupts(INT_RB);
   //Now look at your 'temp' byte, and check if the interrupt was legitimate
   //Key things are that with the 'noclear' option, you now clear the
   //interrupt, not the compiler, and since you read the port just once
   //the very instruction ahead of this, the only place the interrupt can
   //now be missed, is in the time for this one instruction.
   //Make sure you are using fast_io on portb, and you have the tris setup
   //correctly.

}


Best Wishes
matt_at_hanbay



Joined: 06 Jul 2007
Posts: 15
Location: Montreal Canada

View user's profile Send private message Visit poster's website

PostPosted: Mon Mar 24, 2008 10:35 am     Reply with quote

Thanks for the suggestion. I had searched the forum, and had come up empty until just after posting my question. I think 'noclear' is exactly what I was looking for.

Thanks again for the fast reply.
Matro
Guest







PostPosted: Mon Mar 24, 2008 10:58 am     Reply with quote

Personally, I would have cleared the interrupt before storing the value in a variable. So you are sure that you will catch every change. ;-)

Matro.
Ttelmah
Guest







PostPosted: Mon Mar 24, 2008 1:17 pm     Reply with quote

Won't work.
The RB interrupt, is set, whenever the internal 'latch', differs from the value on the pins. You can't clear it, till you read the port to reset the latch. Just like the character received interrupt (where you must read the character, before clearing the interrupt), INT_RB, requires that you read the port _first_, or the bit will simply set itself again...

Best Wishes
Matro
Guest







PostPosted: Mon Mar 24, 2008 1:37 pm     Reply with quote

So just do a "dummy" read before clearing interrupt, read it again and use this last value. ;-)

Matro.
Ttelmah
Guest







PostPosted: Mon Mar 24, 2008 3:53 pm     Reply with quote

Nothing is perfect I'm afraid. Though this will solve the interrupt 'missing' an edge that happens after the read, it potentially adds the ability to miss the original event. If the line that triggered the original interrupt returns to it's 'last' state, between the two reads, another interrupt gets triggered, but neither the current one, or this one, will detect any change in the read value...

Best Wishes
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

PostPosted: Mon Mar 24, 2008 9:09 pm     Reply with quote

Ttelmah wrote:
Nothing is perfect I'm afraid. Though this will solve the interrupt 'missing' an edge that happens after the read, it potentially adds the ability to miss the original event. If the line that triggered the original interrupt returns to it's 'last' state, between the two reads, another interrupt gets triggered, but neither the current one, or this one, will detect any change in the read value...


But that is OK, isn't it? If the original event is A going from 0->1 and then A goes 1->0 before the second read, then that just means the quadrature encoder position briefly went 1 count in one direction and then 1 count back. As long as you know where the encoder is at the end, there is no lasting error.

I think you can't go wrong if you

1. Read Port B and discard the results
2. Clear RBIF
3. Read Port B again and use the results.

Robert Scott
Real-Time Specialties
Guest








PostPosted: Tue Mar 25, 2008 2:28 am     Reply with quote

Ttelmah wrote:
Nothing is perfect I'm afraid. Though this will solve the interrupt 'missing' an edge that happens after the read, it potentially adds the ability to miss the original event. If the line that triggered the original interrupt returns to it's 'last' state, between the two reads, another interrupt gets triggered, but neither the current one, or this one, will detect any change in the read value...

Best Wishes

Sure. I don't know the clock frequency, but with a 8MHz Xtal and a short interrupt routine (for example just in/de-creasing a counter), the processing time is largely lesser than the maximum rotation speed of an encoder. ;-)
But all should be checked carefully especially the time that is spending in the ISR subroutine.

Matro.
Ttelmah
Guest







PostPosted: Tue Mar 25, 2008 3:07 am     Reply with quote

Yes.
In the case of the quadrature encoder (which this thread is about), the read, clear, read again, solution, is fine. I was just warning that data can still be lost in some circumstances, and as a 'generic' solution, you need to be aware of this.
In fact handling a quadrature encoder 'well', with INT_RB on the PIC, if you need reasonable speed, starts to jump into having to handle this in your own INT_GLOBAL handler, etc. etc.. A lot depends on the nature of the encoder output (switch based encoders, versus optical, and any signal processing present). If you can guarantee that that there will never be double pulses, and there is a maximum repetition rate that is below the interrupt interval, then the simple read/reset, is as good.

Best Wishes
Matro
Guest







PostPosted: Tue Mar 25, 2008 3:18 am     Reply with quote

You were totally right to append my post since this solution is not perfect in all cases as you already said. ;-)
For a fully secure solution the only solution is some extra logic hardware processing the encoder outputs. But as you also said here the given answer is sufficient.

See you later.
Matro.
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