Wednesday, March 08, 2006

PIC: Example 4

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.
Example 4 - Using timer TMR0 and Interrupts
Pay attention to a few details:
  • 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