Interrupts - Writing The Code
We covered quite a bit of ground in the last tutorial, and so we think it is time that we wrote our first program. The program we are going to write will count the number of times we turn a switch on, and then display the number. The program will count from 0 to 9, displayed on 4 LEDs
in binary form, and the input or interrupt will be on RB0.
The first thing we need to do is tell the PIC to
jump over the address where the Program Counter points to when an interrupt
occurs. You will notice that We are using a different way of expressing
hexadecimal numbers. Before We used to use F9h where h denoted
hexadecimal. We can write this as 0xF9, and this is the format we are
going to use from now on.
org 0x00 ;This is where
the PC points to on power up and reset
goto main ;Goto
our main program
org 0x04
;This is where our interrupt routine will start
retfie ;This tells the PIC that the interrupt routine has
;finished and the PC will point back to the main
;program
main ;This is the start of our main program
Now we need to tell the PIC that we are going to use interrupts, and we are using RB0 pin 6 as an interrupt pin:
bsf INTCON,7 ;GIE – Global interrupt enable (1=enable)
bsf INTCON,4 ;INTE - RB0 interrupt enable (1=enable)
We are going to clear the interrupt flag just in case (We never trust anything!)
bcf INTCON,1 ;INTF - Clear flag bit just in case
Now we need to set up our two ports. Remember that as we are using RB0 as an interrupt pin, this must be set up as an input:
bsf STATUS,5 ;Switch to Bank 1
movw 0x01 ;
movwf TRISB ;Set RB0 as input
movlw
0x10
;
movwf TRISA ;Set the first 4 pins on PortA as output
bcf STATUS,5 ;Come back to Bank 0
We are going to use a variable called COUNT to store the number of switch counts. We could
just simply increment the value on Port A, but you will see why we are using a variable when we write our interrupt routine.
loop
movf COUNT,0 ;Move the contents of COUNT into W
movwf PORTA ;Now move it to Port A
goto loop ;Keep on doing this
end ;End of our program
So, our main program is written, and now we need to tell the PIC what to do when an interrupt happens. In this instance, our interrupt is going to be the switch. What we want the PIC to is add one to the variable COUNT each time the switch is closed. However, we only want to display the number of times the switch closes from 0 to 9. Above, We said we could have just simply incremented the value on Port A each time there was an interrupt. But, Port A has 5 bits, and if we just simply incremented the port, we will have a maximum count of 31. There are two reasons why we chose not to go up to 31. First, we are going to use a 7-segment display, which can at the most only go from 0 to 15 (0 to F in hex). Secondly, We also want to show you some of the arithmetic commands that you came across in the last couple of tutorials.
So lets get on with our interrupt routine.
Now the first thing we need to do is temporarily store the contents of our w register, as we are using this to transfer the contents of COUNT to PORTA. If we don’t store it, then we could send a completely different number as a
result of our arithmetic. So let’s do that first:
movwf
TEMP
;Store w register in a temporary location
Next we want to add 1 to our variable COUNT:
incf COUNT,1 ;Increment COUNT by 1, and put the result
;back into COUNT
Next we want to do a check on COUNT to se if we have gone past the value of
9. The way we can do this is to subtract it from 10.
movlw 0x0A ;Move the value 10 into w
subwf COUNT,0 ;Subtract w from COUNT, and put the
;result in w
From tutorial 8 we saw that if we subtract a large number from a small number
a Carry flag will be set. This flag will also be set if the numbers are
equal, and we subtract them.
btfss STATUS,0 ;Check the Carry flag. It will be set if
;COUNT is equal to, or is greater than w,
;and will be set as a result of the subwf
;instruction
Now we know if the value of COUNT is 9 or more. What we want to do now is if COUNT is greater than 9, put it back to 0, otherwise go back to the main program so that we can send it to Port A. The BTFSS command as you know will skip the next instruction if the carry flag is set i.e COUNT = 10:
goto carry_on ;If COUNT is <10, then we can carry on
goto clear ;If COUNT is >9, then we need to clear it carry_on
bcf INTCON,0x01 ;We need to clear this flag to enable
;more interrupts movfw
TEMP ;Restore w to the value before the interrupt
retfie ;Come out of the interrupt routine
clear
clrf COUNT ;Set COUNT back to 0
bcf INTCON,1 ;We need to clear this flag to enable ;more interrupts
retfie ;Come out of the interrupt routine
All that is left to do now is put everything together and also define values to our constants, which we can do right at the beginning of our program.
Below is the complete program listing. The circuit is shown after the program listing. Every time you turn the switch on, the LEDs will count up in binary from 0000 to 1010 then back to 0000.
org 0x00 ;This is where we come on power up and reset
;*******************SETUP CONSTANTS*******************
INTCON EQU 0x0B ;Interrupt Control Register
PORTB EQU 0x06 ;Port B register address
PORTA EQU 0x05 ;Port A register address
TRISA EQU 0x85 ;TrisA register address
TRISB EQU 0x86 ;TrisB register address
STATUS EQU 0X03 ;Status register address
COUNT EQU 0x0c ;This will be our counting variable
TEMP EQU 0x0d ;Temporary store for w register
goto main ;Jump over the interrupt address
;***************INTERRUPT ROUTINE***************
org 0x04 ;This is where PC points on an interrupt
movwf
TEMP
;Store the value of w temporarily
incf COUNT,1 ;Increment COUNT by 1, and put the result
;back into COUNT
movlw 0x0A ;Move the value 10 into w
subwf COUNT,0 ;Subtract w from COUNT, and put the result in w
btfss STATUS,0 ;Check the Carry flag. It will be set if
;COUNT is equal to, or is greater than w,
;and will be set as a result of the subwf
;instruction
goto carry_on ;If COUNT is <10, then we can carry on
goto clear ;If COUNT is >9, then we need to clear it
carry_on
bcf INTCON,0x01 ;We need to clear this flag to enable
;more interrupts
movfw TEMP ;Restore w to the value before the interrupt
retfie ;Come out of the interrupt routine
clear
clrf COUNT ;Set COUNT back to 0
bcf INTCON,1 ;We need to clear this flag to enable
;more interrupts
retfie ;Come out of the interrupt routine
;*******************Main Program*********************
main
;*******************Set Up The Interrupt Registers****
bsf INTCON,7 ;GIE – Global interrupt enable (1=enable) bsf INTCON,4 ;INTE - RB0 Interrupt Enable (1=enable) bcf INTCON,1 ;INTF - Clear FLag Bit Just In Case
;*******************Set Up The Ports******************
bsf STATUS,5 ;Switch to Bank 1
movlw 0x01
movwf TRISB
;Set RB0 as input
movlw 0x10
movwf TRISA ;Set R 0 to RA3 on PortA as output
bcf STATUS,5 ;Come back to Bank 0
;*******************Now Send The Value Of COUNT To Port A
loop
movf COUNT,0 ;Move the contents of Count into W
movwf PORTA ;Now move it to Port A
goto loop ;Keep on doing this
end ;End Of Program
The Circuit Diagram
Below is the circuit diagram that will work for the code above. There are two things in the diagram that may throw you. First, We have not included a timing capacitor in the oscillator circuit. This is a clever little trick that you can try if you run out of capacitors. The capacitance comes from the stray capacitance between the oscillator pin and ground. so, with the resistor and the stray capacitance, we have an RC oscillator. Okay, this is not an accurate way of doing it, as the stray capacitance will vary from circuit to circuit. But, We thought you may be interested in seeing this sort of thing. Secondly, We have included a de-bouncing circuit across the switch. This is needed because every time you flick a switch, the contacts will bounce. This will make the PIC think there have been more than one switches. With the de-bouncing circuit, when the switch goes high, the capacitor charges up. no matter how many times the switch goes to +5V, the capacitor will only charge once. The capacitor is discharged when the switch is thrown the other way. If you want to see the effects of switch bounce, then disconnect the capacitor and resistor across the switch.
Click here >>>> Tutorial 13
|