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

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con interrupcion externa y teclado
« Respuesta #30 en: 19 de Marzo de 2013, 10:14:28 »
  Una vez obtenida la tecla pulsada, la puedes ir almacenando en un array de caracteres y vas incrementando el contador a medida que presionas las teclas.
  En este punto, podrías hacer que el array termine de incrementarse cuando el contador del mismo llegue a un número determinado de letras (lo cual daría una longitud de clave fija). O bien crear un array grande y con la posibilidad de finalizar el ingreso con una tecla determinada. Por supuesto tendrás que evaluar algún flag para determinar cuando has culminado de ingresar la clave.

  En cuanto a colocar el programa en una "ventanita", debes usar la opción GeSHi del editor de mensaje.
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 #31 en: 19 de Marzo de 2013, 13:43:25 »
Hola escarrillense,me alegra que ya tengas avances,para lo que comentas de guardar la clave puede ser como comenta AngelGris,un arreglo,bueno como yo lo veo se podría hacer lo siguiente:

1.- Ya tienes declarada una variable dentro de tu rutina de interrupción por cambio de estado que se llama tecla,esa variable yo la colocaría global de manera que las funciones pudieran tener acceso a ella.
2.- De hacerse eso me parece que el arreglo de clave_introducida ya no seria necesario porque utilizarías directamente a tecla por lo tanto tu función escribe clave ya no recibiría parámetros.
3.- Para la captura se podría hacer algo así:

Código: [Seleccionar]
void escribir_clave()            //funcion que escibre la clave tecleado
{
int i=0;
        lcd_putc("\fEscribir clave:\n");   //presentacion
if(!(tecla=='*' || tecla=='#')) // Si no es '*' o '#' en la pantalla aparece un '*'
        {     
           lcd_putc("*");
           clave[i]=tecla;
   if(i<3)
   {
                i++;
           }
   else
   {
i=0;
   }
       } 
}

con lo que cada ves que llames a la función escribir_clave() iniciara guardando la tecla presionada en la posición 0 del arreglo,y preguntara si ya esta cubierta la longitud de la clave esperada,en este caso 3 posiciones,si no se ha cubierto incrementa i,que funciona como un indice para el arreglo,si la longitud ya se ha cumplido se reinicia el indice ( i ) y asi puedes capturar una nueva clave.

4.- Cabe mencionar que para validar la clave tu tendrías que realizar una rutina de checado de los datos del arreglo clave[3],o comparar la cadena como lo habías echo anteriormente con strcmp(str1,str2),yo personalmente siempre comparo valor a valor del arreglo recibido contra uno fijo en mi código,es o debería dar el mismo resultado.

bueno compañero solo son algunas sugerencias jeje ojala tu proyecto te quede excelente ya casi esta solo le falta el ultimo empujon

Saludos desde Morelia
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #32 en: 19 de Marzo de 2013, 15:24:48 »
Muchas gracias a los dos por vuestra ayuda! No se que sería de este proyecto sin vosotros porque estaba chocando todo el rato con una pared y me habeis ayudado a ver la luz al final del tunel. Gracias!

Thegame he probado tu código y funciona perfectamente, eso si, para que me guardara bien los arreglos la variable int i=0 la he tenido que guardar como global porque o me machacaba los datos o en la primera posicion de memoria siempre guardaba un cero si la guardaba de la forma que me has indicado. Lo que no consiguo es que en el lcd aparezca un asterisco por cada tecla que presiono, pero bueno, lo que es el arreglo lo guarda perfectamente.

He conseguido comparar las claves y funciona perfecto. Siguiente paso es poder grabar una clave tecleada en la eeprom.Lo he intentado pero me vuelve siempre al main y se reinicia todo el proceso.Las rutinas escribir_clace y comprobar_claves funcionan, la que no va es la de nueva_clave_admin. Os copio lo nuevo. Ya me direis si he conseguido hacer lo de GeSHI bien jajajja

