¿Como lograr que el TMR1 cuente n cantidad de tiempo?

Hola, estoy desarrollando mi primer proyecto con PICs, un encendido y apagado de LEDs en un intervalo de 300ms. He basado mi desarrollo en un código de apoyo que encontre por internet, debido a que soy principiante en esto de la electrónica.

Mi problema es el siguiente: No entiendo bien cuál es la fórmula que uno debe seguir para calcular las configuraciones necesarias que hay que hacer al TMR1. En mi caso, he visto que han usado un preescaler de 1/8, y un valor precargado de 28036.

¿Puede alguien explicarme por favor cuales son los pasos que uno debe seguir para que el timer1 haga su trabajo? Por favor, si es posible, expliquenme por favor los términos asociados como preescaler y demás, debido a que soy un principiante en estas cosas, y algunos conceptos de internet me parecen algo vagos como para definir lo que busco.

Puedo adjuntar el código, si alguien lo considera necesario.

Disculpen por las molestias, y gracias de antemano por su ayuda.
 

Adjuntos

  • led.txt
    2.3 KB · Visitas: 27
Última edición:
tratare de explicarte de forma simple, para que te hagas una idea, luego cuando leas de nuevo las formulas tendrías que entenderlo.

por empezar tenes un cristal, o un oscilador interno de ciertos mhz, suponiendo que usas un cristal de 4 mhz, significa que se hacen 4 millones de ciclos por segundo, luego tienes que saber que un pic necesita 4 ciclos para completar una instrucción, por lo tanto, el pic ejecuta 1 millón de instrucciones por segundo, hasta acá vamos bien?

ahora pasamos al timer, el timer es un contador, que se incrementa de manera automática cada vez que el pic realiza una instrucción, si lo dejas así como esta, se aumentaría 1 millón de veces por segundo, pero esto puede ser poco practico, entonces esta el prescaler, que lo que hace es que en vez de aumentar 1 vez por ciclo, lo configuras para que aumente 1 vez cada 8 ciclos, o 1 vez cada 256 ciclos, etc, suponiendo que elegís el prescaler 1:256, el timer aumenta su contador 1 vez cada 256 ciclos, entonces, en vez de aumentar 1 millon de veces por segundo como antes, ahora solo aumenta 3906.25 veces.

luego tienes que calcular cada cuanto tiempo se producirá un desborde del timer, como bien dijimos antes el timer es un contador, y ese contador tiene un limite, si es un timer de 8 bits, el desborde se producirá cuando llegue a 255, entonces del numero que veníamos calculando antes, lo dividimos en 256 otra vez, y llegamos al resultado que el timer se desborda 15.31 veces por segundo.

ya teniendo este valor, lo único que queda hacer para calcular los segundos es hacer un contador en la rutina de interrupción por desborde del timer que se ira aumentando cada vez que desborde el timer, como dijimos recién, son 15 desbordes por segundo, entonces haces un if, para que cuando tu contador llegue a 15, aumente alguna variable donde vas guardando los segundos.

espero que te haya quedado un poco mas claro las cosas que utilizan en las formulas del timer y de donde salen, o porque son asi.
por ultimo te dejo una pagina con algunos ejemplos y explicaciones
http://picmania.garcia-cuervo.net/picc.php#RTCC1
http://picmania.garcia-cuervo.net/conceptos.php#CristalyTime
 
Mi problema es el siguiente: No entiendo bien cuál es la fórmula que uno debe seguir para calcular las configuraciones necesarias que hay que hacer al TMR1.
En mi caso, he visto que han usado un preescaler de 1/8, y un valor precargado de 28036.
Para hacer lo que requieres de forma sencilla, existe un programa llamado ConfigPIC, escrito por Suky.
Este programa tiene varias opciones para realizar algunas configuraciones y cálculos.
Están incluidas las siguientes configuraciones para los PIC16F84A, PIC16F628A y F648A.
* Fusibles y puertos.
* Timers (WDT, Timer 0, Timer 1 y Timer 2)
* CPP (Captura, comparación y PWM)
* Comunicación. (Generador del Baud Rate para RS-232)
* Comparadores analógicos. (Configuración)
* Interrupciones. (Todas las disponibles para el PIC seleccionado.)

