# TMR0 pic16f84a ¿configuracion para un tiempo grande?



## jhony85 (Jun 13, 2010)

Hola, llevo ya unos dias dandole vueltas y buscando por todos lados, pero no encuentro la forma de temporizar el TIMER0 de un 16f84a para que me temporize 5 o 10 segundos.

Hace tiempo trabajé con ensamblaje pero veo que no es el mismo que el que utilizan los pics, ya que yo trabajaba con Intel 8051.

parece ser que con pics todo juega con bucles que generan el retardo (con 8051 metias unas semillas que cuanto mas grandes mayor tiempo temporizaban).

¿alguien puede ayudarme?


----------



## Meta (Jun 13, 2010)

Prueba con el 16F88 que tiene un TIMER1 de 16 Bits. El del 16F84A es de 8 Bits.


----------



## jhony85 (Jun 13, 2010)

me gustaria hacerlo con el 16f84a que es con el que estoy trabajando actualmente


----------



## Meta (Jun 13, 2010)

La verdad que tienes que hacer, por ejemplo. Cargas .50 al TIMER0. Son 50 ms por poner un ejemplo.

50 ms = 0.05 segundos.

Multiplícalo por 100, es decir, 0.05 seg * 50 ms = 5 seg.

Ya tienes 5 segundos.

100 es la veces que tienes que cargar 50 ms al TIMER 0.

Cuando lo programes lo pones por aquí.


----------



## ByAxel (Jun 13, 2010)

Mira, en un ejemplo básico usando un oscilador de 4Mhz, el máximo tiempo usando el TMR0 más su pre-divisor con la división al máximo seria de 65536us, lo que es igual a 65.536ms, no puedes alargar más el tiempo usando solamente el TMR0, entonces necesariamente usarás bucles o contadores por software para alargar el tiempo...

Seria un ejemplo:

Activas la interrupción del TMR0.
Usas el pre-divisor al máximo = 256.
Cargas en su contador un valor = 11 para que el conteo lo realice desde ahí y la
interrupción se realizaría cada 256 * (256-11) = 62720us;
ahora dentro de la interrupción haces por software un conteo de 0 hasta 8 por cada
interrupción, entonces seria: 
(256 * (256-11)) * 8 = 501760us que aproximadamente es 500ms que equivale a 1/2 segundo con un margen de error; claro que eso lo puedes calcular mejor.

Como vez no te vas a librar de usar bucles o contadores para crear tiempo más largos usando el TMR0.

Saludos.


----------



## jhony85 (Jun 13, 2010)

no se muy bien la idea que tratas de mostrarme. segun dices es cargarle el numero 50 en decimal a la variable timer y ya tengo 50 ms? es que segun he leido, no va asi. gracias por tu respuesta.



Carlos Alexis dijo:


> Mira, en un ejemplo básico usando un oscilador de 4Mhz, el máximo tiempo usando el TMR0 más su pre-divisor con la división al máximo seria de 65536us, lo que es igual a 65.536ms, no puedes alargar más el tiempo usando solamente el TMR0, entonces necesariamente usarás bucles o contadores por software para alargar el tiempo...
> 
> Seria un ejemplo:
> 
> ...



tienes algun codigo parecido para que me valla fijando?


----------



## Meta (Jun 13, 2010)

Estimado amigo:

Los .50 no son 50 ms, es un ejemplo para que lo entiendas, ejjeje.

Puede que te ayude aquí.

http://www.hispavila.com/3ds/chipspic/tmr0.html

http://perso.wanadoo.es/luis_ju/pic3/index.html
http://perso.wanadoo.es/pictob/micropic16f84_3.htm

Puedes pasar el código al 16F88 y pruebas el TIMER de 16 Bits que está mejor. jejejeje. 

Un cordial saludo.


----------



## jhony85 (Jun 13, 2010)

gracias por los enlaces


----------



## Meta (Jun 13, 2010)

De nada campeón.

Otra cosa. Lo de tener precisión como te indicó nuestro amigo Carlos  Alexis puedes usar la instrucción NOP para tener precisión, lo sabrás mirando el StopWhats del MPLAB.

Es bueno saber de retardos aunque no tenga nada que ver con TIMER0 para usar tiempos muy cortos y precisos como puedes comprobar en esta Web.


