Autor Tema: Problemas con TMR0 (PIC16F877A)  (Leído 2523 veces)

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

Desconectado Oliver Karin

  • PIC10
  • *
  • Mensajes: 6
Problemas con TMR0 (PIC16F877A)
« en: 19 de Abril de 2018, 22:27:41 »
Hola amigos, espero puedan ayudarme porque tengo que hacer un contador de 0 a 99 utilizando un pulsador que cada vez que lo accione aumente 1 y lo muestre en la pantalla utilizando el TMR0 del Pic 16f877a pero ya lo configure e hice la programacion, ahora simulando el programa en ISIS me doy cuenta que no hace nada, tengo el pulsador a tierra en el bit 4 del puerto A como segun debe ser cuando utilizas el TIMER0 pero no detecta nada, ni cuando pongo el pulsador a tierra ni a VCC.
No se que sea ya cambie la configuracion de el registro INTCON Y OPTION_REG varias veces y no logro hacerlo funcionar.
LIST P=16f877A
   INCLUDE<p16f877A.inc>
   __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF 
TIEMPO1 EQU 0X21
TIEMPO2 EQU 0X22
TIEMPO3 EQU 0X23
   #DEFINE LCD PORTC
   #DEFINE ENABLE PORTD,0
   #DEFINE RS PORTD,1

   ORG 0x00   
   GOTO INICIO
   ORG 0X04
   GOTO TTIMER


   TTIMER
   MOVLW D'0'
   SUBWF TMR0,W
   MOVWF LCD
   CALL DATO
   BCF INTCON,2
   RETFIE
INICIO
   BCF STATUS,RP1
   BCF STATUS,RP0
   CLRF PORTD
   CLRF PORTC
   CLRF PORTA

   BSF STATUS,RP0   
   CLRF TRISB
   CLRF TRISC
   CLRF TRISD
   MOVLW B'11111111'
   MOVWF TRISA
   BCF OPTION_REG,7
   BCF OPTION_REG,6
   BSF OPTION_REG,5
   BSF OPTION_REG,4
   BSF OPTION_REG,3
   BCF OPTION_REG,2
   BCF OPTION_REG,1
   BCF OPTION_REG,0

   BCF STATUS, RP0
   BSF INTCON,7
   BSF INTCON,5
   CLRF TMR0


PRINCIPAL
   CALL INILCD

CONT:
   BCF RS
   BSF ENABLE
   MOVLW 0X01
   MOVWF LCD
   CALL RETARDOLCD_15MS
   BCF ENABLE
   BCF RS
   BSF ENABLE
   MOVLW 0X01
   MOVWF LCD
   CALL RETARDOLCD_15MS
   BCF ENABLE
   
   MOVLW   'C'
   CALL   DATO
   MOVLW   'O'
   CALL   DATO
   MOVLW   'N'
   CALL   DATO
   MOVLW   'T'
   CALL   DATO
   MOVLW   'A'
   CALL   DATO
   MOVLW   'D'
   CALL   DATO
   MOVLW   'O'
   CALL   DATO
   MOVLW   'R'
   CALL   DATO
   MOVLW   ':'
   CALL   DATO
   MOVLW   ' '
   CALL   DATO
OTRA

   GOTO OTRA


DATO:
   MOVWF   LCD
   BSF      RS
   BSF      ENABLE
   CALL RETARDOLCD_15MS
   BCF      ENABLE
   RETURN

INILCD
CALL RETARDOLCD_15MS
   BCF RS
   BSF ENABLE
   MOVLW B'00111000'
   MOVWF LCD
   CALL RETARDOLCD_100US
   BCF ENABLE

   BCF RS
   BSF ENABLE
   MOVLW B'00110000'
   MOVWF LCD
   CALL RETARDOLCD_100US
   BCF ENABLE

   BCF RS
   BSF ENABLE
   MOVLW B'00110000'
   MOVWF LCD
   CALL RETARDOLCD_100US
   BCF ENABLE

   BCF RS
   BSF ENABLE
   MOVLW B'00111100'
   MOVWF LCD
   CALL RETARDOLCD_100US
   BCF ENABLE

   BCF RS
   BSF ENABLE
   MOVLW B'00001100'
   MOVWF LCD
   CALL RETARDOLCD_100US
   BCF ENABLE

   BCF RS
   BSF ENABLE
   MOVLW B'00000001'
   MOVWF LCD
   CALL RETARDOLCD_100US
   BCF ENABLE

   BCF RS
   BSF ENABLE
   MOVLW B'00000110'
   MOVWF LCD
   CALL RETARDOLCD_100US
   BCF ENABLE
   RETURN

