Step 5Software
To get the Darrel Taylor (DT) interrupts set up there are two things to do:
1.) Include the DT_INTS-14.bas and ReEnterPBP.bas files in your code.
2.) Copy and paste this into your code.
ASM
INT_LIST macro ;IntSource, Label, Type, ResetFlag?
INT_Handler RBC_INT, _ISR, PBP, yes
endm
INT_CREATE
ENDASM
Insert tabs and spaces like the graphic at the end of the Instructable so you can see things a little easier in your code. You'll need to modify it slightly to fit your needs. Under Label, replace ISR with the name of the subroutine that is your ISR. Don't forget the underscore! You need it!
To get the interrupts working, there are two more things to do:
1.) Write the ISR. You'll write this just like you were going to write a PBP subroutine except that you will need to insert @ INT_RETURN at the end of the subroutine instead of RETURN. This will acknowledge the interrupt and return program execution to where it left off in the main loop.
Inside the ISR, you need to clear the interrupt flag so your program does not get caught in a recursive interrupt. Simply reading PORTB is all that needs to be done to clear the interrupt flag on the PIC16F877A. Each different microcontroller has a different way of clearing interrupt flags. Check the data sheet for your microcontroller.
2.) When you reach the point in your code that you want to enable the interrupt, use this line of code:
@ INT_ENABLE RBC_INT
When you want to disable the interrupt simply use:
@ INT_DISABLE RBC_INT
There's a lot of stuff packed into what I just covered so I'll summarize quickly. So far, your program should look something like this:
; Any needed set up or code
INCLUDE "DT_INTS-14.bas"
INCLUDE "ReEnterPBP.bas"
ASM
INT_LIST macro ;IntSource, Label, Type, ResetFlag?
INT_Handler RBC_INT, _myISR, PBP, yes
endm
INT_CREATE
ENDASM
; Any other needed set up or code
@ INT_ENABLE RBC_INT
; Code that needs to know which way the knob is rotating
@ INT_DISABLE RBC_INT
; Other code
END ; End of program
myISR:
;ISR code here
@ INT_RETURN
(Interrupt Handler Set Up Table)
I think this is where anyone who is not using a PIC or DT interrupts can join in again. Now, we need to actually write the ISR so the microcontroller knows which way the knob is rotating. Recall from the software theory section that we can deduce the direction of rotation if we know the input that caused the interrupt, its new value and the value of the other input. Here's the pseudocode:
Read PORTB into a scratch variable to clear the interrupt flag
Check if A caused the interrupt.
If true,
Compare A and B.
Check if different, if different,
It was clockwise rotation
Else,
It was counterclockwise
Endif
Check if B caused the interrupt.
If true,
Compare A and B
Check if different, if same,
It was clockwise rotation
Else,
It was counterclockwise
Endif
Return from interrupt
How do we know if a change on A or B caused the interrupt? Discovering the new value of the changed input and the other (unchanged) input is easy because we can read them inside the ISR. We need to know what the state of each one was before execution gets sent to the ISR. This happens in the main routine. The main routine sits and waits for a byte variable that we called CWflag to be set to 1 or cleared to 0 by the ISR. After each acknowledged change of the knob or if there is no knob activity, the variable is set to 5 to indicate an idle state. If the flag gets set or is cleared, the main routine immediately increments or decrements the set point pressure appropriately based on the rotation and then sets the CWflag variable back to 5 because the knob is now idle again. As the main routine is checking the CWflag, it is also documenting the state of the A and B rotary switch values. This is really simple and looks like this:
oldA = A
oldB = B
There really is nothing super fancy here. Just include those two lines at the beginning of the loop that checks the CWflag for rotation. We're just updating the logic values of the inputs from the rotary knob inside the increment/decrement loop in the main routine so that we can see what input caused the interrupt when the ISR is executed. Here is the ISR code:
ABchange:
scratch = PORTB ' Read PORTB to clear interrupt flag
' If A causes the interrupt, check B for direction of rotation
IF oldA != A THEN
' If A and B are different, it was clockwise rotation
IF A != B THEN
GOTO CW
' Otherwise, it was counter-clockwise rotation
ELSE
GOTO CCW
ENDIF
ENDIF
' If B causes the interrupt, check A for direction of rotation
IF oldB != B THEN
' If A and B are the same, it was clockwise rotation
IF A == B THEN
GOTO CW
' Otherwise, it was counter clockwise rotation
ELSE
GOTO CCW
ENDIF
ENDIF
CW:
CWflag = 1
@ INT_RETURN
CCW:
CWflag = 0
@ INT_RETURN
I've included the ISR code in a AB_ISR.bas file because the tabs in the code aren't showing up the way they should.
Now, because the ISR has the old values for inputs A and B it can determine which input caused the interrupt, compare it to the other (unchanged) input and determine the direction of rotation. All the main routine has to do is check the CWflag to see which direction the knob has turned (if it has) and increment or decrement a counter, set point or whatever you like or need.
I hope this helps and hasn't been too confusing. This type of interface is especially useful if your system is already using interrupts as this is only one more interrupt to add. Enjoy!
AB_ISR.bas671 bytes| « Previous Step | Download PDFView All Steps | Next Step » |
![]() |
Add Comment
|











































