Autor Tema: Problema con interrupciones Timer0  (Leído 3800 veces)

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

Desconectado Georgev96

  • PIC10
  • *
  • Mensajes: 4
Problema con interrupciones Timer0
« en: 14 de Noviembre de 2016, 13:46:34 »
Buenas tardes, estoy aprendiendo a programar para el PIC16F877A, el otro dia me plantearon un ejercicio que consiste en:


Para este ejercicio se pide mostrar el tiempo en segundos transcurrido entre dos
pulsaciones de la tecla S2 en los displays 1 y 2. El funcionamiento será el siguiente:
- Al inicio de la ejecución, todos los displays estarán apagados.
- La medida comenzará cuando, tras presionarla, se suelte la tecla S2.
- La cuenta permanecerá activa hasta que se vuelva a presionar S2: en este momento se
mostrarán los segundos transcurridos (unidades en display1 y decenas en display2).
- El dato de la cuenta permanecerá en los displays hasta que se vuelva a presionar S2: al
producirse este evento, los displays se desactivarán y comenzará de nuevo el proceso.
- La cuenta máxima será de 20 segundos; si se supera, el dato aparecerá en los displays
hasta que se vuelva a presionar S2.
Se recomienda usar un temporizador para el refresco y otro para el tiempo entre pulsaciones.
Tras las pulsaciones de S2 hay que esperar 20ms para evitar los rebotes.


Y yo he realizado mi programa en C para resolver este ejercicio, pero tengo un problema con la interruciones, cada vez que ejecuto el programa en la tarjeta Microchip, el timer0 se esta desbordando todo el rato sin que lo inicialice, os paso mi programa en C a ver si me encontrais el error.


//Código de partida para los ejercicios propuestos en la Sesión 03

#include<htc.h> //Incluimos librería del micro a usar

__CONFIG(WRT_OFF & WDTE_OFF & PWRTE_OFF & FOSC_XT & LVP_OFF);

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//WRT_OFF = Codigo no Potegido
//WDTE_OFF = Watch Dog Timer Desactivado
//PWRTE_OFF = Power Activado
//FOSC_XT = Osiclador cristal
//LVP_OFF = Low Voltage Porgramming Desactivado
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
   
#define _XTAL_FREQ 4000000             //Oscilador Interno de 4MHZ   
unsigned char temp1=0;
unsigned char marcha=0;
unsigned char comienzo=0;
unsigned char contador=2;
unsigned char unidades=0;
unsigned char decenas=0;

   void pulsador (void)      //Funcion pulsador
   {
   if (RA4==0)               //Si S2 esta pulsado se ejecuta el ciclo
         {   
            __delay_ms(25);         //Delay para evitar los rebotes del pulsador S2
            marcha^=1;            //XOR con uno para cambiar el valor de la variable "marcha" de 0 a 1 y viceversa, con esta variable lo que hacemos es que cuando este en el valor 0 el contador no funcione y cuanto tenga el valor 1 funcione.
            comienzo|=1;         //OR con uno para cambiar el valor inicial de la variable "comienzo" (0) a 1 y luego que se quede siempre en 1
            if (marcha==1)         //Si la variable marcha tiene el valor 1 es que queremos que comience el contador de segundos y por lo tanto tenemos que poner las decenas y las unidades a 0
            {
            decenas=0;
            unidades=0;
            RA0=1;
            RA1=0;
            }
         while (RA4==0)            //Mientras tengamos mantenido el S2 el programa se quedara ejecutando este ciclo, al soltar el S2 comenzara el contador
            {
            }
         }
   return;
   }
   
