Manejar teclado matricial y mostrar en lcd

Buenas tardes compañeros del foro.

Estoy haciendo un juego y la parte primordial es la interfase LDC y teclado... con el usiario.

El problema que tengo es que al oprimir una tecla del teclado matricial 3x4, en la LCD me aparece como si hubiera oprimido la misma tecla muchas veces, o aparecen espacios en la LCD.
Estoy utilizando un PIC16F628A.
Este es mi código:

Código:
lcd_init();             // Se inicializa la pantalla
kbd_init();
while(1){             

   k=0;                    // Contador de teclas oprimidas
   claveOK=0;              // Se limpia la bandera de clave correcta
   
   do{                     // Ciclo infinito
   
  tecla=kbd_getc();
   
   if(tecla >= '0' && tecla <= '9'){  // Si se oprime una tecla numérica
      printf(lcd_putc,"%c",tecla);
      clave[k]=tecla;      // Se guarda el valor de la tecla oprimida
      k=k+1;               // Se incrementa el contador de teclas
      if(k == d){          // Si ya se oprimieron 4 teclas,
      
      for(k=0;k<=d-1;k++){         // Ciclo for de lectura de la EEPROM
      pass[k]=read_eeprom(k)+48; // Se lee el password de la EEPROM
                                 // cada valor se convierte a ASSCII
      }
      
      if(clave[0]== pass[0] &&   // Si la clave es correcta,
         clave[1]== pass[1] &&
         clave[2]== pass[2] &&
         clave[3]== pass[3] &&
         clave[4]== pass[4] &&
         clave[5]== pass[5] &&
         clave[6]== pass[6] &&
         clave[7]== pass[7] &&
         clave[8]== pass[8] &&
         clave[9]== pass[9] &&
         clave[10]== pass[10] &&
         clave[11]== pass[11] &&
         clave[12]== pass[12] &&
         clave[13]== pass[13] &&
         clave[14]== pass[14] &&
         clave[15]== pass[15])
         {
         claveOK=1;             // Se activa la bandera claveOK para salir del
                                // ciclo do-while
         delay_ms(1000);        //  Espera un segundo segundo
         lcd_putc('\f');         // Se borra la Pantalla
         lcd_putc("BOMB DROPPED ;)");
                                
         
      }
      else{              // Si la clave no es correcta,
      delay_ms(1000);        //  Espera un segundo segundo
      lcd_putc('\f');         // Se borra la Pantalla
      lcd_putc("INCORRECT");
      Lcd_gotoxy(1,2);        // Se ubica el cursor al principio de la línea 2
      lcd_putc("PASSWORD!"); // Se borra la línea
      delay_ms(1000);    // Espera 1 segundo
      k=0;               // Se limpia el contador de números introducidos
      lcd_putc('\f');         // Se borra la Pantalla
      lcd_putc("DROP THE BOMB:"); // Se imprime mensaje de para la activación
      lcd_gotoxy(1,2);     // Se ubica el cursor en la posición 9 de la línea 2
      }
         
      } 
   } 
   
   }while(claveOK == 0);
   
   
   
   }

La LCD están al mismo puerto B que el teclado.

El teclado que estoy usando lo hice yo con push-buttons nuevos.

No sé si la solución sea agregar capacitores en paralelo con cada interruptor :confused:

Sin más de momento espero me puedan echar una mano.

GRACIA:DS
 
Última edición:
Ese problema es debido a rebotes en las teclas.
Como lo hiciste con pulsadores sueltos, puedes colocar un capacitor de 470 nF (Tantalio) en cada uno.
Eso hará que el rebote se contenga, pero es mejor que uses un teclado de membrana plateada. Teclado de membrana plateada.JPG
Como no subiste el programa completo, (falta la parte de declaración de variables) aproveché para hacer algunos cambios, y supongo que tienes un arreglo para una clave de 16 dígitos, pero usas sólo 4.
También puse un retardo antirrebote para disminuir el efecto.

PHP:
#include <16f628a.h>
#use     delay(internal = 4MHz)

#include <lcd.c>
#define  use_portb_kbd 1
#include <kbd.c>

// El inicio de direcciones EEPROM en el 16F628A es 0x2100
// De ésta manera se obtiene la dirección en cualquier PIC
#rom getenv("EEPROM_ADDRESS") = {1,2,3,4}   // Clave en EEPROM interna.


