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

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

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Problema con interrupcion externa y teclado
« en: 28 de Febrero de 2013, 05:51:18 »
Hola buenas días!

Llevo un tiempo siguiendo este foro para aprender lenguaje C pero pocas veces me he animado a escribir en el.
Estoy creando un sistema de alarma mediante una contraseña y una interrupción. El programa funcionaba perfectamente,la parta de grabación y comprobación de contraseña, pero al añadirle la interrupción externa no me funciona y la parte de la interrupción por separado si. Es una cosa un poco rara porque si elimino el cable que une el pin del micro correspondiente a la interrupción del interruptor que la genera, el programa funciona correctamente excepto lo que es la interrupción.
Estoy utilizando un PIC16F876, la versión de Proteus que empleo es la 7.7 y el compilador es CCS.
Aquí les dejo el programa para ver si me podeis ayudar. Tambien adjunto los diferentes archivos del programa con la libreria del teclado y el esquema del circuito electrico.

#fuses XT            //Crystal osc <= 4mhz               
#fuses NOWDT         //deshabilita el Watch Dog Timer
#fuses NOPROTECT     //deshabilita la proteccion del codigo del pic
#fuses PUT           //habilita el reseteo de power up timer
#fuses NOLVP         //No Low Voltage Programming on B3(PIC16) or B5(PIC18,no habilita la programacion en bajo voltaje)
#fuses NOBROWNOUT    //No Reset when brownout detected

#use delay(clock = 4000000)

#use fast_io(A)       //con esta instruccion evitamos que
#use fast_io(B)       //se este configurando cada vez que usamos
#use fast_io(C)       //alguna instruccion de entrada o salida
#BYTE TRISA = 0b10000101   //TRISA = 0x85
#BYTE PORTA = 0b00000101   //PORTA = 0x05
#BYTE TRISB = 0b10000110   //TRISB = 0x86
#BYTE PORTB = 0b00000110   //PORTB = 0x06
#BYTE TRISC = 0b10000111   //TRISC = 0x87
#BYTE PORTC = 0b00000111   //PORTC = 0x07

#include <kbd3x4_2.c>         //libreria manejo keypad 3x4
#include <lcd3.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 menu_principal(void);             //funcion que muestra el menu principal
void escribir_clave(char clave[]);     //funcion que escibre la clave tecleada
void cambia_clave_inicial(void);       //funcion que cambia clave
void cambiar_clave(void);              //funcion que cambia clave
int comparar_claves(int);              //función que compara las claves
void nueva_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 escribir_clave_en_eeprom(int);    //función que escribe las claves en la memoria eeprom
void leer_clave_en_eeprom(int);        //función que lee las claves y las guarda en su correspondiente variable
void alarma_general(void);             //funcion que enciende la sirena
void conteo_intentos(void);            //funcion que cuenta el numero de intentos de ingreso de contraseña



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

char clave_inicial[3]= {'1','2','3'};  //variable usada como clave de inicio
char clave_eeprom_admin[3];            //variable usada para comparar los datos de la eeprom contra los datos ingresados             
char clave[3];                         //variable usada para recoger la clave tecleada
char k;                                //variable usada para recoger las teclas pulsadas del teclado
signed char i;                         //variable usada para movernos por las posiciones de la memoria
char clave_introducida[3]={};          //variable usada para los datos ingresados
int alarm_cont=0;                      //variable global que cuenta los fallos
int flag;                             //variable usada como bandera para las interrupciones


//////////////////LLAMADA FUNCION INTERRUPCION//////////////
#int_ext
void int_ext_isr(void)  //funcion que detecta la interrupcion

{
   /* //disable_interrupts(INT_EXT);
   //disable_interrupts(GLOBAL);
    flag=1;    //Se habilita la bandera cuando ocurre una interrupcion.
    //enable_interrupts(INT_EXT);
   //enable_interrupts(GLOBAL);*/
   
   /*set_tris_c(0b11100000);      //pines C0 hasta C4 como salida                             
    output_high(pin_C0);         //enciende la sirena durante 10 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;
    //desactivar_alarma();*/
   
    //clear_interrupt(int_ext);    //ponemos a '0' el flag
   
   int puerto_1;
   disable_interrupts(INT_ext); //deshabilita las interrupciones
   puerto_1 = PORTB & 0b00000001; //lee portb y lo guarda en puerto_1
      if(puerto_1!=0) //si se presionó una tecla (flanco hacia arriba)
      {
         output_b(0x00);                              //aclaro el puerto b
      }
   flag=1;
   set_tris_b(0b00001111);
   output_b(0x0f);
   clear_interrupt(INT_ext);
   enable_interrupts(INT_ext);
}



////////////////////PROGRAMA PRINCIPAL//////////////////////
void main()