void main()
{
   // Tabla con el código 7segmentos complementado
   unsigned char codigo[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x98};
   
   //INICIALIZACIONES PARA EL PIC
   ADCON1=0b00000110;               //Desactivamos PORTA como entrada analógica
   TRISA=0b11111000;                     //Terminal RA0,RA1,RA2,RA3 como terminal de salida, RA4 como entrada
   TRISD=0x00;                     //Todos los terminales del PuertoD como salida                     
   OPTION_REG=0b00000111;            //Configuramos el timer0
   T1CON=0b00110000;               //Configuramos el timer1
   INTCON=0b00110000;
   TMR1IE=1;
                              //Configuración Temporizadores
   // Código del programa principal
   
   while(1)                     //Bluque infinito
   {   
      pulsador();   
      while(marcha==1)         //Mientras la variable marcha este a 1, el contador de segundos funcionará
      {   
            pulsador();
            if (temp1=0)
            {
            TMR1=0;               //Configuramos el TMR1
               TMR1ON=1;            //Iniciamos el Timer1
            temp1=1;            //Ponemos la variable temp1 a 1 para que no se este activando el timer1 todo el rato
            }
            TMR0=235;         //Iniciamos el Timer0 programado para que salte a la rutina de interrupciones cada 0.5ma
            while(RA0==1)      //Mostramos en cada diaplay su numero correspondiente y vamos encendiendolos alternadamente cada 5ms   
            {
            PORTD=codigo[unidades];
            }
            pulsador();
            TMR0=235;
            while(RA1==1)
            {
            PORTD=codigo[decenas];
            }   
      }
      while ((marcha==0) && (comienzo!=0))   //Cuando paremos el contador de segundos, se mostrara en los dos displays los segundo que han corrido desde una pulsacion a otra
      {     
            pulsador();                       
            TMR0=235;
            while(RA0==1)         
            {
            PORTD=codigo[unidades];
            }
            pulsador();
            TMR0=235;
            while(RA1==1)
            {
            PORTD=codigo[decenas];
            }
      }         
   }
}

   static void interrupt isr(void)         //Rutina o funcion de interrupciones
   {   
      if (TMR1IF==1)                  //Con este if comprobamos cual de los dos timer se ha desbordado, si se ha desbordado el timer1 se ejecutará este if, si se ha desbordado el timer0 el programa ira al else de despues.
      {
         temp1=0;                  //Ponemos la variable temp1 a 0 para que cuando se ejecute el programa principal se vuelva a inciar el timer1
         TMR1IF==0;                  //Ponemos el flag del Timer1 a 0
         contador=contador-1;         //Decrementamos contador en uno
         if (contador==0)            //Si contador es igual a 0, es decir, que se ha pasado un sg
         {
         contador=2;                  //Volvemos a inicializar la variable contador a 2
         unidades=unidades+1;         //Sumamos uno a el numero "unidades"
            if (decenas==2)            //Con estos if comprobamos casos especiales.
            {
            decenas=2;
            unidades=0;
            }
            if ((unidades==10) && (decenas==0))
            {
            decenas=1;
            unidades=0;
            }
            if ((unidades==10) && (decenas==1))
            {
            decenas=2;
            unidades=0;
            }
         }
      }
      if (T0IF=1)                        //Para que se ejecute este else tiene que ser el timer0 el que se ha desbordado, eso significa que un display ya ha estado encendido 5ms
      {                           //por lo tanto ponemos el flag del Timer0 a 0 y alternamos el encendido de los displays
      T0IF=0;
      RA0^=1;
      RA1^=1;
      }   
                       
   }

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con interrupciones Timer0
« Respuesta #1 en: 15 de Noviembre de 2016, 10:07:07 »
Citar
Y yo he realizado mi programa en C para resolver este ejercicio, pero tengo un problema con la interruciones, cada vez que ejecuto el programa en la tarjeta Microchip, el timer0 se esta desbordando todo el rato sin que lo inicialice, os paso mi programa en C a ver si me encontrais el error.

Es por que el TMR0 no se detiene. No es como el TMR1 en el cual podes habilitar la cuenta o deshabilitarla. El TMR0 siempre esta contando. Veo que lo cargas con 235, lo cual al hacer 20 cuentas ya estaria ocurriendo su interrupcion.

Un error que encuentro es que estas habilitando la interrupcion externa, la cual no veo codigo.

   INTCON=0b00110000;

De todas formas no deberia entrar a la interrupcion ya que el bit GIE se encuentra en 0.

¿Estas seguro que el problema es la interrupcion y no el programa?

Desconectado Georgev96

  • PIC10
  • *
  • Mensajes: 4
Re:Problema con interrupciones Timer0
« Respuesta #2 en: 15 de Noviembre de 2016, 12:45:11 »
Perdón, subí mal el programa ayer, el INTCON lo tengo puesto asi: 0b11100000 (Para activar la GIE y las interrupciones del timer0)

De todas formas primero gracias por contestarme, el problema en el programa es que lo paso a la tarjeta de microchip (P16F877A) y al ejecutarlo sin que yo pulse ningún botón (Como el S2=RA4) salta a la interrupción del timer0 todo el rato (modo bucle).