void main (void)
{
   char d=4,k,clave[4],pass[4],claveOK,tecla;
   
   lcd_init();                            // Se inicializa la pantalla
   port_b_pullups(1);
   kbd_init();
   
   lcd_putc("\fIngresar clave:");

   while(true)
   {

      k=0;                                // Contador de teclas oprimidas
      claveOK=0;                          // Se limpia la bandera de clave correcta
   
      do                                  // Ciclo infinito
      {
         tecla=kbd_getc();
   
         if(tecla >= '0' && tecla <= '9') // Si se oprime una tecla numérica
         {
            delay_ms(50);                 // Antirrebote
            
            clave[k]=tecla;               // Se guarda el valor de la tecla oprimida
            k=k+1;                        // Se incrementa el contador de teclas
            lcd_gotoxy(k,2);
            printf(lcd_putc,"%c",tecla);
            
            if(k == d)                    // Si ya se oprimieron 4 teclas
            {
               for(k=0;k<d;k++)           // Ciclo for de lectura de la EEPROM
               {
                  pass[k]=read_eeprom(k)+48; // Se lee el password de la EEPROM
                                          // cada valor se convierte a ASSCII
               }
      
               if(clave[0]== pass[0] &&   // Si la clave es correcta,
               clave[1]== pass[1] &&
               clave[2]== pass[2] &&
               clave[3]== pass[3])
               {
         
               claveOK=1;                 // Se activa la bandera claveOK para salir del
               delay_ms(250);
                                          // ciclo do-while
               lcd_putc("\fBOMB DROPPED ;)");
               }
               else                       // Si la clave no es correcta,
               {
                  delay_ms(1000);         //  Espera un segundo segundo
                  lcd_putc("\fINCORRECT");
                  Lcd_gotoxy(1,2);        // Se ubica el cursor al principio de la línea 2
                  lcd_putc("PASSWORD!");  // Se borra la línea
                  delay_ms(1000);         // Espera 1 segundo
                  k=0;                    // Se limpia el contador de números introducidos
                  lcd_putc("\fDROP THE BOMB:"); // Se imprime mensaje de para la activación
                  lcd_gotoxy(1,2);        // Se ubica el cursor en la posición 9 de la línea 2
               }
            }
         }
      }
      while(claveOK == 0);
   }
}
 
Última edición:
Después de realizar algunas modificaciones al programa y al diseño, ya lo tengo funcionando.
Al parecer existe un bug con la instrucción port_b_pullups(true); al trabajar con el PIC16F887.
No activa las resistencias pull-up en el puerto B :unsure:
Como no había usado esa instrucción del PCWHD Compiler con este PIC, no lo había notado.

Adjunto el proyecto con las modificaciones realizadas para activar las resistencias pull-up en el puerto B,y trabajando con el oscilador interno a 8MHz.
Saludos.

Como me rompí la cabeza tratando de hacer andar el teclado por el puerto b en el PIC 16f886!!:cabezon:
no me había dado cuenta que no funcionaban las resistencias pull-up gracias a tu comentario pude solucionarlo, gracias!
 
Última edición:
Como me rompí la cabeza tratando de hacer andar el teclado por el puerto b en el PIC16F886!!:cabezon:
No me había dado cuenta que no funcionaban las resistencias pull-up gracias a tu comentario pude solucionarlo. Gracias!
Un poco tiempo después, vi que en el PIC16F886 / 7 y otros más, la instrucción port_b_pullups(); acepta un parámetro diferente al clásico "TRUE" que se coloca en otros PIC.

Éste parámetro es un valor de 8 bits (Un Byte) llamado "upmask"
Aquí debemos indicar los bits del puerto B a los cuales se les quiere poner resistencias pull-up interna.

Por ejemplo:
port_b_pullups(0b11110000);

Aquí tendrán activa la resistencia pull-up, los bits 7, 6, 5 y 4 del puerto B, y los bits 3, 2, 1 y 0, no la tendrán.

O sea que al PIC16F887 se le pueden activar la resistencias pull-up a cada pin independientemente.

Como siempre nos acostumbramos a usar: port_b_pullups(TRUE);, nunca se iban a activar las demás, porque el valor "TRUE" es igual a "1", por lo tanto únicamente se activaría la pull-up del bit 0 (RB0)

Entonces, dando como parámetro los bits que requieran pull-up, podemos activar las que necesitemos.
De esta forma ya no será requerido declarar los registros.

Siempre funcionó la instrucción port_b_pullups(), pero no se utilizó correctamente en éste PIC.
 
