Controlar el TIMER_0 del PIC 16F84A

Hola:

En la imagen que ven abajo, hay un microinterruptor, ignora el RB4, sólo voy a utilizar los RB5, RB6 y RB7. Al poenrlo a estado 1 o activado del RB5, me gustaría que hubiera un temporizador de 5 minutos, el de RB6 = 30m y el RB7 = 1 hora.

Lo que no se que pasaría si activara todos a 1 todos los RB5 al 7. ¿Se sumarían los tiempos 5, 30 y 60 minutos con el total de 1:35?

Cuál es el código necesario.

Al menos la configuración de los puertos se los pongo aquí.

Código:
LIST		P=16F84A
	INCLUDE		<P16F84A.INC>
	__CONFIG	_CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

; CÓDIGOS 

	ORG 	0
Inicio
	bsf		STATUS,RP0				; Accede al Banco 1.
	clrf	PORTA					; Puerto A como salidas.
	movlw	b'11111111'				; Las 8 líneas del puerto B se configura como entradas.
	movwf	PORTB
	bcf		STATUS,RP0				; Accede al Banco 0.



Un cordial saludos.
 

Adjuntos

  • uinterrutor_195.jpg
    uinterrutor_195.jpg
    17.5 KB · Visitas: 246
Hola Meta

No soy experto en este tema de los microcontroladores, pero ya pasé por dificultades como las que estás teniendo ahora.

Con respecto a lo que decís sobre si se activan todos a la vez, lo que podés hacer si querés que no pase esto, es crear tres banderas en un registro x que se pongan en 1 cuando se produce una interrupción en rb5, rb6, o rb7 correspondiéndole un bit de dicho registro a cada uno y después en la subrutina lo primero que hacés es verificar que estos bit estén en cero. Si es así, atiendes la interrupcion, si está en 1 cualquiera de ellos, no atiendes la interrupción y retornas a la rutina.
Claro que esto te serviría para usar sólo una vez la interrupción.
No sé si deseás que se produzca más de una vez la interrupción.
¿Podés explicar un poco más en qué consiste el programa?
Explicanos más o menos qué debe hacer el programa y para qué es y te vamos a poder orientar un poco mejor.
 
Pues el PIC 16F84a en el puerto A como salida, sólo un bit. En los puertos B como entradas. Cuando el RB3 está a 1, se activa una salida del puerto A. Al desactivarse el RB3, el puerto A se queda a 0 o desactivado inmediatamente.

Ahora pulsamos el microinterruptor RB5 que significa 5 minutos. Si lo dejas pulsado, ahora en vez de desactivarse el puerto A nada más al desactivarse el RB3, tarda 5 minutos.

¿Se entiende? En caso contrario lo explicaré mejor.
 
A ver si entendí...
Lo que hace el programa es leer todo el tiempo RB3, y en caso de que se active, activa una salida del puerto A hasta que RB3 vuelva a estar en 0. En caso de que se produzca una interrupción en RB5, RB6 o RB7, se produce una demora en la que no se puede activar esta salida hasta que termine el tiempo. En el caso de RB5 es de 5 min., RB6 es de 30, y RB7 de 60 min.
Eso es lo que entendí, espero no haberme equivocado.
Una única pregunta: En caso de que la interrupción se produzca cuando la salida del puerto A está a 1, ¿se debe apagar esta salida y esperar la demora con esta salida apagada o debe permanecer en el estado en que se encontraba?

Acá va lo que yo pienso que debes hacer en base a lo que entiendo, pero quizá tengo una visión equívoca de tu proyecto, de ser así, corregime.
Lo que creo que debes hacer es crear el programa con tres bits de un registro que usarás como bandera de las interrupciones.
El programa hace lo habitual y cuando se produce una interrupción, debes setear o poner a uno el bit que correspondea esa interrupción y crear la demora (5 min., 30 min., o 60 min.) con la salida del puerto A apagada o en el estado en que se encontraba (No sé qué prefieres hacer con él).
Después, cuando se produce cada interrupción lo primero que hacés es leer que estos bits estén en cero y si no lo están no ejecutás la subrutina.
Y después de un tiempo x de que se produjo la interrupción, ponés en cero los tres bits de dicho registro para que vuelvan a ser atendidas las interrupciones.

Lo que te pido es que comentes para qué es este proyecto (salvo que sea un secreto de la CIA, jeje) y me aclares las dudas que te planteé porque sino no podré ayudarte en cuanto al programa del mismo.
Además, no especificaste si querés que las interrupciones se atiendan una sola vez como dije antes o con un cierto tiempo entre una y otra como el ejemplo que di ahora.
 
