Autor Tema: Problema con interrupciones en PIC16F877A  (Leído 1285 veces)

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

Desconectado Georgev96

  • PIC10
  • *
  • Mensajes: 4
Problema con interrupciones en PIC16F877A
« en: 14 de Noviembre de 2016, 13:43:10 »

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;
      }   
                        
   }