{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   
   flag=0;                       //pongo la variable de la bandera a '0'
   set_tris_b(0b00001111);       //configuro el puerto b
   set_tris_c(0b11100000);       //configuro el puerto c
   port_b_pullups(true);         //activo las resistencias de pullup
   ext_int_edge(L_TO_H);         //activo la interrupcion externa por cambio de bajo a alto
   clear_interrupt(int_ext);     //pongo a '0' el flag de la interrupcion externa
   enable_interrupts(int_ext);   //habilito la interrupcion externa
   enable_interrupts(GLOBAL);    //habilito las interrupciones
   
   
   lcd_init();            //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
   
   
   while(true)
   {
     if(flag==1)
      {
         //disable_interrupts(int_ext);  //deshabilitamos la interrupcion externa
         //clear_interrupt(int_ext);     //ponemos a '0' el flag
         flag=0;                       //ponemos la variable flag a '0'
         delay_ms(20);                 //antirrebote
         alarma_general ();            //activamos la alarma
         flag=0;                       //ponemos la variable flag a '0'
         //enable_interrupts(int_ext);   //habilito la interrupcion externa
      }
      else
      {
         cambia_clave_inicial();    //cambio la contraseña que viene por defecto
         menu_principal();          //voy al menu principal
      }
   }
   
}


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

{
int p;
   clave_introducida=0;                //pongo la clave tecleada a 0
   escribir_clave(clave_introducida);  //tecleo la contraseña
   p=strcmp(clave_introducida , clave_inicial);    //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_introducida=0;      //borro la clave introducida
          //conteo_intentos();
          alarma_general ();        //activo la alarma
         }
}

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

{
int i=0;
   lcd_putc("\fEscribir clave:\n");   //presentacion
   do{
         do{               //espera hasta...
            k=kbd_getc();   
           }while(k==0);   //...pulsar una tecla
         
            if(!(k=='*' || k=='#')) // Si no es '*' o '#' en la pantalla aparece un '*'
            {     
            lcd_putc("*");
            clave=k;
            }       
     i++;
     
     }while( !(k=='*' || k=='#') );        //Si '*' o '#' señalamos que hemos terminado de introducir la contraseña
}



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

{
     for(; ;)
    {
      lcd_putc("\f0-Activa Alarma\n1-Cambia Clave");
      do{               //espera hasta...
         k=kbd_getc();   
         }while(k==0 || k==1);   //...pulsar una tecla
     
     switch (k)
     {
      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;
   escribir_clave(clave_introducida);  //escribimos la contraseña
   leer_clave_en_eeprom(i);            //lee la contraseña que antes hemos cambiado
   p=comparar_claves(i);               //compara ambas claves
   if (p==0)                           //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          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);
          clave_introducida=0;         //borra la clave ahora introducida
          alarma_general ();           //activa la alarma
         }
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)                 //funcion que añade la nueva clave administrativa

{
int i=0;
   lcd_putc("\fNueva clave:\n");   //presentacion
   do{
         do{               //espera hasta...
            k=kbd_getc();   
           }while(k==0);   //...pulsar una tecla
         
            if(k!='*' || k!='#')    // Si no es '*' o '#' en la pantalla aparece un '*'   
            {     
            lcd_putc("*");
            clave=k;
            }
     escribir_clave_en_eeprom(i);   //guardamos la nueva clave en la memoria EEPROM
     i++;
     
     }while( !(k=='*' || k=='#') );       //Si '*' o '#' señalamos que hemos terminado de introducir la contraseña
}


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

{
int i=0;
int s=0;
   for (i=0;i<3;i++)    //comparo caracter a caracter las claves
   {
      if (clave_introducida==clave_eeprom_admin)   //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'
}


//////////ACTIVAR ALARMA
void activar_alarma(void)           //funcion que activa la alarma

{
int i=0;
int p=0;
   escribir_clave(clave_introducida);     //escribimos la contraseña
   leer_clave_en_eeprom(i);               //lee la contraseña administrativa grabada anteriormente en la EEPROM
   p=comparar_claves(i);                  //compara ambas claves
   if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma Activada");
          delay_ms(2000);
          desactivar_alarma();            //vamos a la rutina para desactivar la alarma
         }
   if (p!=0)                                 //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          clave_introducida=0;               //borra la clave ahora introducida
          alarma_general ();                 //activo la alarma
         }
}


//////////DESACTIVAR ALARMA
void desactivar_alarma(void)           //funcion que desactiva la alarma

{
int i=0;
int p=0;
   lcd_putc("\fDesactivar alarma\n");   //presentacion
   escribir_clave(clave_introducida);  //escribimos la contraseña
   leer_clave_en_eeprom(i);            //lee la contraseña administrativa grabada anteriormente en la EEPROM
   p=comparar_claves(i);               //compara ambas claves
   if (p==0)                           //si son iguales...
         {lcd_putc("\fAlarma\nDesactivada");
          delay_ms(2000);
          break;                          //vuelve al menu principal
         }
   if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          clave_introducida=0;            //borra la clave ahora introducida
          alarma_general ();              //activo la alarma
         }
}


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

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


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

