Interrupts and status
John Couture
Posts: 370
Problem:· Port B is used to detect interrupts.· Some are random (i.e. rain guage) some are on a schedule (i.e. 1Hz pulse from Real Time Clock).· I can get interrupts to work but the RTC produces a 1Hz pulse with a 50% duty cycle (i.e. 500ms on, 500ms off).· Thus interrupt is caught MANY times (the darn SX52 is FAST!).
I suspect that I need to do something with the WKPND_B register (SX-Key Dev System, pg 169)· but I can't figure out the syntax.
Something like:
'
'· Inside the Interrupt routine, determine if the RTC pulsed
'
IF WKPND_B.7 = 1 then
··· ' handle RTC interrupt
··· WKPND_B.7 = 0··· ' stop listening until next change
ENDIF
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
John J. Couture
San Diego Miramar College
I suspect that I need to do something with the WKPND_B register (SX-Key Dev System, pg 169)· but I can't figure out the syntax.
Something like:
'
'· Inside the Interrupt routine, determine if the RTC pulsed
'
IF WKPND_B.7 = 1 then
··· ' handle RTC interrupt
··· WKPND_B.7 = 0··· ' stop listening until next change
ENDIF
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
John J. Couture
San Diego Miramar College
Comments
you can't directly read the WKPND_B register, or single bits in this register.
To access this register, use the following sequence inside the ISR instead:
mode $09 ; select the WKPND_B register
clr w
mov !rb, w ; exchange WKPND_B and w
The mov !rb,w instruction does not simply move its contents into the WKPND_B register. Instead, it exchanges the contents of both registers. IOW, after this instruction has been executed, WKPND_B contains 0 (because w was cleared before), and w the status of the WKPND_B bits. This is a bit tricky but a clever method to clear the WKPND_B bits (absolutely necessary to avoid another interrupt after terminating the ISR), and to retrieve the WKPND_B bits with just one instruction using clock cycle. Once you have the WKPND_B bits in the w register, you may evaluate them as necessary.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Greetings from Germany,
G
I guess what I was hoping for was a way to tell the mcu to disregard that port pin until it flip-flopped again. Also, your solution above is in assembler ... is there an SX/B solution? I would normally put pauses in the interrupt code but I already got zapped for doing that (grin)!
It would seem like it would be something simple like telling the mcu to raise an interrupt ONLY when there is a change from high to low (or visa versa).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
John J. Couture
San Diego Miramar College
The port B interrupts are edge detecting, so you won't have retriggering until you get a valid transition.· And yes, you can do what you want in SX/B; for example:
INTERRUPT
ISR_Start:
· rbStatus = 0
· WKPND_B = rbStatus················ ·' get bits that changed
· IF rbStatus.0 = 1 THEN
··· INC secs
··· IF secs = 60 THEN
····· secs = 0
····· mins = mins + 1
······IF mins = 60 THEN
······· mins = 0
······· hours = hours + 1
····· ENDIF
····ENDIF
· ENDIF
· IF rbStatus.1 = 1 THEN
··· INC rain
· ENDIF
· RETURNINT
·
[noparse][[/noparse]Edit] -- I decided to try it for myself and whipped up the attached program on a PDB (You have one, right? ).· I used the Pulse Generator to drive one of the RB pins.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Post Edited (Jon Williams (Parallax)) : 10/20/2005 9:58:34 PM GMT
I was trying to read the pin directly instead of reading the WKPND_B which is a "latch" that indicates that the pin was toggled.
Interesting. In "classic" programming, the data goes from right to left on an equals sign, as in:
a = b + c
Yet, at the top of your program, you have
WKPND_B = rbStatus
which implies that the rbStatus receives the data not the WKPND_B?
Is that just because the compiler was designed that way?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
John J. Couture
San Diego Miramar College
Humm ... I don't know about what you consider classic but let's take some old FORTRAN for example:
I = I + 1
is often used to increment the integer variable I from its old value to a new value one larger and the 'expression' (quotes here because this is _not_ algebra!) is evaluated first on the right with operator precedence and then the result is placed in the location on the left.
Most programming languages I know operate in much the same way.
Best,
Sandy
· WKPND_B = rbStatus
... produces this code:
· MODE $09
· MOV !RB, rbStatus
· MOV rbStatus, W
So the effect is that WKPND_B and rbStatus are exchanged.· I've updated the program (attached above)·to clear rbStatus before the exchange -- this gets what's in WKPND_B and clears it at the same time.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Yes, that was my point. Most languages go from right to left (as does Fortran above). I guess I was trying to state that most languages put the receiving operand on the left of the equals sign, yet the WKPND_B = rbStatus seems to defy that logic (grin).
Jon,
Thus, it looks like the statement is actually a swap (something very common in assemblers). I never got into compiler design (a magical art in my opinion) so sometimes the syntax of the language is a little mysterious to me.
I'll have to play around with the syntax and see what kind of assembler code it produces (something I should have done before I posted this, sorry).
Anyway, it works great. Now to gather it together into a tutorial.
Thanks again.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
John J. Couture
San Diego Miramar College
·· WKPND_B = rbStatus
does an exchange, not a simple assignment.· I suppose we could have used:
· rbStatus = WKPND_B
but then those looking "under the hood" (as we hope will ultimately happen) would wonder why it generated this code:
· MODE $09
· MOV !RB, rbStatus
· MOV rbStatus, W
since the MOV instruction is defined as:
· MOV destination, source
As I pointed out to a student in one of our other forums, engineers are faced with choices every day -- sometimes the choice will make sense to others without explanation, sometimes not.· This is one of those cases where we thought that one familiar with how the WKPND_B register is handled it would make sense.
In the FWIW category, this note is in the SX/B help file:
2· When changed (i.e., Register = Variable), Variable is swapped with Register.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
MODE $09
MOV !RB, rbStatus
MOV rbStatus, W
may still look mysterious to some readers, wondering about how W gets the correct value. So it is important to note that
MOV !RB, rbStatus
is a multi-word instruction. When SASM generates the instruction code, it actually generates the following sequene:
MODE $09
W, rbStatus ; replacement for
MOV !RB, W ; MOV !RB, rbStatus
MOV rbStatus, W
As Jon mentioned, the MOW !RB, W does not just copy W into !RB but it exchanges the contents of both registers. So W will hold the status of the WKPND_B bits after this exchange. Provided that rbStatus is cleared before, all WKPND_B bits will be reset after the exchange. Please note that this is very important. When the bits are not all cleared, another interrupt will be fired immediately after leaving the ISR with a RETI, or RETIW instruction.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Greetings from Germany,
G
MASK equ value· ;clear bits for unused inputs
mode $09
clr w
mov !rb,w· ;clear wkpnd_B
and w,#MASK ;clear unused pins
or rbstatus,w· ;add new pin interrupts to status byte
This allows also to delay pin interrupts to main code if allowed
(for example, a button press). Once a pin interrupt task is completed,
the appropiate bit in rbstatus is cleared.
regards peter
Alas, of the many languages I have learned in my career, I never really liked assembler and considering how many I have tried (Assembler 360, Knuth's MIX, PDP 11, Honeywell something, HP something else, Z80, 8051 ... ) you'd think I'd be better at it and remember the points that you all brought up (grin).
Anyway, the SX/B code is working perfectly and again thank you.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
John J. Couture
San Diego Miramar College