|
|
View previous topic :: View next topic |
Author |
Message |
matt_at_hanbay
Joined: 06 Jul 2007 Posts: 15 Location: Montreal Canada
|
16f628 clearing INT_RB problem/workaround |
Posted: Mon Mar 24, 2008 9:53 am |
|
|
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
|
|
Posted: Mon Mar 24, 2008 10:02 am |
|
|
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
|
|
Posted: Mon Mar 24, 2008 10:35 am |
|
|
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
|
|
Posted: Mon Mar 24, 2008 10:58 am |
|
|
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
|
|
Posted: Mon Mar 24, 2008 1:17 pm |
|
|
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
|
|
Posted: Mon Mar 24, 2008 1:37 pm |
|
|
So just do a "dummy" read before clearing interrupt, read it again and use this last value. ;-)
Matro. |
|
|
Ttelmah Guest
|
|
Posted: Mon Mar 24, 2008 3:53 pm |
|
|
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
|
|
Posted: Mon Mar 24, 2008 9:09 pm |
|
|
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
|
|
Posted: Tue Mar 25, 2008 2:28 am |
|
|
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
|
|
Posted: Tue Mar 25, 2008 3:07 am |
|
|
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
|
|
Posted: Tue Mar 25, 2008 3:18 am |
|
|
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. |
|
|
|
|
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
|