```
; Retardo = 5 segundos
; Frecuencia Reloj = 4 MHz

; Retardo actual = 5 segundos = 5000000 ciclos
; Error = 0 %

    cblock
    d0
    d1
    d2
    endc

Retardos
            ;4999993 ciclos
    movlw    0x2C
    movwf    d0
    movlw    0xE7
    movwf    d1
    movlw    0x0B
    movwf    d2
Retardos_0
    decfsz    d0, f
    goto    $+2
    decfsz    d1, f
    goto    $+2
    decfsz    d2, f
    goto    Retardos_0

            ;3 ciclos
    goto    $+1
    nop

            ;4 ciclos (incluyendo call)
    return
```
http://www.golovchenko.org/cgi-bin/delay

Saludo.


----------



## jhony85 (Jun 14, 2010)

Meta dijo:


> De nada campeón.
> 
> Otra cosa. Lo de tener precisión como te indicó nuestro amigo Carlos  Alexis puedes usar la instrucción NOP para tener precisión, lo sabrás mirando el StopWhats del MPLAB.
> 
> ...



muy interesante lo de los retardos, en vez de timer, lo que no entiendo muy bien es la funcion de 

cblock
    d0
    d1
    d2
    endc

Cuando kiera realizar la temporizacion llamo a la rutina Delay verdad?

Os muestro el codigo que tengo yo a ver qué pensais.


```
LIST P=16F84A
    #INCLUDE P16F84A.INC

    __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC

RESET

    ORG 0x00
        GOTO INICIO
    ORG 0X05

INICIO

    MOVLW b'00000100'
    MOVWF OPTION_REG
    BCF STATUS,RP1
    MOVLW b'00001000'
    MOVWF TRISB
    
PPAL

    BCF PORTB,2; LED APAGADO
    BTFSC PORTB,3; PREGUNTAMOS SI PORTB 3 ESTA A 1
    CALL TIMER
    GOTO PPAL; ESPERAMOS LA ACTIVACION DEL INTERRUPTOR
    
    GOTO PPAL

TIMER
    BSF PORTB,2; ENCENDEMOS LED
    MOVLW d'125'
    MOVWF TMR0
    BCF INTCON,T0IF

DESBORD
    BTFSS INTCON,T0IF
    GOTO DESBORD    
    RETURN



    
    END
```


----------



## Meta (Jun 14, 2010)

Está mejor ello esa que tienes.

Lo malo que está adaptada a 4 MHz. Mejor hacer librerías bien completas como la del libro www.pic16f84a.org a 8 MHz por si quieres usar el oscilador interno a esa frecuencia algún día. Luego otra de 20 MHz, cosas así.


----------



## jhony85 (Jun 15, 2010)

Meta dijo:


> Está mejor ello esa que tienes.
> 
> Lo malo que está adaptada a 4 MHz. Mejor hacer librerías bien completas como la del libro www.pic16f84a.org a 8 MHz por si quieres usar el oscilador interno a esa frecuencia algún día. Luego otra de 20 MHz, cosas así.



No he entendido nada de lo que me has dicho... jeje

el oscilador que uso es uno RC aproximadamente de 4MHz q es lo maximo que puedo usar.


----------



## Meta (Jun 15, 2010)

Para temas de temporizadores usa un cristal que tiene más precisión.


----------



## jhony85 (Jun 15, 2010)

lo se pero ahora mismo no dispongo de cristal de 4Mhz y me cuesta bastante caro conseguirlo porque tengo q pedir los componentes por internet.

El codigo que hice funcionaria?


----------



## jhony85 (Jun 16, 2010)

Bueno, llevo un par de dias probando el circuito con Proteus, y veo 2 fallas:

La primera es que depurando, veo que al llegar a la instruccion BSF PORTB,2; para encender un led no lo enciende ni siquiera sale el puntito rojo de que hay tension en esa patilla aunque la instruccion si que la ejecuta.

El segundo es que el timer no se desborda y el programa no sale de la subrutina DESBORD.

Por favor, alguien que me ilumine...


----------



## ByAxel (Jun 16, 2010)

> La primera es que depurando, veo que al llegar a la instruccion BSF PORTB,2; para encender un led no lo enciende ni siquiera sale el puntito rojo de que hay tension en esa patilla aunque la instruccion si que la ejecuta.



Para eso, asegúrate de haber puesto el pin RB2 como salida, que seria algo así:
Escoges Banco 1
*movlw  b'00000000*' 
*movwf  TRIS*B          ; Todo el PORTB como salida.

o tambien
*bcf    TRISB,2*
Escoges Banco 0
...
...