{
    for (i=0;i<3;i++)
    {
      clave_eeprom_admin = read_eeprom(i);      //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==3)
   {
      alarma_general();
   }
   else
   {
      alarm_cont++;
   }
}*/


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

{
    set_tris_c(0b11100000);      //pines C0 hasta C4 como salida                             
    output_high(pin_C0);         //enciende la sirena durante 10 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;
    //desactivar_alarma();
}

Muchas gracias por todo de antemano

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #1 en: 07 de Marzo de 2013, 05:40:01 »
Buenos días!

Aquí sigo con mi problema. Dándole muchas vueltas al asunto he descubierto que el problema creo que es la librería del teclado o como la gestiono en el programa ya que se produce un lío si a la vez el programa esta atento a la interrupción. Ya les informare de posibles avances o si alguien me puede ayudar se lo agradecería ya que llevo mucho tiempo atascado con este problema

Desconectado Vayadespiste

  • PIC12
  • **
  • Mensajes: 53
Re: Problema con interrupcion externa y teclado
« Respuesta #2 en: 08 de Marzo de 2013, 02:47:56 »
Hola, solo he mirado un poquito el archivo del teclado (no soy experto :( ) por lo poquito que he podido ver en la librería del teclado inicialmente está el nible bajo como entrada y con pull-up activado, es decir que inicialmente está a valor '1' y pasará a '0' cuando se pulsa a tecla. Por tanto la interrupción externa no se debería ver en el flanco que sube, por otra parte yo lo poco que  he usado una interrupción para teclado he usado la de cambio de estado (INTCONTbits.RBIE) y no la de entrada externa(INTCONbits.INT0IE).

Un saludo.

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #3 en: 08 de Marzo de 2013, 06:24:29 »
Muchas gracias Vayadespiste por tu atención! Creo que me explique mal en el primer post. La interrupción no la quiero generar con el teclado sino con el switch que está conectado a RB0, por eso utilizo la interrupción de entrada externa ya que será un evento que se producirá de forma puntual. El teclado sólo lo uso para la introducción de contraseñas, que es independiente de lo que es la interrupcion.
Lo del pull-up lo he quitado a ver si es el problema y sigue sin detectar la interrupción.

Un saludo y gracias

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con interrupcion externa y teclado
« Respuesta #4 en: 08 de Marzo de 2013, 09:30:03 »
  Creo que podría ser  de ayuda si colocas un esquema del circuito.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #5 en: 09 de Marzo de 2013, 14:17:22 »
Ok lo siento! pensaba que lo habia introducido en el .zip que adjunté en el primer post. En el que adjunto ahora he introducido algun cambio sin importancia como el traslado del lcd al puerto B pero ya lo he modificado en su libreria. ¿Podría ser el fallo la librería del teclado o como la gestiono en el programa la causa del problema de que no me detecte las teclas? El otro problema que tengo, el de la interrupción, me detecta la interrupción, entra en ella, pero luego no llega al main para leer el flag=1 de la rutina de la interrupción.  Vuelvo a poner el programa con alguna modificacion que he hecho pero sigue sin funcionar.

#fuses XT            //Crystal osc <= 4mhz               
#fuses NOWDT         //deshabilita el Watch Dog Timer
#fuses NOPROTECT     //deshabilita la proteccion del codigo del pic
#fuses PUT           //habilita el reseteo de power up timer
#fuses NOLVP         //No Low Voltage Programming on B3(PIC16) or B5(PIC18,no habilita la programacion en bajo voltaje)
#fuses NOBROWNOUT    //No Reset when brownout detected

#use delay(clock = 4000000)

#use fast_io(A)       //con esta instruccion evitamos que
#use fast_io(B)       //se este configurando cada vez que usamos
#use fast_io(C)       //alguna instruccion de entrada o salida
#BYTE TRISA = 0b10000101   //TRISA = 0x85 Registro de direccionamiento Puerto A
#BYTE PORTA = 0b00000101   //PORTA = 0x05 Puerto A
#BYTE TRISB = 0b10000110   //TRISB = 0x86 Registro de direccionamiento Puerto B
#BYTE PORTB = 0b00000110   //PORTB = 0x06 Puerto B
#BYTE TRISC = 0b10000111   //TRISC = 0x87 Registro de direccionamiento Puerto C
#BYTE PORTC = 0b00000111   //PORTC = 0x07 Puerto C
//#bit RB0=0x06.1
#byte kbd_port_b = 6

#include <kbd3x4_2.c>         //libreria manejo keypad 3x4
#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 menu_principal(void);             //funcion que muestra el menu principal
void escribir_clave(char clave[]);     //funcion que escibre la clave tecleada
void cambia_clave_inicial(void);       //funcion que cambia clave
void cambiar_clave(void);              //funcion que cambia clave
int comparar_claves(int);              //función que compara las claves
void nueva_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 escribir_clave_en_eeprom(int);    //función que escribe las claves en la memoria eeprom
void leer_clave_en_eeprom(int);        //función que lee las claves y las guarda en su correspondiente variable
void alarma_general(void);             //funcion que enciende la sirena
void conteo_intentos(void);            //funcion que cuenta el numero de intentos de ingreso de contraseña



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

char clave_inicial[3]= {'1','2','3'};  //variable usada como clave de inicio
char clave_eeprom_admin[3];            //variable usada para comparar los datos de la eeprom contra los datos ingresados             
char clave[3];                         //variable usada para recoger la clave tecleada
char k;                                //variable usada para recoger las teclas pulsadas del teclado
signed char i;                         //variable usada para movernos por las posiciones de la memoria
char clave_introducida[3]={};          //variable usada para los datos ingresados
int alarm_cont=0;                      //variable global que cuenta los fallos
//int flag;                              //variable usada como bandera para las interrupciones
static int flag;


//////////////////LLAMADA FUNCION INTERRUPCION//////////////
#INT_EXT
void int_ext_isr(void)  //funcion que detecta la interrupcion


     flag=1;    //Se habilita la bandera cuando ocurre una interrupcion.
     output_b(input_b()); // leer/escribir el puerto B al finalizar la interrupción para que no se vuelva a ejecutar
   
   
    /*set_tris_c(0b11111110);      //pines 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
    output_b(input_b());         // leer/escribir el puerto B al finalizar la interrupción para que no se vuelva a ejecutar
    clear_interrupt(int_ext);    //ponemos a '0' el flag*/
   
}



////////////////////PROGRAMA PRINCIPAL//////////////////////
void main()

{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   
   flag=0;                       //pongo la variable de la bandera a '0'
   set_tris_b(0b00001111);       //configuro el puerto b
   set_tris_c(0b11111111);       //configuro el puerto c
   //port_b_pullups(true);         //activo las resistencias de pullup
   ext_int_edge(L_TO_H);         //activo la interrupcion externa por cambio de bajo a alto
   clear_interrupt(int_ext);     //pongo a '0' el flag de la interrupcion externa
   enable_interrupts(int_ext);   //habilito la interrupcion externa
   enable_interrupts(GLOBAL);    //habilito las interrupciones
   
   lcd_init();            //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
   
    while(true)
   {
     
     if(flag==1)
      {
         disable_interrupts(int_ext);  //deshabilitamos la interrupcion externa
         clear_interrupt(int_ext);     //ponemos a '0' el flag
         delay_ms(20);                 //antirrebote
         alarma_general ();            //activamos la alarma
         flag=0;                       //ponemos la variable flag a '0'
         enable_interrupts(int_ext);   //habilito la interrupcion externa
         enable_interrupts(GLOBAL);    //habilito las interrupciones
         
      }
     else
      {
         cambia_clave_inicial();    //cambio la contraseña que viene por defecto
         menu_principal();          //voy al menu principal
      }
   }
}


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

{
int p;
   clave_introducida=0;                //pongo la clave tecleada a 0
   escribir_clave(clave_introducida);  //tecleo la contraseña
   p=strcmp(clave_introducida , clave_inicial);    //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_introducida=0;      //borro la clave introducida
          //conteo_intentos();
          alarma_general ();        //activo la alarma
         }
}
 
   
//////////FUNCION ESCRIBIR NUEVA CLAVE
void escribir_clave(char clave[])            //funcion que escibre la clave tecleada