juan_g dijo:
A ver si entendí...
Lo que hace el programa es leer todo el tiempo RB3,

Sí.

y en caso de que se active, activa una salida del puerto A hasta que RB3 vuelva a estar en 0.

Sí.

En caso de que se produzca una interrupción en RB5, RB6 o RB7, se produce una demora en la que no se puede activar esta salida hasta que termine el tiempo. En el caso de RB5 es de 5 min., RB6 es de 30, y RB7 de 60 min.

El problema es que no he usado interrupción ya que uso retardos y el PIC se queda esclavisado, no hace otra operación hasta que termine los 5 minutos o pulse el botón de Reset.

Eso es lo que entendí, espero no haberme equivocado.
Una única pregunta: En caso de que la interrupción se produzca cuando la salida del puerto A está a 1,

En concreto RA3.

¿se debe apagar esta salida y esperar la demora con esta salida apagada o debe permanecer en el estado en que se encontraba?

La salida RA3 puede estar a 1 activado o 0 desactivado en función de que se cumpla. Si no hay contacto activado de los tiempos de cualquier entrada de los 5m. (RB5), 30m. (RB6) y 60m. (RB7), tan pronto como se activa el RB3 se activa el RA3. Ahora si conectas o activa a 1 la entrada RB5 y lo dejas así mientras RB6 y RB7 están desconectados, salta a 5 m. programado, es decir, que desde que se active el RB3 y tienes el RB5 (5m.) activo, no se desactiva a 0 RA3 hasta que el contador llegue a 0 minutos.

Acá va lo que yo pienso que debes hacer en base a lo que entiendo, pero quizá tengo una visión equívoca de tu proyecto, de ser así, corregime.
Lo que creo que debes hacer es crear el programa con tres bits de un registro que usarás como bandera de las interrupciones.

Eso te lo dejo en tus manos.


El programa hace lo habitual y cuando se produce una interrupción, debes setear o poner a uno el bit que correspondea esa interrupción y crear la demora (5 min., 30 min., o 60 min.) con la salida del puerto A apagada o en el estado en que se encontraba (No sé qué prefieres hacer con él).

Puede estar apagado o encendido, normalmente apagado o a 0, desactivado.

Después, cuando se produce cada interrupción lo primero que hacés es leer que estos bits estén en cero y si no lo están no ejecutás la subrutina.
Y después de un tiempo x de que se produjo la interrupción, ponés en cero los tres bits de dicho registro para que vuelvan a ser atendidas las interrupciones.

No entiendo mucho, por lo que entiendo, comprueba en que tiempo está para poder configurarlo.


Lo que te pido es que comentes para qué es este proyecto (salvo que sea un secreto de la CIA, jeje) y me aclares las dudas que te planteé porque sino no podré ayudarte en cuanto al programa del mismo.

Este proyecto está dirigido para una revista oficial de España de electrónica, no me conviene enseñarlo ni decir pistas de que va exactamente porque me podrían tobar el trabajo, me lo aconsejan los otros autores de sus proyecto y la propia revista que tenga mucha precaución para esto. Cuando lo acabe y lo publiquen, entrego todo, diré el nº y páginas.

Además, no especificaste si querés que las interrupciones se atiendan una sola vez como dije antes o con un cierto tiempo entre una y otra como el ejemplo que di ahora.

Cuando cambias de tiempo a elegir, que sea instantáneo. Lo que no se que pasa si conecto las tras juntas que ya sumarían 1 hora y 35 minutos. ¿Se suma? Con retardos si, pero con el TIMER0 no lo se.

Muchas gracias por tu tiempo.
 
Hola:

Si tu problema es definir cómo se acumulan los tiempos yo implementaría una variable de acumulacion del tiempo transcurrido. Cuando termina la cuenta que sea, y se fije nuevamente
el estado de los bits RB5, RB6 y RB7, según el estado actual descontará el tiempo que ya ha pasado.
Una vez que el retraso total ha terminado y los tres bits están desactivados, el prog. ppal.
sigue con su control de RA3 según el estado de RB3, y revisando cada tanto si alguno se ha activado.

Para no repetir períodos lo que está entre ; ********* puede omitirse (goto test5)
Si los tiempos deben ser acumulativos TACUM = 0, o no se usa

A ver si esto se aproxima a tu problema:

Código:
Lazo
TACUM = 0
   btfss RB3        ; Analiza estado de RB3
   goto   clear3
   goto   set3
clear3
   bcf RA3           ; Define estado bajo de RB3
   goto sal3
set3
   bsf RA3           ; Define estado alto de RB3
sal3
;
; Analiza estado de RB5, RB6, RB7
;
test5
; Si RB5 es activo
;     Inicia contador C1 con T1 = 5 min
;     Termina contador C1 
;     TACUM = TACUM + 5 ; Acumula 5 min
;     Este acumulador lo usa si los tiempos NO deben ser acumulativos
;     Caso contrario TACUM = 0 siempre
; *********
      goto test5 ; acá se fija si repite 
;     ; Si al terminar RB5 está activo suma otros 5 min
; *********
;
test6
; Si RB6 es activo
;       Inicia contador C2 con T2 = 30 min - TACUM
;       Termina contador C2 
;       TACUM = TACUM + 30 ; Acumula 30 min
;       Este acumulador lo usa si los tiempos NO deben ser acumulativos
;       Caso contrario TACUM = 0 siempre
; *********
        goto test5 ; acá se fija si repite desde RB5
;     ; Si al terminar RB5 o RB6 todavía están activos sumará otros 5 min o 30 min
;     ; Ya con 2 veces RB6 se pasaría de 60;
     ; Pero para mostrar la idea creo que alcanza (!)
; *********
;
test7
; Si RB7 es activo
;       Inicia contador C3 con T3 = 60 min - TACUM
;       Termina contador C3 
;       TACUM = 60 ; Pone acumulador de tiempo en 60 min
;       Este acumulador lo usa si los tiempos NO deben ser acumulativos
;       Caso contrario TACUM = 0 siempre
; *********
        goto test5 ; acá se fija si repite desde RB5
; *********
;
goto Lazo
 
Muchas gracias, voy analizar y probar el código en el MPLAB v8.14


Lazo
TACUM = 0
btfss RB3 ; Analiza estado de RB3
goto clear3
goto set3
clear3
bcf RA3 ; Define estado bajo de RB3
goto sal3
set3
bsf RA3 ; Define estado alto de RB3
sal3
;
; Analiza estado de RB5, RB6, RB7
;
test5
; Si RB5 es activo
; Inicia contador C1 con T1 = 5 min
; Termina contador C1
; TACUM = TACUM + 5 ; Acumula 5 min
; Este acumulador lo usa si los tiempos NO deben ser acumulativos
; Caso contrario TACUM = 0 siempre
; *********
goto test5 ; acá se fija si repite
; ; Si al terminar RB5 está activo suma otros 5 min
; *********
;
test6
; Si RB6 es activo
; Inicia contador C2 con T2 = 30 min - TACUM
; Termina contador C2
; TACUM = TACUM + 30 ; Acumula 30 min
; Este acumulador lo usa si los tiempos NO deben ser acumulativos
; Caso contrario TACUM = 0 siempre
; *********
goto test5 ; acá se fija si repite desde RB5
; ; Si al terminar RB5 o RB6 todavía están activos sumará otros 5 min o 30 min
; ; Ya con 2 veces RB6 se pasaría de 60;
; Pero para mostrar la idea creo que alcanza (!)
; *********
;
test7
; Si RB7 es activo
; Inicia contador C3 con T3 = 60 min - TACUM
; Termina contador C3
; TACUM = 60 ; Pone acumulador de tiempo en 60 min
; Este acumulador lo usa si los tiempos NO deben ser acumulativos
; Caso contrario TACUM = 0 siempre
; *********
goto test5 ; acá se fija si repite desde RB5
; *********
;
goto Lazo
 
Hola nuevamente...
Te comento que acabo de hacer un programita sencillo para lo que pedís.
Cosas importantes que debes saber sobre él:
1) Es de tiempo acumulativo (Si querés que no sea así, sólo tenés que borrar el contenido del registro de tiempo acumulado cada vez que vas a sumarle el tiempo de la interrupción).
2) Usa interrupcionesp para simplificar el problema.
3) Lo hice como para un pic 16f877 con una oscilación de 4 MHz. Quizá debas hacerles algunas modificaciones para adaptarlo al micro que tenés. Es que nunca hice programa para el 16f84... No sé si sus registros son iguales a los del pic 16f877.

Suerte y cualquier duda reguntá...

Nota final: No lo probé en el MPLAB, sería mejor que lo simules a ver si funciona... No tuve tiempo de verificarlo...
 

Adjuntos

  • ayuda_con_tmr0_para_un_forero_187.asm
    5.4 KB · Visitas: 16
Hola de nuevo...
Acá va el programa anterior con algunos cambios que le hice para que funcione. sería bueno que igualmente lo pruebes a ver si funciona.
Suerte
 

Adjuntos

  • ayuda_con_tmr0_para_un_forero_434.asm
    6.5 KB · Visitas: 12
Atrás
Arriba