RETARDOLCD_100US
   MOVLW    D'1'
    MOVWF    TIEMPO3
TRES3
   MOVLW    D'1'
    MOVWF    TIEMPO2
DOS3
   MOVLW    D'100'
    MOVWF    TIEMPO1
UNO3
   DECFSZ   TIEMPO1
   GOTO    UNO3
   DECFSZ   TIEMPO2
   GOTO    DOS3
   DECFSZ   TIEMPO3
   GOTO    TRES3
   RETURN

RETARDOLCD_15MS
   MOVLW    D'30'
    MOVWF    TIEMPO3
TRES1
   MOVLW    D'10'
    MOVWF    TIEMPO2
DOS1
   MOVLW    D'50'
    MOVWF    TIEMPO1
UNO1
   DECFSZ   TIEMPO1
   GOTO    UNO1
   DECFSZ   TIEMPO2
   GOTO    DOS1
   DECFSZ   TIEMPO3
   GOTO    TRES1
   RETURN

RETARDO:
   MOVLW D'49'
   MOVWF TIEMPO1
TRES
   MOVLW D'80'
   MOVWF TIEMPO2
DOS
   MOVLW D'248'
   MOVWF TIEMPO3
UNO
   NOP
   NOP
   DECFSZ TIEMPO3,1
   GOTO UNO
   DECFSZ TIEMPO2,1
   GOTO DOS
   DECFSZ TIEMPO1,1
   GOTO TRES
   RETURN

   END     

Desconectado nico

  • PIC16
  • ***
  • Mensajes: 180
Re:Problemas con TMR0 (PIC16F877A)
« Respuesta #1 en: 19 de Abril de 2018, 23:17:20 »
Buenas, lo primero es colocarle una resistencia pull-up al port, para que cuente los pulsos, ya que no la tiene, y por lo tanto el pin esta al "aire". De esta manera se hara efectiva cada transición.

Segundo, mire muy por arriba el código, por lo que no se si esta todo inicializado ok. Veo dos cosas, alguien seguro verá alguna mas..

1, en el programa principal enciendes las interrupciones globales y habilitas las interrupciones por "overflow" del tmr 0, acto seguido haces cero el registro tmr0, por lo que para que se desborde, y viendo que tienes el preescaler apagado, necesitas 255 pulsos. Para solucionarlo y leer el pulsador con la interrupcion podrías cargar el tmr0 con 255, el próximo pulso que de el pulsador desbordara el tmr, hara la interrupcion y podras leer este dato, que tendras que guardar en una variable aparte.

2. dentro de la rutina del desborde haces una resta, pero seguro que teniendo en cuenta que ibas a ir allí con cada pulsación, pero recuerda que solo ira a la interrupcion al desbordar el timer, por lo tanto la resta no iria, dentro del tmr podrías sumar uno a tu variable externa, y volver a dejar cargado el timer con 255 para que al presionar de nuevo el boton se desborde, luego en el programa principal actualizas el valor en pantalla.

Esto en el caso que quieras contar y mostrar cada pulso que cuentas con el tmr0, ahora bien, tal vez sino haya entendido mal lo que quieras hacer. Mas sencillo sería hacerlo con RB0/int.

Espero haberme explicado.
Salutes.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problemas con TMR0 (PIC16F877A)
« Respuesta #2 en: 19 de Abril de 2018, 23:23:35 »
(escribi la respuesta mientras nico respondia, asi que el mensaje va para el autor del hilo) (Quite algunas cosas que ya dijo nico)
Pienso que estas muy equivocado en lo que estas planteando realizar. Tu codigo me suena a que estas intentando contar los pulsos externos con el TMR0 (luego de mirar el esquema es obvio que era esto). Y me explico el porque.

Si quisiera detectar un pulso, usaria RB0 y no el TMR0, ya que este pin me permite detectar un pulso.
La interrupcion del TMR ocurre unicamente cuando el TMR pasa de 0xFF a 0x00, asi que si no cargaste el timer con ningun valor y asumimos que esta en 0, deberias presionar 256 veces para entrar a la interrupcion, Y aca quiero hacerte ver que si usas el TMR, a no ser que siempre lo cargues con 0xFF, no te va a ir a la interrupcion apenas presiones el boton. Y si usas el valor 0xFF vas a tener que usar otro registro para llevar la cuenta.
Pero por que complicarla tanto con el Timer existiendo otras formas de hacerlo? Por ejemplo usando RB0 o un comparador si es que posee.