{
int i=0;

   lcd_putc("\fEscribir clave:\n");   //presentacion
   do{
         do{               //espera hasta...
            k=kbd_getc();   
           }while(k==0);   //...pulsar una tecla
         
            if(!(k=='*' || k=='#')) // Si no es '*' o '#' en la pantalla aparece un '*'
            {     
            lcd_putc("*");
            clave=k;
            }       
     i++;
     
     }while( !(k=='*' || k=='#') );        //Si '*' o '#' señalamos que hemos terminado de introducir la contraseña
     
}



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

{
     for(;;)
    {
      lcd_putc("\f0-Activa Alarma\n1-Cambia Clave");
      do{               //espera hasta...
         k=kbd_getc();   
         }while(k==0 || k==1);   //...pulsar una tecla
     
     switch (k)
     {
      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;
   escribir_clave(clave_introducida);  //escribimos la contraseña
   leer_clave_en_eeprom(i);            //lee la contraseña que antes hemos cambiado
   p=comparar_claves(i);               //compara ambas claves
   if (p==0)                           //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          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);
          clave_introducida=0;         //borra la clave ahora introducida
          alarma_general ();           //activa la alarma
         }
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)                 //funcion que añade la nueva clave administrativa

{
int i=0;
   lcd_putc("\fNueva clave:\n");   //presentacion
   do{
         do{               //espera hasta...
            k=kbd_getc();   
           }while(k==0);   //...pulsar una tecla
         
            if(k!='*' || k!='#')    // Si no es '*' o '#' en la pantalla aparece un '*'   
            {     
            lcd_putc("*");
            clave=k;
            }
     escribir_clave_en_eeprom(i);   //guardamos la nueva clave en la memoria EEPROM
     i++;
     
     }while( !(k=='*' || k=='#') );       //Si '*' o '#' señalamos que hemos terminado de introducir la contraseña
}


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

{
int i=0;
int s=0;
   for (i=0;i<3;i++)    //comparo caracter a caracter las claves
   {
      if (clave_introducida==clave_eeprom_admin)   //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'
}


//////////ACTIVAR ALARMA
void activar_alarma(void)           //funcion que activa la alarma

{
int i=0;
int p=0;
   escribir_clave(clave_introducida);     //escribimos la contraseña
   leer_clave_en_eeprom(i);               //lee la contraseña administrativa grabada anteriormente en la EEPROM
   p=comparar_claves(i);                  //compara ambas claves
   if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma Activada");
          delay_ms(2000);
          desactivar_alarma();            //vamos a la rutina para desactivar la alarma
         }
   if (p!=0)                                 //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          clave_introducida=0;               //borra la clave ahora introducida
          alarma_general ();                 //activo la alarma
         }
}


