Temporizar un LED sin instrucción "delay_ms()"

Hola amigos del foro.
Quisiera temporizar un led o lámpara y manejarlo con un switch o botón, como un temporizador común pero sin delay_ms()
¿Podrían enseñarme cuál es el código?

Tengo poco tiempo estudiando C y es lo que mas estoy empapado.
Mi compilador es PIC C Compiler.

PHP:
#include <16f628A.h>
Fuses Xt,NOWDT 
use delay(clock=4M)

int tiempo;
int8 start = 0;
#int_TIMER1
void TIMER1_isr(){
   tiempo = tiempo ++;
   set_timer1(0);
   if (tiempo > 5 ){ //  para 2.5 segundos encedido led aproximadamente
      output_low(PIN_B7);
      disable_interrupts(INT_TIMER1); //paramos timer1
      start = false;
   }
}
void main()
 {
      set_tris_b (0b00000001);   //Puerto B como salidas bits de 1 a 7, el 0 es entrada
      ext_int_edge(L_TO_H);   // activacion flanco de subida ,aunque por default es por flanco de subida .
      setup_timer_1(RTCC_INTERNAL| RTCC_DIV_4);
      set_timer1(192);
      enable_interrupts(INT_TIMER1);
      enable_interrupts(GLOBAL);

  while(1)
  {

         }
   }
 
Última edición por un moderador:
Hola, hay varias maneras para lograr tu cometido.
Una de ellas es utilizar la interrupción de un timer interno. Cuando se desborda, gestiona el evento que deseas.
Otro forma es incrementar un número, un determinado número de veces cómo por ejem.: contar++;
Luego cuando la variable "contar" alcanza un valor dado, realiza de igual manera el evento deseado.
 
Hola, hay varias maneras para lograr tu cometido.
Una de ellas es utilizar la interrupción de un timer interno. Cuando se desborda, gestiona el evento que deseas.
Otro forma es incrementar un número, un determinado número de veces cómo por ejemplo: contar++;
Luego cuando la variable "contar" alcanza un valor dado, realiza de igual manera el evento deseado.
Así es cómo lo está haciendo. :cool:
Hola amigos del foro.
Quisiera temporizar un led o lámpara y manejarlo con un switch o botón, como un temporizador común pero sin delay_ms()

Así cómo lo estás haciendo con un timer y un conteo, está bien.
El problema que tiene tu programa es de configuración.
Estás usando el Timer 1 con constantes para el Timer 0, aparte de no ser correcto su valor.

Si requieres que el Timer 1 desborde cada 500 mS @ 4 MHz, su valor de carga debe ser de 3036 o 0xBDC en hexadecimal y el prescaler con un divisor entre 8.
¿Podrían enseñarme cuál es el código?
Algo así:
PHP:
#include <16f628A.h>
#use     delay(crystal = 4MHz)

int8 tiempo = 0;

#INT_TIMER1
void sdi_desborde_timer1 (void)
{
   tiempo ++;                                   // Incrementar la variable "tiempo"
   
   if (tiempo > 4 )                             //  0.5 x 5 = 2.5 Segundos.
   {
      tiempo = 0;                               // Retornar la variable "tiempo" a 0
      output_toggle(PIN_B7);                    // Cambiar de estado el pin RB7
   }
   
   set_timer1(3036);                            // Recargar el Timer 1
}

void main (void)
{
      setup_timer_1(T1_INTERNAL | T1_DIV_BY_8); // Reloj interno para el Timer 1 y prescaler entre 8
      set_timer1(3036);                         // Cargar el Timer 1 para que desborde cada 500 mS. @ 4 MHz.
      enable_interrupts(INT_TIMER1);
      enable_interrupts(GLOBAL);
      
      output_high(PIN_B7);                      // RB7 en 1 al iniciar.

  while (true);
  
}
 
OK! Gracias , ya entiendi .Ahora veo que puedo configurar los tiempos de prendido y apagado
inclusive jugar y poner otros leds o lamparas. Pero ,como pudedo poner un tiempo prefijado con unos botones ejemplo sw1 timpo 10s , sw2 30s y asi cosa de manejarlo desde afuera?.Si hay algo que no puedo hacer es hacer que el programa salga de ahi de es bucle . Tambien pense en un boton de parada no se como manejar las banderas o flags pero no sale de ahi.:)
Baje el manual de proteus y c compiler pero no entiendo mucho .La verdad es que estos circuitos me parecen fascinantes . Realice el grabador ,compre mi primer pic un 16F628A lo queme y flash de ahi creo que me enamore de c y estos integrados fue un flash ,pero cuanto mas me meto mas complicado es . (y)
 
