desktop

Mostrar valores de keypad 4x4 con PIC

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

}
}
 
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.
 
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 :)
 
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.
 
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
 
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é?
 
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
 
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

  • Teclado Matricial 4X4.rar
    70.3 KB · Visitas: 11
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

  • Teclado Matricial 4x4.rar
    30.3 KB · Visitas: 18
Buenas. Soy nuevo en este foro.
Verán, tengo una duda. Debo realizar un código en PIC16F877A que funcione como multiplexado u otra forma para que los números que digite se muevan de derecha a izquierda empleando dos displays de 7 segmentos.
He iniciado un código pero en la simulación en la parte de que debe moverse el número me genera problemas.
Me gustaría que pudieran ayudarme.
Código:
list p=16F877A             

include <P16F877A.INC>                                         





__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _RC_OSC & _WRT_OFF & _LVP_ON & _CPD_OFF ;(__config h'3f18')


;zona de mencion de variables.

CONT equ h'02'

cblock h'20'            ; Dentro de este cblock y endc, podemos definir nuestras variables. Más información sobre esto, más adelante.


    _button            ; esta variable se utiliza para identificar qué botón hemos presionado.

    _butto


    endc            ; Ese es el fin de definir nuestras variables.


org h'0000'; Esta línea solo le dice al microcontrolador de qué dirección comenzar a ejecutar nuestro programa.

            ; Siempre será 0000 hex para todos los tutoriales.



;BANCO 1

BSF STATUS, RP0

MOVLW 0xF0

MOVWF TRISB

CLRF TRISC     

CLRF TRISD

BCF STATUS, RP0

CLRF PORTC

CLRF PORTD



goto Program



;TABLA BINARIA DE LCD

digit_data      ; Esta rutina contiene todos los datos para nuestros varios dígitos.


movf _button, w; antes de llegar aquí, la variable _button contendrá


; Un cierto número que copiamos en el registro w.

addwf CONT; Luego agregamos este número a nuestro contador del programa que saltará

; directamente a una determinada declaración que corresponderá

; al número que pulsamos en el teclado.

retlw    b'0111111'      ; 0   7SEG-CATODO COMUN


retlw    b'0000110'      ; 1


retlw    b'1011011'      ; 2


retlw    b'1001111'      ; 3


retlw    b'1100110'      ; 4


retlw    b'1101101'      ; 5


retlw    b'1111101'      ; 6


retlw    b'0000111'      ; 7


retlw    b'1111111'      ; 8


retlw    b'1101111'      ; 9


retlw   b'1110111'      ;10 a

              

retlw   b'1111100'      ;11  b


retlw   b'0111001'      ;12 c


retlw   b'1011110'      ;13 d


retlw   b'1110110'      ;14  #



    Program                            ;en program configuraremos todo


        clrf _butto

        clrf _button        ;    se encargara de que en el 7 segmentos nos aparezca 0 al incio

        clrf PORTD                ;    Aún no estamos buscando ninguna tecla presionada, por lo tanto, haga PORT B ceros,es decir limpia el puerto A.

            clrf PORTC

begin                            ;    nuestro programa principal

    call Teclado            ;    llamamos a la rutina TECLADO

    call display_digit            ;    call the display_digit routine and then return


    call display_digit2

    goto begin                    ;    go back to the beginning and do it all again.