lcd_init();            //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
   
   while(TRUE)
   {
   if(flag_teclado==1)
      {
      cambia_clave_inicial();    //cambio la contraseña que viene por defecto
      flag_teclado=0;
      }
    if(bandera==1)
      {
         bandera=0;
         alarma_general();
      }
   }
}   


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

{
int p;
   
   escribir_clave();  //tecleo la contraseña
   if (d==3)
   {
      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);
          nueva_clave_admin();      //introduzco la nueva clave
         }
      if (p!=0)                        //si las dos claves son distintas
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          clave=0;      //borro la clave introducida
          alarma_general ();        //activo la alarma
         }
   }
   
}

//////////FUNCION ESCRIBIR NUEVA CLAVE
void escribir_clave()            //funcion que escibre la clave tecleada

{
   lcd_putc("\fEscribir clave:\n");   //presentacion
   if(!(tecla=='*' || tecla=='#')) // Si no es '*' o '#' en la pantalla aparece un '*'
   {     
      lcd_putc("*");
      clave[d]=tecla;
      if(d<3)
      {
         d++;
      }
      else
      {
         d=0;
      }
   } 
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)                 //funcion que añade la nueva clave administrativa
{
//int e=0;
   clave=0;                //pongo la clave tecleada a 0
   tecla=0;
   lcd_putc("\fNueva clave:\n");   //presentacion
   if(!(tecla=='*' || tecla=='#')) // Si no es '*' o '#' en la pantalla aparece un '*'
   {     
      lcd_putc("*");
      clave[e]=tecla;
      if(e<3)
      {
         escribir_clave_en_eeprom(e);   //guardamos la nueva clave en la memoria EEPROM
         e++;
      }
      else
      {
         e=0;
      }
   } 
}


//////////ESCRIBIR_CLAVE_EN_EEPROM
void escribir_clave_en_eeprom(int e)     //función que escribe las claves en la memoria eeprom

{
   write_eeprom (e,tecla);             //guardamos cada valor de la variable global correspondiente
   delay_ms(20);                   //en la direccion e + 0 (para no pisar datos) de la eeprom
   e++;                            //en una palabra escribe de la posicion 0 a la 2 (3 lugares)
}

« Última modificación: 20 de Marzo de 2013, 08:14:25 por escarrillense »

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #33 en: 20 de Marzo de 2013, 13:27:50 »
hola,que bueno que ha quedado,con lo de la eeprom déjame ver que puedo investigar o probar, básicamente quieres que la clave tecleada se grabe en la eeprom por lo que entiendo,es así??,lo importante es que gran parte de tu proyecto ya esta funcionando.

p.d. jeje no te ha salido lo del geshi, podrías usar la etiqueta de código,es la que lleva el símbolo de gatito,con esa queda bien
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #34 en: 21 de Marzo de 2013, 07:52:55 »
Correcto! Lo que quiero es que una vez que introduzco la clave, en este caso llamada clave_inicial, que viene por defecto (como en muchos aparatos que hay que escribir 0000, o en mi caso 123, cuando los conectas por primera vez), cambiar esa clave por otra que yo quiera, en mi caso la llamare clave_admin, y que esta nueva clave se grabe en la eeprom. Y usar esta clave para el resto de menus que necesito como activar y desactivar la alarma o volver a cambiar esta clave por la razon que sea.

La parte de teclear las clave_inicial y comprobar si es la correcta funciona (ya lo puse en mi anterior post). Lo que no consigo hacer es grabar la nueva clave en la eeprom. Limpio la variable tecla y el arreglo clave (este último se me limpian las dos primeras teclas pero la ultima no se porque no). Despues, al pulsar una tecla para introducir la nueva clave vuelve a la parte del main de flag_teclado==1 y continua con lo de cambiar la clave_inicial, es decir, que se reinicia todo el proceso de nuevo. Lo cual me impide grabar la nueva clave en la eeprom. El problema creo que lo tengo en que no se bien donde poner las rutinas si dentro del While o dentro del if (flag_teclado==1) o donde. Me imagino que este asunto me dará problemas en el futuro con la gestión de los menus (tengo ya uno hecho de cuando empecé con este proyecto con un switch para que según la tecla pulsada active la alarma o cambie la clave_admin) y con la escritura y lectura de claves en la eeprom para los cambios de clave y activación y desactivación de la alarma.