Última edición:
Para cambiar el periodo, puedes usar una variable que le asigne un nuevo valor al Timer.
Para que el servicio de interrupción ya no se ejecute, deshabilita su bit de activación.
En PIC C de CCS se hace con la instrucción "disable_interrupts(level);"
Por ejemplo: disable_interrupts(TIMER1);

Y yo pienso lo contrario, que mientras más los uses, más los comprendes.

Suerte.
 
disable_interrupts(INT_TIMER0);
sentencia
retardo
enable_interrupts(INT_TIMER0);

esto es solo en el RB0 entrada externa . solo podes colocar un sw .Pero no se si me podes ayudar a lo mejor se necesita tiempo y sapiencia .y no siempre van de la mano .por eso no me gusta pedir mucho.:apreton:

El tema de temporizar es complejo ,porque de no ser asi el codigo estaría a la vista .
Y he navegado y estudiado y probado codigo pero nada .
Esto es ,como puedo poner un tiempo prefijado a unos botones ejemplo sw1 =tiempo 10segundo , sw2 =30s. Los sw son interruptores mecanicos tipo botones ,no se si se entiende .lo aclaro para que no se entienda que son los sw o interruptores interno del pic .
 
Es muy sencillo. Crea una rutina con un Timer para que se desborde cada X tiempo.
Ya con eso puedes calcular cuantas veces se necesitan para que durante el conteo incremental de cada desborde, obtengas el tiempo que necesitas.

Por ejemplo, si usas el Timer 1 con un cristal externo de 32768 Hz. para su oscilador, (Sincronización externa)
y lo configuras para que desborde cada 1000 ms. Entonces nada más tienes que indicarle a la rutina de conteo, cuantas veces en segundos necesitas para que se ejecute el evento.

Ahora que si requieres el tiempo en minutos, únicamente multiplicas los minutos requeridos por 60.
Por ejemplo: 7 x 60 = 420 (420 conteos de un segundo, equivalen a 7 minutos)

Así de fácil, y ejemplos sobre lo que te menciono ya los he comentado y subido al Foro.
 
Si tal cual ,creo que ya llegue a eso o me parece con ciertas dificultades .Utilice la condicion
if para incrementar la variable conteo o contador en un sw 200000 conteos y en otro sw 300000 conteos ,son muchos porque esta echo con el timer0 al ser de 8 bits no pude incrementar mas su tiempo .
pero hay problemas hay tiempos de apagado y tiempos de prendido por la sentencia toggle
no hay un sw de apagado no puedo apagar o hacer que se apague totalmente no conosco la sentencia que va en c . bueno y otras .
 
Por lo que he visto, lo que aquí hace falta es que expliques bien qué es lo que quieres hacer realmente.
Temporizar usando los Timers no es complicado, y obviamente vas a encontrar muchos programas de ejemplo.
No te servirán si los aplicas directamente, pero te están dando la base para que lo puedas entender.

Ahora, empezar a programar se te hará complicado en un principio, pero así lo es todo.
No te puedes poner a hacer pasteles cuando lo único que sabes hacer son galletas.
Necesitas estudiar bien el lenguaje que más has comprendido, aunque lo hagas cómo autodidacta.

Entonces... Si nos explicas bien qué proyecto deseas hacer, te podremos orientar mejor.
 
Voy hacer una pregunta, se dice que usar delays hay que evitarlo siempre que se pueda o no usarlos, que es mejor usar interrupciones o timers.

Mi pregunta es, cuando esta la interrupcion activada para suplir un delay, en teoria no se usa el mismo tiempo? si se usa delay se para y hasta que no termina no continua el programa, pero cuando entra una interrupcion, mas o menos tambien ocurre lo mismo no?

La verdad sea dicha, es que se me atragantan las interrupciones y suelo usar vastante los delays jejeje.
 
Última edición:
Si haces el retardo por conteos usando el desborde de un timer, la ejecución del programa continúa normalmente.
También las interrupciones continúan en funcionamiento aunque se tengan retardos con delay_xx(); dentro del bucle del programa.
Lo que sí detiene el programa principal, es usar delay_xx(); dentro del servicio de interrupción.

Adjunto un pequeño ejemplo para que lo compruebes.
 

Adjuntos

  • Interrupciones y retardos.rar
    15.9 KB · Visitas: 13
Voy hacer una pregunta, se dice que usar delays hay que evitarlo siempre que se pueda o no usarlos, que es mejor usar interrupciones o timers.

Mi pregunta es, cuando esta la interrupcion activada para suplir un delay, en teoria no se usa el mismo tiempo? si se usa delay se para y hasta que no termina no continua el programa, pero cuando entra una interrupcion, mas o menos tambien ocurre lo mismo no?

