Example 4
Using timer TMR0 and Interrupts
If you have read the previous example, you would have noticed a disadvantage of providing delays using loops. In all these cases, the microcontroller is "captive" and does nothing. It simply waits for some time to pass. Such wasting of time is an unacceptable luxury and some other method should be applied.Do you remember the story about the timers? About interrupts? This example makes links between them in a practical way. The schematic is still the same as well as the challenge. It is necessary to provide delay long enough to notice changes on a port. This time, the timer TMR0 with the assigned prescaler is used for that purpose. Interrupt occurs on every timer register overflow and interrupt routine increments the number in port B by 1. The whole procedure is performed "behind the scenes" of the whole process, which enables the microcontroller to do other things.
- Even though it is unnecessary in this case, the contents of the most important registers (W, STATUS and PCLATH) must be saved at the beginning of the interrupt routine;
- Interrupt causes the appropriate flag bit to be automatically set and the GIE bit to be automatically cleared. At the end of the interrupt routine, do not forget to return these bits to the state they had prior to the interrupt occurring; and
- At the end of the interrupt rutine, important registers should be given the original content.
Source Code
;********************** Header **********************************************
;**************** DEFINING VARIABLES ****************************************
cblock 0x20 ; Block of variables starts at address 20h
w_temp ; Variable at address 20h
pclath_temp ; Variable at address 21h
status_temp ; Variable at address 22h
endc
;************************ START OF PROGRAM **********************************
org 0x0000 ; Address of the first program instruction
goto main ; Go to label "main"
;************************ INTERRUPT ROUTINE *********************************
org 0x0004 ; Interrupt vector
movwf w_temp ; Saves value in register W
movf STATUS ; Saves value in register STATUS
movwf status_temp
movf PCLATH ; Saves value in register PCLATH
movwf pclath_temp
banksel PORTB ; Selects bank containing PORTB
incf PORTB ; Increments register PORTB by 1
banksel INTCON ; Selects bank containing INTCON
bcf INTCON,TMR0IF ; Clears interrupt flag TMR0IF
movf pclath_temp,w ; PCLATH is given its original content
movwf PCLATH
movf status_temp,w ; STATUS is given its original content
movwf STATUS
swapf w_temp,f ; W is given its original content
swapf w_temp,w
bsf INTCON,GIE ; Global interrupt enabled
retfie ; Return from interrupt routine
;************************ MAIN PROGRAM **************************************
main ; Start of the main program
banksel ANSEL ; Bank containing register ANSEL
clrf ANSEL ; Clears registers ANSEL and ANSELH
clrf ANSELH ; All pins are digital
banksel TRISB ; Selects bank containing register TRISB
clrf TRISB ; All port B pins are configured as outputs
banksel OPTION_REG ; Bank containing register OPTION_REG
bcf OPTION_REG,T0CS ; TMR0 counts pulses from oscillator
bcf OPTION_REG,PSA ; Prescaler is assign to timer TMR0
bsf OPTION_REG,PS0 ; Prescaler rate is 1:256
bsf OPTION_REG,PS1
bsf OPTION_REG,PS2
banksel INTCON ; Bank containing register INTCON
bsf INTCON,TMR0IE ; TMR0 interrupt overflow enabled
bsf INTCON,GIE ; Global interrupt enabled
banksel PORTB ; Bank containing register PORTB
clrf PORTB ; Clears port B
loop
goto loop ; Remain here
end ; End of program