Espero haberme explicado bien y que hayais entendido lo que quiero hacer. Muchas gracias por vuestra ayuda y seguiré luchando

pd: es para que me mateis pero no encuentro lo de la etiqueta de código (simbolo del gatito) o no me aparece. Creo que el bloqueo mental que llevo me impide verlo y seguro que lo tengo en frente de mis narices
« Última modificación: 21 de Marzo de 2013, 08:57:24 por escarrillense »

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #35 en: 21 de Marzo de 2013, 13:39:42 »
Hola compañero,ok entendido y enterado,vamos por partes

1.- Para el borrado del arreglo clave (o inicializacion),lo que deberemos hacer es un pequeño ciclo de borrado,algo como lo que sigue:

     for(k=0;k<3;k++)
     {
            clave[k]=0x00;
      }

     Obviamente deberemos declarar la variable k previamente,si checas inicia desde la pocision 0 hasta la posicion 2 ya que al llegar a 3 la condición de "paro" del for ya no se cumple por lo que ahi termina,si deseas que borre mas posiciones solo hay que incrementar este numero de "paro" o "fin".

     Ahora,el cuando llames este pequeño ciclo,tendria que ser al accesar a la funcion que te cambia la clave por default es decir nueva_clave_admin .


2.- Con lo que comentas de que te regresa al proceso de introducción de clave y no al de cambio de clave,yo pondria dos claves,una de usuario regular y una de administrador y en esta parte:

Código: [Seleccionar]
p=strncmp(clave , clave_inicial,3);    //comparo la clave por defecto con la tecleada
pondria:

Código: [Seleccionar]
p1=strncmp(clave_usuario , clave_inicial,3);    //comparo la clave de usuario
p2=strncmp(clave_admin , clave_inicial,3);    //comparo la clave de administrador

y despues preguntaria cual de las dos es la que se acceso:

Código: [Seleccionar]
if((p1==0)&&(p2!=0))
{
    lcd_putc("\fClave Correcta\n");
    //Y aqui colocas todo lo que puede hacer el usuario regular
}
if((p1!=0)&&(p2==0))
{
    lcd_putc("\fClave de administrador Correcta\n");
    lcd_putc("\fDeseas cambiar tu clave??  1=si  2=no\n");

    while(flag_tecla!=1);
     
     if(flag_tecla==1)
    {
          if(tecla==1)
         {
              nueva_clave_admin();
         }
         else
         {
              break;
         }
     }
}


basicamente lo que se intenta hacer es: si es clave de usuario le das acceso y funciones de usuario,si es de administrador le das acceso y opciones de administrador,esto le da un grado mas de seguridad ya que si no cualquiera podria cambiar la contraseña de administrador ya que nunca haces distincion de si puede o no.

solo es una posible solucion ya sabes que hay muchos caminos para llegar a roma.


P.D. checa la imagen para lo de la etiqueta codigo:
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #36 en: 21 de Marzo de 2013, 15:08:07 »
Muchas gracias thegame! Ahora me pongo a añadir lo que me has puesto y ya voy comentando los progresos. Lo de distinguir entre usuario y administrador es buena idea pero de momento voy a intentar hacerlo con uno solo y mas adelante iré añadiendo mejoras.

Acabo de probar lo de borrar la clave y funciona perfectamente.