Te hago el comentario por que cuando hago alguna prueba con el proteus, si no pongo un retardo de minimo 250 ms, me salta muy rapido la pulsaciones, ojo esta claro que nunca he puesto en las pruebas ningun condensador, que por lo que estoy viendo, es necesario por lo de filtro.
 
El proceso debe ser rápido, no veo motivo para que se tenga que esperar la ejecución de tecla presionada.
Lo que si debe preocuparte son los rebotes, y obvio que con retardos altos se eliminan, pero ralentizas el proceso.
 
Pues a mi con 4Mhz 50ms era demasiado poco. Ahora utilizo esto como antirrabote. Teniendo en cuenta que el teclado se lee en la interrupción RB

#INT_RB
void RB_isr(void){
lee=(Input_B () & 0XF0)>>4;///esto hace que la lectura 16 a 255 pase de 1 a 15
clear_interrupt(INT_RB);
}
///////
void AntiRebote(int1 pulsa){
if(lee>0 || pulsa){//en caso contrario no hagas nada
lee=0;
disable_interrupts(INT_RB);
unsigned int8 rss;
//1//DISABLE RB Hasta que b4-7=0000 (siempre)
do{ rss=Input_B () & 0XF0; }while(rss>0); //No sale de aquí hasta mientras se mantenga pulsada //cualquier tecla
//2//pulsa=1 DISABLE RB Hasta que se pulse cualkier tecla (opcional)
if(pulsa){
do{ rss=Input_B () & 0XF0; }while(rss<1); }
clear_interrupt(INT_RB);
enable_interrupts(INT_RB);
} }

Eso si. Si lo que te interesa es que la lectura se repita manteniendo la tecla pulsada, esto nunca va a ocurrir.
 
Buen día

Estoy intentando hacer un teclado matricial 4x3 con el codificador 74C922 y el decodificador 7448. Conecte el teclado como aparece en el datasheet del codificador, pero tengo un problema que al presionar el botón "2" la salida en el display me aparece "1". Como podría solucionarlo para que cuando oprima un numero, el display me arroje el que es. Adjunto el circuito que tengo para ver si alguien me puede colaborar en darle solución.

Gracias!



Gracias por la respuesta! Seguire provando porque mis numeros van en columnas de 3 i el IC los da en columnas de 4, no se si me explico muy bien.

De todas formas, gracias por tu interes y ayuda!

Buen día

De casualidad pudiste darle solución a tu problema, porque yo también tengo el problema que cuando presiono el "2", el display me aparece el "1". Te agradecería si me dijeras como pudiste solucionarlo

Gracias.
 

Adjuntos

  • Matricial.rar
    18.8 KB · Visitas: 13
  • Teclado matricial 4x3.jpg
    Teclado matricial 4x3.jpg
    98.4 KB · Visitas: 17
Última edición:
La distribución y numeración de teclas no corresponde con las posibles conexiones que muestra la hoja de datos.
Para no modificar el componente "KEYPAD-PHONE", es mejor que lo hagas con pulsadores.

Algo así:
MM74C922.JPG
 
Es que la única manera en que cuadren las teclas, es modificando el componente.
De otra forma tendrás que interpretar los números de las teclas y hacer la conexión correcta.

Así quedaría y se mostrarán los dígitos en el orden que se muestra en la hoja de datos.
MM74C922 KEYPAD-4x4.jpg

Entonces el orden de las teclas sería el siguiente:
Tecla:
7 = 0
8 = 1
9 = 2
Entre = 3
4 = 4
5 = 5
6 = 6
X = 7
1 = 8
2 = 9
3 = 10
- = 11
C\ON = 12
0 = 13
= = 14
+ = 15

Y si lo quieres hacer con el teclado 3x4 "KEYPAD-PHONE", también tienes que modificar el orden de las conexiones.
 
El presente proyecto tiene como función, almacenar números en 16 posiciones de memoria.
Cuando llega a la posición 16, debe indicar lleno en el LCD.

El problema reside en que cuando estoy presionando el teclado y presiono 1,2,3, cuando llego a 3 todo sigue automáticamente y sólo se almacenan 3

El circuito y la programación están aquí abajo.

Gracias.
 

Adjuntos

  • eprom2.3.rar
    32.9 KB · Visitas: 12
Última edición por un moderador:
Buenos días Alcocer Garcia Felix Davi

En el esquema DSN que has posteado, los dos extremos del Cuarzo están conectados a Masa, de esta manera no podrá oscilar.

