View Full Version : DT Interupts PortA or PortB?
ShaneMichael
- 8th December 2011, 00:48
I need a little help, I'm using a 18F2550, and I'm counting how often a switch opens/closes on PortA.5 (Maybe 4, I don't have my circuit in front of me). I'm looping in my main code counting the changes, but I'd like to use DT's interupts, seems like a good fit. I'm using them already for comm and timing. It's working great. What I'm not finding in the posts I've read so far is when I create and enable "INT_INT" how do I control what port triggers the interupt? I'm already doing A/D conversion on PortA.0-3 And have things happening on PortB, so i don't want the changing values on the other pins to trigger the interupt, just a single pin if possible?
What I have works, but I think I may miss some state changes if the switch operates too fast.
Any idea's or suggestions would be great.
Thanks,
Shane
Charles Linquis
- 8th December 2011, 02:34
There is no hardware support for interrupts on PORTA. But that doesn't mean you can't use interrupts to do what you want.
A good way is to determine the shortest switch closure that you must detect (50mSec?). Then set up a timer that interrupts
at that rate. You mention that you are already using DT-INTs for timing, if you are using a timer for that, just "piggyback" on
that INT. If you aren't, just set up another timer (I like TMR3 for such things). The interrupt rate must be as fast as the shortest
switch closure you want to be able to detect. You ISR could be something like -
SwitchInt: ; The ISR
IF PORTA.5 = 0 THEN
IF SwitchHasBeenClosed = 0 then
Pause 10; Debounce
IF PORTA.5 = 0 then ; Still low?
SwitchHasBeenClosed = 1
SwitchHasBeenClosedFlag = 1
ENDIF
ENDIF
ELSE
IF SwitchHasBeenClosedFlag = 1 then
Pause 10 ; Debounce time
IF PORTA.5 = 1 then ; Still high?
SwitchHasBeenClosedFlag = 0
SwitchHasBeenClosedThenOpened = 1
ENDIF
ENDIF
ENDIF
@ INT_RETURN
; You can clear the flags as appropriate such that you don't perform multiple operations with one switch push.
ShaneMichael
- 8th December 2011, 08:48
Charles, Thanks for the suggestion, that's working better. How do I make TMR3 faster? It seems to check the interupt at about 76 hz, I'd like to be around 350 hz? Is there a way to do it without messing up TMR1 that I'm already using? I'm figuring 350 hz because the switch will open/close at about 44hz, but it only stays closed for about 45 degrees or 1/8 of the time. So 44hz=22.7ms, 1/8 of 22.7ms = 0.00284 s, .00284 s = 352 hz. I'm using a 20Mhz XTAL, here are some of my other settings:
asm
__CONFIG _CONFIG1L, _PLLDIV_5_1L & _CPUDIV_OSC3_PLL4_1L & _USBDIV_2_1L
__CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H
__CONFIG _CONFIG2L ,_BOR_ON_2L & _BORV_2_2L
endasm
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts
INCLUDE "Elapsed_INT-18.bas" ; Elapsed Timer Routines
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _ClockCount, PBP, yes
INT_Handler RX_INT, _Check_Command, PBP, yes
INT_Handler TMR3_INT, _CheckWind, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE TMR1_INT
@ INT_ENABLE RX_INT
@ INT_ENABLE TMR3_INT
For reference here is how I count number of times the switch closes, my version of what you posted, seems to work good.
CheckWind:
If Wpin = %1 Then
WindThsState = %1
Else
WindThsState = %0
EndIF
If WindThsState <> WindLstState Then 'Spinning
WindCnt = WindCnt +1
ENDIF
WindLstState = WindThsState
@ INT_RETURN
Let me know where I should modify, Thanks again for the help.
Shane
HenrikOlsson
- 8th December 2011, 09:56
Hello Shane,
I'm jumping in here with my couple of cents worth...
TMR3 trips an interrupt when it overflows. It's 16bits wide so it counts from 0 to 65535 and then overflows back to 0, tripping the interrupt. If you have the TMR3 prescaler set to 1:1 (which you have) the timer "ticks" at Fosc/4 or 5Mhz in the case of a 20MHz x-tal. 5MHz/65536=76.3Hz which is your interrupt frequency.
If you want it to interrupt at higher frequency all you need to do is preload TMR3 with a suitable value each time it interrupt. If you preload it with 51350 then you'll get an interrupt frequency of roughly 5Mhz/(65536-51350)=352Hz.
Remember that you have to load the timer each time it overflows, not just once. This is best done by stopping the timer and then ADD the preload value to the content of the timer registers, this way the interrupt latency is catered for.
Using TMR2 may be better since it interrupts when it matched PR2 and automatically resets so you don't need to preload in each interrupt.
With all that said, if you're already HAVE a timer interrupt (TMR1 in your case) why not use that. There's no reason you can't check your input AND keep time (if that's what you're doing) from within the same ISR. There's usually no need to have a separate timer for each and every task.
/Henrik.
Charles Linquis
- 8th December 2011, 13:45
The preload value for a timer is easily calculated with Mister E's PIC MultiCalc.
http://www.picbasic.co.uk/forum/atta...7&d=1225550328 (http://www.picbasic.co.uk/forum/attachment.php?attachmentid=2957&d=1225550328)
ShaneMichael
- 8th December 2011, 17:34
Charles and Henrik;
Preloading TMR3 Worked like a charm, I made it go just a little faster than I need just for some room for error. With a preload of:
TMR3Preload CON 51650
I put this at the end of my TMR3 interupt routine to preload:
T3CON.0 = %0 'Turn Timer Off To preload for frequency I need.
TMR3Now.Highbyte = TMR3H
TMR3Now.LowByte = TMR3L
TMR3Now = TMR3Now + TMR3PreLoad
TMR3H = TMR3Now.HighByte
TMR3L = TMR3Now.LowByte
T3Con.0 = %1 'Turn Timer on
Seems to run at 355-360 hz. The error is probably in how I'm capturing the frequency, it's probably more accurate than that. That's what I need though, MISTER E's MultiCalc is handy for this, so thanks also to Mister E and everyone else. I didn't know I could preload the timer, I'm learning more all the time.
Thanks Again,
Shane
Powered by vBulletin® Version 4.1.7 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.