Autor Tema: Como generar la rutina de timer con 16f84  (Leído 8731 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado MAT

  • PIC10
  • *
  • Mensajes: 22
Como generar la rutina de timer con 16f84
« en: 22 de Junio de 2006, 12:14:56 »
Hola amigos le comento que estoy ahciendo un frecuencimetro y ya tengo en marcha el contador de 6 digito que estoy usando para visualisar la frecuencia con el micro y tengo timer externo que manda un pulsoen alto para habilitar la cuenta del pic duarante 100 mseg ahora mi pregunta esto se puede hacer dentrodel mismo micro para evita en timer externo
agradeceria su ayuda garacia marcos 73

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Como generar la rutina de timer con 16f84
« Respuesta #1 en: 22 de Junio de 2006, 17:48:01 »
Hola marcos. El 16F84 trae un timer interno, que puede facilitar tu tarea de crear pasos de 100ms.A la info de como utilizar este timer la puedes encontrar o bien en el datasheet de este PIC o bien en este foro en el cual se ha hablado infinidad de veces del 16F84 y del timer0. Proba con el buscador del foro.
Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado MAT

  • PIC10
  • *
  • Mensajes: 22
Re: Como generar la rutina de timer con 16f84
« Respuesta #2 en: 23 de Junio de 2006, 10:46:13 »
Hola Bruno F
   Bueno te comento que ya encontre la falla es que estaba declarando el preselector en el wdt y no en el tmr0 para usarlo como contador de pulsos externos, bueno ahora me faltaria saber como calcular el tiempo para logra que cuente en 100 mseg, y otra cosa veo que cuando le inyecto frecuencia me cuenta y eso esta bien perolo que no entiendo es que al subir la frecuencia me decrementa la cuenta en ves de incrementarla no se si estoy haciendo algo mal o trabaja asi el tmr0, bueno aca te paso algo del codigo para que lo veas

 bcf status, 5
 movlw b'10100111'
 movwf tmr0
 ............
 bsf status, 5
 .
 .....
 .....
 ....
 .....
 clrf trm0
 inc:
      call subir ; rutana de incremento en digito para visualisar el display
      btfss intcon, 2
      goto inc
      bsf intcon, 2
  ....
 ....
 Rutina de visualizacíon

Bueno eso es lo que tengo echo y esta funcionado mal pero en fin funca ahora me queda eso de ver asi que si me puedes dar una mano con el tema te lo agradeceria mucho saludos
Marcos 73

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Como generar la rutina de timer con 16f84
« Respuesta #3 en: 23 de Junio de 2006, 23:44:00 »
Hola. Bueno, el tiempo que tarda el timer en desbordar depende de la frecuencia de oscilacion en la cual estes haciendo trabajar al PIC. Supongo que utilizas 4 Mhz.
La formula de maxima duracion del Timer seria: (4/FOSC)* 256(tmr0)*256(prescaler rate)

Suponiendo que trabajas a 4mhz, entonces nos quedaria: (4/4000000) * 256 *256 = 0,000001s*256*256 = 1us * 256*256= 0.001ms * 256*256 = 65,536ms
Este es el maximo tiempo que el modulo Timer0 puede contar @4Mhz.
Ahora, para lograr valores de tiempo mayores(como en tu caso 100ms) hay que utilizar registros auxiliares, que debes crear tu para que vayan contando cada vez que se desborde el timer, y que generen la rutina correspondiente cuando el timer se ha desbordado X cantidad de veces.

Bien, como 100ms no es un multiplo entero de 65,536ms, nos convendria acomodar el tiempo que tarda en desbordar a tiempos multiplos de 100ms. Por lo que podemos aprovechar la opcion que nos brinda el PIC, de modificar el valor inicial del registro TMR0.
Voy a buscar un divisor perfecto de 100ms: que el timer cuente 50ms. Como 50ms es bastante cercano a 65,536, es facil darse cuenta que debemos setear el prescaler a su valor maximo( 256).Ahora buscaremos el valor que debemos escribir en el registro TMR0 para obtener los 50ms.

De esta forma, la misma formula anterior toma la siguiente forma: (4/FOSC)* (256-TMR0)*256

Reemplazando obtenemos:    (4/4000000)* (256-TMR0)*256  = 0,001ms*(256-TMR0)*256= 50ms
Haciendo pasaje de terminos:
(256-TMR0)*256= 50ms/0,001ms
(256-TMR0)= 50ms/(0.001ms*256)
-TMR0 = (50ms/(0.001ms*256))-256
TMR0= -(50ms/(0.001ms*256))+256
TMR0= 60,68

Hemos encontrado el valor que debemos escribir en el registro TMR0 para obtener un timer de 50ms.
Como no podemos poner un valor decimal en el registro TMR0, debemos redondear a un valor entero el numero encontrado.
Yo voy a redondear hacia arriba el 60,68, obteniendo 61.
Podemos comprobar que nuestros calculos han sido correctos volviendo a plantear la formula con el valor encontrado:

(4/4000000)* (256-TMR0)*256  = 0,001ms*(256-TMR0)*256 = 0.001ms*(256-61)*256 =  0.001ms*195*256=49.92ms

El valor obtenido es suficiente, muy cercano a los 50ms.
Ahora solo debemos utilizar una variable auxiliar que cuente 2 veces que se desborde el Timer(2 veces * 49.92ms = 99.84ms(practicamente 100ms))



En el programa podes setear el timer asi:

bsf  STATUS,5
movlw b'11010111'
movwf OPTION_REG
bcf STATUS,5
movlw .61
movwf TMR0
clrf CONTADOR     ;defini esta variable para que cuente la cantidad de desbordamientos del timer.
....
inc:
      call subir ; rutana de incremento en digito para visualisar el display
      btfss intcon, 2
      goto inc

      bcf intcon, 2  <-Ojo! hay que limpiar el flag de interrupcion! no volver a setearlo

      movlw .61
      movwf TMR0   ;volver a setear valor inicial del registro TMR0

      incf  CONTADOR,F
      movf  CONTADOR,W

      xorlw .2  ;se ha desbordado por segunda vez? 2 veces = 2*50 ms = 100ms
      btfss STATUS,Z
      goto inc      ;todavia no se ha desbordado dos veces, volver a esperar.     

      clrf  CONTADOR ;reiniciar contador de desbordamientos
      ....
      ....
      Rutina de visualizacíon
      goto inc



El timer se desborda cuando el registro TMR0 pasa de valer 0xFF a 0x00. Es decir que el registro TMR se incrementa, y al producirse del desbordamiento, produce el seteo del flag correspondiente. Por lo tanto, el registro timer cero se incrementa, nunca se decrementa automaticamente.

Espero haya quedado claro.
Exitos!
« Última modificación: 24 de Junio de 2006, 00:15:00 por BrunoF »
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Como generar la rutina de timer con 16f84
« Respuesta #4 en: 24 de Junio de 2006, 00:01:36 »
Bueno, me he fijado en tu programa, y como no se que es lo que queres hacer, puede que el programa se comporte erroneamente. Es cuestion de acomodar las rutinas. Si queres que el el valor mostrado en los displays se incremente cada 100ms y mientras tanto que se refresquen los displays(que seguramente tenes multiplexados) tenes que intercambiar de lugar las rutinas "subir" y la rutina de visualizacion.
Saludos
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado MAT

  • PIC10
  • *
  • Mensajes: 22
Re: Como generar la rutina de timer con 16f84
« Respuesta #5 en: 24 de Junio de 2006, 09:23:45 »
Hola, gracias por ayudarme con los calculos de tiempo para el TMR0
Bueno mira el proyecto se trata de un frecuencimetro para medir hasta 40 mhz  con el 16F84 y esta funcionado pero me cuenta al reves es decir yo inyecto en el pin RA4 una frecuencia de 4 Mhz , me visualisa 3 Mhz y si yo subo la frecuencia de entrada en el pin RA4 la que me visualisa va bajando por ej 5 Mhz, muestra 2 Mhz y haci sucesivamente y no puedo sacar la falla, si bien en este foro mas abajo pregunte por el frecuencimetro y me ayudaron , ahora me queda eso por terminar para que funciones bien, bueno aca te mando el programa para que lo veas y me puedas ayudar desde ya te comento que se trata de un contador de 6 digitos en el cual necesito mostrar los pulsos contador durante 100 mseg

       List P = 16f84
       Include <P16f84.inc>

  __config _XT_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF

indo    equ     00h             ;registro de indireccion
pc       equ     02h             ;contador de programa
status  equ     03h             ;registro de estado
fsr      equ     04h             ;registro de seleccion
intcon equ   0bh
tmr0   equ   01h
ptoa    equ     05h             ;puerto a
ptob    equ     06h             ;puerto b
rota    equ     2fh             ;variable para desplazamiento de display
trisa   equ     85h             ;configuracion puerto a
trisb   equ     86h             ;configuracion puerto b
dig2    equ     d'12'           ;acumulador cent. mil
dig3    equ     d'13'           ;acumulador dec. mil
dig4    equ     d'14'           ;acumulador unid. mil
dig5    equ     d'15'           ;acumulador centenas
dig6   equ   d'16'      ;acumulador decenas
dig7   equ   d'17'      ;acumulador unidades
loops   equ     1dh             ;variables usadas en retardos
loops2  equ     1eh
ciclo   equ   1fh
z       equ     02h             ;flag de cero
ram     equ     05h             ;bit de seleccion de pagina de memoria
c       equ     00h             ;flag de acarreo
w       equ     00h             ;bit de destino a variable de trabajo

reset   org     00
        goto    inicio
        org     05h

retardo                         ;subrutina de retardo
        movwf   loops           ;la variable de trabajo contiene la cant.
top2    movlw   d'110'          ;de ms a demorar
        movwf   loops2
top     nop
        decfsz  loops2          ;controla si termina 1mS
        goto    top
        decfsz  loops           ;controla si termina el retardo completo
        goto    top2
        retlw   0

x100                            ;rutina de incremento x 100000
        clrf    dig3            ;pone a cero las decena de miles
        incf    dig2            ;incrementa el contador de centenas de miles   
        movf    dig2, w         ;carga en work el conteo de las centenas de miles   
        xorlw   0ah             ;si work era 10, entonces quedara en cero
        btfsc   status, z       ;si es cero, el flag z queda alto
        clrf   dig2            ;inicializa lascentenas de miles   
        return

x10                             ;rutina de incremento x 10000
        clrf    dig4            ;pone a cero las unidades de mil
        incf    dig3            ;incrementa el contador de decenas de mil   
        movf    dig3, w         ;carga en work el conteo de las decenas miles   
        xorlw   0ah             ;si work era 10, entonces quedara en cero
        btfsc   status, z       ;si es cero, el flag z queda alto
        call    x100            ;incrementa las centenas de mil   
        return

x1                              ;rutina de incremento x 1000
        clrf    dig5            ;pone a cero las centena
        incf    dig4            ;incrementa el contador de unidad  miles   
        movf    dig4, w         ;carga en work el conteo de las unidades miles   
        xorlw   0ah             ;si work era 10, entonces quedara en cero
        btfsc   status, z       ;si es cero, el flag z queda alto
        call    x10             ;incrementa los decenas miles   
        return

s100                            ;rutina de incremento x 100
        clrf    dig6            ;pone a cero las decenas
        incf    dig5            ;incrementa el contador centenas
        movf    dig5, w         ;carga en work el conteo de las centenas
        xorlw   0ah             ;si work era 10, entonces quedara en cero
        btfsc   status, z       ;si es cero, el flag z queda alto
        call    x1              ;incrementa los unidades mil   
        return

s10                             ;rutina de incremento x 10
        clrf    dig7            ;pone a cero las unidades
        incf    dig6            ;incrementa el contador de decenas
        movf    dig6, w         ;carga en work el conteo de las decenas
        xorlw   0ah             ;si work era 10, entonces quedara en cero
        btfsc   status, z       ;si es cero, el flag z queda alto
        call    s100            ;incrementa las centenas   
        return

subir                           ;rutina de incremento
        incf    dig7            ;incrementa el contador de unidades
        movf    dig7, w         ;carga en work el conteo de las unidades
        xorlw   0ah             ;si work era 10, entonces quedara en cero
        btfsc   status, z       ;si es cero, el flag z queda alto
        call    s10             ;incrementa las decenas
        return

tabla                           ;genera los numeros sobre el display
        addwf   pc              ;agrega al cont. programa el valor de work
        retlw   b'0000'           ;genera el 0
        retlw   b'0001'    ;genera el 1
        retlw   b'0010'           ;genera el 2
        retlw   b'0011'         ;genera el 3
        retlw   b'0100'         ;genera el 4
        retlw   b'0101'         ;genera el 5
        retlw   b'0110'         ;genera el 6
        retlw   b'0111'         ;genera el 7
        retlw   b'1000'         ;genera el 8
        retlw   b'1001'         ;genera el 9

inicio                          ;programa principal
        bsf     status, ram     ;selecciona el banco de memoria alto
   movlw   b'10100111'
   movwf   tmr0
        movlw   b'00010000'     ;configura el puerto a
        movwf   trisa           ;bit 4 entrada, demas bits salidas.
        movlw   b'11000000'     ;configura el puerto b
        movwf   trisb           ;como salidas
        bcf     status, ram     ;selecciona el banco de memoria bajo
       
empe   
          clrf   dig2
   clrf   dig3
   clrf   dig4
   clrf   dig5
   clrf   dig6
   clrf   dig7

        movlw   00              ;envia ceros a los transistores para apagar
        movwf   ptob            ;todos los displays
      
   movlw   02h
   movwf   ciclo
con   movlw   d'61'
   movwf   tmr0
inc     call    subir           ;llama la rutina de incremento
   btfss   intcon, 2
   goto   inc
   bcf   intcon, 2   
   decfsz   ciclo
   goto   con
   
        movlw   0x01            ;iniciar un 1 en el registro de rotacion
        movwf   rota            ;inicializa el display
        movlw   d'12'           ;con el registro selector (fsr) se apunta
        movwf   fsr             ;al primer dato que se va a mostrar
disp    movf    indo, w        ;lee el dato del registro apuntado por fsr
   call   tabla
        movwf   ptoa           ;envia el digito al puerto b
   
   btfsc   rota, 0
   bsf   ptob, 0
   
   btfsc   rota, 1
   bsf   ptob, 1

   btfsc   rota, 2
   bsf   ptob, 2

   btfsc   rota, 3
   bsf   ptob, 3

   btfsc   rota, 4
   bsf   ptob, 4

   btfsc   rota, 5
   bsf   ptob, 5

   movlw   d'03'
   call   retardo
   clrf   ptob
   btfsc   rota, 5
        goto   empe            ;si termino, vuelve desde el comienzo
        bcf     status, c       ;carry en cero para no afectar las rotaciones
        rlf     rota            ;desplaza el 1 que enciende los displays
        incf    fsr, 1          ;incrementa el puntero. Apunta el proximo
        goto    disp            ;digito a mostrar           ;digito a mostrar
   

        end



bueno saludos 73

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Como generar la rutina de timer con 16f84
« Respuesta #6 en: 24 de Junio de 2006, 12:07:14 »
hola. Aca me cambiaste mucho las pautas.
Entonces vos lo que queres es que el Timer0 en modo CONTADOR, no en MODO TIMER.
Todo lo que yo te explique era para modo timer.En modo timer, el Timer0 solamente cuenta tiempo,pero no pulsos en el pin RA4...

El datasheet aclara que el pulso enviado a RA4 posee ademas un retardo(es decir, que no es perfectamente preciso).
Por eso seguramente lea 3mhz en lugar de 4mhz.

Explicame bien si vos lo que queres es contar la cantidad de pulsos recibidos por el pin RA4 para determinar la frecuencia porque no me queda claro.
Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado MAT

  • PIC10
  • *
  • Mensajes: 22
Re: Como generar la rutina de timer con 16f84
« Respuesta #7 en: 24 de Junio de 2006, 12:34:20 »
Hola , bueno si yo quiero contar la cantidad de pulsos para determinar la frecuencia es decir hacer un frecuencimetro
Y ok que lo de tmr0 es para timer no para contador
Bueno espero que me entiendas ahora lo que quiero hacer, te comento que asi funciona pero con el detalle que te comente que a mayor frecuencia es decir pulsos en la entrada menor es la cuenta y a menor pulsos en la entrada mayor es la cuenta ¿por que?.
Bueno espero que me ayas entendido
Saludo 73

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Como generar la rutina de timer con 16f84
« Respuesta #8 en: 24 de Junio de 2006, 15:38:48 »
Hola MAT. Bueno, lo que esta pasando es que cuanto mayor sea la frecuencia que ingreses por el pin RA4, menor va a ser el tiempo que tarda en desbordarse el TIMER. Por eso a > frecuencia < cuenta y viceversa.

Vos necesitas comparar la cantidad de pulsos recibidos durante X cantidad de tiempo. Te hace falta un tiempo de referencia para poder determinar la frecuencia ingresada por el pin RA4.
Esta X cantidad de tiempo dependera del refresh que queres que tenga el frecuenciometro, y de la precision del mismo.
Espero haber entendido tu idea. Saludos.

"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado MAT

  • PIC10
  • *
  • Mensajes: 22
Re: Como generar la rutina de timer con 16f84
« Respuesta #9 en: 24 de Junio de 2006, 15:52:38 »
Bueno Bruno, entendido lo que me pasa pero conrespecto a mayor frecuencia menor visaulisacion.
 y si esa es mi idea,  ahora yo soy el que no entiende como hacer para comparar los pulsos no me doy cuenta, por que hace poco que empese con esto de los pic y bueno de apoco voy aprendiendo , si me podes decir mo arrancar porlomenos te agradeceria , por que no enteindo como hacelo ; esto se puede hacer sobre el mismo programa o  no y como te agradeceria si me dices como o me muestras un ejemplo para verlo y entenderlo desde ya muchas gracias Bruno por ayudarme con este tema
Saludo MArcos