Otra pregunta.. Porque usar una interrupcion? Tu codigo tranquilamente se podria quedar esperando que se presione el boton, actualizar 2 digitos del LCD, esperar que se suelte el boton y repetir. Ese es todo tu programa.

Y algunos errores o cosas que veo en tu programa que a pesar que no le encuentro el sentido de implementacion

- Acostumbrate a guardar y recuperar los valores de STATUS y W al entrar a la interrupcion, en el datasheet si buscas por W_TEMP Microchip te da el codigo que va en la interrupcion.
- Nunca uses funciones que ocupan mucho tiempo en una interrupcion, como es el caso de la subrutina DATO que tiene delays dentro. Entonces usas algun bit de unregistro para que en el loop fuera del a interrupcion se actualice cuando sea necesario.
- Los Labels PRINCIPAL y CONT no tienen ningun sentido en el programa, deberian ser parte del "inicio", podes separarlo en otra subrutina por supuesto.
- Crea una subrutina para apuntar el cursor a un punto especifico. Asi al momento de actualizar el valor lo llevas a ese punto, y solo pensa en escribir, sino siempre se va escribiendo al lado
- D'0' no es lo mismo que '0'
« Última modificación: 19 de Abril de 2018, 23:26:28 por KILLERJC »

Desconectado Oliver Karin

  • PIC10
  • *
  • Mensajes: 6
Re:Problemas con TMR0 (PIC16F877A)
« Respuesta #3 en: 19 de Abril de 2018, 23:38:01 »
Amigos ya estoy haciendo los cambios que sugirieron, pero el problema es que no detecta la pulsacion, ya cargue con 255 el TMR0 para qeu a la siguiente pulsacion desborde pero no lo detecta, es es el problema. Y yambien estoy de acuerdo con lo de hacerlo con RB0 pero el profesor lo pidio asi, el de RB0 fue el programa pasado. Gracias por contertar amigos, y espero me ayuden a resolver porque no detecta la pulsacion.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problemas con TMR0 (PIC16F877A)
« Respuesta #4 en: 20 de Abril de 2018, 10:24:51 »
Hay que definir primero como es que queres que funcione el programa.

Actualizar el LCD lo haces unicamente cuando cambias el numero, entonces solo nos queda determinar como cambiar el numero.

El Timer lo podemos usar de 2  formas.

Que el TMR0 lleve la cuenta, esto tiene una ventaja y una desventaja. La ventaja es que al llegar "a 100" (en realidad 0) tenemos la interrupcion y lo volvemos a nuestro 0 (-99). Como solo va a ocurrir la interrupcion en ese punto, entonces en nuestro loop principal vamos a tener que revisar continuamente el valor del TMR0, comparamos con el valor guardado de cuando entro antes, si es distinto procede a mostrarde nuevo y actualizar el valor anterior.

Que el TMR0 solo funcione como un RB0, en este caso necesitamos cargar con 0xFF el TMR y al presionar el boton pasaria a 0x00, tendriamos que usar otro registro para llevar la cuenta, al momento del cambio, como se realiza con un boton, podriamos actualizarlo desde esa interrupcion. Que es lo que estas buscando hacer parece.

Asi que voy a ir por esta ultima opcion

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problemas con TMR0 (PIC16F877A)
« Respuesta #5 en: 20 de Abril de 2018, 11:22:49 »
Me di cuenta que realizando el programa nunca pusiste el puerto A como digital. Seguramente por eso no funcione tu codigo. Pero aca va mi codigo (en realidad tu codigo un poquito modificado):