Gracias tambien por la imagen. Ya me olía yo que lo tenía delante y no lo veía jajja
« Última modificación: 21 de Marzo de 2013, 16:41:53 por escarrillense »

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #37 en: 22 de Marzo de 2013, 07:42:14 »
Hola! Sigo con lo de intentar grabar la nueva clave en la eeprom pero no lo consigo. Llego a la función nueva_clave_admin y puedo poner el primer valor en el arreglo clave pero al introducir el segundo, el programa me lleva de nuevo a la función comprobar_clave por lo que se me reinicia todo. Copio el código para ver si me podeis echar una mano.

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 cambia_clave_inicial(void);       //funcion que cambia la clave iinicial
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);
void alarma_general(void);             //funcion que enciende la sirena


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

int flag_teclado;
int tecla,fila,columna;
char bandera=0;
char clave[3]={};                         //variable usada para recoger la clave tecleada y guardarla en ROM
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
//int e=0;
             
 
/********************************
Esta Rutina permite rastrear el teclado
y devuelve el valor de la tecla que se
ha presionado
************************************/
int captura(void)
{
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];
return(tecla);
}
 
/***************************************
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;
   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.
   {                                   
      tecla = captura();
      flag_teclado=1;
   }
   set_tris_b(0b11110000);
   output_b(0b00001111);
   clear_interrupt(INT_RB);
   set_tris_b(0b11110001);

}


//////////////INTERRUPCION EXTERNA//////////////////
#INT_EXT
void externa(void)
{
   bandera=1;
}


//////////////PROGRAMA PRINCIPAL///////////////////////
void main()
{
   set_tris_b(0b11110001);
   set_tris_c(0b11111111);       //configuro el puerto c
   enable_interrupts(INT_RB);
   ext_int_edge(H_TO_L);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   
   lcd_init();            //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
   
   while(TRUE)
   {
   if(flag_teclado==1)
      {
      cambia_clave_inicial();    //cambio la contraseña que viene por defecto
      flag_teclado=0;
      }
    if(bandera==1)
      {
         bandera=0;
         alarma_general();
      }
   }
}   


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

{
int p;
   
   escribir_clave();  //tecleo la contraseña
   if (d==3)
   {
      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();
          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();
          alarma_general ();        //activo la alarma
         }
   }
   
}

//////////FUNCION ESCRIBIR NUEVA CLAVE
void escribir_clave()            //funcion que escibre la clave tecleada

{
   lcd_putc("\fEscribir clave:\n");   //presentacion
   lcd_putc("*");
   clave[d]=tecla;
      if(d<3)
      {
         d++;
      }
      else
      {
         d=0;
      }
   
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)                 //funcion que añade la nueva clave administrativa
{
int d=0;
 clave=0;                //pongo la clave tecleada a 0
 tecla=0;
//int fila=0;
//int columna=0;
   lcd_putc("\fNueva clave:\n");   //presentacion
   if(tecla!=0)
   {   
      lcd_putc("*");
      clave[d]=tecla;
      if(d<3)
      {
         escribir_clave_en_eeprom(d);   //guardamos la nueva clave en la memoria EEPROM
         d++;
      }
      else
      {
         d=0;
      }
      }
   
}


//////////ESCRIBIR_CLAVE_EN_EEPROM
void limpiar_clave()     //función que escribe las claves en la memoria eeprom

{
int k;
   for(k=0;k<3;k++)
     {
        clave[k]=0x00;
     }
}


//////////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 e + 0 (para no pisar datos) de la eeprom
   d++;                            //en una palabra escribe de la posicion 0 a la 2 (3 lugares)
}


//////////FUNCION ALARMA GENERAL
void alarma_general (void)

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

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #38 en: 22 de Marzo de 2013, 16:14:12 »
ok veamos checa los cambios que he echo

1.- En la funcion captura() no es necesario que la declares que regresa un valor int,en este caso modificas a la variable tecla y como es global no hace falta que regrese algún valor

2.- Coloque un mensaje en el display de "Escribir clave" despues del "Bienvenido inicial,ya que solo lo veo que lo tienes pero hasta que presionan una tecla

3.- La variable d,es global,no es necesario redeclararla,eso lo tienes para varias variables,checalo,si esta como global no tiene sentido redeclararla

4.- Cambie la forma en la que inicializas la variable clave,de clave=0 a clave[3]={'0','0','0'},es lo mismo en teoria pero no me fio jeje

5.- Coloque un delay de 500ms despues del mensaje de "Nueva Clave"

6.- Cambie el lugar donde tienes tu funcion de captura,solo la movi mas abajo,despues del main()

6.- En tu funcion que cambia la clave de administrador agregue un ciclo para asegurarnos que no salga de alli hasta que alla capturado los 3 nuevos valores y claro que los alla guardado

coloco el codigo checalo y prueba y ya me diras si va o no va


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 cambia_clave_inicial(void);       //funcion que cambia la clave iinicial
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);
void alarma_general(void);             //funcion que enciende la sirena


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

int flag_teclado;
int tecla,fila,columna;
char bandera=0;
char clave[3]={};                         //variable usada para recoger la clave tecleada y guardarla en ROM
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
//int e=0;
 
/***************************************
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;
   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;
  captura();
   }
   set_tris_b(0b11110000);
   output_b(0b00001111);
   clear_interrupt(INT_RB);
   set_tris_b(0b11110001);

}


//////////////INTERRUPCION EXTERNA//////////////////
#INT_EXT
void externa(void)
{
   bandera=1;
}


//////////////PROGRAMA PRINCIPAL///////////////////////
void main()
{
   set_tris_b(0b11110001);
   set_tris_c(0b11111111);       //configuro el puerto c
   enable_interrupts(INT_RB);
   ext_int_edge(H_TO_L);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   
   lcd_init();            //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
   lcd_putc("\fEscribir clave:\n");
   
   while(TRUE)
   {
   if(flag_teclado==1)
      {
flag_teclado=0;
cambia_clave_inicial();    //cambio la contraseña que viene por defecto
     
      }
    if(bandera==1)
      {
         bandera=0;
         alarma_general();
      }
   }
}   

/********************************
Esta Rutina permite rastrear el teclado
y devuelve el valor de la tecla que se
ha presionado
************************************/
void captura(void)
{
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];
return(tecla);
}
//////////FUNCION CAMBIAR CLAVE INICIAL
void cambia_clave_inicial(void)             //funcion que cambia clave administrativa
{
int p;
   
   escribir_clave();  //tecleo la contraseña
   if (d==3)
   {
      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();
          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();
          alarma_general ();        //activo la alarma
         }
   }
   
}