La verdad sea dicha, es que se me atragantan las interrupciones y suelo usar vastante los delays jejeje.

Es que siempre, absolutamente siempre hay cosas que hacer y si haces un delay matas y entierras al sistema hasta que acabe.
Cosas que hacer; refrescar el display, enviar datos por el puerto serie, verificar si se pulsa una tecla, mirar la temperatura ambiente... siempre hay algo que hacer, siempre.
Si tu sistema no tiene nada que hacer, es que es de juguete; todos los sistemas semi serios tienen al menos un paro de emergencia o un registro de lo que pasa etc...

El símil humano sería quedarte enfrente del reloj mirando sin parar hasta que se haga la hora, además con tapones en los oídos y orejeras para solo ver y vivir para ver el reloj frente a poner una alarma y mientras tanto dedicarte a hacer todo lo demás.
Si crees que es mejor quedarte hipnotizado mirando el reloj y no hacer nada mas en tu casa, entonces los delays son para ti. Yo que soy talibán antidelays creo que sobran y no tienen ningún uso, mas que hacer el mono en sistemas de medio prueba. En sistemas "de verdad" tan solo he hecho bucles de 10 o 20µs y pocos, si necesitaba mas tiempo leía una entrada analógica y actualizaba su dato en el registro interno, por ejemplo. Un delay de 1ms son 16000 instrucciones tiradas por la ventana.

Y si, usar interrupciones marea hasta que lo entiendes y ya no puedes vivir sin ellas.
 
Última edición:
Tienes mucha razon Scooter, nunca me habia planteado el que en vez de poner un delay usar el mismo tiempo haciendo comprovaciones de esto o aquello, tambien es cierto que los programas que me hago son para tareas sencillas, tala vez por eso no me molestado en meterme mas de lleno con el tema de las interrupciones.

Tengo que aprender, si o si, a manejarme con las interrupciones.
 
De lo contrario solo harás una cosa, lo cual es insuficiente el 99,99% de los casos.
La forma de hacer varias cosas "a ala vez" es usar interrupciones.
Es mentira, solo se hace una pero parecen varias.
 
Si haces el retardo por conteos usando el desborde de un timer, la ejecución del programa continúa normalmente.
También las interrupciones continúan en funcionamiento aunque se tengan retardos con delay_xx(); dentro del bucle del programa.
Lo que sí detiene el programa principal, es usar delay_xx(); dentro del servicio de interrupción.

Adjunto un pequeño ejemplo para que lo compruebes.

D@rkbytes permiteme una pregunta, estoy mirando el ejemplo que has adjuntado y quisiera, si te parce,que me expliques, para que lo pueda entender, como el parpadeo del led D1 por que supuestamente cuando entra en el bucle del while se supone que que esa funcion ya no la deveria hacer, ya que no sales del bucle, y eso no lo entiendo.

todo lo otro lo comprendo y ya hago alguna que otra prueba con los tiempos del set_timer, en este caso el que has puesto es el clasico de "3036", eso se hacerlo tambien, pero lo otro no lo comprendo.
 
Es simple. Como cada servicio de interrupción es independiente, no importa que el bucle del programa principal tenga retardos con delay_xx();
El Timer sigue haciendo su función y cuando desborde, se cambiará de estado un pin. (Para un LED en éste caso.)
El servicio de interrupción externa por RB0, también hará su función aunque se encuentre un retardo de 3 segundos en el bucle principal.
Así que usando interrupciones se pueden seguir haciendo otras tareas. (Sistema usado por RTOS)
Pero como es obvio, si hay retardos, siempre detendrás el programa principal hasta que se cumplan.
Y por lógica, el programa también será detenido hasta que se salga de una interrupción.
De ahí el nombre del proceso.
 
La cosa es que si en el bucle principal tienes retardos, estos se verán alterados por las interrupciones y se alargarán. Si no te importa falsear un poco el tiempo, es un sistema válido, pero si es crítico el tiempo tendrás que buscar otro sistema; usar otro timmer o algo así.
Lo bueno de las interrupciones es "que no haces nada, van solas", en el bucle principal te olvidas de ellas, cada vez que desborda el timer o se activa un pin te interrupción, se sale del bucle, se hace lo que se tenga que hacer y vuelve al mismo sitio en donde se quedó.

El símil humano sería: Estás haciendo tu tarea y llaman por teléfono, anotas en la pila por donde vas, contestas al teléfono y cuando cuelgas sacas de la pila por donde estabas y sigues haciendo lo mismo que hacías en el mismo momento.
Puede que configurar interrupciones sea lioso, pero programar eso por polling es un dolor de muelas muchísimo peor
 
Última edición:
Atrás
Arriba