Ventana del cálculo de temporización del Timer 1 a 300Ms. (4MHz.)
Temporización Timer1.jpg


Como podrás ver, este programa te será útil ahora que estás aprendiendo con el PIC16F628A

Suerte, ya verás que te será de utilidad.

PD:
Adjunto un ejemplo en ensamblador para prender y apagar un LED cada 300Ms, usando el Timer 1.
 

Adjuntos

  • ConfigPIC.rar
    85.1 KB · Visitas: 65
  • 16F628A Ejemplo TMR1.rar
    22.8 KB · Visitas: 60
Última edición:
Gracias a todos por su ayuda. Oye, Darkbytes, intenté usar el ejecutable pero me da error. Dice algo como "La aplicacion no se pudo inicializar...". Creo que está hecha para otro SO de Windows superior. En cuanto al código y la simulación que me brindaste, gracias por ello. Son muy útiles.

Pero, aún sigo sin entender muy bien lo que hay que hacer exactamente para que el TMR1 cuente n cantidad de tiempo. Usando las páginas de apoyo que me ha brindado martin12as, he encontrado las siguientes fórmulas:

Código:
MiTIMER0 = 256 - (Time / (4/FOSC) )

¿Será que esa fórmula que es de TMR0 sirve para TMR1? No soy muy diestro en esto de los PICs, pero me parece que ese valor 256 limita la cuenta a un byte, que es la longitud máxima de TMR0, o será que me sirve??

En mi busqueda no encuentro una especifíca para TMR1. ¿Sustituyo el valor de 256 (byte) a uno de word, o lo dejo así? Tampoco encuentro algo que me diga que preescalador usar.

Por favor, necesito ayuda. Gracias por su colaboración. Seguiré buscando mientras tanto a ver si encuentro algo...
 
Gracias a todos por su ayuda. Oye, Darkbytes, intenté usar el ejecutable pero me da error. Dice algo como "La aplicación no se pudo inicializar...". Creo que está hecha para otro SO de Windows superior. En cuanto al código y la simulación que me brindaste, gracias por ello. Son muy útiles.
Yo uso Windows XP SP3 y funciona bien.
Descarga el instalador del programa desde este enlace:
Automatizando la configuración del PIC (PIC16F84A/PIC16F628A/PIC16F648A)

Posiblemente usando el instalador lo puedas ejecutar.
¿Será que esa fórmula que es de TMR0 sirve para TMR1?
Nop, El Timer1 es de 16 bits y se usa esta fórmula:
Fórmula_Timer1.jpg
formula_1.png
En mi busqueda no encuentro una especifíca para TMR1.
Mira por aquí: Uso del TMR1 como Temporizador
También dale una leída a la Hoja de datos, en la sección 7.0 Timer1 Module

Suerte.
 
Última edición:
Ah, gracias por la aclaración, martin12as.

D@rkbytes, gracias por la ayuda. Estuve probando los cálculos con tu fórmula, y los resultados aparentes fueron satisfactorios. Ya lo único que me queda es depejar los valores que necesito en particular.

Bueno, gracias a todos. Aún no entiendo un poco lo del preescaler. No sé que valor debería darle si en algún proyecto diferente llegase a necesitar un tiempo distinto. Según lo que me han explicado, es algo así como que hace que el contador se incremente cada 8, 16, 32 o X cantidad de ciclos después.

Por favor, si es posible ayudenme en explicarme un poco ese concepto, y que valor elegir. Es lo único que me falta para completar mi entendimiento sobre como funciona el TMR1. Supongo que el valor de preescaler se puede deducir a partir de la fórmula, ¿o no?.