//////////FUNCION ESCRIBIR NUEVA CLAVE
void escribir_clave()            //funcion que escibre la clave tecleada
{
   lcd_putc("*");
   clave[d]=tecla;
      if(d<3)
      {
         d++;
      }
      else
      {
         d=0;
      }
   
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)                 //funcion que añade la nueva clave administrativa
{
 clave[3]={'0','0','0'};                //pongo la clave tecleada a 0
 tecla=0;
aux=0;
//int fila=0;
//int columna=0;
   lcd_putc("\fNueva clave:\n");   //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
while(tecla==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;
      }
   }
   
}


//////////ESCRIBIR_CLAVE_EN_EEPROM
void limpiar_clave()     //función que escribe las claves en la memoria eeprom
{
int k;
   for(k=0;k<3;k++)
     {
        clave[k]=0x00;
     }
}


//////////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 e + 0 (para no pisar datos) de la eeprom
   d++;                            //en una palabra escribe de la posicion 0 a la 2 (3 lugares)
}


//////////FUNCION ALARMA GENERAL
void alarma_general (void)
{
    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;
}
« Última modificación: 22 de Marzo de 2013, 16:52:19 por thegame »
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #39 en: 23 de Marzo de 2013, 08:47:43 »
Muchas gracias thegame! Las molestias y la atención que estas tomando conmigo no tienen precio. Pues he probado todo lo que me dijiste y solo he encontrado un par de fallos, uno lo he solucionado y el otro estoy en ello. Te comento punto a punto y asi nos entenderemos mejor:

1.- La función captura() la tengo que declarar que regresa un valor int ya que al final de la misma tenemos un return (tecla) y si la pongo como void me da error. Así que declarándola como int captura (void) funciona perfectamente

2.- Lo de escribir el mensaje "Escribir clave" es un detalle del que me había dado cuenta pero lo había ido dejando y ya no lo había puesto, gracias de todas formas

3.- Lo de la variable d no me había dado cuenta y la tenía declarada como global int d=0, por lo que tienes razon en que no tenía por qué redeclararla

4.- Me he dado cuenta que poner clave=0 o clave[3]={'0','0','0'} no es necesario ya que antes de ir a la función nueva_clave_admin tenemos la rutina limpiar_clave que ya deja la variable clave con todos sus valores a '0'

5.- Gracias por poner ese delay antes de "Nueva clave" ya que de esta manera queda mejor

6.- El mover el lugar de la función captura me ha gustado ya que yo también prefiero poner todas las funciones después del main ya que está todo mas ordenado, pero como empezamos haciéndolo así ya no la moví

7.- No había caido en lo del ciclo para asegurarnos de que no saliera hasta que hubiera capturado los tres valores. Los coge perfectamente pero al teclear el primer valor de la nueva variable en el display aparece un asterisco de sobra aunque en el arreglo solo aparece un valor (que es lo que quiero). El motivo es que el valor de la variable d viene con valor 0x03 de la anterior función. Así que si poniendo d=0 antes del mensaje "Nueva clave" se soluciona. Otro detalle del que me he dado cuenta es que en la función nueva clave admin hay que declarar la variable aux e igualarla a 0 que se nos había olvidado

Me he dado cuenta que mientras ingresamos la nueva clave la interrupción externa no funciona

De momento el código va así con todos los cambios hechos:

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////////////////////////////

int captura(void);
void cambia_clave_inicial(void);       //funcion que cambia la clave iinicial
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);
void escribir_clave_en_eeprom(int d);     //función que escribe las claves en la memoria eeprom
void alarma_general(void);             //funcion que enciende la sirena


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

int flag_teclado;
int tecla,fila,columna;
char bandera=0;
char clave[3]={};                         //variable usada para recoger la clave tecleada y guardarla en ROM
char clave_inicial[3]= {'1','2','3'};  //variable usada como clave de inicio                         
int d=0;


/***************************************
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;
   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;
     captura();
   }
   set_tris_b(0b11110000);
   output_b(0b00001111);
   clear_interrupt(INT_RB);
   set_tris_b(0b11110001);

}


//////////////INTERRUPCION EXTERNA//////////////////
#INT_EXT
void externa(void)
{
   bandera=1;
}


//////////////PROGRAMA PRINCIPAL///////////////////////
void main()
{
   set_tris_b(0b11110001);       //configuro el puerto b
   set_tris_c(0b11111111);       //configuro el puerto c
   enable_interrupts(INT_RB);
   ext_int_edge(H_TO_L);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   
   lcd_init();            //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
   lcd_putc("\fEscribir clave:\n");
   
   while(TRUE)
   {
   if(flag_teclado==1)
      {
      flag_teclado=0;
      cambia_clave_inicial();    //cambio la contraseña que viene por defecto
     
      }
    if(bandera==1)
      {
         bandera=0;
         alarma_general();
      }
   }
}   


/********************************
Esta Rutina permite rastrear el teclado
y devuelve el valor de la tecla que se
ha presionado
************************************/
int captura(void)
{
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];
return(tecla);
}