//////////DESACTIVAR ALARMA
void desactivar_alarma(void)           //funcion que desactiva la alarma

{
int i=0;
int p=0;
   lcd_putc("\fDesactivar alarma\n");   //presentacion
   escribir_clave(clave_introducida);  //escribimos la contraseña
   leer_clave_en_eeprom(i);            //lee la contraseña administrativa grabada anteriormente en la EEPROM
   p=comparar_claves(i);               //compara ambas claves
   if (p==0)                           //si son iguales...
         {lcd_putc("\fAlarma\nDesactivada");
          delay_ms(2000);
          break;                          //vuelve al menu principal
         }
   if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          clave_introducida=0;            //borra la clave ahora introducida
          alarma_general ();              //activo la alarma
         }
}


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

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


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

{
    for (i=0;i<3;i++)
    {
      clave_eeprom_admin = read_eeprom(i);      //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==3)
   {
      alarma_general();
   }
   else
   {
      alarm_cont++;
   }
}*/


//////////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;
    //desactivar_alarma();
}
« Última modificación: 09 de Marzo de 2013, 14:42:28 por escarrillense »

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Problema con interrupcion externa y teclado
« Respuesta #6 en: 09 de Marzo de 2013, 15:02:41 »
yo que tú, eliminaría todo lo que pudiera dentro de la interrupción, ese retardo de 2 segundos en una interrupción no es conveniente, me imagino que habrá veces que el teclado no responderá.

yo dejaría solo banderas dentro de la interrupción y crearía una función abajo que comprobaría la bandera y haría el resto.

y para complicar (mejorar) mas el asunto, trataría el teclado por interrupción del nibble alto del portb

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #7 en: 09 de Marzo de 2013, 15:15:27 »
Muchas gracias! la parte de codigo donde sale el delay de 2 segundos la tenia anulada y al copiar el codigo no me he acordado de borrarlo, lo siento. Estudiaré lo de tratar el teclado por interrupción del nibble alto, era algo que ya tenia en mente.
 Muchas gracias y aun así se admiten sugerencias

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #8 en: 09 de Marzo de 2013, 19:56:16 »
Hola! He probado lo que me contestaste PalitroqueZ y continua si funcionar. Presiono las teclas y no consigo que entre en la interrupcion de nibble alto del portb

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Problema con interrupcion externa y teclado
« Respuesta #9 en: 10 de Marzo de 2013, 22:22:21 »
podrías poner el último código ya corregido, porque no entiendo, al principio pusiste un código y después resulta que lo corregiste y total que no se entiende bien cual es el problema.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #10 en: 11 de Marzo de 2013, 05:50:29 »
Perdon a todos! Llevo un par de meses con este problema y despues de hacer tantos cambios y probar tantas cosas ya no se ni lo que guardo ni lo que subo al foro y ya casi ni lo que hago!
El programa funcionaba correctamente, lo que es la parte de introducción de contraseñas mediante el teclado y la comprobación de las mismas. El problema vino al introducir la interrupción externa ya que ya no me detecta las teclas que pulso. El otro problema que tengo, es que detecta la interrupción externa, pero no llega a ir al main para leer la bandera que he puesto en la interrupción a 1 y que se produzca el parpadeo del led, sino que me manda a la libreria del teclado y como no me detecta las teclas pues poco puedo hacer.
Vuelvo a poner el codigo y adjunto todos los archivos y librerias que estoy usando. Voy a seguir probando lo que me dijiste PalitroqueZ del nibble alto pero el otro día no me funcionaba
Muchas gracias y perdon por las molestias que esta causando el caos que llevo en la cabeza