El programa esta hecho para que al pasarlo a la tarjeta, antes de que pulse el boton RA4 no haga nada, luego al pulsar el boton RA4 pone la variable marcha a 1 y es cuando entran en juego los timers y las interrupciones.

Algo tiene que estar mal en el programa para que sin iniciar en ningún momento ninguno de los timer, salte a las interrupciones. ¿Puede haber algún otro motivo que haga al programa saltar a la dirección de las interrupciones?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con interrupciones Timer0
« Respuesta #3 en: 15 de Noviembre de 2016, 15:36:55 »
Exacto, vos estas haciendo esto:

Citar
Perdón, subí mal el programa ayer, el INTCON lo tengo puesto asi: 0b11100000 (Para activar la GIE y las interrupciones del timer0)

Eso lo haces antes de que pulses algun boton, entonces el TMR0 sigue contando (siempre esta contando), y al pasar de 255 a 0 se produce la interrupcion. Tal ves lo que vos buscas es activar la interrupcion global luego de detectar el boton R4 y finalmente desactivarla cuando llega a 20 la cuenta o lo que sea del Timer0 o cuando se presione de nuevo R4, ahora si tu idea es bloquear la interrupcion del Timer0 solo, desactiva nomas el TMR0IE y no la GIE.

Desconectado Georgev96

  • PIC10
  • *
  • Mensajes: 4
Re:Problema con interrupciones Timer0
« Respuesta #4 en: 15 de Noviembre de 2016, 16:26:43 »
Vale vale, capto la idea.
No sabia que el timer0 siempre estaba contado, pensaba que solo contaba cuando tu le pasabas un valor al TMR0, entonces lo que puedo hacer es activar las interrupciones del timer0 en el momento que vaya a utilizarlo. Gracias por las respuestas.

Desconectado trucksbear

  • PIC10
  • *
  • Mensajes: 10
Re:Problema con interrupciones Timer0
« Respuesta #5 en: 14 de Diciembre de 2016, 04:08:31 »
Hola, estuve leyendo bastante sobre el tema de utilizar el Timerdel pic, sea el 0,1,2 etc
pero no entendí bien como hacer la comparación, en el caos de que yo quiera medir lapsos de 70uS, por ejemplo, se que con set_timer0,1,2(X); siendo x cualqueir valor de 0 a 255 le cargo un valor al timer y que con get_timer0,1,2(); obtengo el valor del timer
yo en este caso necesitaría hacer algo así
tiempo_timer = get_timer();
if (tiempo_timer == 70uS){printf ("El tiempo medido es correcto");}
else{printf ("Recalcular tiempo de comparación")}
gracias


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con interrupciones Timer0
« Respuesta #6 en: 14 de Diciembre de 2016, 14:05:49 »
Hola, estuve leyendo bastante sobre el tema de utilizar el Timerdel pic, sea el 0,1,2 etc
pero no entendí bien como hacer la comparación, en el caos de que yo quiera medir lapsos de 70uS, por ejemplo, se que con set_timer0,1,2(X); siendo x cualqueir valor de 0 a 255 le cargo un valor al timer y que con get_timer0,1,2(); obtengo el valor del timer
yo en este caso necesitaría hacer algo así
tiempo_timer = get_timer();
if (tiempo_timer == 70uS){printf ("El tiempo medido es correcto");}
else{printf ("Recalcular tiempo de comparación")}
gracias

Te sugiero que leas el datasheet del microcontrolador o en su defecto algun tutorial de como es que funciona el/los Timers:
http://www.aquihayapuntes.com/indice-practicas-pic-en-c/uso-del-tmr0-como-temporizador.html

Cada Timer funciona igual pero tienen distintas caracteristicas, ejemplo el TMR0 no puede ser detenido y es de 8bits, el TMR1 suele ser de 16bits y puede ser detenido, el TMR1 tambien puede ser usado para el modulo CCP en caso que lo posea el micro. Algunos disponen de un TMR2 el cual es de 8bits y posee otros preescalers distinto del TMR0, puede ser usado para el CCP segun el PIC. Hay PICs con mas timers. otros que pueden trabajar juntos y formar uno de 16bits entre los 2. Eso va a depender del micro que poseas, por eso lo mejor es leer el datasheet del microcontrolador que estes usando.
« Última modificación: 14 de Diciembre de 2016, 14:08:57 por KILLERJC »


 

anything