Mostrar valores de keypad 4x4 con PIC

#1
Hola a todos. He estado jugando un poco con PICC y el teclado matricial 4x4 y logré que la tecla presionada apareciera en un display 7 segmentos.
El siguiente paso que he intentado dar pero nada que sale, es poder guardar un número de tres cifras <=255 (8 bits) para poder mostrarlo en una pantalla o enviarlo como parámetro a una función cualquiera.
En la web ya he visto algunas métodos pero usan la librería especial para eso; eso es lo que no quiero.
Les dejo el código, ya está probado y funciona a la perfección.
Código:
#include "main.h"
#byte PORTB=6
#byte PORTD=8
void main()
{
   int teclado;
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_psp(PSP_DISABLED);
   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);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   set_tris_b(0x0F); //RB7_RB4 Salidas RB3_RB0 Entradas
   set_tris_d(0);
   portd=0xff;
   
   while(TRUE)
   {
      
      portb=0x00;
      portb=0x8F;
      
      if(input(pin_b3)==1)
      {
         teclado=0x01;
      }
      else
      {
         if(input(pin_b2)==1)
         {
            teclado=0x02;
         }
         else
         {
            if(input(pin_b1)==1)
            {
               teclado=0x03;
            }
            else
            {
               if(input(pin_b0)==1)
               {
                  teclado=0x0a;
               }
               else
               {
                  portb=0x4f;
                  if(input(pin_b3)==1)
                  {
                     teclado=0x04;
                  }
                  else
                  {
                     if(input(pin_b2)==1)
                     {
                        teclado=0x05;
                     }
                     else
                     {
                        if(input(pin_b1)==1)
                        {
                           teclado=0x06;
                        }
                        else
                        {
                           if(input(pin_b0)==1)
                           {
                              teclado=0x0b;
                           }
                           else
                           {
                              portb=0x2f;
                              if(input(pin_b3)==1)
                              {
                                 teclado=0x07;
                              }
                              else
                              {
                                 if(input(pin_b2)==1)
                                 {
                                    teclado=0x08;
                                 }
                                 else
                                 {
                                    if(input(pin_b1)==1)
                                    {
                                       teclado=0x09;
                                    }
                                    else
                                    {
                                       if(input(pin_b0)==1)
                                       {
                                          teclado=0x0c;
                                       }
                                       else
                                       {
                                          portb=0x1f;
                                          if(input(pin_b3)==1)
                                          {
                                             teclado=0x7e;
                                          }
                                          else
                                          {
                                             if(input(pin_b2)==1)
                                             {
                                                teclado=0x00;
                                             }
                                             else
                                             {
                                                if(input(pin_b1)==1)
                                                {
                                                   teclado=0x7e;
                                                }
                                                else
                                                {
                                                   if(input(pin_b0)==1)
                                                   {
                                                      teclado=0x0d;
                                                   }
                                                }
                                             }
                                          }
                                       }
                                    }
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
      }
      switch(teclado)
      {
         case 0: portd=0x01;
                 break;
         case 1: portd=0x4f;
                 break;
         case 2: portd=0x12;
                 break;
         case 3: portd=0x06;
                 break;
         case 4: portd=0x4c;
                 break;
         case 5: portd=0x24;
                 break;
         case 6: portd=0x20;
                 break;
         case 7: portd=0x0f;
                 break;
         case 8: portd=0x00;
                 break;
         case 9: portd=0x0c;
                 break;
         case 10: portd=0x08;
                  break;
         case 11: portd=0x60;
                  break;
         case 12: portd=0x31;
                  break;
         case 13: portd=0x42;
                  break;
         default: portd=0x7e;
                  break;
      }
    }
   
}
He pensado en hacer una función que acumule los valores ingresados.
Algo así
Código:
float valor_teclado()
{
    conta1++;                                    //los "conta" sirven para saber el numero de pulsaciones...supuestamente
    if(conta1>1)
    {
         conta2++;
         if(conta2>1)
         {
             conta3++;
             acc3=teclado;
         }
         else
         {
             acc2=10*teclado;
          }
    }
    else
    {
       acc1=100*teclado;
    }
   return (acc1+acc2+acc3);
}
Pero no funciona. Espero que me puedan ayudar para solucionar este problema.
Les agradezco mucho. Estoy usando el PIC16F877A
 
Última edición por un moderador:
#2
jaja me dio pereza leer tu codigo
pero digamos que vamos a leer un caracter digamos 1
lo pisamos y aparece en el display ¿no?

digamos que apretamos 123#

y queremos que despues de pisar # se muestre 123

¿como lo hacemos?

debemos hacer una condicional que valla leyendo y guardando en un array hasta que pisemos #
esto se hace asi:

void main()
{
//reservamos un array llamado tecla que guardara hasta la tecla #
char tecla[10];

//una variable de incremento
char i=0;


while(1)
{

while(tecla!='#')
{
//tu funcion para leer teclado
//lo que pongas se guardara en una variable llamada tecla

tecla=teclado;

i++;
}

//para mostrar el contenido

//reiniciamos el contador a 0
i=0;
while(tecla!=#)
{
//tu funcion para desplegar lo que hay en tecla

}
}
 
#3
Bienvenido a los foros de electrónica, @dchico3.

¿Cómo controlas que una tecla ha dejado de pulsarse?

Por favor, reedita tu mensaje y mete el código, formateado, entre marcas CODE o PHP, para que sea más fácil de leer.
 
#4
TRYLO-BYTE,
resulta que en mi programación al pulsar la tecla y encontrar la coincidencia de fila con columna guardo un número en una variable de tipo entero que yo nombre teclado. Para hacerlo con caracteres, debo entonces guardar un caracter en vez de un entero?
JoaquinFerrero
La verdad no sabría responder a tu pregunta, tal y como está el código al pulsar un botón este aparece en el display hasta que presiono otra tecla. Es decir, no tengo la necesidad de quedarme presionando el 1 para que aparezca, con solo una pulsación aparece en el display hasta que presione otra y el 7 seg cambia

Gracias a ambos por ayudarme en este tema :)
 
#5
Pero eso te impide meter números que tengan cifras repetidas, como por ejemplo '11'.

Lo que puedes hacer es inicializar el valor de teclado a un valor que signifique 'no pulsado' antes de entrar en los if() en cascada. De esa manera, si no hay nada pulsado, no entrará en el switch. Y de la misma manera, al saber que hay algo pulsado, puedes llamar a la rutina de control de entrada, para que sume un nuevo valor.

Bueno, se puede hacer de varias formas. Habría que tener en cuenta los posibles rebotes que el teclado pudiera crear.
 
#6
Vale, lo tendré en cuenta junto con el array de caracteres. Una pregunta más, así como puedo hacer un array de caracteres puedo hacer uno de enteros?

Gracias
 
#8
Bueno seguí los consejos del array pero con enteros. Entonces le agregué esto
PHP:
int tecla[10];
int i=0;
while(true)
{
    while(teclado!=0x7e)     //este valor se guarda cuando es pulsado * o #
    {
       función de teclado con if(), cuando se cierra el else grandote coloco
       tecla[i]=teclado;
       i++;
    }
    //Luego para visualizarlo en leds coloco
    i=0;
    for(i=0;i<=2;i++)
    {
        portc=tecla[i];            //Definiendo antes #byte portc=7 y set_tris_c(0)
        delay_ms(1000);
    }
    teclado=0;      //Reset para el ultimo valor que es 0x7e
    i=0;              //Reset contadora
}
La idea para probar que funcione es si ingreso 123# por el puerto c aparezca en binario 1, luego 2 y por ultimo 3...Pero no funciona :confused: . Me encantaría saber por qué?
 
#9
Están las cosas un poco mezcladas... un retraso de tiempo de 1 s puede liarte un poco a la hora de meter los datos (mientras está esperando, no está leyendo el teclado).

Lo ideal es que fuera algo así (no es la única manera):

  • Bucle infinito
    • Leer estado del teclado
    • Si hay una tecla pulsada
      • Si el estado anterior del teclado es de no haber estado pulsado,
        • tomamos la nueva tecla como la pulsada ahora
        • guardamos la tecla en el búfer de entrada
        • esperamos unos milisegundos para evitar rebotes
        • marcamos el estado de pulsación del teclado a verdadero
      • Si el estado anterior del teclado es de que ya estaba pulsado,
        • no hacemos nada (salvo que queramos tener en cuenta los casos de lectura de pulsaciones múltiples simultáneas -si el teclado lo permite-)
    • Si no hay una tecla pulsada
      • marcamos el estado de pulsación del teclado a falso
    • Presentamos el búfer en el puerto de salida
 
#10
Muy buenas a todos los amantes de los PICs ... pues mi consulta a lo siguiente y quisiera que me ayuden... talvez es algo simple... pero al punto my friends...
tengo el siguiente Codigo:

#include <16f887.h>
#fuses XT,NOWDT,NOPUT,NOLVP
#use delay (clock=4Mhz)

#include <kbd4x4.c>

#byte wpub=0x95
#byte option_reg=0x81

#byte portb=6
#byte portc=7
#byte portd=8


byte const display[10] = { 0b0000, 0b0001,0b0010,
0b0011,0b0100,
0b0101,0b0110,
0b0111,0b1000, 0b1001 };
char k;

void main () {

option_reg=0;
wpub=0B11111111;
kbd_init();

set_tris_a(0x00);
set_tris_c(0x00);
set_tris_d(0x00);
output_low(PIN_D0);

while (true) {

k=kbd_getc();

switch (k) {
case '0' : { portc=(display[8]);
break; }
case '1' : { portc=(display[1]);
break; }
case '2' : { portc=(display[3]);
break; }
case '3' : { portc=(display[6]);
break; }
default : { portc=0;
break; }
}
}

}

Ahora bien como pueden observar... de manera practica lo que deberia hacer el programa es selecccionar un caracter pulsado del TECLADO4X4 por lo que despues el valor obtenido tendria que entrar al SWITCH-CASE para luego seleccionar cualquiera de los casos presentes.. que en este caso es mostrar en un display de 7segmentos...

El problema resulta en que el SWITCH-CASE no reconoce dicha propuesta... por lo tanto para hacerlo mas facil... o que lo pueda agilizar de mejor manera hice otra alternativa... pero de la misma forma no funciona...:

Se declara un int x ; como variable global para luego realizar una conversión o eso pienso yo... apartir de k=kbd_getc() ; ----- x=k-48 ; ... esto daría como resultado un valor entero ya que estaría restando 48 al valor ASCII que se almacena en K... pero ya obteniendo el valor para X de forma entera este podria utilizar en el SWITCH-CASE mas facil manejando enteros... pero aun asi no ejecuta la simulacion de forma correcta... ya que no hace caso al valor de X pero tal fuera el caso de que utilice un IF (EJEMPLO IF( x == 2 ) ), el valor de X almacenado recien acepta la accion y la ejecuta...

Espero no haberles aburridos amigos... pero espero me puedan ayudar... les paso la simulacion mas pa que lo puedan probar ustedes y ver los resultados...

Adjunto la simulacion - la libreria KBD4X4 - y el CodiGo
:)(y)
 

Adjuntos

#13
Usé este simple código y funcionó sin problemas:
C:
#include <16F887.h>
#use delay (INTERNAL = 8 MHz)
#fuses NOFCMEN
#use fast_io (C)

#use RS232 (UART1)

#define use_portb_kbd    TRUE
#include "KBD4X4.C"

void main (void)
{
    char k;
    
    putc(0x00);
    delay_ms(100);
    printf("Teclado Matricial 4x4\r\n");
    
    port_b_pullups(0xFF);
    set_tris_c(0xF0);
    output_c(0x00);
    
    while (TRUE)
    {
        k = kbd_getc();
        
        if(k != '\0')
        {
            printf("Num Tecla = %c\r\n", k);
            printf("Val Tecla = %u\r\n", k);
            output_c(k);
        }
    }
}
Obviamente solo estoy usando el valor BCD, pero se puede usar la selección.

Adjunto el proyecto.
 

Adjuntos

Temas similares


Arriba