# Interrupcion de timer y externa en CCS



## jaiser (Ene 6, 2009)

Saludos, estoy trabajando con las interrupciones externa y del timer1 del pic 16f877a, se como trabajan por separado y las he controlado bien con pulsadores, pero al usarlas de manera dependiente una de otra se daña el programa y pierde la sincronizacion la interrupcion externa.

El programa consiste en que al ocurrir la interrupcion externa se activa el timer con el valor calculado (el cual funciona bien), luego al desbordar el timer se ejecutan las instrucciones correspondientes a la interrupcion dl timer la primera vez y luego se vuelve loco y pierde el sincronismo con la interrupcion externa.

cuando desabilito la interrupcion del timer despues que pasa por alli la primera vez hace bien la rutina de la interrupcion externa, pero necesito la interrupcion del timer cuando se desborde despues de activarlo en la interrupcion externa. Alguien puede darme alguna recomendacion, ya utilice el buscador y el tema mas parecido que encontre fue el de interrupciones multiples en C18, pero no entiendo muy bien lo que se hace alli, otro detalle es que yo uso es el compilador de CCS. Parece un problema de prioridad entre las interrupciones.

Dejo adjunto el archivo del codigo del programa hecho en CCS.


----------



## El nombre (Ene 6, 2009)

En primer lugar y asi como el que no quiere la cosa
¿Qué hace la configuracion del timer dentro de un bucle infinito? y la segunda y la tercera.
Lo lanzas y lo dejas en un bucle muerto. eso para empezar.

Le metes un Delay dentro de la interrupcion exterior. por tanto el flag de la interrupcion queda activqdo al salir de la exterior.

Mira todo eso y reprograma correctamete. 
Saludos y suerte


----------



## jaiser (Ene 7, 2009)

ok entiendo lo del retardo dentro de la interrupcion pero eso lo coloque con la intensión de ver en el simulador que la interrupcion externa se realiza correctamente, me gustaria que me dieras alguna sugerencia de la interrupcion del timer ya que ese basicamente es el problema, cuando entra la primera vez a la interrupcion del timer mando a desactivar la interrupcion por timer para que espere la proxima interrupcion externa donde se vuelve a habilitar y se arranca el timer, pero no me funciona bien.

Fijate en el codigo:

#INT_EXT
Ext_Int_Handler()  
{
output_HIGH(PIN_D0);   // esta es la salida que quiero controlar
output_HIGH(PIN_D1);   // esta salida es de referencia para el simulador
ENABLE_INTERRUPTS(INT_timer1);
set_timer1(65500);
DELAY_ms(1);              // para generar un pulso pequeño en D1 que se vea en el oscilosciopio del simulador
output_LOW(PIN_D1);
}

#int_timer1
timer1_handler(){
output_LOW(PIN_D0);   // se apaga la salida
setup_timer_1(T1_DISABLED);
DISABLE_INTERRUPTS(INT_timer1);
}

que opinan?


----------



## Ferny (Ene 7, 2009)

¿Para qué vuelves a habilitar la interrupción del timer en el bucle infinito?


----------



## El nombre (Ene 7, 2009)

Ahí has estado al quite ferny.
Es lo primero que comente. dejalo trabajando en un while (1);


----------



## jaiser (Ene 9, 2009)

Explico mejor por pasos
1. Ocurre el evento externo y al entrar en la rutina de interrupcion externa 
      //  se activa el timer
      //  se activa la salida
      //  se habilita la interrupcion por timer.
2. al desbordarse el timer con el tiempo (para dar un retardo especifico) 
     //  entra a la interrupcion del timer
     //  se apaga la salida 
     //  desabilita la interrupcion del timer para asegurar que espera hasta la siguiente interrupcion externa.

la idea del programa es controlar unos tiristores con un retardo de encendido.

Alguien tiene alguna sugerencia?


----------



## Ferny (Ene 9, 2009)

Eso es correcto, lo que no es correcto es el bucle principal de tu programa... Simplemente pon un while(1); y te olvidas del resto. Es que si te fijas estás volviendo a activar la interrupción dentro del bucle principal. Es decir, cambia esto:


```
ENABLE_INTERRUPTS(INT_timer1);
enable_interrupts(INT_EXT);
EXT_INT_EDGE(H_TO_L);
enable_interrupts(GLOBAL);

   do {
     setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
      ENABLE_INTERRUPTS(INT_timer1);
      ENABLE_INTERRUPTS(INT_EXT);
     } while (true);
```

Por esto:


```
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
ENABLE_INTERRUPTS(INT_timer1);
ENABLE_INTERRUPTS(INT_EXT);
EXT_INT_EDGE(H_TO_L);
enable_interrupts(GLOBAL);

while (true);
```

Por cierto otra cosa, los delay los printf quítalos de las interrupciones, también puede ser por eso que se te vuelva "loco" el PIC...


----------



## Ferny (Ene 9, 2009)

Claro que para que eso funcione no tienes que deshabilitar la interrupción externa dentro de la rutina de interrupción del timer... porque ya no volverías a activarla. Es decir quitar esta línea:


```
#int_timer1
timer1_handler(){
printf(" pase por aqui ");
output_LOW(PIN_D0);
setup_timer_1(T1_DISABLED);
DISABLE_INTERRUPTS(INT_timer1);
DISABLE_INTERRUPTS(INT_EXT); <----------------- QUITAR
}
```

O bien la dejas puesta y luego en el bucle principal del programa la habilitas, pero sólo la externa no la del timer.


----------



## jaiser (Ene 12, 2009)

Gracias Ferny me ayudo a resolver el problema


----------



## tomvg100 (Feb 25, 2012)

hola saludos me podrias ayudar con un programa de interrupcion externa en el pic 18f4550 el programa lo quisiera en CSS Compiler.???
quiero hacer un contador del 0 al 99. quiero que se active un numero ala ves por cada interrupcion.(si le doy un pulso a la interrupcion, que se active un "1" en un display, si doy otro pulso, que se active el siguiente numero "2" y asi susesivamente hasta al 99)

si pudieras aportarme algun ejemplo por lo menos del 1 al cinco...graxiaz

hola saludos alguien me puede ayudar con un programa de interrupcion externa en el pic 18f4550 el programa lo quisiera en CSS Compiler.???
quiero hacer un contador del 0 al 99. quiero que se active un numero ala ves por cada interrupcion.(si le doy un pulso a la interrupcion, que se active un "1" en un display, si doy otro pulso, que se active el siguiente numero "2" y asi susesivamente hasta al 99)

si pudieras aportarme algun ejemplo por lo menos del 1 al cinco...graxiaz


----------



## Mikepower (Abr 10, 2012)

Buen día compañeros
estoy haciendo un programa para un pic12f629 que me de unas secuencias de encendido de leds y que al presionar un push button cambia inmediatamente a la siguiente secuencia, hasta ahora ya puedo hacer que cambie de una a otra pero no lo hace inmediatamente cuando pulso el push, alguien me podria sugerir que debo cambiar en siguiente programa
#include <12F629.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOBROWNOUT               //No brownout reset

#use delay(int=4000000)

#USE FAST_IO (A)
void main()
{
   SET_TRIS_A(0x01);
   while(TRUE)
   {
   int8 menu;
   if(input(PIN_A0)==0)
         {            //controla el boton up...
         delay_ms(50);
         if(input(PIN_A0)==0)
         menu++;
         if(menu>3)
         {
         menu=0; 
         } 
         } 
   switch(menu){
   case 0: output_low(PIN_A1);
           output_low(PIN_A2);
           output_low(PIN_A4);
           output_low(PIN_A5);
           break;
   case 1: output_high(PIN_A1);
           output_high(PIN_A2);
           output_high(PIN_A4);
           output_high(PIN_A5);
           delay_ms(90);
           output_low(PIN_A1);
           output_low(PIN_A2);
           delay_ms(30);
           output_low(PIN_A4);
           output_low(PIN_A5);
           delay_ms(1000);
           break;
   case 2: output_high(PIN_A1);
           output_high(PIN_A2);
           delay_ms(90);
           output_low(PIN_A1);
           output_low(PIN_A2);
           delay_ms(90);
           output_high(PIN_A1);
           output_high(PIN_A2);
           delay_ms(90);
           output_low(PIN_A1);
           output_low(PIN_A2);
           delay_ms(600);
           output_high(PIN_A4);
           output_high(PIN_A5);
           delay_ms(90);
           output_low(PIN_A4);
           output_low(PIN_A5);
           delay_ms(90);
           output_high(PIN_A4);
           output_high(PIN_A5);
           delay_ms(90);
           output_low(PIN_A4);
           output_low(PIN_A5);
           delay_ms(600);
           break;
   case 3: output_high(PIN_A1);
           output_high(PIN_A5);
           delay_ms(100);
           output_low(PIN_A1);
           output_low(PIN_A5);
           delay_ms(100);
           output_high(PIN_A2);
           output_high(PIN_A4);
           delay_ms(100);
           output_low(PIN_A2);
           output_low(PIN_A4);
           delay_ms(600);
           break;
   }

   }

}


----------

