Timer - Contador TMR0
 
El registro TMR0 puede contar ciclos de instrucción interna o pulsos de entrada por RA4 según el valor del bit 5 del registro OPTION (TOCS). Si este bit está a "1" TMR0 cuenta pulsos por RA4 y se le llama Contador; si el bit está a "0" cuenta ciclos de instrucción interna y se le llama Timer.
 
Cada ciclo de instrucción dura 4 veces el ciclo del reloj del pic (para un reloj de 4MHz ==> Ciclo reloj=0,25 µSeg ==> Ciclo instrucción = 4 X 0,25 = 1µSeg)
 
Cuando lo usamos como contador (Por RA4) podemos determinar si el incremento se hará por flanco ascendente o descendente con el bit 4 del registro OPTION (TOSE)
 
Podemos leer o escribir el registro TMR0 en cualquier momento. Cuando escribamos en él deja de contar durante dos ciclos, cuando lo leamos no pasa nada.
 
Podemos asignar el prescaler al TMR0, si hacemos esto podemos elegir el factor en el que se verá dividido el conteo mediante los bits del 0 al 2 del registro OPTION según la tabla del factor de división. Por ejemplo, si elegimos un factor de división de 1/2 tienen que entrar 2 pulsos para que TMR0 se incremente en uno, si está a 1/4 tienen que entrar 4... etc.
 
También podemos utilizar la interrupción que se produce cuando se desborda el TMR0, es decir, cuando pasa de FFh a 00h. (se configura desde el registro INTCON)
 
El siguiente ejemplo usa la interrupción por desbordamiento de TMR0 para obtener una onda cuadrada a la salida RB0:
 
;*******************************************
 
;*         EJEMPLO 4: USO DEL TMR0         *
 
;*******************************************
 
;* Este programa crea una señal cuadrada a *
 
;* la salida RB0, para ello utiliza el TMR0*
 
;* y la interrupción por desbordamiento del*
 
;* mismo. Se le asignará el prescaler con  *
 
;* un factor de división de 1/2. De esta   *
 
;* forma las interrupciones saltarán a     *
 
;* intervalos fijos de tiempo. Invirtiendo *
 
;* el estado de RB0 durante las            *
 
;* interrupciones se conseguirá una onda   *
 
;* cuadrada perfecta                       *
 
;*******************************************
 
 
 
 
 
OPTIONR EQU     01H    ;Registro para configuración del TMR0
 
STATUS  EQU     03H
 
TRISB   EQU     06H
 
PORTB   EQU     06H
 
INTCON  EQU     0BH
 
 
 
ACUM    EQU     0CH
 
STAT    EQU     0DH
 
 
 
F       EQU     1
 
w       EQU     0
 
 
 
#DEFINE BANCO0  BCF     STATUS,5
 
#DEFINE BANCO1  BSF     STATUS,5
 
 
 
 
 
 
 
        ORG     00H
 
        GOTO    INICIO ;ponemos este GOTO al principio para poder poner
 
                       ;el subprograma de las interrupciones a partir de
 
                       ;la dirección 04h
 
 
 
                       ;Comienza la interrupción:
 
                       ;=========================
 
 
 
        ORG     04H    ;El pic salta a esta dirección cuando se produce
 
                       ;una interrupción
 
        BCF     INTCON,2 ;bit que indica desbordamiento de TMR0, recuerda
 
                       ;que hay que ponerlo a "0" por programa, este es
 
                       ;el momento
 
 
 
                       ;comenzamos guardando el contenido del acumulador
 
                       ;y del STATUS para restaurarlos antes de salir de
 
                       ;la interrupción (es recomendable hacer esto
 
                       ;siempre que se usen interrupciones)
 
 
 
        MOVWF   ACUM   ;Copia el acumulador al registro ACUM
 
        MOVF    STATUS,W;Guarda STATUS en el acumulador
 
        BANCO0        ;Por si acaso, nunca se sabe en que parte de
 
                       ;programa principal salta la interrupción
 
        MOVWF   STAT   ;Copia el acumulador al registro STAT
 
 
 
                       ;Para generar una onda cuadrada Invertimos el
 
                        ;estado de RB0 cada vez que salta una interrupción
 
                       ;=================================================
 
 
 
        BTFSC   PORTB,0 ;si RB0 es "0" salta la siguiente instrucción
 
        GOTO    ESUNO  ;vete a ESUNO
 
        BSF     PORTB,0;Pon a "1" RB0 (porque era "0")
 
        GOTO    HECHO  ;ya está invertido RB0, vete a HECHO
 
 
 
ESUNO   BCF     PORTB,0;Pon a "0" RA0 (Porque era "1")
 
 
 
                       ;Ya se ha invertido el estado de RB0
 
                       ;===================================
 
 
 
                       ;ahora hay que restaurar los valores del STATUS y
 
                       ;del acumulador antes de salir de la interrupción:
 
 
 
HECHO   MOVF    STAT,W ;Guarda el contenido de STAT en el acumulador
 
        MOVWF   STATUS ;Restaura el STATUS
 
        SWAPF   ACUM,F ;Da la vuelta al registro ACUM
 
        SWAPF   ACUM,W ;Vuelve a dar la vuelta al registro ACUM y restaura
 
                       ;el acumulador (Con la instruccion SWAPF para no
 
                       ;alterar el STATUS, la instrucción MOVF altera el
 
                       ;bit 2 del STATUS)
 
        RETFIE        ;fin de la interrupción
 
 
 
                       ;Fin de la interrupción
 
                       ;======================
 
 
 
 
 
INICIO  BANCO1        ;Pasamos al banco 1
 
        BCF     TRISB,0;RB0 como salida
 
        BCF     OPTIONR,3;Asignamos el preescaler a TMR0
 
        BCF     OPTIONR,0;\
 
        BCF     OPTIONR,1; }Prescaler a 1/2
 
        BCF     OPTIONR,2;/
 
        BCF     OPTIONR,5;Entrada de TMR0 por ciclo de
 
                       ;instrucción interna (se pone a contar)
 
        BANCO0        ;Volvemos al banco 0
 
       
 
                       ;Configuración de las interrupciones:
 
                       ;====================================
 
 
 
        BSF     INTCON,7;Habilita las interrupciones globalmente
 
        BSF     INTCON,5;Habilita la interrupción por desbordamiento de TMR0
 
 
 
                       ;====================================
 
                       ;ya están configuradas las interrupciones, a
 
                       ;partir de ahora cuando cuando se desborde TMR0
 
                       ;saltará la interrupción (a la dirección 04h de
 
                       ;programa)
 
 
 
       
 
 
 
NADA    GOTO    NADA   ;En este ejemplo no se hace nada en el programa
 
                       ;principal, simplemente se espera a que salte la
 
                       ;interrupción. La verdadera utilidad de las
 
                       ;interrupciones es que se pueden hacer "cosas"
 
                       ;mientras sin preocuparse de las interrupciones
 
 
 
 
 
        END           ;FIN DE PROGRAMA