Gracias a todos por su colaboración.
 
Última edición:
Claro, si usas 1:1 se incrementa en cada ciclo y desborda después de 256 ciclos. Si usas 1:2 se incrementa cada 2 ciclos, por lo cual desbordaría después de 512 ciclos. Si usas 1:4 desborda cada 1024 ciclos. Y así sucesivamente.
 
Aún no entiendo un poco lo del preescaler. No sé que valor debería darle si en algún proyecto diferente llegase a necesitar un tiempo distinto.
Según lo que me han explicado, es algo así como que hace que el contador se incremente cada 8, 16, 32 o X cantidad de ciclos después.

Por favor, si es posible ayúdenme en explicarme un poco ese concepto, y que valor elegir.
Es lo único que me falta para completar mi entendimiento sobre como funciona el TMR1.
Supongo que el valor de preescaler se puede deducir a partir de la fórmula, ¿o no?.
A ver si puedo explicarlo de forma sencilla para que comprendas que valor debes usar para el prescaler.

El Timer1 sólo tiene 4 tipos de división para el prescaler; 1:8, 1:4, 1:2 y 1:1
Por medio de la fórmula expuesta en el Post #6, puedes determinar cual factor usar.

Veamos un ejemplo:
Tenemos los siguientes datos...
Fosc = 4MHz.
Temporización requerida = 300Ms.
Prescaler = 1
Entonces usando la fórmula con el prescaler 1:1, obtenemos lo siguiente:
Desborde del Timer1 = 4 / Fosc * Prescaler * (65536 - Timer1)
Desborde del Timer1 = 4 / 4000000 * 1 * (65536 - 0) = 0.065536 = (65.5Ms.)
Como queremos 300Ms. Entonces el prescaler 1:1 no nos sirve.
Con el prescaler 1:2 tampoco serviría pues el desborde del Timer1 ocurriría cada 131.072Ms.
Con el prescaler 1:4 sería de 262.14Ms. Y tampoco llegamos al valor necesario.
Nos queda usar el prescaler 1:8 y entonces...
Desborde del Timer1 = 4 / 4000000 * 8 * (65536 - 0) = 0.524288 = (524.28Ms.)
Con este factor de división si podemos estar dentro del rango antes de que se desborde el Timer1.

Ahora; ¿Qué valor debo cargar al Timer1 para lograr que desborde cada 300Ms.?
Usando esta fórmula:
Valor para cargar el Timer1 = (65536 - (Temporización * Fosc) / (4 * Prescaler))
Valor para cargar el Timer1 = (65536 - (0.3 * 4000000) / (4 * 8)) = 28036 "Hex = 6D84"

Como el Timer1 es de 16 bits, se usan dos registros de 8 bits: TMR1H y TMR1L
Entonces cargamos en TMR1H el MSB = 6D y en TMR1L el LSB = 84

Espero me haya explicado y logres entender lo que expliqué.

PD. Adjunto un programa escrito por mi para el cálculo del valor a cargar en el Timer1.
Espero este si lo puedas ejecutar, pues tan sólo necesita el .NET Framework 2.0

Saludos.
 

Adjuntos

  • Timer1 Calc.rar
    11.4 KB · Visitas: 59
Última edición:
Muchas gracias D@rkbytes. Ya entiendo bien lo que hay que hacer. Entonces uno debe usar un preescalador cuya cuenta máxima de tiempo este por encima del valor requerido, y luego cargar un valor en TMR1 que haga que se dispare un poco antes, de manera, que dé el tiempo deseado. Al menos eso fue lo que entendí.

Gracias por las fórmulas, y también por el programa. El programa es sencillo de comprender y muy útil. Bueno, gracias a todos por su colaboración. Daré por finalizado mi problema.
 
Hola, amigos. Disculpen que vuelve a retomar un tema, pero tengo un problema: Estoy intentando hacer un TMR1 que se dispare luego de 1000 ms (1 seg), pero me he dado cuenta que no es posible alcanzar dicho valor.