#fuses XT            //Crystal osc <= 4mhz               
#fuses NOWDT         //deshabilita el Watch Dog Timer
#fuses NOPROTECT     //deshabilita la proteccion del codigo del pic
#fuses PUT           //habilita el reseteo de power up timer
#fuses NOLVP         //No Low Voltage Programming on B3(PIC16) or B5(PIC18,no habilita la programacion en bajo voltaje)
#fuses NOBROWNOUT    //No Reset when brownout detected

#use delay(clock = 4000000)

#use fast_io(A)       //con esta instruccion evitamos que
#use fast_io(B)       //se este configurando cada vez que usamos
#use fast_io(C)       //alguna instruccion de entrada o salida
#BYTE TRISA = 0b10000101   //TRISA = 0x85 Registro de direccionamiento Puerto A
#BYTE PORTA = 0b00000101   //PORTA = 0x05 Puerto A
#BYTE TRISB = 0b10000110   //TRISB = 0x86 Registro de direccionamiento Puerto B
#BYTE PORTB = 0b00000110   //PORTB = 0x06 Puerto B
#BYTE TRISC = 0b10000111   //TRISC = 0x87 Registro de direccionamiento Puerto C
#BYTE PORTC = 0b00000111   //PORTC = 0x07 Puerto C
//#bit RB0=0x06.1
#byte kbd_port_b = 6

#include <kbd3x4_2.c>         //libreria manejo keypad 3x4
#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 menu_principal(void);             //funcion que muestra el menu principal
void escribir_clave(char clave[]);     //funcion que escibre la clave tecleada
void cambia_clave_inicial(void);       //funcion que cambia clave
void cambiar_clave(void);              //funcion que cambia clave
int comparar_claves(int);              //función que compara las claves
void nueva_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 escribir_clave_en_eeprom(int);    //función que escribe las claves en la memoria eeprom
void leer_clave_en_eeprom(int);        //función que lee las claves y las guarda en su correspondiente variable
void alarma_general(void);             //funcion que enciende la sirena
void conteo_intentos(void);            //funcion que cuenta el numero de intentos de ingreso de contraseña



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

char clave_inicial[3]= {'1','2','3'};  //variable usada como clave de inicio
char clave_eeprom_admin[3];            //variable usada para comparar los datos de la eeprom contra los datos ingresados             
char clave[3];                         //variable usada para recoger la clave tecleada
char k;                                //variable usada para recoger las teclas pulsadas del teclado
signed char i;                         //variable usada para movernos por las posiciones de la memoria
char clave_introducida[3]={};          //variable usada para los datos ingresados
int alarm_cont=0;                      //variable global que cuenta los fallos                             
static int flag;                       //variable usada como bandera para las interrupciones


//////////////////LLAMADA FUNCION INTERRUPCION//////////////
#INT_EXT
void int_ext_isr(void)  //funcion que detecta la interrupcion


     flag=1;    //Se habilita la bandera cuando ocurre una interrupcion.
     output_b(input_b()); // leer/escribir el puerto B al finalizar la interrupción para que no se vuelva a ejecutar
}



////////////////////PROGRAMA PRINCIPAL//////////////////////
void main()

{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   
   flag=0;                       //pongo la variable de la bandera a '0'
   set_tris_b(0b00001111);       //configuro el puerto b
   set_tris_c(0b11111111);       //configuro el puerto c
   port_b_pullups(true);         //activo las resistencias de pullup
   ext_int_edge(L_TO_H);         //activo la interrupcion externa por cambio de bajo a alto
   clear_interrupt(int_ext);     //pongo a '0' el flag de la interrupcion externa
   enable_interrupts(int_ext);   //habilito la interrupcion externa
   enable_interrupts(GLOBAL);    //habilito las interrupciones
   
   lcd_init();            //inicializa lcd
   delay_ms(1000);
   lcd_putc ("   Bienvenido   ");
   delay_ms(1000);
   
    while(true)
   {
     
     if(flag==1)
      {
         disable_interrupts(int_ext);  //deshabilitamos la interrupcion externa
         clear_interrupt(int_ext);     //ponemos a '0' el flag
         delay_ms(20);                 //antirrebote
         alarma_general ();            //activamos la alarma
         flag=0;                       //ponemos la variable flag a '0'
         enable_interrupts(int_ext);   //habilito la interrupcion externa
         enable_interrupts(GLOBAL);    //habilito las interrupciones
         
      }
     else
      {
         cambia_clave_inicial();    //cambio la contraseña que viene por defecto
         menu_principal();          //voy al menu principal
      }
   }
}


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