Código: ASM
  1. START:
  2.  
  3.    BANKSEL PORTA        ; BANCO 0
  4.    CLRF PORTD
  5.    CLRF PORTC
  6.    CLRF PORTA
  7.  
  8.    BANKSEL TRISA        ; BANCO 1
  9.    CLRF TRISB
  10.    CLRF TRISC
  11.    CLRF TRISD
  12.    MOVLW B'11111111'
  13.    MOVWF TRISA
  14.    MOVLW B'00111000'
  15.    MOVWF OPTION_REG
  16.    MOVLW 0X6
  17.    MOVWF ADCON1
  18.  
  19.    BANKSEL PORTA        ; BANCO 0
  20.    CALL INILCD
  21.    CALL LCDCONTADOR
  22.    MOVLW 0X12           ; MUEVO EL CURSOR EN EL LCD A LA FILA 0 COLUMNA 12
  23.    CALL POSICIONLCD
  24.    
  25.    MOVLW 0XFF
  26.    MOVWF TMR0
  27.    
  28.    BCF INTCON,TMR0IF    ; LIMPIAMOS FLAG
  29.    BSF INTCON,TMR0IE    ; HABILITAMOS LA INT DE TMR0
  30.    BSF INTCON,GIE       ; ACTIVAMOS LA INTERRUCPION GLOBLA
  31.    
  32. LOOP:
  33.    GOTO LOOP
  34.  
  35.  
  36. DATO:
  37.    MOVWF   LCD
  38.    BSF      RS
  39.    BSF      ENABLE
  40.    CALL RETARDOLCD_15MS
  41.    BCF      ENABLE
  42.    RETURN
  43.  
  44. INILCD
  45.     CALL RETARDOLCD_15MS
  46.    BCF RS
  47.    BSF ENABLE
  48.    MOVLW B'00111000'
  49.    MOVWF LCD
  50.    CALL RETARDOLCD_100US
  51.    BCF ENABLE
  52.  
  53.    BCF RS
  54.    BSF ENABLE
  55.    MOVLW B'00110000'
  56.    MOVWF LCD
  57.    CALL RETARDOLCD_100US
  58.    BCF ENABLE
  59.  
  60.    BCF RS
  61.    BSF ENABLE
  62.    MOVLW B'00110000'
  63.    MOVWF LCD
  64.    CALL RETARDOLCD_100US
  65.    BCF ENABLE
  66.  
  67.    BCF RS
  68.    BSF ENABLE
  69.    MOVLW B'00111100'
  70.    MOVWF LCD
  71.    CALL RETARDOLCD_100US
  72.    BCF ENABLE
  73.  
  74.    BCF RS
  75.    BSF ENABLE
  76.    MOVLW B'00001100'
  77.    MOVWF LCD
  78.    CALL RETARDOLCD_100US
  79.    BCF ENABLE
  80.  
  81.    BCF RS
  82.    BSF ENABLE
  83.    MOVLW B'00000001'
  84.    MOVWF LCD
  85.    CALL RETARDOLCD_100US
  86.    BCF ENABLE
  87.  
  88.    BCF RS
  89.    BSF ENABLE
  90.    MOVLW B'00000110'
  91.    MOVWF LCD
  92.    CALL RETARDOLCD_100US
  93.    BCF ENABLE
  94.    RETURN
  95.    
  96. LCDCONTADOR:
  97.    BCF RS
  98.    BSF ENABLE
  99.    MOVLW 0X01
  100.    MOVWF LCD
  101.    CALL RETARDOLCD_15MS
  102.    BCF ENABLE
  103.    BCF RS
  104.    BSF ENABLE
  105.    MOVLW 0X01
  106.    MOVWF LCD
  107.    CALL RETARDOLCD_15MS
  108.    BCF ENABLE
  109.    
  110.    MOVLW   'C'
  111.    CALL   DATO
  112.    MOVLW   'O'
  113.    CALL   DATO
  114.    MOVLW   'N'
  115.    CALL   DATO
  116.    MOVLW   'T'
  117.    CALL   DATO
  118.    MOVLW   'A'
  119.    CALL   DATO
  120.    MOVLW   'D'
  121.    CALL   DATO
  122.    MOVLW   'O'
  123.    CALL   DATO
  124.    MOVLW   'R'
  125.    CALL   DATO
  126.    MOVLW   ':'
  127.    CALL   DATO
  128.    MOVLW   ' '
  129.    CALL   DATO
  130.    RETURN
  131.    
  132. RETARDOLCD_100US:
  133.    MOVLW    D'1'
  134.     MOVWF    TIEMPO3
  135. TRES3:
  136.    MOVLW    D'1'
  137.     MOVWF    TIEMPO2
  138. DOS3:
  139.    MOVLW    D'100'
  140.     MOVWF    TIEMPO1
  141. UNO3:
  142.    DECFSZ   TIEMPO1
  143.    GOTO    UNO3
  144.    DECFSZ   TIEMPO2
  145.    GOTO    DOS3
  146.    DECFSZ   TIEMPO3
  147.    GOTO    TRES3
  148.    RETURN
  149.  
  150. RETARDOLCD_15MS:
  151.    MOVLW    D'30'
  152.     MOVWF    TIEMPO3
  153. TRES1:
  154.    MOVLW    D'10'
  155.     MOVWF    TIEMPO2
  156. DOS1:
  157.    MOVLW    D'50'
  158.     MOVWF    TIEMPO1
  159. UNO1:
  160.    DECFSZ   TIEMPO1
  161.    GOTO    UNO1
  162.    DECFSZ   TIEMPO2
  163.    GOTO    DOS1
  164.    DECFSZ   TIEMPO3
  165.    GOTO    TRES1
  166.    RETURN
  167.  
  168. RETARDO:
  169.    MOVLW D'49'
  170.    MOVWF TIEMPO1
  171. TRES:
  172.    MOVLW D'80'
  173.    MOVWF TIEMPO2
  174. DOS:
  175.    MOVLW D'248'
  176.    MOVWF TIEMPO3
  177. UNO:
  178.    NOP
  179.    NOP
  180.    DECFSZ TIEMPO3,1
  181.    GOTO UNO
  182.    DECFSZ TIEMPO2,1
  183.    GOTO DOS
  184.    DECFSZ TIEMPO1,1
  185.    GOTO TRES
  186.    RETURN    
  187.  
  188. TTIMER:
  189.    ; COMO ESTA VACIO EL LOOP PRINCIPAL PUEDO OMITIR EL GUARDAR/REESTABLECER
  190.    ; STATUS Y W
  191.    INCF CONTADOR, F
  192.    ; EL NUMERO NECESITO SEPARARLO EN DECENAS Y UNIDADES , ADEMAS SUMARLE '0'
  193.    CALL INT_TO_BCD
  194.    ; ANTES DE ENVIAR LOS DATOS, NECESITO POSICIONAR EL CURSOR (DONDE VA A ESCRIBIR).
  195.    MOVLW 0X12
  196.    MOVWF POSICIONLCD
  197.    ; ENVIO PRIMERO LAS DECENAS
  198.    MOVF DECENAS
  199.    MOVWF LCD
  200.    CALL DATO
  201.    ;LUEGO ENVIO LAS UNIDADES
  202.    MOVF UNIDADES
  203.    MOVWF LCD
  204.    CALL DATO
  205.    ;ACTUALIZADO EL LCD, PROCEDO A LIMPIAR EL FLAG Y RECARGAR EL TIMER
  206.    BCF INTCON,TMR0IF
  207.    MOVLW 0XFF
  208.    MOVWF TMR0
  209.    RETFIE  
  210.    
  211.    END