//////////FUNCION CAMBIAR CLAVE INICIAL
void cambia_clave_inicial(void)             //funcion que cambia clave administrativa
{
int p;
   
   escribir_clave();  //tecleo la contraseña
   if (d==3)
   {
      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();
          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();
          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)
      {
         d++;
      }
      else
      {
         d=0;
      }
   
}


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

   lcd_putc("\fNueva clave:\n");   //presentacion
   delay_ms(500);
   for(aux=0;aux<3;aux++)
   {
   while(tecla==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;
      }
     }
   }
   
}


//////////ESCRIBIR_CLAVE_EN_EEPROM
void limpiar_clave()     //función que escribe las claves en la memoria eeprom
{
int k;
   for(k=0;k<3;k++)
     {
        clave[k]=0x00;
     }
}


//////////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 e + 0 (para no pisar datos) de la eeprom
   d++;                            //en una palabra escribe de la posicion 0 a la 2 (3 lugares)
}


//////////FUNCION ALARMA GENERAL
void alarma_general (void)
{
    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;
}

De nuevo muchas gracias por todo ya que sin vuestra ayuda no se como estaría ahora. Muchas veces nos atascamos en algo durante tiempo y con la ayuda de otra persona se resuelve en un momento. Ya iré comentando mis avances y lo que vaya añadiendo al proyecto. Le quiero ir añadiendo lo que tenía hecho en el primer post que escribí, que en resumen es: añadir un menu y comparar ahora la clave tecleada con la que tengo en la eeprom para activar y desactivar la alarma
« Última modificación: 23 de Marzo de 2013, 13:51:15 por escarrillense »

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #40 en: 23 de Marzo de 2013, 16:04:58 »
hola compañero

ok lo que creo que pasa en el punto 1 acerca de la funcion es que como la tienes declarada en las definiciones de funciones,como que te regresa un c¿valor int,por eso marca el error al ponerla como void en el cuerpo de la funcion,hay que cambiar eso,ademas de que tienes que quitarle el return dentro de la misma,porque como anteriormente te comente,tecla es global y todas las funciones tienen acceso a ella por lo que el decirle que la regrese podria estar de mas,pero,si asi queda no hay problema jeje :D

ahora,lo del punto numero 4,tienes razon el arreglo se limpia antes.

lo que me causa intriga es lo de la interrupcion externa,tendrias que revisar si en algun momento deshabilitas la interrupcion o si se esta deshabilitando,esto lo puedes checar en el registro INTCON me parece,que es donde se ve si esta o no habilitada,lo puedes hacer en proteus o en el mismo MPLAB haciendo debug paso a paso y checando que pasa cuando entras en la rutina de cambio de clave,si se llegara a deshabilitar en ese punto,se tendria que agregar una instruccion de enable_interrupts(INT_EXT) para asegurar que no se deshabilite,pero primero checalo.

seguimos al pendiente por aqui.

saludos y suerte
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #41 en: 24 de Marzo de 2013, 06:33:00 »
Hola thegame!

He cambiado lo de la función captura. La he declarado como void captura (void) y quitado lo del return y funciona correctamente. No se que haría ayer mal.

En lo de la interrupción externa si que hay mas tela que cortar. Compruebo el INTCON y la interrupción está habilitada constantemente. Al pulsar el interruptor se ve en proteus como los pines cambian de estado pero ya no hace nada mas. Creo que el problema está en el while (tecla==0). El uso de whiles ya me ha dado problemas anteriormente cuando quería usar a la vez la interrupción externa, así que probaré otras formas de hacer lo mismo para no usar el while.

Un saludo y muchas gracias por todo

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #42 en: 24 de Marzo de 2013, 20:09:31 »
que tal compañero escarillense

mmm  :?,bueno el uso del while en esa parte del codigo lo coloque de manera que se mantuviera en el hasta que tecla cambiara,al ser tecla global si se daria cuenta del cambio de valor en la misma,pero tienes razon no es que no se dispare la interrupcion si no que como ocurre cuando tu programa esta atrapado en el while,regresa a ese mismo while y continua quedandose atrapado el flujo del programa jeje lo siento ese ha sido error mio,lo que podrias hacer es colocar dentro de la condicional tecla==0 una comparativa con la bandera  de la interrupcion es decir en ves de:

Código: [Seleccionar]
while(tecla==o);
colocar algo como;

Código: [Seleccionar]
while(tecla==0 && bandera==0);
de esta forma despues de cambiar el estado de bandera se saldria de ese while y ya no quedaria atrapado en el mismo,ahora despues de eso tendrias que colocar una llamada a la funcion que atiende cuando se dispara la interrupcion.

talves es lo que necesitas,yo no considere que se oprimiria la int_ext estando en la rutina de cambio de clave de admin,pense que ese proceso seria continuo hasta terminar de introducir la clave nueva de admin,pero con esa modificacion tambien se considera el caso que comentas,solo recuerda borrar el flag de bandera de la int_ext

saludos
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #43 en: 25 de Marzo de 2013, 06:03:57 »
Muchas gracias thegame! no se me había ocurrido lo de while(tecla==0 && bandera==0); , la verdad es que soy un poco torpe con las puertas lógicas, y solo con ese cambio el programa funciona correctamente. Una vez que salta la interrupción se produce el parpadeo del led como quería. Lo único que cuando salta la int_ext se añaden uno o dos '*' en el display según el número de teclas pulsadas que lleve y aparecen tres '*'. Es decir, si llevo una tecla pulsada se añaden dos '*' y si llevo dos teclas pulsadas se añade un '*'. Pero ni en el arreglo clave[3] ni en la eeprom se añade ningun valor.

He empezado con lo del menu y la comparación de claves. Lo que pretendo es que una vez guardada la nueva clave admin, ir a un menu en el cual segun la tecla pulsada podamos cambiar la clave o activar y desactivar la alarma. He conseguido que llegue al menu pero a la hora de introducir las funciones para que haga lo que quiero según la tecla pulsada me sale el siguiente error al compilar y no se que puede ser:
Recursion not permitted. The linker will not allow recursive function calls.  A function may not call itself and it may not call any other function that will eventually re-call it.

La estructura es la misma que cuando empecé con el proyecto en el primer post de este tema y al compliar no me salía dicho error.

Copio el programa para que le podais echar un vistazo. Saludos y muchas gracias

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

/***************************************
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
          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;
}
« Última modificación: 25 de Marzo de 2013, 08:56:05 por escarrillense »

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #44 en: 25 de Marzo de 2013, 15:06:30 »
pues si efectivamente lo he compilado y me sale lo mismo que a ti,al parecer estas haciendo que la funcion se llame a si misma jeje,al parecer el problema esta en la ubicación de la llamada a menu_principal(),normalmente este tipo de menus yo los he visto en el while infinito del main,es decir,dentro del main,ahora la pregunta es: quieres que siempre se muestre el menu??? o quieres que solo en ciertas situaciones se muestre?? o presionando una tecla en particular??? eso ya es facil,solo cambia la ubicacion de la llamada a la funcion de menu_principal(),si quieres que se vea siempre,ponlo dentro del while infinito,si quieres que se muestre con una tecla en particular (que para mi punto de vista seria lo ideal),solo coloca una condicional dentro del while infinito para que cuando se presione ese tecla se muestre el menu.

con eso se soluciona el problema de la compilacion,por ahi sale un warning referente a la deshabilitacion de alguna de las interrupciones,yo pienso que se refiere a la de cambio de estado del puerto B,recuerda que muchas operaciones dentro de una interrupcion no son muy recomendables,el manejo de banderas es lo que se recomienda,podrias igual que en la int_ext colocar una bandera en la de int_rb,y chequearla de la misma manera dentro del while infinito del main. con eso se quita el warning,aunque no te da problemas si lo dejas jeje

saludos y seguimos en contacto
Nunca se deja de aprender


 

anything