{
int p;
   clave_introducida=0;                //pongo la clave tecleada a 0
   escribir_clave(clave_introducida);  //tecleo la contraseña
   p=strcmp(clave_introducida , clave_inicial);    //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_introducida=0;      //borro la clave introducida
          alarma_general ();        //activo la alarma
         }
}
 
   
//////////FUNCION ESCRIBIR NUEVA CLAVE
void escribir_clave(char clave[])            //funcion que escibre la clave tecleada

{
int i=0;

   lcd_putc("\fEscribir clave:\n");   //presentacion
   do{
         do{               //espera hasta...
            k=kbd_getc();   
           }while(k==0);   //...pulsar una tecla
         
            if(!(k=='*' || k=='#')) // Si no es '*' o '#' en la pantalla aparece un '*'
            {     
            lcd_putc("*");
            clave=k;
            }       
     i++;
     
     }while( !(k=='*' || k=='#') );        //Si '*' o '#' señalamos que hemos terminado de introducir la contraseña
     
}



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

{
     for(;;)
    {
      lcd_putc("\f0-Activa Alarma\n1-Cambia Clave");
      do{               //espera hasta...
         k=kbd_getc();   
         }while(k==0 || k==1);   //...pulsar una tecla
     
     switch (k)
     {
      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;
   escribir_clave(clave_introducida);  //escribimos la contraseña
   leer_clave_en_eeprom(i);            //lee la contraseña que antes hemos cambiado
   p=comparar_claves(i);               //compara ambas claves
   if (p==0)                           //si son iguales...
         {lcd_putc("\fClave Correcta\n");
          delay_ms(2000);
          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);
          clave_introducida=0;         //borra la clave ahora introducida
          alarma_general ();           //activa la alarma
         }
}


//////////FUNCION NUEVA CLAVE
void nueva_clave_admin(void)                 //funcion que añade la nueva clave administrativa

{
int i=0;
   lcd_putc("\fNueva clave:\n");   //presentacion
   do{
         do{               //espera hasta...
            k=kbd_getc();   
           }while(k==0);   //...pulsar una tecla
         
            if(k!='*' || k!='#')    // Si no es '*' o '#' en la pantalla aparece un '*'   
            {     
            lcd_putc("*");
            clave=k;
            }
     escribir_clave_en_eeprom(i);   //guardamos la nueva clave en la memoria EEPROM
     i++;
     
     }while( !(k=='*' || k=='#') );       //Si '*' o '#' señalamos que hemos terminado de introducir la contraseña
}


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

{
int i=0;
int s=0;
   for (i=0;i<3;i++)    //comparo caracter a caracter las claves
   {
      if (clave_introducida==clave_eeprom_admin)   //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'
}


//////////ACTIVAR ALARMA
void activar_alarma(void)           //funcion que activa la alarma

{
int i=0;
int p=0;
   escribir_clave(clave_introducida);     //escribimos la contraseña
   leer_clave_en_eeprom(i);               //lee la contraseña administrativa grabada anteriormente en la EEPROM
   p=comparar_claves(i);                  //compara ambas claves
   if (p==0)                              //si son iguales...
         {lcd_putc("\fAlarma Activada");
          delay_ms(2000);
          desactivar_alarma();            //vamos a la rutina para desactivar la alarma
         }
   if (p!=0)                                 //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          clave_introducida=0;               //borra la clave ahora introducida
          alarma_general ();                 //activo la alarma
         }
}


//////////DESACTIVAR ALARMA
void desactivar_alarma(void)           //funcion que desactiva la alarma

{
int i=0;
int p=0;
   lcd_putc("\fDesactivar alarma\n");   //presentacion
   escribir_clave(clave_introducida);  //escribimos la contraseña
   leer_clave_en_eeprom(i);            //lee la contraseña administrativa grabada anteriormente en la EEPROM
   p=comparar_claves(i);               //compara ambas claves
   if (p==0)                           //si son iguales...
         {lcd_putc("\fAlarma\nDesactivada");
          delay_ms(2000);
          break;                          //vuelve al menu principal
         }
   if (p!=0)                              //si son distintas...
         {lcd_putc("\fClave Incorrecta\n");
          delay_ms(2000);
          clave_introducida=0;            //borra la clave ahora introducida
          alarma_general ();              //activo la alarma
         }
}


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

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


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

{
    for (i=0;i<3;i++)
    {
      clave_eeprom_admin = read_eeprom(i);      //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)

{
    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
    alarm_cont = 0;              //pongo a cero el contador de errores
}
« Última modificación: 11 de Marzo de 2013, 06:01:51 por escarrillense »

Desconectado thegame

  • PIC18
  • ****
  • Mensajes: 439
    • Mcu Tronics
Re: Problema con interrupcion externa y teclado
« Respuesta #11 en: 11 de Marzo de 2013, 17:19:56 »
Bueno que yo sepa lo de leer o escribir el puerto B se hace para la interrupcion por cambio de estado en el puerto B no para la interrupcion externa.

Ahora,cuando abro tu archivo en proteus veo que segun el codigo debes tener las pullups habilitadas en el puerto B,sin embargo en proteus no se mantienen de echo papadean van de tierra a vcc continuamente,desconozco si en lo que programaste,solo le di un vistazo rapido.

Por ultimo,yo no me confiaria de la funcion clear_interrupt() para borrar el flag de interrupcion,ya me paso,yo checaria directamente el bit en el registro de interrupcion y veria si se mantiene o si efectivamente se limpia.

ahora que tenga mas tiempo lo simulo con mas calma y si puedo aportar mas lo hare vale

Saludos y no desesperes que ya saldra
Nunca se deja de aprender

Desconectado escarrillense

  • PIC10
  • *
  • Mensajes: 41
Re: Problema con interrupcion externa y teclado
« Respuesta #12 en: 12 de Marzo de 2013, 06:03:22 »
Hola a todos!Aquí sigo con mi lucha.

Lo de leer o escribir el puerto B lo puse porque solo escribiendo flag=1 no me funcionaba e investigando por el foro lo encontré y lo puse por probar, pero no sabía que solo se sirve para la interrupción por cambio de estado en el puerto B (otra cosa mas que ya he aprendido).

Lo del parpadeo de las pull-ups también me tiene bastante intrigado pero por lo menos he conseguido que me detecte las teclas. Y la solución ha sido sustituir el pull-up que tenía montado en Proteus por una pull-down.La interrupción externa sigue sin funcionar, no la detecta, no se si por problemas de rebotes o por otro motivo, así que seguiré probando cosas.Adjunto el nuevo archivo de Proteus

muchas gracias por intentar ayudarme.

Intento no desesperar y seguir luchando. Un saludo
« Última modificación: 12 de Marzo de 2013, 08:40:48 por escarrillense »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con interrupcion externa y teclado
« Respuesta #13 en: 12 de Marzo de 2013, 09:41:50 »
  Pido disculpas por si esta intervención ocasiona mas dudas. pero... o yo no estoy entendiendo bien el programa o hay algo mal.

  Dentro del while, se chequea si la variable flag es 1 y de ser así se activa la alarma.
  Si flag es 0, se ingresa siempre al cambio de clave inicial y también se ingresa siempre al menu principal.
  Menu principal es un ciclo infinito, por lo tanto nunca podrías atender el flag generado por la interrupción externa. Creo que dicho flag deberías evaluarlo dentro de la rutina del menu principal.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Problema con interrupcion externa y teclado
« Respuesta #14 en: 12 de Marzo de 2013, 13:41:12 »
escarrillense he probado el último archivo que subiste y al parecer no hay problemas con el teclado. pero hay un par de cosas que desde mi punto de vista no haría.

- colocar los mismos pines del teclado para la pantalla lcd, las librerías del teclado configuran sus pines para una función especifica, y entonces la librería de la lcd hace lo mismo. Habría que estudiar a fondo ambas librerías y determinar si no hay un "choque" de configuración de pines cuando cada periférico le toque hacer uso de esos 4 pines del portb.

- la linea

output_b(input_b()); // leer/escribir el puerto B al finalizar la interrupción para que no se vuelva a ejecutar

dentro de int_ext no comprendo su utilidad, en la datasheet de estos pic, mencionan limpiar el puerto, pero es cuando se está utilizando la interrupcion del nibble alto del portb y la libreria kbd3x4_2.c no hace uso de interrupciones.

si quieres usar correctamente la interrupción por cambio de flanco del pin rb0, los pasos son los siguientes:

- definir rb0 como entrada (usar el trisb con precaución, sin alterar el estado de los otros pines)
- definir el flanco mediante ext_int_edge();
- configurar la interrupción.
- colocar solo el flag en int_ext
- colocar una rutina o funcion en main que pregunte por ese flag
-- si es muy importante atender esa interrupción, entonces apagar las interrupciones globalmente, sino, apagar solo la de int_ext
-- hacer lo que quieras hacer con esa interrupcion
-- antes de salir de esa función, apagar banderas y usar clear_interrupt(INT_EXT);
- a nivel de hardware es preferible usar pull-up externas, aquí en el foro han habido reportes de problemas con pull-up internas, entonces es preferible sacrificar unos milímetros de espacio en el pcb y poner unas resistencia de 1/8w a que lidiar con los bugs del pic o del compilador.

la librería que estás usando está correcta, si te funciona esa librería entonces no hay necesidad de complicarse (aunque en el futuro descubrirás que es mejor usar el teclado por interrupciones).

en resumen, creo que lo que está causando problemas es esa dualidad del nibble alto del portb, y como dices que llevas tiempo con ese problema, lo mejor es rediseñar el hardware y reescribir el código.


saludos


La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek