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