En cuanto al problema de la programación, seguramente algún compañero del foro te podrá ayudar, yo de programación se lo mismo que de "sexar" pollos.

Sal U2
 
Hola Alcocer
El problema de tu código es que no estas usando un anti rebote en la lectura del teclado
Podrias hacer asi:
PHP:
 Teclado:
        Tu codigo
        PAUSE 200; ANTI REBOTE
        return ' Retorna una línea después del llamado "Call" 
        END

O tambien Asi:
PHP:
Teclado:
        Tu codigo
        GOSUB ANTIREBOTE; ANTI REBOTE
        return ' Retorna una línea después del llamado "Call" 
        
 ;RUTINA ANTI REBOTE
       ANTIREBOTE:
       FOR R = 1 TO 200
        PAUSE 1
       NEXT R
       RETURN 

END
 
Hola colegas del foro, en estos dias me ubicaron pidiendome ayuda para la programacion de un pic18f4550, para mi sorpresa ya tenian el circuito armado las conecciones del teclado, lcd, ds1302 y demas sensores todo ya en fisico.

Al principio mi problema fue enviar datos al LCD4x20 porque usaron todo un PuertoD y PuertoE para el LCD, logre resolver esa parte pero ahora el problema es como les muestro en la imagen el Teclado 4x3.
Esta es la conexion por si no se ve la imagen.
Fila A >> RC2
Fila B >> RC6
Fila C >> RC1
Fila D >> RC0

Columna 1 >> RB2
Columna 2 >> RB3
Columna 3 >> RB4

Logre hacer un codigo para el teclado con esa configuracion de pines y ya me detecta los numeros y simbolos.
Pero cuando captura repite el numero varias veces.
Si alguien es tan amable de decirme que estoy haciendo mal o si tiene una libreria que pueda colocarle los pines en esa forma por favor ayudemne.

Estoy usando Picc Compiler

p2aFullKey4x3.c

HTML:
/*
Mapa de pines para el teclado 4x3 
RB2  COL0
RB3  COL1
RB4  COL2

RC0  FIL3
RC1  FIL2
RC2  FIL0
RC6  FIL1
*/

#BYTE PORTA = 0xF80
#BYTE PORTD = 0xF83
#BYTE PORTE = 0xF84
#BYTE TRISA = 0xF92
#BYTE TRISB = 0xF93
#BYTE TRISC = 0xF94
#BYTE TRISD = 0xF95
#BYTE TRISE = 0xF96


#BYTE PORTB = 0xF81
   #BIT RB0 = PORTB.0
   #BIT RB1 = PORTB.1
   #BIT RB2 = PORTB.2
   #BIT RB3 = PORTB.3
   #BIT RB4 = PORTB.4
   #BIT RB5 = PORTB.5
   #BIT RB6 = PORTB.6
   #BIT RB7 = PORTB.7
   
#BYTE PORTC = 0xF82
   #BIT RC0 = PORTC.0
   #BIT RC1 = PORTC.1
   #BIT RC2 = PORTC.2
   #BIT RC4 = PORTC.4
   #BIT RC5 = PORTC.5
   #BIT RC6 = PORTC.6
   #BIT RC7 = PORTC.7
   


void key_init(void);
unsigned char getkey(unsigned char kbd);
unsigned char rotabit(void);
unsigned char value, key;
static int1 kbd_down;
static char last_key;
   
   
void key_init(void){
   TRISB=0b00011100;   //RB2-RB4 com entradas
   TRISC=0b00111000;   //RC0-RC2, RC6 como salidas
   RC2 = 0; //A
   RC6 = 1; //B
   RC1 = 1; //C
   RC0 = 1; //D
}


unsigned char getkey(){
 
   
    last_key = rotabit();
    RC2 = 0;
    
    if(kbd_down) {
           kbd_down=FALSE;
           key=last_key;
           last_key='\0';
         
       }else{
         kbd_down = TRUE;
         
       }
    return key;
}
 
unsigned char rotabit(){ 
//pines      RC0 RC1 RC6 RC2
// incia en   1   1   1   0

     if(input_state(PIN_C2)==0){  
            RC6 = 1; //B
            RC1 = 1; //C
            RC0 = 1; //D
        
          delay_ms(5);
        if(RB2==0 && RB3==1 && RB4==1){
           
           value=1;
         //  return value;
          }
        if(RB2==1 && RB3==0 && RB4==1){
            
           value=2;
         //  return value;
          }
        if(RB2==1 && RB3==1 && RB4==0){
            
           value=3;
        //   return value;
           }
            RC2 = 1; //C
            RC6 = 0;
       //  return value;
      }//fin fila A
           
     
     if(input_state(PIN_C6)==0){
            RC2 = 1; //A
            RC1 = 1; //C
            RC0 = 1; //D
         
           delay_ms(5);
         if(RB2==0 && RB3==1 && RB4==1){
           
           value=4;
        //   return value;
          }
         if(RB2==1 && RB3==0 && RB4==1){
            
           value=5;
         //  return value;
          }
         if(RB2==1 && RB3==1 && RB4==0){
            
           value=6;
          // return value;
           }
             RC6 = 1;
            RC1 = 0;
       // return value;
      }//fin fila B
     
     if(input_state(PIN_C1)==0){
            RC2 = 1; //A
            RC6 = 1; //C
            RC0 = 1; //D
         
          delay_ms(5);
        if(RB2==0 && RB3==1 && RB4==1){
           
           value=7;
          // return value;
          } 
        if(RB2==1 && RB3==0 && RB4==1){
            
           value=8;
         //  return value;
          }
        if(RB2==1 && RB3==1 && RB4==0){
            
           value=9;
          // return value;
           }
            RC1 = 1;
            RC0 = 0;
           
        //return value;
      }//fin fila C
     
     if(input_state(PIN_C0)==0){
            RC2 = 1; //A
            RC1 = 1; //C
            RC6 = 1; //D
        
            delay_ms(5);
        if(RB2==0 && RB3==1 && RB4==1){
           
           value="*";
          // return value;
          }
        if(RB2==1 && RB3==0 && RB4==1){
            
           value=0;
          // return value;
          }
        if(RB2==1 && RB3==1 && RB4==0){
            
           value="#";
          // return value;
          }
             RC0 = 1;
            RC2 = 0;
            
       // return value;
      }//fin fila D
     
     return value;
}

main.c
HTML:
#include "C:\Documents and Settings\Administrador\Escritorio\Proyecto_vascula2016\cabecera.h"
/*****************************NO TOCAR ****************************************/

//*********Variables para las funciones del teclado

unsigned char k,NUM1,NUM2,NUM3,NUM4, tecla;
int x=4;




void sethora()
{
//Establece fecha y hora 
i2c_start(); //Inicia I2C 
i2c_write(0xd0); //Direcciona DS1307 write 
i2c_write(ds_seconds); //Indica que empiece en registro ds_seconds 
i2c_write(seconds); 
i2c_write(minutes); 
i2c_write(hours); 
i2c_write(control); 
i2c_stop(); //Ya puso la hora y fecha 
//El RTC ya está marcando el tiempo y fecha 
}

void setfecha()
{
//Establece fecha y hora 
i2c_start(); //Inicia I2C 
i2c_write(0xd0); //Direcciona DS1307 write 
i2c_write(ds_date); //Indica que empiece en registro ds_seconds 
i2c_write(date); 
i2c_write(month); 
i2c_write(year); 
i2c_write(control); 
i2c_stop(); //Ya puso la hora y fecha 
//El RTC ya está marcando el tiempo y fecha 
}

void cheqhr()
{                                    
    if(hours==0x0a)hours=0x10;
    if(hours==0x1a)hours=0x20;
    if(hours==0x24)hours=0x00;
}
void cheqmin()
{                                    
    if(minutes==0x0a)minutes=0x10;
    if(minutes==0x1a)minutes=0x20;
    if(minutes==0x2a)minutes=0x30;
    if(minutes==0x3a)minutes=0x40;
    if(minutes==0x4a)minutes=0x50;
    if(minutes==0x5a)minutes=0x00;
}
void cheqday()
{                                    
    if(date==0x0a)date=0x10;
    if(date==0x1a)date=0x20;
    if(date==0x2a)date=0x30;
    if(date==0x32)date=0x01;
}
void cheqmon()
{                                    
    if(month==0x0a)month=0x10;
    if(month==0x13)month=0x01;
}
void cheqyear()
{                                    
    if(year==0x1a)year=0x20;
    if(year==0x21)year=0x10;
}



/*FUNCION DE ASIGNA VALOR A VARIABLES POR CADA TECLA PULSADA  */
unsigned char ASIGVALOR(unsigned char t){

unsigned char k = t;
        
      if (x==4){
      NUM4=k;
    //  lcd_gotoxy(1,3);
    //  printf(lcd_putc,"NUM1:%d ",NUM1);
      //x=4;
      }
      else if (x==3){
      NUM3=k;
     // lcd_gotoxy(1,3);
     // printf(lcd_putc,"NUM2:%d ",NUM2);
     // x=1;
      }
      else if(x==2){
      NUM2=k;
     // lcd_gotoxy(1,3);
     // printf(lcd_putc,"NUM3:%d ",NUM3);
     // x=2;
      }
      else if(x==1){
      NUM1=k;
     // lcd_gotoxy(1,3);
    //  printf(lcd_putc,"NUM4:%d ",NUM4);
     // x=3;
      }
      
      lcd_gotoxy(1,3);
      printf(lcd_putc," %d%d%d%d ",NUM4, NUM3, NUM2, NUM1);
      return x;
}


void main(void){ 


   int16 centenas;               //variable para las centenas del ángulo
   int decenas,unidades;         //Variable para las decenas y unidades del ángulo
    int16 angulo;                 //Ángulo del servo
setup_adc_ports(NO_ANALOGS); 
setup_adc(ADC_OFF); 
setup_psp(PSP_DISABLED); 
setup_spi(FALSE); 
setup_timer_0(T0_OFF); 
setup_timer_1(T1_DISABLED); 
setup_timer_2(T2_DISABLED,0,1); 
setup_comparator(NC_NC_NC_NC); 


set_tris_A(0x20);
set_tris_B(0b00000000);
PORTA =0;
RB5 =0;
RB6 =0;
RB7 =0;
PORTC =0;

       lcd_init(); 
       key_init();
       lcd_putc("\f");
       lcd_putc("Teclado y LCD");
       
       
while(true){
     
     
       k=getkey();  
       
      if (k!=35&&k!=42){ //Solo se toman los valores numéricos
        
         do{           
            k=getkey();
            tecla=k;
               if (k!=42&&k!=35){    //Solo se toman los valores numéricos
                  centenas=decenas;
                  decenas=unidades;
                  unidades=tecla;
                  lcd_gotoxy(1,2);
                  printf(lcd_putc,"Angulo = %ld%d%d", centenas, decenas, unidades);
                  
                  angulo=(centenas*100)+(decenas*10)+unidades;
                  lcd_gotoxy(1,4);
                  printf(lcd_putc,"T. Angulo = %ld", angulo);
                }
          }while(x!=42)// fin do{}while (x!=42)
      
      }// fin if (k!=35&&k!=42)
 
    }//fin while tru principal
}//fin void main

cabecera.h
HTML:
#define PROYECTO_PIC18F4550

#if defined(PROYECTO_PIC18F4550)
  
   #include <18f4550.h>
   #device ADC = 10
   #Fuses  XT,NOWDT,NOPROTECT,NOLVP,NODEBUG,CPUDIV1,VREGEN,MCLR
  
   #use delay(clock=4M)
   
   #include "C:\Documents and Settings\Administrador\Escritorio\Proyecto_vascula2016\p2a_lcd.c"
   #include "C:\Documents and Settings\Administrador\Escritorio\Proyecto_vascula2016\p2aFullKey4x3.c"
   #use i2c(MASTER, SDA=PIN_b0, SCL=PIN_b1,slow) 

   #use fast_io(a)
   #use fast_io(b)
   #use fast_io(c)

   #define OFF    0
   #define ON     1   
   
//Registros DS1307 
#define ds_seconds 0x00 
#define ds_minutes 0x01 
#define ds_hours 0x02 
#define ds_day 0x03 
#define ds_date 0x04 
#define ds_month 0x05 
#define ds_year 0x06 
#define ds_control 0x07 

//DS1307 
//Vbat a tierra 

//// Declarando variables////////


//Dato en registro ds, a mandar o leer 
int seconds,minutes,hours,day,date,month,year,control;

#endif

p2a_lcd.c
HTML:
// Change these pins to fit your own board.

#define LCD_DB4 PIN_D4
#define LCD_DB5 PIN_D5
#define LCD_DB6 PIN_D6
#define LCD_DB7 PIN_D7

#define LCD_RS PIN_E0
#define LCD_RW PIN_D1
#define LCD_E  PIN_E1

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

//#define USE_LCD_RW 1

//========================================

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
  0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
  0xc, // Display on
  1, // Clear display
  6 // Increment cursor
};


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
  // Note: !! converts an integer expression
  // to a boolean (1 or 0).
  output_bit(LCD_DB4, !!(nibble & 1));
  output_bit(LCD_DB5, !!(nibble & 2));
  output_bit(LCD_DB6, !!(nibble & 4));
  output_bit(LCD_DB7, !!(nibble & 8));

  delay_cycles(1);
  output_high(LCD_E);
  delay_us(2);
  output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
  int8 retval;
  // Create bit variables so that we can easily set
  // individual bits in the retval variable.
  #bit retval_0 = retval.0
  #bit retval_1 = retval.1
  #bit retval_2 = retval.2
  #bit retval_3 = retval.3

  retval = 0;

  output_high(LCD_E);
  delay_cycles(1);

  retval_0 = input(LCD_DB4);
  retval_1 = input(LCD_DB5);
  retval_2 = input(LCD_DB6);
  retval_3 = input(LCD_DB7);

  output_low(LCD_E);

  return(retval);
}
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
  int8 low;
  int8 high;

  output_high(LCD_RW);
  delay_cycles(1);

  high = lcd_read_nibble();

  low = lcd_read_nibble();

  return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
  output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

  if(address)
  output_high(LCD_RS);
  else
  output_low(LCD_RS);

  delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

  output_low(LCD_E);

  lcd_send_nibble(n >> 4);
  lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
  int8 i;

  output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

  output_low(LCD_E);

  delay_ms(15);

  for(i=0 ;i < 3; i++)
  {
    lcd_send_nibble(0x03);
    delay_ms(5);
  }

  lcd_send_nibble(0x02);

  for(i=0; i < sizeof(LCD_INIT_STRING); i++)
  {
    lcd_send_byte(0, LCD_INIT_STRING[i]);

    // If the R/W signal is not used, then
    // the busy bit can't be polled. One of
    // the init commands takes longer than
    // the hard-coded delay of 60 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}

}

//----sab 01/10/16 se agrego funciones para LCD 4x16
//----PARA TRABAJAR CON LCD4X16 COMENTE LAS FUNCIONES -------
//---- lcd_gotoxy 
//---- lcd_putc
/*
void lcd_gotoxy(int8 x, int8 y)
{
  int8 address;

  if(y != 1)
  address = lcd_line_two;
  else
  address=0;

  address += x-1;
  lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
  switch(c)
  {
    case '\f':
      lcd_send_byte(0,1);
      delay_ms(2);
      break;

    case '\n':
      lcd_gotoxy(1,2);
      break;

    case '\b':
      lcd_send_byte(0,0x10);
      break;

    default:
      lcd_send_byte(1,c);
      break;
  }
}
*/
//------------------------------

//----PARA TRABAJAR CON LCD2X16 COMENTE LAS FUNCIONES -------
//----lcd_gotoxy 
//----lcd_putc 
//---- Tambien comente BYTE lcdline; busque por arriba

BYTE lcdline;
void lcd_gotoxy( BYTE x, BYTE y) {
   BYTE address;

   switch(y) {
 
     case 1 : address=0x80;break;
     case 2 : address=0xc0;break;
     case 3 : address=0x90;break;
     case 4 : address=0xd0;break;
  
   }
   address+=x-1;
   lcd_send_byte(0,address);
}

void lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   lcdline=1;
                   lcdline=2;
                   lcdline=3;
                   lcdline=4;
                   delay_ms(2);
                   break;
     case '\n'   : lcd_gotoxy(1,++lcdline);break;
     case '\b'   : lcd_send_byte(0,0x10);  break;
     default     : lcd_send_byte(1,c);     break;
   }
}


//------------------------------


#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
  char value;

  lcd_gotoxy(x,y);

  // Wait until busy flag is low.
  while(bit_test(lcd_read_byte(),7));

  output_high(LCD_RS);
  value = lcd_read_byte();
  output_low(lcd_RS);

  return(value);
}
#endif

void lcd_setcursor_vb(short visible, short blink) {
  lcd_send_byte(0, 0xC|(visible<<1)|blink);
}
 

Adjuntos

  • Imagen1.jpg
    Imagen1.jpg
    166.1 KB · Visitas: 17
  • xx.rar
    69.4 KB · Visitas: 12
hola ASDRUBAL2, te comento que el problema sucede debido a que tu rutina de lectura de teclado sigue enviando el valor de la tecla mientras esta se mantiene presionada.
aquí algunas modificaciones.

Rutina de lectura de teclado.
Código:
//retorna el codigo ascci asociado a la tecla presionada.
//retorna 0 si no se presiono alguna tecla
/***********************************
Mapa de pines para el teclado 4x3 
***********************************/
#define COL0 pin_b2  //RB2
#define COL1 pin_b3  //RB3
#define COL2 pin_b4  //RB4

#define FIL3 pin_c0  //RC0
#define FIL2 pin_c1  //RC1
#define FIL0 pin_c2  //RC2
#define FIL1 pin_c6  //RC6
/*************************************/
void key_init(void);
unsigned char getkey(unsigned char kbd);
   
void key_init(void)
{
   set_tris_b(0b00011100); //RB2-RB4 com entradas
   set_tris_c(0b00111000); //RC0-RC2, RC6 como salidas
//!   output_low(FIL0);//RC2 = 0; //A
//!   output_high(FIL1);//RC6 = 1; //B
//!   output_high(FIL2);//RC1 = 1; //C
//!   output_high(FIL3);//RC0 = 1; //D
}
unsigned char getkey()
{
   char tecla1=0;
   static char tecla0;
   output_low(FIL0);output_high(FIL1);output_high(FIL2);output_high(FIL3);
   if(input(COL0)==0){tecla1='1';}
   else if(input(COL1)==0){tecla1='2';}
   else if(input(COL2)==0){tecla1='3';}
   output_high(FIL0);output_low(FIL1);output_high(FIL2);output_high(FIL3);
   if(input(COL0)==0){tecla1='4';}
   else if(input(COL1)==0){tecla1='5';}
   else if(input(COL2)==0){tecla1='6';}
   output_high(FIL0);output_high(FIL1);output_low(FIL2);output_high(FIL3);
   if(input(COL0)==0){tecla1='7';}
   else if(input(COL1)==0){tecla1='8';}
   else if(input(COL2)==0){tecla1='9';}
   output_high(FIL0);output_high(FIL1);output_high(FIL2);output_low(FIL3);
   if(input(COL0)==0){tecla1='*';}
   else if(input(COL1)==0)
   {tecla1='0';}
   else if(input(COL2)==0){tecla1='#';}
   if(tecla1&&!tecla0){return tecla0=tecla1;}
   tecla0=tecla1;
   return 0;
}

Ejemplo de uso en la rutina main.
Código:
void main(void)
{
//!   int16 centenas;               //variable para las centenas del ángulo
//!   int decenas,unidades;         //Variable para las decenas y unidades del ángulo
//!   int16 angulo;                 //Ángulo del servo
   unsigned int16 angulo=0;
   char key;
   
   setup_adc_ports(NO_ANALOGS); 
   setup_adc(ADC_OFF); 
   setup_psp(PSP_DISABLED); 
   setup_spi(FALSE); 
   setup_timer_0(T0_OFF); 
   setup_timer_1(T1_DISABLED); 
   setup_timer_2(T2_DISABLED,0,1); 
   setup_comparator(NC_NC_NC_NC); 
   set_tris_A(0x20);
   set_tris_B(0b00000000);
   set_tris_C(0);
   output_a(0);//PORTA =0;
   output_low(pin_b5);//RB5 =0;
   output_low(pin_b6);//RB6 =0;
   output_low(pin_b7);//RB7 =0;
   output_c(0);//PORTC =0;
   lcd_init(); 
   key_init();
   lcd_putc("\f");
   lcd_putc("Teclado y LCD");    
   while(true)
   {     
      key=getkey();   
      if(key==0)
      {
         lcd_gotoxy(1,4);
         printf(lcd_putc,"T. Angulo = %lu",angulo);
      }
      else
      {
         angulo=angulo*10+(key&0x0f);
      }
      delay_ms(50);  //solo para que no haya problemas con la simulacion 
      
//!      if (k!=35&&k!=42)
//!      {
//!         do
//!         {
//!            k=getkey()&&0x0f;
//!            tecla=k;
//!            if(k!=42&&k!=35)
//!            {
//!               centenas=decenas;
//!               decenas=unidades;
//!               unidades=tecla;
//!               lcd_gotoxy(1,2);
//!               printf(lcd_putc,"Angulo = %ld%d%d", centenas, decenas, unidades);
//!               angulo=(centenas*100)+(decenas*10)+unidades;
//!               lcd_gotoxy(1,4);
//!               printf(lcd_putc,"T. Angulo = %ld", angulo);
//!            }
//!         }while(x!=42);
//!      }
   }
}
 
Atrás
Arriba