Autor Tema: Problema con interrupcion externa y teclado  (Leído 10981 veces)

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

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #45 en: 25 de Marzo de 2013, 15:12:18 »
checa,compilando con las modificaciones que te menciono no hay mas problema

Código: [Seleccionar]
#include<16f876.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay (CLOCK=4000000)
#use fast_io(A)
#use fast_io(B)
#byte port_b = 0x06
#byte tris_b = 0xff

#include <LCD4.c>             //libreria manejo lcd 8 bits
#include <string.h>           //libreria manejo cadenas

#rom 0x2100={0,0,0,0,0,0,0}   //la EEPROM se carga con los valores 00h desde la direccion 00h hasta 06h


////////////////DEFINICION DE FUNCIONES////////////////////////////

void captura(void);                    //funcion que captura la clave tecleada
void cambia_clave_inicial(void);       //funcion que cambia la clave inicial
void escribir_clave(void);             //funcion que escibre la clave tecleada
void nueva_clave_admin(void);          //funcion que añade la nueva clave administrativa
void limpiar_clave(void);              //funcion que pone a '0' la variable clave
void escribir_clave_en_eeprom(int d);  //función que escribe las claves en la memoria eeprom
void menu_principal(void);             //funcion que muestra el menu principal
void cambiar_clave(void);              //funcion que cambia clave admin
void leer_clave_en_eeprom(int);        //función que lee las claves y las guarda en su correspondiente variable
int comparar_claves(int);              //función que compara las claves
void alarma_general(void);             //funcion que enciende la sirena


////////////////VARIABLES GLOBALES///////////////////////////

int flag_teclado=0;                       //flag que señala que una tecla ha sido pulsada
char bandera=0,bandera_rb=0;                           //flag que señala que se ha producido una interrupcion externa
int tecla;                                //variable que recoge la tecla pulsada
int fila,columna;                         //variables que recogen la fila y columna de la tecla pulsada
char clave[3]={};                         //variable usada para recoger la clave tecleada
char clave_inicial[3]= {'1','2','3'};     //variable usada como clave de inicio                         
int d=0;                                  //variable usada para movernos por las posiciones de la memoria
char clave_eeprom_admin[3];               //variable usada para comparar los datos de la eeprom contra los datos ingresados
int lectura_1,lectura_2;                  //variables locales para detectar la tecla pulsada

/***************************************
Rutina de Interrupcion.
- Antirebote.
- Llama a rutina "captura" para saber
  la tecla presionada.
- Activa la bandera "flag_teclado"
  a usar en el main o en otra parte
  del programa.
***************************************/
#INT_RB
void tecla_presionada()
{
   bandera_rb=1;
}


//////////////INTERRUPCION EXTERNA//////////////////
#INT_EXT
void externa(void)
{
   bandera=1;                    //marcamos que se ha producido una interrupcion externa
}


//////////////PROGRAMA PRINCIPAL///////////////////////
void main()
{
   set_tris_b(0b11110001);       //configuro el puerto b
   set_tris_c(0b11111111);       //configuro el puerto c
   enable_interrupts(INT_RB);    //habilito la interrupcion por cambio de nibble alto
   ext_int_edge(H_TO_L);         //habilito la interrupcion externa por cambio de flanco
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);    //habilito las interrupciones
   
   lcd_init();                   //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
   lcd_putc("\fEscribir clave:\n");
   
   while(TRUE)
   {
  menu_principal();
      if(flag_teclado==1)           //Si se ha pulsado una tecla
      {
         flag_teclado=0;
         cambia_clave_inicial();    //cambio la contraseña que viene por defecto
      }
  if(bandera_rb==1)
  {
   bandera_rb=0;
     lectura_1 = port_b & 0b11110000;          //lee portb4:7 y lo guarda en lectura_1
   delay_ms(10);                             //Funcion AntiRebotes: Espero 10ms.
   lectura_2 = port_b & 0b11110000;          //Vuelvo a leer el puerto.
   if(lectura_1==lectura_2 && lectura_1!=0)  //Si el valor es igual y distinto de 0 es porque en realidad se presiono una tecla.
   {                                   
     flag_teclado=1;                         //marcamos que se ha pulsado una tecla
     captura();                              //capturamos dicha tecla
   }
   set_tris_b(0b11110000);
   output_b(0b00001111);
   clear_interrupt(INT_RB);
   set_tris_b(0b11110001);
  }
      if(bandera==1)                //Si se ha producido una interrupcion externa
      {
         bandera=0;
         alarma_general();          //activo la sirena
      }
   }
}   


/********************************
Esta Rutina permite rastrear el teclado
y devuelve el valor de la tecla que se
ha presionado
************************************/
void captura(void)               //funcion que captura la clave tecleada
{
int const teclado[4][4] = {{0,'1','2','3'},
                           {0,'4','5','6'},
                           {0,'7','8','9'},
                           {0,'*','0','#'}};
int lectura,i;
for(i=0;i<4;i++)
{
output_b(0);
bit_set(port_b,i);
lectura = port_b & 0b11110000;
switch(lectura)
{
case 0b00010000: fila=0;
 columna=i;
 break;
case 0b00100000: fila=1;
 columna=i;
 break;
case 0b01000000: fila=2;
 columna=i;
 break;
case 0b10000000: fila=3;
 columna=i;
 break;
}
}
tecla = teclado[fila][columna];
}


//////////FUNCION CAMBIAR CLAVE INICIAL
void cambia_clave_inicial(void)              //funcion que cambia la clave inicial
{
int p;
   
   escribir_clave();                         //tecleo la contraseña
   if (d==3)                                 //Si ya se han introducido todos los valores de la clave
   {
      p=strncmp(clave , clave_inicial,3);    //comparo la clave por defecto con la tecleada
      if (p==0)                              //si las dos claves son iguales:
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          nueva_clave_admin();               //introduzco la nueva clave
         }
      if (p!=0)                              //si las dos claves son distintas
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          alarma_general ();                 //activo la alarma
         }
   }
   
}

//////////FUNCION ESCRIBIR CLAVE
void escribir_clave()            //funcion que escibre la clave tecleada
{
   lcd_putc("*");
   clave[d]=tecla;
      if(d<3)                    //Si no se han introducido todos los valores...
      {
         d++;                    //... incremento una posicion de memoria
      }
      else                       //Si se han introducido todos los valores...
      {
         d=0;                    //... salgo
      }
}


//////////LIMPIAR CLAVE
void limpiar_clave()     //función que pone a '0' la variable clave
{
int k;
   for(k=0;k<3;k++)      //limpiamos uno a uno cada valor de la variable
     {
        clave[k]=0x00;
     }
}


/////FUNCION MENU PRINCIPAL   
void menu_principal (void)             //funcion que muestra el menu principal

{
tecla=0;
d=0;
     lcd_putc("\f0-Activa Alarma\n1-Cambia Clave");
     delay_ms(2000);
     while(tecla==0 && bandera==0);
     {
         switch (tecla)
         {
         case '0':         //si '0' va a activar la alarma
            //activar_alarma();
            alarma_general();
         break;
         case '1':         //si '1' va a comprobar clave para despues cambiar la clave
            cambiar_clave();
         break;
         }
     }
}


//////////FUNCION CAMBIAR CLAVE
void cambiar_clave(void)             //funcion que cambia clave administrativa

{
int p;
   escribir_clave();  //escribimos la contraseña
   if (d==3)                                 //Si ya se han introducido todos los valores de la clave
   {
      leer_clave_en_eeprom(d);            //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);               //compara ambas claves
      if (p==0)                           //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          nueva_clave_admin();         //vamos a la rutina para introducir la nueva clave
         }
      if (p!=0)                           //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          alarma_general ();           //activa la alarma
         }
   }
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)          //funcion que añade la nueva clave administrativa
{
tecla=0;                          //limpio las variables
int aux=0;
d=0;

   lcd_putc("\fNueva clave:\n");   //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
      while(tecla==0 && bandera==0);
      {
         flag_teclado=0;
         lcd_putc("*");
         clave[d]=tecla;
         if(d<3)
         {
            escribir_clave_en_eeprom(d);   //guardamos la nueva clave en la memoria EEPROM
            tecla=0;
            d++;
         }
         else
         {
            d=0;
            break;
         }
      }   
   }
   //menu_principal();          //voy al menu principal
}


//////////FUNCION COMPARAR CLAVES
int comparar_claves(int)                  //funcion que compara la clave administrativa y la introducida

{
   d=0;
   int s=0;
   for (d=0;d<3;d++)    //comparo caracter a caracter las claves
   {
      if (clave[d]==clave_eeprom_admin[d])   //si el caracter es igual en las dos claves
        s++;                                             //paso al siguiente caracter
      else                                               //si es distinto la contraseña es incorrecta
        {s=0;
         lcd_putc("\fClave Incorrecta\n");
         break;
        }
   }
   if (s==3)                           //si todos los tres caracteres son iguales
      return 0;                        //devuelvo un '0'
}


//////////ESCRIBIR_CLAVE_EN_EEPROM
void escribir_clave_en_eeprom(int d)     //función que escribe las claves en la memoria eeprom
{
   write_eeprom (d,tecla);               //guardamos cada valor de la variable global correspondiente
   delay_ms(20);                         //en la direccion d + 0 (para no pisar datos) de la eeprom
   d++;                                  //en una palabra escribe de la posicion 0 a la 2 (3 lugares)
}


//////////LEER_CLAVE_EN_EEPROM
void leer_clave_en_eeprom(int d)       //función que lee las claves y las guarda en su correspondiente variable

{
    for (d=0;d<3;d++)
    {
      clave_eeprom_admin[d] = read_eeprom(d);      //guardamos cada valor de la direccion i + 0 (para no pisar datos)
      delay_ms(20);                                //de la eeprom en la variable global correspondiente
    }
}


//////////FUNCION ALARMA GENERAL
void alarma_general (void)       //funcion que enciende la sirena
{
    set_tris_c(0b11111110);      //pin C0 como salida                             
    output_high(pin_C0);         //enciende la sirena durante 2 seg y muestra mensaje
    //lcd_putc("\fALARMA\n");         
    delay_ms(2000);
    output_low(pin_C0);          //apaga la sirena
    //alarm_cont = 0;            //pongo a cero el contador de errores
    break;
}


solo comente la linea de la llamada a menu_principal() que es la que causa el error y la coloque al inicio del while,pero como mencione puedes cambiarla segun tus necesidades

saludos
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #46 en: 26 de Marzo de 2013, 08:18:26 »
Hola thegame! Probé tu código y no me funciona. Se queda en el mensaje del menu principal y de ahí no se mueve. Detecta que se pulsan las teclas y la interrupción externa pero no hace nada.
 
Lo que quiero hacer es que siempre que acabe de introducir la nueva clave (la que guardo en eeprom) vaya despues al menú principal, por eso había puesto al final de nueva_clave_admin la llamada al menú. Consigo llegar al menú con el código que postee ayer y que detecte la tecla pulsada (sé que le detecta porque he hecho que parpadee el led cuando la detecte). El problema viene porque en la función cambiar_clave (función que utilizo para cambiar la clave guardada en la eeprom) llamo a nueva_clave_admin() para introducir la nueva clave que nos apetezca. Pero esa llamada es la que da el error. La solución creo que está en quitar dicha llamada y enganchar de alguna manera ambas funciones. He probado el poner la función del menú despues de la de cambiar_clave_inicial que hay en el main pero no funciona o no lo hago de la manera correcta. También he probado el poner ambas funciones despues de comprobar ambas banderas y tampoco. Otra cosa que he probado ha sido el quitar cambiar_clave_inicial del main y sustituirlo por escribir_calve() únicamente y gestionar fuera de la lectura de las banderas el cambiar la clave inicial, el menú y todo y tampoco me ha funcionado o no he sabido hacerlo correctamente.

Solucionar este problema y conseguir comparar la clave tecleada con la que tenemos en la eeprom creo que son los dos grandes obstáculos que me quedan y seguire luchando por conseguir sacar adelante este proyecto
« Última modificación: 26 de Marzo de 2013, 08:39:12 por escarrillense »

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #47 en: 26 de Marzo de 2013, 13:06:55 »
hola compañero,mmm ok, haré algunas pruebas mas y te cuento,ya casi esta solo son detalles que se están escapando
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #48 en: 27 de Marzo de 2013, 08:47:00 »
Hola the game! Yo también continuo haciendo pruebas pero sigo sin conseguir el resultado que yo quiero. El error consigo que se vaya si elimino la llamada a la función nueva_clave_admin que hay en cambiar_clave() y lo sustituyo por otra cosa pero ya no consigo hacer lo que deseo.

Informaré de como van mis resultados. Un saludo

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #49 en: 28 de Marzo de 2013, 15:55:27 »
que pasa amigo escarrilense,has logrado algo mas?? yo no he tenido chance por el trabajo pero ya se viene el puente de semana santa (a bendito dios  :-/) y me pondre a checar y hacer algunas pruebas

saludos
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #50 en: 01 de Abril de 2013, 05:21:13 »
Hola compañero! Pues no hay avances, además tampoco he tenido tiempo de hacer mucho y el puente he estado fuera (que necesitaba un poco de descanso) así que a ver si esta semana le doy un buen empujon y saco esto a delante

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #51 en: 01 de Abril de 2013, 14:44:56 »
hola,si este puente ha venido bien para descansar un poco,yo he tenido algo de trabajo y tampoco he podido checar esos detallitos que aun estan,pero seguimos en la batalla jeje
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #52 en: 02 de Abril de 2013, 08:10:06 »
Hola! He solucionado lo de la recursion de una manera un poco chapucera pero ya no me da error. He creado una función igual que la llamada nueva_clave_admin pero con el nombre cambio_clave_admin. Ya se que no es la mejor solución pero de momento nos evitamos el error.

Ahora consigo entrar en la función cambiar_clave del menú principal pero al escribir la clave para luego compararla con la que tenemos en la eeprom el primer dato que tecleo se me escribe dos veces y no se por qué. Copio los cambios realizados en el código por si me podeis echar una mano. El resto sigue como en anteriores post

Código: [Seleccionar]
/////FUNCION MENU PRINCIPAL   
void menu_principal (void)             //funcion que muestra el menu principal

{
tecla=0;
d=0;
     lcd_putc("\f0-Activa Alarma\n1-Cambia Clave");
     delay_ms(2000);
     while(tecla==0 && bandera==0);
     {
         switch (tecla)
         {
         case '0':         //si '0' va a activar la alarma
            //activar_alarma();
            alarma_general();
         break;
         case '1':         //si '1' va a comprobar clave para despues cambiar la clave
           
            cambiar_clave();
           
         break;
         }
     }
}


//////////FUNCION CAMBIAR CLAVE
void cambiar_clave(void)             //funcion que cambia clave administrativa

{
int p;
tecla=0;
d=0;

   lcd_putc("\fEscribir clave:\n");
   limpiar_clave();                          //pongo a '0' la variable clave
    while(tecla==0 && bandera==0);
    {
   escribir_clave();                         //escribimos la contraseña
   if (d==3)                                 //Si ya se han introducido todos los valores de la clave
   {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          cambio_clave_admin();             //vamos a la rutina para introducir la nueva clave
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          alarma_general ();                 //activa la alarma
         }
   }
    }
}


//////////FUNCION CAMBIO CLAVE ADMIN
void cambio_clave_admin(void)           //funcion que añade la nueva clave administrativa
{
tecla=0;                               //limpio las variables
int aux=0;
d=0;

   lcd_putc("\fNueva clave:\n");       //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
      while(tecla==0 && bandera==0);
      {
         flag_teclado=0;
         lcd_putc("*");
         clave[d]=tecla;
         if(d<3)
         {
            escribir_clave_en_eeprom(d);   //guardamos la nueva clave en la memoria EEPROM
            tecla=0;
            d++;
         }
         else
         {
            d=0;
            break;
         }
      }   
   }
 
}

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #53 en: 03 de Abril de 2013, 15:15:24 »
Hola! Esto parece que marcha! Solucionados los problemas que postee ayer. He conseguido ir desde el menu principal a las distintas funciones, que coja las teclas correctamente como su posterior comparación con la de la eeprom y la grabación en la eeprom de una nueva clave en el caso que deseemos cambiar la que tenemos.

Pero como este proyecto no está siendo un camino de rosas me ha aparecido un inconveniente que ya me ha dado problemas anteriormente y es el de la recursión. Una vez acabada la función cambio_clave_admin y en el caso de que desactivemos la alarma me gustaría volver al menú principal pero aparece dicho problema. Cuando se acaba la alarma (parpadeo del led) querría ir a la función cambiar_clave y tambien me da ese error. Copio la parte nueva de código por si me podeis echar una mano ya que el resto sigue igual. He marcado los puntos donde me aparece el error de la recursión comentando esa línea con la palabra ERROR.

El siguiente paso que quiero hacer es añadir un contador de errores, es decir, tener tres intentos para introducir la clave o si no que se active la alarma y no como ahora que al primer error ya saltaba. Lo que no se es como hacerlo para que despues de los dos primeros intentos vuelva al principio de la función en la que estoy. Me pongo con ambas cosas a ver si las consigo sacar.

Muchas gracias por vuestra ayuda y un saludo muy fuerte

Código: [Seleccionar]
//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)           //funcion que añade la nueva clave administrativa
{
tecla=0;                               //limpio las variables
int aux=0;
d=0;

   lcd_putc("\fNueva clave:\n");       //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
      while(tecla==0 && bandera==0);
      {
         flag_teclado=0;
         lcd_putc("*");
         clave[d]=tecla;
         if(d<3)
         {
            escribir_clave_en_eeprom(d);   //guardamos la nueva clave en la memoria EEPROM
            tecla=0;
            d++;
         }
         else
         {
            d=0;
            limpiar_clave();
            break;
         }
      }   
   }
   menu_principal();          //voy al menu principal
}



/////FUNCION MENU PRINCIPAL   
void menu_principal (void)             //funcion que muestra el menu principal

{
tecla=0;
d=0;
     lcd_putc("\f0-Activa Alarma\n1-Cambia Clave");
     delay_ms(2000);
     while(tecla==0 && bandera==0);
     {
         switch (tecla)
         {
         case '0':         //si '0' va a activar la alarma
            activar_alarma();
         break;
         case '1':         //si '1' va a comprobar clave para despues cambiar la clave
            cambiar_clave();
         break;
         }
     }
}


//////////FUNCION CAMBIAR CLAVE
void cambiar_clave(void)             //funcion que cambia clave administrativa
{
int p;
tecla=0;
d=0;
int aux=0;
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                         
   while(tecla==0 && bandera==0);
   {
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          cambio_clave_admin();              //vamos a la rutina para introducir la nueva clave
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          alarma_general ();                 //activa la alarma
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////FUNCION COMPARAR CLAVES
int comparar_claves(int)                  //funcion que compara la clave administrativa y la introducida

{
d=0;
int s=0;
   for (d=0;d<3;d++)    //comparo caracter a caracter las claves
   {
      if (clave[d]==clave_eeprom_admin[d])   //si el caracter es igual en las dos claves
         s++;                                             //paso al siguiente caracter
      else                                               //si es distinto la contraseña es incorrecta
        {s=0;
         lcd_putc("\fClave Incorrecta\n");
         break;
        }
   }
   if (s==3)                           //si todos los tres caracteres son iguales
      return 0;                        //devuelvo un '0'
}


//////////FUNCION CAMBIO CLAVE ADMIN
void cambio_clave_admin(void)           //funcion que añade la nueva clave administrativa
{
tecla=0;                               //limpio las variables
int aux=0;
d=0;

   lcd_putc("\fNueva clave:\n");       //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
      while(tecla==0 && bandera==0);
      {
         flag_teclado=0;
         lcd_putc("*");
         clave[d]=tecla;
         if(d<3)
         {
            escribir_clave_en_eeprom(d);   //guardamos la nueva clave en la memoria EEPROM
            tecla=0;
            d++;
         }
         else
         {
            d=0;
            break;
         }
      }   
   }
   //menu_principal();          //ERROR
}


//////////ACTIVAR ALARMA
void activar_alarma(void)           //funcion que activa la alarma
{
int p;
tecla=0;
d=0;
int aux=0;
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                         
   while(tecla==0 && bandera==0);
   {
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma Activada\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          desactivar_alarma();            //vamos a la rutina para desactivar la alarma
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          alarma_general ();                 //activa la alarma
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////DESACTIVAR ALARMA
void desactivar_alarma(void)           //funcion que desactiva la alarma
{
int p;
tecla=0;
d=0;
int aux=0;
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                         
   while(tecla==0 && bandera==0);
   {
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma\nDesactivada");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          break;
          //menu_principal();          //ERROR
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fALARMA\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          alarma_general ();                 //activa la alarma
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////ESCRIBIR_CLAVE_EN_EEPROM
void escribir_clave_en_eeprom(int d)     //función que escribe las claves en la memoria eeprom
{
   write_eeprom (d,tecla);               //guardamos cada valor de la variable global correspondiente
   delay_ms(20);                         //en la direccion d + 0 (para no pisar datos) de la eeprom
   d++;                                  //en una palabra escribe de la posicion 0 a la 2 (3 lugares)
}


//////////LEER_CLAVE_EN_EEPROM
void leer_clave_en_eeprom(int d)       //función que lee las claves y las guarda en su correspondiente variable

{
    for (d=0;d<3;d++)
    {
      clave_eeprom_admin[d] = read_eeprom(d);      //guardamos cada valor de la direccion i + 0 (para no pisar datos)
      delay_ms(20);                                //de la eeprom en la variable global correspondiente
    }
}


//////////FUNCION ALARMA GENERAL
void alarma_general (void)       //funcion que enciende la sirena
{
    set_tris_c(0b11111110);      //pin C0 como salida                             
    output_high(pin_C0);         //enciende la sirena durante 2 seg y muestra mensaje         
    delay_ms(2000);
    output_low(pin_C0);          //apaga la sirena
   
    //cambio_clave_admin();   //ERROR
}
« Última modificación: 04 de Abril de 2013, 14:50:41 por escarrillense »

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #54 en: 08 de Abril de 2013, 07:42:40 »
Hola! Sigo con los problemas del contador y la recursion. El problema de la recursión no se como solucionarlo porque no puedo estar continuamente copiando funciones y cambiandoles el nombre, ya que esa solución me parece muy chapucera.

El contador de errores lo tengo hecho y cuando cambio la clave inicial me funciona. El problema me viene cuando lo utilizo en el resto de funciones ya que al salir del contador me lleva al while(true) que tengo en el main y no al punto de escribir de nuevo la funcion.

Copio el código por si me podeis ayudar

Código: [Seleccionar]
#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay (CLOCK=4000000)
#use fast_io(A)
#use fast_io(B)
#byte port_b = 0x06
#byte tris_b = 0xff

#include <LCD4.c>             //libreria manejo lcd 8 bits
#include <string.h>           //libreria manejo cadenas

#rom 0x2100={0,0,0,0,0,0,0}   //la EEPROM se carga con los valores 00h desde la direccion 00h hasta 06h


////////////////DEFINICION DE FUNCIONES////////////////////////////

void captura(void);                    //funcion que captura la clave tecleada
void cambia_clave_inicial(void);       //funcion que cambia la clave inicial
void escribir_clave(void);             //funcion que escibre la clave tecleada
void nueva_clave_admin(void);          //funcion que añade la nueva clave administrativa
void limpiar_clave(void);              //funcion que pone a '0' la variable clave
void escribir_clave_en_eeprom(int d);  //función que escribe las claves en la memoria eeprom
void menu_principal(void);             //funcion que muestra el menu principal
void cambiar_clave(void);              //funcion que cambia clave admin
int comparar_claves(int);              //función que compara las claves
void cambio_clave_admin(void);         //funcion que añade la nueva clave administrativa
void activar_alarma(void);             //funcion que activa la alarma
void desactivar_alarma(void);          //funcion que desactiva la alarma
void leer_clave_en_eeprom(int);        //función que lee las claves y las guarda en su correspondiente variable
void conteo_intentos(void);            //funcion que cuenta el numero de intentos de ingreso de contraseña
void alarma_general(void);             //funcion que enciende la sirena


////////////////VARIABLES GLOBALES///////////////////////////

int flag_teclado=0;                       //flag que señala que una tecla ha sido pulsada
char bandera=0;                           //flag que señala que se ha producido una interrupcion externa
int tecla;                                //variable que recoge la tecla pulsada
int fila,columna;                         //variables que recogen la fila y columna de la tecla pulsada
char clave[3]={};                         //variable usada para recoger la clave tecleada
char clave_inicial[3]= {'1','2','3'};     //variable usada como clave de inicio                         
int d=0;                                  //variable usada para movernos por las posiciones de la memoria
char clave_eeprom_admin[3];               //variable usada para comparar los datos de la eeprom contra los datos ingresados
int alarm_cont=0;                         //variable global que cuenta los fallos


/***************************************
Rutina de Interrupcion.
- Antirebote.
- Llama a rutina "captura" para saber
  la tecla presionada.
- Activa la bandera "flag_teclado"
  a usar en el main o en otra parte
  del programa.
***************************************/
#INT_RB
void tecla_presionada()
{
   int lectura_1,lectura_2;                  //variables locales para detectar la tecla pulsada
   lectura_1 = port_b & 0b11110000;          //lee portb4:7 y lo guarda en lectura_1
   delay_ms(10);                             //Funcion AntiRebotes: Espero 10ms.
   lectura_2 = port_b & 0b11110000;          //Vuelvo a leer el puerto.
   if(lectura_1==lectura_2 && lectura_1!=0)  //Si el valor es igual y distinto de 0 es porque en realidad se presiono una tecla.
   {                                   
     flag_teclado=1;                         //marcamos que se ha pulsado una tecla
     captura();                              //capturamos dicha tecla
   }
   set_tris_b(0b11110000);
   output_b(0b00001111);
   clear_interrupt(INT_RB);
   set_tris_b(0b11110001);
}


//////////////INTERRUPCION EXTERNA//////////////////
#INT_EXT
void externa(void)
{
   bandera=1;                    //marcamos que se ha producido una interrupcion externa
}


//////////////PROGRAMA PRINCIPAL///////////////////////
void main()
{
   set_tris_b(0b11110001);       //configuro el puerto b
   set_tris_c(0b11111111);       //configuro el puerto c
   enable_interrupts(INT_RB);    //habilito la interrupcion por cambio de nibble alto
   ext_int_edge(H_TO_L);         //habilito la interrupcion externa por cambio de flanco
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);    //habilito las interrupciones
   
   lcd_init();                   //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
   lcd_putc("\fEscribir clave:\n");
   
   while(TRUE)
   {
      if(flag_teclado==1)           //Si se ha pulsado una tecla
      {
         flag_teclado=0;
         cambia_clave_inicial();    //cambio la contraseña que viene por defecto
      }
      if(bandera==1)                //Si se ha producido una interrupcion externa
      {
         bandera=0;
         alarma_general();          //activo la sirena
      }
   }
}   


/*********************************
Esta Rutina permite rastrear el teclado
y devuelve el valor de la tecla que se
ha presionado
************************************/
void captura(void)               //funcion que captura la clave tecleada
{
int const teclado[4][4] = {{0,'1','2','3'},
                           {0,'4','5','6'},
                           {0,'7','8','9'},
                           {0,'*','0','#'}};
int lectura,i;
for(i=0;i<4;i++)
{
output_b(0);
bit_set(port_b,i);
lectura = port_b & 0b11110000;
switch(lectura)
{
case 0b00010000: fila=0;
 columna=i;
 break;
case 0b00100000: fila=1;
 columna=i;
 break;
case 0b01000000: fila=2;
 columna=i;
 break;
case 0b10000000: fila=3;
 columna=i;
 break;
}
}
tecla = teclado[fila][columna];
}


/////////FUNCION CAMBIAR CLAVE INICIAL
void cambia_clave_inicial(void)              //funcion que cambia la clave inicial
{
int p;
   
   escribir_clave();                         //tecleo la contraseña
   if (d==3)                                 //Si ya se han introducido todos los valores de la clave
   {
      p=strncmp(clave , clave_inicial,3);    //comparo la clave por defecto con la tecleada
      if (p==0)                              //si las dos claves son iguales:
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          nueva_clave_admin();               //introduzco la nueva clave
         }
      if (p!=0)                              //si las dos claves son distintas
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
   }
   
}

//////////FUNCION ESCRIBIR CLAVE
void escribir_clave()            //funcion que escibre la clave tecleada
{
   flag_teclado=0;
   lcd_putc("*");
   clave[d]=tecla;
      if(d<3)                    //Si no se han introducido todos los valores...
      {
         d++;                    //... incremento una posicion de memoria
      }
      else                       //Si se han introducido todos los valores...
      {
         d=0;                    //... salgo
      }
   
}


//////////LIMPIAR CLAVE
void limpiar_clave()     //función que pone a '0' la variable clave
{
int k;
   for(k=0;k<3;k++)      //limpiamos uno a uno cada valor de la variable
     {
        clave[k]=0x00;
     }
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)           //funcion que añade la nueva clave administrativa
{
tecla=0;                               //limpio las variables
int aux=0;
d=0;

   lcd_putc("\fNueva clave:\n");       //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
      while(tecla==0 && bandera==0);
      {
         flag_teclado=0;
         lcd_putc("*");
         clave[d]=tecla;
         
         if(d<3)
         {
            escribir_clave_en_eeprom(d);   //guardamos la nueva clave en la memoria EEPROM
            tecla=0;
            d++;
         }
         else
         {
            d=0;
            limpiar_clave();
            break;
         }
      }   
   }
   menu_principal();          //voy al menu principal
}



/////FUNCION MENU PRINCIPAL   
void menu_principal (void)             //funcion que muestra el menu principal

{
tecla=0;
d=0;
     lcd_putc("\f0-Activa Alarma\n1-Cambia Clave");
     delay_ms(2000);
     while(tecla==0 && bandera==0);
     {
         switch (tecla)
         {
         case '0':         //si '0' va a activar la alarma
            activar_alarma();
         break;
         case '1':         //si '1' va a comprobar clave para despues cambiar la clave
            cambiar_clave();
         break;
         }
     }
}


//////////FUNCION CAMBIAR CLAVE
void cambiar_clave(void)             //funcion que cambia clave administrativa
{
int p;
tecla=0;
d=0;
int aux=0;
   limpiar_clave();
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                         
   while(tecla==0 && bandera==0);
   {
     flag_teclado=0;
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          cambio_clave_admin();              //vamos a la rutina para introducir la nueva clave
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////FUNCION COMPARAR CLAVES
int comparar_claves(int)                  //funcion que compara la clave administrativa y la introducida

{
d=0;
int s=0;
   for (d=0;d<3;d++)    //comparo caracter a caracter las claves
   {
      if (clave[d]==clave_eeprom_admin[d])   //si el caracter es igual en las dos claves
         s++;                                             //paso al siguiente caracter
      else                                               //si es distinto la contraseña es incorrecta
        {s=0;
         lcd_putc("\fClave Incorrecta\n");
         break;
        }
   }
   if (s==3)                           //si todos los tres caracteres son iguales
      return 0;                        //devuelvo un '0'
}


//////////FUNCION CAMBIO CLAVE ADMIN
void cambio_clave_admin(void)           //funcion que añade la nueva clave administrativa
{
tecla=0;                               //limpio las variables
int aux=0;
d=0;

   lcd_putc("\fNueva clave:\n");       //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
      while(tecla==0 && bandera==0);
      {
         flag_teclado=0;
         lcd_putc("*");
         clave[d]=tecla;
         if(d<3)
         {
            escribir_clave_en_eeprom(d);   //guardamos la nueva clave en la memoria EEPROM
            tecla=0;
            d++;
         }
         else
         {
            d=0;
            break;
         }
      }   
   }
   //menu_principal();          //ERROR RECURSION
}


//////////ACTIVAR ALARMA
void activar_alarma(void)           //funcion que activa la alarma
{
int p;
tecla=0;
d=0;
int aux=0;
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                         
   while(tecla==0 && bandera==0);
   {
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma Activada\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          desactivar_alarma();            //vamos a la rutina para desactivar la alarma
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////DESACTIVAR ALARMA
void desactivar_alarma(void)           //funcion que desactiva la alarma
{
int p;
tecla=0;
d=0;
int aux=0;
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                         
   while(tecla==0 && bandera==0);
   {
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma\nDesactivada");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          //menu_principal();          //ERROR RECURSION
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////ESCRIBIR_CLAVE_EN_EEPROM
void escribir_clave_en_eeprom(int d)     //función que escribe las claves en la memoria eeprom
{
   write_eeprom (d,tecla);               //guardamos cada valor de la variable global correspondiente
   delay_ms(20);                         //en la direccion d + 0 (para no pisar datos) de la eeprom
   d++;                                  //en una palabra escribe de la posicion 0 a la 2 (3 lugares)
}


//////////LEER_CLAVE_EN_EEPROM
void leer_clave_en_eeprom(int d)       //función que lee las claves y las guarda en su correspondiente variable

{
    for (d=0;d<3;d++)
    {
      clave_eeprom_admin[d] = read_eeprom(d);      //guardamos cada valor de la direccion i + 0 (para no pisar datos)
      delay_ms(20);                                //de la eeprom en la variable global correspondiente
    }
}


////////////FUNCION CONTEO INTENTOS
void conteo_intentos(void)             //funcion que cuenta el numero de intentos de ingreso de contraseña
{
   if (alarm_cont==2)
   {
      alarm_cont = 0;            //pongo a cero el contador de errores
      alarma_general();
   }
   else
   {
      alarm_cont++;
      tecla=0;                               //limpio las variables
      d=0;
      lcd_putc("\fEscribir clave:\n");
   }
}


//////////FUNCION ALARMA GENERAL
void alarma_general (void)       //funcion que enciende la sirena
{
    set_tris_c(0b11111110);      //pin C0 como salida                             
    output_high(pin_C0);         //enciende la sirena durante 2 seg y muestra mensaje
    //lcd_putc("\fALARMA\n");         
    delay_ms(2000);
    output_low(pin_C0);          //apaga la sirena
   
    //cambio_clave_admin();
}

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con interrupcion externa y teclado
« Respuesta #55 en: 08 de Abril de 2013, 08:47:05 »
  En ocasiones ocurre que es necesario replantearse el orden o la estructura del programa.

  Tal vez deberías dejar el menu_principal() dentro del main y llamar desde allí mismo al resto de las funciones. Así, cuando retornes de cualquier función, volverías al flujo normal del programa.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #56 en: 08 de Abril de 2013, 14:20:01 »
que tal amigo escarrillense,yo pienso que el problema esta como dice el amigo AngelGris en la secuencia o flujo del programa por eso te los problemas de la recursividad, no he tenido chance de probar pero porque no haces lo que te sugiere y pruebas
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #57 en: 09 de Abril de 2013, 08:20:30 »
Muchas gracias a ambos por dar en el clavo! Teníais toda la razón con lo de mover la función menu_principal al main y reestructurar el programa. He hecho lo del main y eliminado alguna función como la de escribir_clave y la de cambio_clave_inicial y directamente he grabado la clave por defecto en la eeprom al inicio del programa y así he evitado duplicidades y funciones muy parecidas con el mismo nombre.

Quedan por pulir un par de detalles que ahora comento. El primero de ellos trata sobre el contador de errores. Cuando sale de esa función me lleva al while(true) y me gustaría que me llevara de nuevo a la función donde se ha producido la clave incorrecta. He intentado hacerlo pero no se como o es que no se puede hacer lo que yo quiero. De la forma en que está ahora tampoco me desagrada y si se tiene que quedar asi tampoco sufriría pero de la otra me gusta mas jeje. O si opinais que así queda mejor seguiré vuestros sabios consejos.

El segundo detalle es que cuando se produce la interrupción externa se llena el arreglo de la clave y lo cuenta como un intento incorrecto y despues me lleva a la función alarma_general (que es lo que yo quiero que haga), ¿cómo puedo hacer para que directamente me lleve a esa función sin pasar por la del contador de intentos?. Igual tampoco se puede hacer lo que deseo. Tampoco sufriría si se queda así pero me gustaría de la otra forma.
Otro fallo que tengo es que al producirse la interrupción externa cuando estoy en la funcion nueva_clave_admin se me borra la clave que tengo guardada en la eeprom a partir de la tecla pulsada en adelante. Es decir, si llevo una tecla pulsada y se producen la interrupción, se me borran los dos valores siguientes y en la eeprom solo se me queda guardado el que he pulsado, lo cual daría lugar a futuros fallos ya que no sabriamos cuantos valores tenemos en caso de que se produjera un problema.

Espero haberme expresado bien y muchas gracias por toda la ayuda mostrada. Copio el código por si me podeis ayudar

Código: [Seleccionar]
#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay (CLOCK=4000000)
#use fast_io(A)
#use fast_io(B)
#byte port_b = 0x06
#byte tris_b = 0xff

#include <LCD4.c>             //libreria manejo lcd 8 bits
#include <string.h>           //libreria manejo cadenas

#rom 0x2100={'1','2','3',0,0,0,0}   //la EEPROM se carga con los valores 00h desde la direccion 00h hasta 06h


////////////////DEFINICION DE FUNCIONES////////////////////////////

void captura(void);                    //funcion que captura la clave tecleada
void nueva_clave_admin(void);          //funcion que añade la nueva clave administrativa
void limpiar_clave(void);              //funcion que pone a '0' la variable clave
void escribir_clave_en_eeprom(int d);  //función que escribe las claves en la memoria eeprom
void menu_principal(void);             //funcion que muestra el menu principal
void cambiar_clave(void);              //funcion que cambia clave admin
int comparar_claves(int);              //función que compara las claves
void activar_alarma(void);             //funcion que activa la alarma
void desactivar_alarma(void);          //funcion que desactiva la alarma
void leer_clave_en_eeprom(int);        //función que lee las claves y las guarda en su correspondiente variable
void conteo_intentos(void);            //funcion que cuenta el numero de intentos de ingreso de contraseña
void alarma_general(void);             //funcion que enciende la sirena


////////////////VARIABLES GLOBALES///////////////////////////

int flag_teclado=0;                       //flag que señala que una tecla ha sido pulsada
char bandera=0;                           //flag que señala que se ha producido una interrupcion externa
int tecla;                                //variable que recoge la tecla pulsada
int fila,columna;                         //variables que recogen la fila y columna de la tecla pulsada
char clave[3]={};                         //variable usada para recoger la clave tecleada                        
int d=0;                                  //variable usada para movernos por las posiciones de la memoria
char clave_eeprom_admin[3];               //variable usada para comparar los datos de la eeprom contra los datos ingresados
int alarm_cont=0;                         //variable global que cuenta los fallos


/***************************************
Rutina de Interrupcion.
- Antirebote.
- Llama a rutina "captura" para saber
  la tecla presionada.
- Activa la bandera "flag_teclado"
  a usar en el main o en otra parte
  del programa.
***************************************/
#INT_RB
void tecla_presionada()
{
   int lectura_1,lectura_2;                  //variables locales para detectar la tecla pulsada
   lectura_1 = port_b & 0b11110000;          //lee portb4:7 y lo guarda en lectura_1
   delay_ms(10);                             //Funcion AntiRebotes: Espero 10ms.
   lectura_2 = port_b & 0b11110000;          //Vuelvo a leer el puerto.
   if(lectura_1==lectura_2 && lectura_1!=0)  //Si el valor es igual y distinto de 0 es porque en realidad se presiono una tecla.
   {                                    
     flag_teclado=1;                         //marcamos que se ha pulsado una tecla
     captura();                              //capturamos dicha tecla
   }
   set_tris_b(0b11110000);
   output_b(0b00001111);
   clear_interrupt(INT_RB);
   set_tris_b(0b11110001);
}


//////////////INTERRUPCION EXTERNA//////////////////
#INT_EXT
void externa(void)
{
   bandera=1;                    //marcamos que se ha producido una interrupcion externa
}


//////////////PROGRAMA PRINCIPAL///////////////////////
void main()
{
   set_tris_b(0b11110001);       //configuro el puerto b
   set_tris_c(0b11111111);       //configuro el puerto c
   enable_interrupts(INT_RB);    //habilito la interrupcion por cambio de nibble alto
   ext_int_edge(H_TO_L);         //habilito la interrupcion externa por cambio de flanco
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);    //habilito las interrupciones
  
   lcd_init();                   //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
  
   while(TRUE)
   {
      lcd_putc("\f0-Activa Alarma\n1-Cambia Clave");
      delay_ms(1000);
      if(flag_teclado==1)           //Si se ha pulsado una tecla
      {
         flag_teclado=0;
         menu_principal();          //voy al menu principal
      
      }
      if(bandera==1)                //Si se ha producido una interrupcion externa
      {
         bandera=0;
         alarma_general();          //activo la sirena
      }
   }
  
}  


/*********************************
Esta Rutina permite rastrear el teclado
y devuelve el valor de la tecla que se
ha presionado
************************************/
void captura(void)               //funcion que captura la clave tecleada
{
int const teclado[4][4] = {{0,'1','2','3'},
                           {0,'4','5','6'},
                           {0,'7','8','9'},
                           {0,'*','0','#'}};
int lectura,i;
for(i=0;i<4;i++)
{
output_b(0);
bit_set(port_b,i);
lectura = port_b & 0b11110000;
switch(lectura)
{
case 0b00010000: fila=0;
 columna=i;
 break;
case 0b00100000: fila=1;
 columna=i;
 break;
case 0b01000000: fila=2;
 columna=i;
 break;
case 0b10000000: fila=3;
 columna=i;
 break;
}
}
tecla = teclado[fila][columna];
}


///////FUNCION MENU PRINCIPAL  
void menu_principal (void)             //funcion que muestra el menu principal
{
d=0;
     switch (tecla)
         {
         case '0':         //si '0' va a activar la alarma
            activar_alarma();
         break;
         case '1':         //si '1' va a comprobar clave para despues cambiar la clave
            cambiar_clave();
         break;
         }
}


//////////FUNCION CAMBIAR CLAVE
void cambiar_clave(void)             //funcion que cambia clave administrativa
{
int p;
tecla=0;
d=0;
int aux=0;
   limpiar_clave();
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                          
   while(tecla==0 && bandera==0);
   {
     flag_teclado=0;
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          nueva_clave_admin();               //introduzco la nueva clave
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////FUNCION COMPARAR CLAVES
int comparar_claves(int)                  //funcion que compara la clave administrativa y la introducida

{
d=0;
int s=0;
   for (d=0;d<3;d++)    //comparo caracter a caracter las claves
   {
      if (clave[d]==clave_eeprom_admin[d])   //si el caracter es igual en las dos claves
         s++;                                             //paso al siguiente caracter
      else                                               //si es distinto la contraseña es incorrecta
        {s=0;
         lcd_putc("\fClave Incorrecta\n");
         break;
        }
   }
   if (s==3)                           //si todos los tres caracteres son iguales
      return 0;                        //devuelvo un '0'
}


//////////LIMPIAR CLAVE
void limpiar_clave()     //función que pone a '0' la variable clave
{
int k;
   for(k=0;k<3;k++)      //limpiamos uno a uno cada valor de la variable
     {
        clave[k]=0x00;
     }
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)           //funcion que añade la nueva clave administrativa
{
tecla=0;                               //limpio las variables
int aux=0;
d=0;

   lcd_putc("\fNueva clave:\n");       //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
      while(tecla==0 && bandera==0);
      {
         flag_teclado=0;
         lcd_putc("*");
         clave[d]=tecla;
         if(d<3)
         {
            escribir_clave_en_eeprom(d);   //guardamos la nueva clave en la memoria EEPROM
            tecla=0;
            d++;
         }
         else
         {
            d=0;
            limpiar_clave();
         }
      }  
   }
}


//////////ACTIVAR ALARMA
void activar_alarma(void)           //funcion que activa la alarma
{
int p;
tecla=0;
d=0;
int aux=0;
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                          
   while(tecla==0 && bandera==0);
   {
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma Activada\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          desactivar_alarma();            //vamos a la rutina para desactivar la alarma
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////DESACTIVAR ALARMA
void desactivar_alarma(void)           //funcion que desactiva la alarma
{
int p;
tecla=0;
d=0;
int aux=0;
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                          
   while(tecla==0 && bandera==0);
   {
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma\nDesactivada");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////ESCRIBIR_CLAVE_EN_EEPROM
void escribir_clave_en_eeprom(int d)     //función que escribe las claves en la memoria eeprom
{
   write_eeprom (d,tecla);               //guardamos cada valor de la variable global correspondiente
   delay_ms(20);                         //en la direccion d + 0 (para no pisar datos) de la eeprom
   d++;                                  //en una palabra escribe de la posicion 0 a la 2 (3 lugares)
}


//////////LEER_CLAVE_EN_EEPROM
void leer_clave_en_eeprom(int d)       //función que lee las claves y las guarda en su correspondiente variable
{
    for (d=0;d<3;d++)
    {
      clave_eeprom_admin[d] = read_eeprom(d);      //guardamos cada valor de la direccion i + 0 (para no pisar datos)
      delay_ms(20);                                //de la eeprom en la variable global correspondiente
    }
}


////////////FUNCION CONTEO INTENTOS
void conteo_intentos(void)             //funcion que cuenta el numero de intentos de ingreso de contraseña
{
   if (alarm_cont==2)
   {
      alarm_cont = 0;            //pongo a cero el contador de errores
      alarma_general();
   }
   else
   {
      alarm_cont++;
      tecla=0;                               //limpio las variables
      d=0;
      lcd_putc("\fEscribir clave:\n");
   }
}


//////////FUNCION ALARMA GENERAL
void alarma_general (void)       //funcion que enciende la sirena
{
    set_tris_c(0b11111110);      //pin C0 como salida                            
    output_high(pin_C0);         //enciende la sirena durante 2 seg y muestra mensaje
    lcd_putc("\fALARMA\n");          
    delay_ms(2000);
    output_low(pin_C0);          //apaga la sirena
}
« Última modificación: 10 de Abril de 2013, 05:10:15 por escarrillense »

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #58 en: 11 de Abril de 2013, 14:17:27 »
Hola de nuevo! He conseguido solucionar el segundo detalle, el de la interrupción. Lo he hecho creando una nueva función llamada regreso_menu() que nos hace escribir la contraseña que teníamos cuando se produjo la interrupción y a continuación escribir una nueva clave. No se si es la forma mas bonita pero funciona. Asi de esta forma no se nos queda la clave a cero o con valores incontrolados. Lo que respecta al contador de errores no he conseguido solucionarlo de la mejor manera. He puesto alarm_cont =0 en los lugares necesarios y de esta manera no lo sumaría. Creo que entra en la función del conteo de intentos porque cuando se produce la interrupción primero tiene que terminar de hacer lo que le pide la función en la que está (así que tiene que pasar por la funcion conteo_intentos) y después hace lo que le pide la interrupción. ¿Estoy en lo cierto?

Lo del primer punto a corregir, lo que respecta al contador de intentos que me lleva al while(true) no lo consigo programar como me gustaría. Veré que hago aunque no sería problema dejarlo así.

Me estoy volviendo un poco loco y estoy barajando la posibilidad de añadirle un simulador de presencia al sistema, para que se enciendan unos led a unas determinadas horas. He visto que se puede hacer con un ds1307 o similar y me ha surgido una duda. ¿Se podría hacer solo por software o sería muy complicado?

Copio el código y gracias por todo

Código: [Seleccionar]
#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay (CLOCK=4000000)
#use fast_io(A)
#use fast_io(B)
#byte port_b = 0x06
#byte tris_b = 0xff

#include <LCD4.c>             //libreria manejo lcd 8 bits
#include <string.h>           //libreria manejo cadenas

#rom 0x2100={'1','2','3',0,0,0,0}   //la EEPROM se carga con los valores 00h desde la direccion 00h hasta 06h


////////////////DEFINICION DE FUNCIONES////////////////////////////

void captura(void);                    //funcion que captura la clave tecleada
void nueva_clave_admin(void);          //funcion que añade la nueva clave administrativa
void limpiar_clave(void);              //funcion que pone a '0' la variable clave
void escribir_clave_en_eeprom(int d);  //función que escribe las claves en la memoria eeprom
void menu_principal(void);             //funcion que muestra el menu principal
void cambiar_clave(void);              //funcion que cambia clave admin
int comparar_claves(int);              //función que compara las claves
void activar_alarma(void);             //funcion que activa la alarma
void desactivar_alarma(void);          //funcion que desactiva la alarma
void leer_clave_en_eeprom(int);        //función que lee las claves y las guarda en su correspondiente variable
void conteo_intentos(void);            //funcion que cuenta el numero de intentos de ingreso de contraseña
void alarma_general(void);             //funcion que enciende la sirena
void regreso_menu(void);

////////////////VARIABLES GLOBALES///////////////////////////

int flag_teclado=0;                       //flag que señala que una tecla ha sido pulsada
char bandera=0;                           //flag que señala que se ha producido una interrupcion externa
int tecla;                                //variable que recoge la tecla pulsada
int fila,columna;                         //variables que recogen la fila y columna de la tecla pulsada
char clave[3]={};                         //variable usada para recoger la clave tecleada                        
int d=0;                                  //variable usada para movernos por las posiciones de la memoria
char clave_eeprom_admin[3];               //variable usada para comparar los datos de la eeprom contra los datos ingresados
int alarm_cont=0;                         //variable global que cuenta los fallos


/***************************************
Rutina de Interrupcion.
- Antirebote.
- Llama a rutina "captura" para saber
  la tecla presionada.
- Activa la bandera "flag_teclado"
  a usar en el main o en otra parte
  del programa.
***************************************/
#INT_RB
void tecla_presionada()
{
   int lectura_1,lectura_2;                  //variables locales para detectar la tecla pulsada
   lectura_1 = port_b & 0b11110000;          //lee portb4:7 y lo guarda en lectura_1
   delay_ms(10);                             //Funcion AntiRebotes: Espero 10ms.
   lectura_2 = port_b & 0b11110000;          //Vuelvo a leer el puerto.
   if(lectura_1==lectura_2 && lectura_1!=0)  //Si el valor es igual y distinto de 0 es porque en realidad se presiono una tecla.
   {                                    
     flag_teclado=1;                         //marcamos que se ha pulsado una tecla
     captura();                              //capturamos dicha tecla
   }
   set_tris_b(0b11110000);
   output_b(0b00001111);
   clear_interrupt(INT_RB);
   set_tris_b(0b11110001);
}


//////////////INTERRUPCION EXTERNA//////////////////
#INT_EXT
void externa(void)
{
   bandera=1;                    //marcamos que se ha producido una interrupcion externa
}


//////////////PROGRAMA PRINCIPAL///////////////////////
void main()
{
   set_tris_b(0b11110001);       //configuro el puerto b
   set_tris_c(0b11111111);       //configuro el puerto c
   enable_interrupts(INT_RB);    //habilito la interrupcion por cambio de nibble alto
   ext_int_edge(H_TO_L);         //habilito la interrupcion externa por cambio de flanco
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);    //habilito las interrupciones
  
   lcd_init();                   //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
  
   while(TRUE)
   {
      lcd_putc("\f0-Activa Alarma\n1-Cambia Clave");
      delay_ms(1000);
      if(flag_teclado==1)           //Si se ha pulsado una tecla
      {
         flag_teclado=0;
         menu_principal();          //voy al menu principal
      
      }
      if(bandera==1)                //Si se ha producido una interrupcion externa
      {
         bandera=0;
         alarma_general();          //activo la sirena
         regreso_menu();
      }
   }
  
}  


/*********************************
Esta Rutina permite rastrear el teclado
y devuelve el valor de la tecla que se
ha presionado
************************************/
void captura(void)               //funcion que captura la clave tecleada
{
int const teclado[4][4] = {{0,'1','2','3'},
                           {0,'4','5','6'},
                           {0,'7','8','9'},
                           {0,'*','0','#'}};
int lectura,i;
for(i=0;i<4;i++)
{
output_b(0);
bit_set(port_b,i);
lectura = port_b & 0b11110000;
switch(lectura)
{
case 0b00010000: fila=0;
 columna=i;
 break;
case 0b00100000: fila=1;
 columna=i;
 break;
case 0b01000000: fila=2;
 columna=i;
 break;
case 0b10000000: fila=3;
 columna=i;
 break;
}
}
tecla = teclado[fila][columna];
}


///////FUNCION MENU PRINCIPAL  
void menu_principal (void)             //funcion que muestra el menu principal
{
d=0;
     switch (tecla)
         {
         case '0':         //si '0' va a activar la alarma
            activar_alarma();
         break;
         case '1':         //si '1' va a comprobar clave para despues cambiar la clave
            cambiar_clave();
         break;
         }
}


//////////FUNCION CAMBIAR CLAVE
void cambiar_clave(void)             //funcion que cambia clave administrativa
{
int p;
tecla=0;
d=0;
int aux=0;

   leer_clave_en_eeprom(d);
   limpiar_clave();
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                          
   while(tecla==0 && bandera==0);
   {
     flag_teclado=0;
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          alarm_cont = 0;
          limpiar_clave();                   //pongo a '0' la variable clave
          nueva_clave_admin();               //introduzco la nueva clave
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////FUNCION COMPARAR CLAVES
int comparar_claves(int)                  //funcion que compara la clave administrativa y la introducida

{
d=0;
int s=0;
   for (d=0;d<3;d++)    //comparo caracter a caracter las claves
   {
      if (clave[d]==clave_eeprom_admin[d])   //si el caracter es igual en las dos claves
         s++;                                             //paso al siguiente caracter
      else                                               //si es distinto la contraseña es incorrecta
        {s=0;
         lcd_putc("\fClave Incorrecta\n");
         break;
        }
   }
   if (s==3)                           //si todos los tres caracteres son iguales
      return 0;                        //devuelvo un '0'
}


//////////LIMPIAR CLAVE
void limpiar_clave()     //función que pone a '0' la variable clave
{
int k;
   for(k=0;k<3;k++)      //limpiamos uno a uno cada valor de la variable
     {
        clave[k]=0x00;
     }
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)           //funcion que añade la nueva clave administrativa
{
tecla=0;                               //limpio las variables
int aux=0;
d=0;

   lcd_putc("\fNueva clave:\n");       //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
      while(tecla==0 && bandera==0);
      {
         flag_teclado=0;
         lcd_putc("*");
         clave[d]=tecla;
         if(d<3)
         {
            escribir_clave_en_eeprom(d);   //guardamos la nueva clave en la memoria EEPROM
            tecla=0;
            d++;
         }
         else
         {
            d=0;
            limpiar_clave();
         }
      }  
   }
}


//////////ACTIVAR ALARMA
void activar_alarma(void)           //funcion que activa la alarma
{
int p;
tecla=0;
d=0;
int aux=0;
   leer_clave_en_eeprom(d);
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                          
   while(tecla==0 && bandera==0);
   {
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma Activada\n");
          delay_ms(2000);
          alarm_cont = 0;
          limpiar_clave();                   //pongo a '0' la variable clave
          desactivar_alarma();            //vamos a la rutina para desactivar la alarma
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////DESACTIVAR ALARMA
void desactivar_alarma(void)           //funcion que desactiva la alarma
{
int p;
tecla=0;
d=0;
int aux=0;
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                          
   while(tecla==0 && bandera==0);
   {
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      leer_clave_en_eeprom(d);               //lee la contraseña que antes hemos cambiado
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma\nDesactivada");
          delay_ms(2000);
          alarm_cont = 0;
          limpiar_clave();                   //pongo a '0' la variable clave
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          conteo_intentos();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}


//////////ESCRIBIR_CLAVE_EN_EEPROM
void escribir_clave_en_eeprom(int d)     //función que escribe las claves en la memoria eeprom
{
   write_eeprom (d,tecla);               //guardamos cada valor de la variable global correspondiente
   delay_ms(20);                         //en la direccion d + 0 (para no pisar datos) de la eeprom
   d++;                                  //en una palabra escribe de la posicion 0 a la 2 (3 lugares)
}


//////////LEER_CLAVE_EN_EEPROM
void leer_clave_en_eeprom(int d)       //función que lee las claves y las guarda en su correspondiente variable
{
    for (d=0;d<3;d++)
    {
      clave_eeprom_admin[d] = read_eeprom(d);      //guardamos cada valor de la direccion i + 0 (para no pisar datos)
      delay_ms(20);                                //de la eeprom en la variable global correspondiente
    }
}


////////////FUNCION CONTEO INTENTOS
void conteo_intentos(void)             //funcion que cuenta el numero de intentos de ingreso de contraseña
{
   if (alarm_cont==2)
   {
      alarm_cont = 0;            //pongo a cero el contador de errores
      alarma_general();
   }
   else
   {
      alarm_cont++;
      tecla=0;                               //limpio las variables
      d=0;
      lcd_putc("\fEscribir clave:\n");
   }
}


//////////FUNCION ALARMA GENERAL
void alarma_general (void)       //funcion que enciende la sirena
{
    set_tris_c(0b11111110);      //pin C0 como salida                            
    output_high(pin_C0);         //enciende la sirena durante 2 seg y muestra mensaje
    lcd_putc("\fALARMA\n");          
    delay_ms(2000);
    output_low(pin_C0);          //apaga la sirena
    alarm_cont = 0;
}


//////////FUNCION REGRESO MENU
void regreso_menu(void)
{
int p;
tecla=0;
d=0;
int aux=0;

   limpiar_clave();
   lcd_putc("\fEscribir clave:\n");
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {                          
   while(tecla==0 && bandera==0);
   {
     flag_teclado=0;
     lcd_putc("*");
     clave[d]=tecla;
     d++;
     if (d==3)                                 //Si ya se han introducido todos los valores de la clave
     {
      
      p=comparar_claves(d);                  //compara ambas claves
      if (p==0)                              //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          nueva_clave_admin();               //introduzco la nueva clave
         }
      if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          limpiar_clave();                   //pongo a '0' la variable clave
          alarma_general();
         }
     }
     else
     {
         tecla=0;
     }
   }
   }
}

« Última modificación: 12 de Abril de 2013, 07:41:15 por escarrillense »

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #59 en: 12 de Abril de 2013, 13:13:59 »
Hola compañero, ya veo que has logrado avanzar bastante eso me gusto,he estado algo ausente por el trabajo pero te comento:

Lo del DS1307 no es complicado,solo requieres esencialmente de dos pines libres de PIC que idealmente te recomendaría fuesen los destinados al protocolo I2C,que es el que usa el RTC DS1307, así se haría todo con el hardware integrado del pic (que si no me equivoco si cuenta con I2C),pero,en caso de no contar con I2C por hardware,no hay problema una de las bondades del CCS es que puede emular el protocolo tan solo con indicarselo en la directiva de configuracion del mismo (checa la ayuda en el apartado #use i2c).

El comunicarse y configurar el DS1307 no implica nada dificil hay muchos post que hablan de ello y por supuesto puedo ayudarte en lo que pueda si lo requieres.

suerte y saludo.
Nunca se deja de aprender


 

anything