Otra cosa que me llama la atención es que el PIC16F84A no tiene habilitado el bit RP1 del registro STATUS al tener solo dos Bancos según la hoja de datos ese bit no es necesario y tu lo estas usando...
Como buena práctica, te debes de asegurar en que banco estás trabajando, aunque escribas un poco más es mejor... utiliza BANKSEL..

     BANKSEL OPTION_REG
...
...
     BANKSEL TRISA
...
...
     BANKSEL PORTA
...
...
etc... 

Trabaja en el banco respectivo para acceder a los registros que desees de lo contrario el PIC hará todo mal o no hará nada.


----------



## jhony85 (Jun 17, 2010)

Si te fijas en el código una de las instrucciones es

MOVLW b'00001000'
MOVWF TRISB

Con esto supuestamente le estoy diciendo que todas el puerto B es salida excepto la RB3 que seria la entrada del pulsador.


En cuanto al tema de los bancos, aun no los domino mucho, voy a buscar informacion acerca de ellos.

Que me dices en cuanto al tema del timer?

Bueno he hecho varios cambios y me gustaria que me los comentaseis a ver si logro hacer que funcione:


```
LIST P=16F84A
    #INCLUDE P16F84A.INC

    __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC

RESET

    ORG 0x00
        GOTO INICIO
    ORG 0X04
DESBORD
    BCF INTCON,T0IF; BAJAMOS EL FLAG
    BCF PORTB,2; APAGAMOS LED 
    RETFIE    

INICIO
    MOVLW b'00000000'
    MOVWF STATUS
    MOVWF PORTB
    MOVLW b'10100000'
    MOVWF INTCON
    MOVLW b'00100000'
    MOVWF STATUS
    MOVLW b'01000111'
    MOVWF OPTION_REG
    MOVLW b'00001000'
    MOVWF TRISB
    BCF PORTB,2; LED APAGADO
    
PPAL
    
    MOVLW d'125'
    BTFSC PORTB,3; PREGUNTAMOS SI PORTB 3 ESTA A 1
    cALL TIMER    
    GOTO PPAL; ESPERAMOS LA ACTIVACION DEL INTERRUPTOR


TIMER
    BSF PORTB,2; ENCENDEMOS LED
    MOVWF TMR0
    
    RETURN  

    END
```

Tambien he sacado una captura de la simulacion en proteus, y es que ni siquiera cuando pulso el pulsador, el RB3 se me pone en estado alto.





Decir tambien que ambas fuentes de alimentacion son de 5V


----------



## ByAxel (Jun 17, 2010)

En la hoja de datos está todo http://ww1.microchip.com/downloads/en/devicedoc/35007b.pdf
aunque en ingles, prácticamente es el manual completo, solo le hace falta más ejemplos...
Ha y eso de los bancos es importante en ASM, por ejemplo para acceder a los registros TRISx debes de hacerlo en el Banco 1, para acceder a los registros PORTx debes de hacerlo en el banco 0, el STATUS o INTCON no hay problema ya que se repite en ambos bancos (es el mismo reflejado en ambos bancos).

Ok, con respecto a tu ejemplo se te olvido volver al Banco 0, antes de * BCF PORTB,2; LED APAGADO*, por lo que en realidad no puede escribir en los PORTx, en TMR0 y demás porque no está en el Banco 0.

Con respecto al Timer si esta bien, aunque el efecto va a ser un poco rápido, creo ya que nunca he trabajado con el oscilador en RC.

Con respecto al circuito la parte del pulsador está mal ya que siempre debe de tener una resistencia a Pull-up o pull-down, en tu caso a Pull-down para que siempre esté a *"0"* la entrada del PIC y al pulsar se ponga a *"1"* (En un circuito real sin la resistencia, el pic seria totalmente inestable).

Sobre el oscilador, pues no importa ya que el proteus ni lo simula... solo es necesario poner la frecuencia en sus propiedades... 

Ánimo...


----------



## Meta (Jun 17, 2010)

Hola:

Para no tener problemas con los bancos, usa la directiva BANKSEL, busca los bancos automaticamente.

Un cordial saludo.


----------



## jhony85 (Jun 18, 2010)

le he hecho unos cambios en cuanto a los bancos y parece ser que la simulaicon va bien ya que el led se enciende, el problema está en que no se apaga y que cuando suelto el pulsador en la ventana q estoy visualizando PORTB me dice que RB3 sigue a 1 aunque en el dibujo de proteus el cuadradito esta azul .


----------