Usé el preescalador con valor de 8, sólo puedo alcanzar el valor de 524.288 ms. ¿No hay forma de conseguir un 1 seg con el TMR1?? ¿Será que tendré que hacer el retardo usando rutinas? Sé que es posible hacerlo con rutinas, pero quería profundizar en el TMR1.

Ah, otra pregunta breve: ¿Dónde puedo conseguir la frecuencia del oscilador interno?? He considerado en mis cálculos unos 4khz, pero no estoy muy seguro.

Seguiré investigando en los datasheet de Microchip a ver si lo encuentro, y en internet para aclarme mejor.

Gracias a todos de antemano. Perdonen si mis preguntas son de principiante.
 
Última edición:
Hola, amigos. Disculpen que vuelve a retomar un tema, pero tengo un problema: Estoy intentando hacer un TMR1 que se dispare luego de 1000 ms (1 seg), pero me he dado cuenta que no es posible alcanzar dicho valor.

Usé el preescalador con valor de 8, sólo puedo alcanzar el valor de 524.288 ms. ¿No hay forma de conseguir un 1 seg con el TMR1?? ¿Será que tendré que hacer el retardo usando rutinas? Sé que es posible hacerlo con rutinas, pero quería profundizar en el TMR1.

Gracias a todos de antemano. Perdonen si mis preguntas son de principiante.

tenes que hacer un contador, podrías precargar el timer con algún valor para que quede aproximadamente en 500ms, y luego haces un contador dentro de la interrupción para que algo suceda cada 2 interrupciones..

por ejemplo te dejo un código que tengo acá a mano, lo estoy usando para contar segundos también.
Código:
#int_RTCC                
void RTCC_isr()          
{             
   if(++contador_interrupciones==interrupciones_para_1segundo)
   {
      contador_interrupciones=0;
      set_timer0(4);
      cambio=1;
   }
}

como vez, pongo en 1 el valor cambio, para que mi programa, dentro de la función main, realice alguna función cuando detecta eso.
 
Ah, gracias martin12as. Ahora ya tengo una idea más clara de que debería hacer. Bueno, lo haré en ensamblador. Supongo que sólo será cuestión de traducirlo. Gracias por tu ayuda.
 
Hola, amigos. Disculpen que vuelve a retomar un tema, pero tengo un problema: Estoy intentando hacer un TMR1 que se dispare luego de 1000 ms (1 seg), pero me he dado cuenta que no es posible alcanzar dicho valor.

Usé el preescalador con valor de 8, sólo puedo alcanzar el valor de 524.288 ms.
¿No hay forma de conseguir un 1 seg con el TMR1?
¿Será que tendré que hacer el retardo usando rutinas? Sé que es posible hacerlo con rutinas, pero quería profundizar en el TMR1.
Para hacer que el Timer1 desborde cada 1 segundo, se hace uso de un cristal de 32768Hz.
Este cristal se conecta en los pines RB6 y RB7 que son para el oscilador o la sincronización externa del Timer1.
De esta forma es como se consigue generar un 1Hz. Y con bastante precisión usando el Timer1.
Así te evitas el uso de rutinas de conteo, pues la división es directamente entre 32768 y prescaler 1:1.

Este ejemplo lo he hecho para PICBasic, para C y ahora lo pongo aquí en lenguaje ensamblador.

Saludos.
 

Adjuntos

  • Esquema_TMR1_1Hz.jpg
    Esquema_TMR1_1Hz.jpg
    70.7 KB · Visitas: 19
  • 16F628A Timer1 1Hz.rar
    25.7 KB · Visitas: 34
Gracias por tu ayuda D@rkbytes. He estado mirando el código y se ve bien. Gracias por la simulacion. Bueno, veré si compro el cristal. De todas maneras, sólo estoy empezando y no es muy importante la precisión.
 
Atrás
Arriba