Teclado                    ;esta rutina nos encargamos de la interacion del teclado

        movf _button, w        ;    Queremos copiar nuestro último dígito que fue presionado en w

        movf _butto, w                ; así que en caso de que NO presionemos una tecla en este escaneo del teclado

                            ; porque al final de esta sub-rutina, automáticamente

                            ; w de nuevo en la variable what_button. Esto asegura que mantengamos la

                            ; Último dígito presionado en la pantalla.


        bsf PORTB, 0            ;   vamos a escanear la primera columna de claves     

        btfsc PORTB, 4            ;    ¿Se ha pulsado la tecla 1? si si entonces

        movlw d'01'                ;    copy decimal number 01 into w. but if not then continue on.

        btfsc PORTB, 5            ;    has the 4 key been pressed? if yes then

        movlw d'04'                ;    copy decimal number 04 into w. but if not then continue on.

    

        btfsc PORTB, 6            ;    has the 7 key been pressed? if yes then

        movlw d'07'                ;    copy decimal number 07 into w. but if not then continue on.

        ;btfsc PORTB, 7            ;    has the * key been pressed? if yes then

        ;movlw d'10'                ;    copia el número decimal 10 en w. pero si no, entonces continúa.

        bcf PORTB, 0            ;    Ahora hemos terminado de escanear la primera columna de claves.


    bsf PORTB,1   ; vamos a escanear la columna central de teclas

    btfsc PORTB, 4 ; ha sido presionada la tecla 2? si si entonces

    movlw d'02'    ; copiar el número decimal 02 en w. pero si no, entonces continúa.

   btfsc PORTB, 5   ; ha sido presionada la tecla 5? si si entonces

   movlw d'05'      ; Copie el número decimal 05 en w. pero si no, entonces continúa.

   btfsc PORTB, 6   ; ¿Se ha pulsado la tecla 8? si si entonces

   movlw d'08'     ; copia el número decimal 08 en w. pero si no, entonces continúa.

   btfsc PORTB, 7  ; ha sido presionada la tecla 0? si si entonces

   movlw d'00'    ; copiar el número decimal 00 en w. pero si no, entonces continúa.

   bcf PORTB,1  ; Ahora hemos terminado de escanear la columna central de teclas.


    bsf PORTB,2    ; vamos a escanear la última columna de claves

    btfsc PORTB, 4  ; ha sido presionada la tecla 3? si si entonces

    movlw d'03'    ; copia el número decimal 03 en w. pero si no, entonces continúa.

    btfsc PORTB, 5  ; ¿Se ha pulsado la tecla 6? si si entonces

    movlw d'06'    ; Copie el número decimal 06 en w. pero si no, entonces continúa.

    btfsc PORTB, 6  ; ha sido presionada la tecla 9? si si entonces

    movlw d'09'    ; copiar el número decimal 09 en w. pero si no, entonces continúa.

    btfsc PORTB, 7  ; ha sido presionada la tecla #? si si entonces movimiento de 11 '; copiar el número decimal 11 en w. pero si no, entonces continúa.

    movlw d'14'

    bcf PORTA,2    ; Ahora hemos terminado de escanear la última columna de claves.


    bsf PORTB,3    ; vamos a escanear la última columna de claves

    btfsc PORTB, 4  ; ha sido presionada la tecla a? si si entonces

    movlw d'10'    ; copia el número decimal a en w. pero si no, entonces continúa.

    btfsc PORTB, 5  ; ¿Se ha pulsado la tecla 6? si si entonces

    movlw d'11'    ; Copie el número decimal 06 en w. pero si no, entonces continúa.

    btfsc PORTB, 6  ; ha sido presionada la tecla 9? si si entonces

    movlw d'12'    ; copiar el número decimal 09 en w. pero si no, entonces continúa.

    btfsc PORTB, 7  ; ha sido presionada la tecla #? si si entonces movimiento de 11 '; copiar el número decimal 11 en w. pero si no, entonces continúa.

    movlw d'13'

    bcf PORTA,3    ; Ahora hemos terminado de escanear la última columna de claves.


 

    movwf _button   ; Cuando lleguemos aquí, tendremos un cierto número en nuestro registro w,

    movwf _butto                   ; luego lo copiamos de w en _button para que podamos usarlo para saltar

                        ; a una cierta instrucción retlw para agarrar los datos relevantes para mostrar

                        ; El dígito que pulsamos.

 

         RETURN                    ; Y ahora volvemos a la rutina principal.


     display_digit   ; Esta sub-rutina mostrará el dígito en la pantalla.

    call digit_data  ; llame a digit_data para obtener nuestra información relevante de 8 bits

                      ; para cualquier botón que hayamos presionado.

     movwf PORTD      ; y mueva estos 8 bits de datos a PORTA para visualizarlos en la pantalla

  

     RETURN

;---------------------------------------------------------------------

   display_digit2

 

    bsf PORTB, 0            ;   vamos a escanear la primera columna de claves     

        btfss PORTB, 4            ;    ¿Se ha pulsado la tecla 1? si si entonces

                                ;    copy decimal number 01 into w. but if not then continue on.

        Movwf _butto

        movwf PORTC

        clrf PORTD

        btfss PORTB, 5            ;    has the 4 key been pressed? if yes then

                                ;    copy decimal number 01 into w. but if not then continue on.

        Movwf _butto

        movwf PORTC

        clrf PORTD 

        btfss PORTB, 6            ;    has the 7 key been pressed? if yes then

                            ;    copy decimal number 01 into w. but if not then continue on.

        Movwf _butto

        movwf PORTC

           clrf PORTD            ;    copia el número decimal 10 en w. pero si no, entonces continúa.

        bcf PORTB, 0            ;    Ahora hemos terminado de escanear la primera columna de claves.


  

    


     RETURN                        ; y luego volver a nuestro programa principal.






END
En algunas partes reutilicé código y borraba algunas cosas, así que no todos los comentarios son correctos y en la última parte display2, estaba intentando probar el funcionamiento con la columna 1 del rodamiento de los números.
 

Adjuntos

  • Sin título.png
    Sin título.png
    91.7 KB · Visitas: 13
Hola. Buen día. Disculpen, tengo un código pero tengo problema con la librería, debido a que no responde a la función del código.
Entonces tengo problema para modificar la librería con respecto al código.
Les comparto mi código original y el de la librería, junto con los errores.
La librería es keypad4x4 abcd y el código corresponde a un invernadero inteligente.
 

Adjuntos

  • Proyecto Invernadero.rar
    103.1 KB · Visitas: 5
  • DriverTec4x4.rar
    638 bytes · Visitas: 4
Última edición por un moderador:
Atrás
Arriba