En este codigo hay que hacer un par de funciones, declarar otro par de registros y por ultimo crear la limitacion de tu contador.

Necesitas crear las siguientes funciones:

POSICIONLCD, esta funcion lo que hace es posicionar el cursor en el LCD, me voy con un ejemplo.

Vos escribiste "CONTADOR:"
Si escribis 1 letra o numero mas aparece despues de los 2 puntos, supongamos que escribimos 10 queda asi:
"CONTADOR:10"
Si quiero escribir 11 ahora, si escribo asi nomas me encuentro conque hace esto:
"CONTADOR:1011"
Entonces te quedan 2 opciones, o volves al comienzo y escribis contador + el nuevo numero, o te vas a donde comienza el numero es decir posicionas el cursor despues de los 2 puntos, y escribis 11, asi se sobreescribe el valor y queda:
"CONTADOR:11"

INT_TO_BCD (en realidad seria INT_TO_ASCII )
Vos tenes un numero en formato binario, que en realidad es un entero, el problema que el LCD lo que recibe son caracteres ASCII, Esta subrutina deberia hacer lo que voy a hacer en el ejemplo. Supongamos que tengo el numero 38 y quiero enviarlo al LCD, entonces primero necesito separar las decenas y las unidades (lo podes hacer restando de 10 en 10), por un lado en un registro (DECENAS) voy a tener 3 y por el otro otro registro (UNIDADES) con el valor 8. Con esto me aseguro que en los registros solo tengo los valores de 0 a 9
Pero ese no es el valor ASCII, si quiero imprimero un '3' deberia enviar 0x33, el '0' es 0x30. entonces lo que voy a hacer es sumarlo 0x30 o '0' que es lo mismo. Entonces me queda DECENAS = 0x33 = '3' y UNIDADES = 0x38 = '8'
De alli solo me queda enviarlo.

------------

Registros a usar.

Tambien vamos a necesitar registros para usar. Como ya viste necesitamos uno de DECENAS y UNIDADES para obtener los valores a enviar, pero tambien necesitamos de otro registro para contar cuantas veces entro al TMR0, para eso usamos CONTADOR.
A ese rgistro en el codigo hay que agregarle el limite, ya que puede pasar a mas de 99, deberias ANTES de llamar a INT_TO_BCD, revisar si CONTADOR es mayor a 99, y si lo es proceder a ponerlo a 0 o no modificarlo.


 

anything