Programación Específica > Soluciones de Hard y Soft

 Teclado Matricial y Display 7 Segmentos - ATMEL AVR

(1/1)

netshark:
EL TECLADO MATRICIAL
Implementado con un Micro ATMEL AVR ATMEGA 8535

Para entender un poco sobre el funcionamiento eléctrico de un teclado matricial, lean la siguiente presentación:
Acá la presentación: EL_TECLADO_MATRICIAL_v1_4.pdf (1.6 MB)

Para la práctica se necesita un teclado matricial de 4X4, lo pueden comprar o fabricarlo.
Si tienen los recursos, pueden comprar el teclado, pero les costará alrededor de 135 pesos.



Una forma mucho más económica y didáctica es construirlo ustedes mismos.

Material:
- 16 pushbuttons pequeños
- 1 PCB tipo "Easy Circuit" que pueda alojar todos los botones
- Cable y soldadura

Debemos conectar los switches de forma que toda una fila de ellos tengan una terminal común, así las 4 filas cada una. Después cada columna debe tener la otra terminal común.
Se ve claramente en el diagrama:


Y si prefieren usar un display de 7 segmentos, el circuito es el siguiente:


El display de 7 segmentos está construido de la siguiente forma:


Además una sencilla tabla de cuales segmentos encender para cada número:


Teclado hecho en casa



Se tuvieron que cortar algunas pistas verticales con cutter para separar las columnas, y funciona a la perfección.





En este caso se usó un microcontrolador ATMEL ATMEGA8535 datasheet pero puede bien ser implementado en un microcontrolador más pequeño, como el ATMEGA8 sin mucha dificultad, sólo habría que cambiar el acomodo de los puertos y el cableado, (datasheet)

Se implementó un programa para controlar el teclado matricial, y según la tecla que se presione, aparecerá:

1) LEDs encendidos en una tira de leds en función de la fila-columna
2) Código del 0 a la F en un display de 7 segmentos.



La tira de 10 leds sirve para ver qué tecla se presionó. De izquierda a derecha, los primeros dos leds no se utilizan, los siguientes 4 indican la columna y los ultimos 4 indican el renglón. Hay un led ROJO cercano al AVR (concretamente en el pin PD7) que se prende cuando detecta alguna tecla presionada y se apaga cuando termina la decodificación ó si descarta que se haya presionado (por si fue ruido o un falso contacto)



Ejemplo al presionar la tecla en la ultima fila de la ultima columna...



Aparecen:


Es el programa básico con decodificación de filas y columnas y tiene protección antirrebotes. Ésta es la versión que jala con la tira de LEDs:


--- Código: Text ---;Código decodificador de teclado matricial;Implementado por David Valencia Pesqueira en UPIITA-IPN 2009;Profesor: Dr. Antonio Hernández Zavala;GRUPO 4BM3;;   El siguiente programa decodifica un teclado matricial;   de 16 teclas. Éste tipo de algoritmo está diseñado para;   detectar sólo una tecla a la vez, ya que para detectar;   más de una se requieren diodos por cada interruptor en la;   construcción del teclado matricial y éso ya queda fuera;   del enfoque didáctico de éste programa.;;   Para más información sobre la construcción de teclados;   matriciales con diodos visitar:;   http://www.dribin.org/dave/keyboard/one_html/;;Historial;v0.1 - Pruebas de las resistencias Pull-UP --- OK;v0.2 - Probando la salida del tempscan;v0.3 - Nueva estructura de tempscan -- OK;v0.4 - Salida por tira de leds en PORTA -- OK;;Hardware en un ATMEL ATMega 8535;El teclado está conectado de la siguiente manera:;;          COLUMNAS;              0    1   2   3;   ;   FILAS   0  X    X   X   X  PC4;;           1  X    X   X   X  PC5;;           2  X    X   X   X  PC6;;           3  X    X   X   X  PC7;           ;              PC0  PC1 PC2 PC3;;######################################################;CABECERA.include "m8535def.inc" ;######################################################;Vector de Interrupciones.org 0x00    rjmp reset ;interrupción de Reset;;######################################################;Variables Globales;La variable tempscan se acomoda de la siguiente forma ;tempscan = [fila3,fila2,fila1,fila0,col3,col2,col1,col0];Son "banderas" que se prenden para indicar en qué fila; y qué columna se halla la tecla.  .def tempscan=r17.def temp=r16 ;Rutina Principalreset:    ;inicializar pila    cli    ldi temp,low(ramend)    out spl,temp    ldi temp,high(ramend)    out sph,temp    sei    rjmp init init:    ;Inicializar Puertos    ;Este código emplea el puerto C, con los bits 0 al 3 para las columnas    ;y los bits 4 al 7 para las filas.    ;Inicia con las filas como salidas con ceros y las columnas como entradas    ;que se mantienen en un nivel alto mientras no estén conectadas    ;Para lograr esto, se habilitan las "resistencias pull-up" que conectan    ;el pin deseado hacia VCC.    ;Para hacerlo se declaran los pines como entradas (DDRC=0) pero    ;enviamos 0xFF al registro PORTC para activarlas.     ;Declarando al nibble alto como salida y al bajo como entrada    ldi temp,0b11110000    out DDRC,temp    ;Activando las resistencias pull-up en la parte baja    ldi temp,0x0F    out PORTC,temp    ;Si se presiona una tecla, el "0" de alguna fila será    ;detectado por las columnas, y entonces comienza el    ;proceso de decodificación.     ldi temp,0b10000000    out DDRD,temp    ;Puerto D como salida para cuando detecta tecla    ser temp    out DDRA,temp    ;Nibble bajo del puerto A como salida    clr temp    out PORTA,temp     clr tempscan ;Borra el resultado del escaneo     rjmp begin begin:    clr temp    out PORTD,temp    ;Probar si algun botón fue presionado    in temp,PINC    cpi temp,0x0F ;Si hay algun cero en las columnas, buscar la tecla    brne antirrebotesrjmp begin antirrebotes:;Esta rutina espera un corto periodo de tiempo mientras el interruptor;se estabiliza para evitar que el micro detecte la misma tecla varias;veces al igual que posible ruido.    ;Vuelve a leer las entradas    ser temp    out PORTD,temp    rcall delay    in temp,PINC    cpi temp,0x0F    ;Si detecta el cero de nuevo, procesa la detección    brne deteccion    ;Si fue un falso contacto, vuelve a empezar    rjmp begin;FIN DE ANTIRREBOTES deteccion:    clr tempscan    ;inicializamos el código de escaneo temporal    ldi tempscan,0x00    ;Buscar las columnas    colscan:        sbis pinc,0 ;prueba la columna 0        ldi tempscan,0x01        sbis pinc,1 ;prueba la columna 1        ldi tempscan,0x02        sbis pinc,2 ;prueba la columna 2        ldi tempscan,0x04        sbis pinc,3 ;prueba la columna 3        ldi tempscan,0x08         cpi tempscan,0x00 ;si no halló la columna, repetir    breq init     ;Ahora que se encontró la columna, tienen que invertirse     ;los sentidos del nibble bajo y el alto para buscar la    ;fila    rcall invertir    ;Ahora invertidos, buscaremos si alguna fila está    ;baja    in temp,PINC    cpi temp,0xF0 ;Si hay algun cero en las columnas, buscar la tecla    brne filadetectada    rjmp init ;Si no hay fila con cero, devuelve los puertos    ;a su estado original y reinicia el programa        filadetectada:    ;Buscar la fila    filascan:        ldi temp,0x10         sbis pinc,4 ;Prueba la fila 0        rjmp col0        sbis pinc,5 ;Prueba la fila 1        rjmp col1        sbis pinc,6 ;Prueba la fila 2        rjmp col2        sbis pinc,7 ;Prueba la fila 3        rjmp col3        rjmp init ;Si no halla la fila, reinicia         ;A continuación se escribirá el valor correspondiente        ;a la fila, se usa el comando ROL para multiplicar por 2        ;pero se limpia antes la bandera de acarreo para evitar        ;que se sume y entregue valores erróneos.        col0:            add tempscan,temp            rjmp fincol         col1:            ldi temp,0x20            add tempscan,temp            rjmp fincol                col2:            ldi temp,0x40            add tempscan,temp            rjmp fincol         col3:            ldi temp,0x80            add tempscan,temp            rjmp fincol        fincol:     ;Toca procesar el código temporal para sacarlo    ;por los leds, en este caso sale en 4 leds en puertoA    out PORTA,tempscan    clr tempscan    rcall desinvertir ;devolver los puertos al estado original    rjmp begin ;Subrutinas delay:    cli    ;Respaldar variables globales en la pila    push r16    push r17    ;Inicia secuencia de retraso    loop0: ldi r17,0x04    loop1: ldi r16,0xFF    loop2: dec r16        brne loop2        dec r17        brne loop1    sei    ;Restaurar las variables desde la pila    pop r17    pop r16ret invertir: ;Inversión de los pines    ldi temp,0b00001111    out DDRC,temp    ;Activando las resistencias pull-up en la parte alta    ldi temp,0xF0    out PORTC,temp    ;Ahora la parte alta es entrada con pullup y la parte    ;baja son salidas con cerosret desinvertir: ;Devolver los pines al estado inicial    ldi temp,0b11110000    out DDRC,temp    ;Activando las resistencias pull-up en la parte alta    ldi temp,0x0F    out PORTC,temp    ;Ahora la parte baja es entrada con pullup y la parte    ;alta son salidas con cerosret ;FIN DEL PROGRAMA TECLADO MATRICIAL  
Esta otra versión saca qué tecla fue presionada en un display de 7 segmentos:

Aquí unas fotos:



--- Código: Text ---;Código decodificador de teclado matricial;Implementado por David Valencia Pesqueira en UPIITA-IPN 2009;Profesor: Dr. Antonio Hernández Zavala;GRUPO 4BM3;;   El siguiente programa decodifica un teclado matricial;   de 16 teclas. Éste tipo de algoritmo está diseñado para;   detectar sólo una tecla a la vez, ya que para detectar;   más de una se requieren diodos por cada interruptor en la;   construcción del teclado matricial y éso ya queda fuera;   del enfoque didáctico de éste programa.;;   Para más información sobre la construcción de teclados;   matriciales con diodos visitar:;   http://www.dribin.org/dave/keyboard/one_html/;;Historial;v0.1 - Pruebas de las resistencias Pull-UP --- OK;v0.2 - Probando la salida del tempscan;v0.3 - Nueva estructura de tempscan -- OK;v0.4 - Salida por tira de leds en PORT_DISP -- OK;v0.5 - Salida por tira de leds en 4 pines de PORT_DISP -- OK;;Hardware en un ATMEL ATMega 8535;El teclado está conectado de la siguiente manera:;;          COLUMNAS;              0    1   2   3;   ;   FILAS   0  X    X   X   X  PC4;;           1  X    X   X   X  PC5;;           2  X    X   X   X  PC6;;           3  X    X   X   X  PC7;           ;              PC0  PC1 PC2 PC3;;######################################################;CABECERA.include "m8535def.inc" ;######################################################;EQUIVALENCIAS;Puerto para el teclado.equ PORT_K=PORTC.equ PIN_K=PINC.equ DDR_K=DDRC;Puerto de salida para el display de Siete Segmentos.equ PORT_DISP=PORTA.equ DDR_DISP=DDRA ;######################################################;Vector de Interrupciones.org 0x00    rjmp reset ;interrupción de Reset;;######################################################;Variables Globales;La variable tempscan se acomoda de la siguiente forma ;tempscan = [-,-,-,-,fila01,fila00,col01,col00];Son "banderas" que se prenden para indicar en qué fila;y qué columna se halla la tecla.; .def tempscan=r17.def temp=r16 ;Rutina Principalreset:    ;inicializar pila    cli    ldi temp,low(ramend)    out spl,temp    ldi temp,high(ramend)    out sph,temp    sei    rjmp init init:    ;Inicializar Puertos    ;Este código emplea el puerto C, con los bits 0 al 3 para las columnas    ;y los bits 4 al 7 para las filas.    ;Inicia con las filas como salidas con ceros y las columnas como entradas    ;que se mantienen en un nivel alto mientras no estén conectadas    ;Para lograr esto, se habilitan las "resistencias pull-up" que conectan    ;el pin deseado hacia VCC.    ;Para hacerlo se declaran los pines como entradas (DDR_K=0) pero    ;enviamos 0xFF al registro PORT_K para activarlas.     ;Declarando al nibble alto como salida y al bajo como entrada    ldi temp,0b11110000    out DDR_K,temp    ;Activando las resistencias pull-up en la parte baja    ldi temp,0x0F    out PORT_K,temp    ;Si se presiona una tecla, el "0" de alguna fila será    ;detectado por las columnas, y entonces comienza el    ;proceso de decodificación.     ldi temp,0b10000000    out DDRD,temp    ;Puerto D como salida para cuando detecta tecla        ser temp    out DDR_DISP,temp    ;Puerto A como salida    ldi temp,0b00000010 ;Enviar un guion al puerto A    out PORT_DISP,temp     clr tempscan ;Borra el resultado del escaneo     rjmp begin begin:    clr temp    out PORTD,temp    ;Probar si algun botón fue presionado    in temp,PIN_K    cpi temp,0x0F ;Si hay algun cero en las columnas, buscar la tecla    brne antirrebotesrjmp begin antirrebotes:;Esta rutina espera un corto periodo de tiempo mientras el interruptor;se estabiliza para evitar que el micro detecte la misma tecla varias;veces al igual que posible ruido.    ;Vuelve a leer las entradas    ser temp    out PORTD,temp    rcall delay    in temp,PIN_K    cpi temp,0x0F    ;Si detecta el cero de nuevo, procesa la detección    brne deteccion    ;Si fue un falso contacto, vuelve a empezar    rjmp begin;FIN DE ANTIRREBOTES deteccion:    clr tempscan    ;inicializamos el código de escaneo temporal    ldi tempscan,0x00    ;Buscar las columnas    colscan:        sbis PIN_K,0 ;prueba la columna 0        ldi tempscan,0x00        sbis PIN_K,1 ;prueba la columna 1        ldi tempscan,0x01        sbis PIN_K,2 ;prueba la columna 2        ldi tempscan,0x02        sbis PIN_K,3 ;prueba la columna 3        ldi tempscan,0x03     ;Ahora que se encontró la columna, tienen que invertirse     ;los sentidos del nibble bajo y el alto para buscar la    ;fila    rcall invertir    ;Ahora invertidos, buscaremos si alguna fila está    ;baja    in temp,PIN_K       cpi temp,0xF0 ;Si hay algun cero en las columnas, buscar la tecla    brne filadetectada    rjmp init ;Si no hay fila con cero, devuelve los puertos    ;a su estado original y reinicia el programa        filadetectada:    ;Buscar la fila    filascan:                sbis PIN_K,4 ;Prueba la fila 0        rjmp fila0        sbis PIN_K,5 ;Prueba la fila 1        rjmp fila1        sbis PIN_K,6 ;Prueba la fila 2        rjmp fila2        sbis PIN_K,7 ;Prueba la fila 3        rjmp fila3        rjmp init ;Si no halla la fila, reinicia         ;A continuación se escribirá el valor correspondiente        ;a la fila, se usa el comando ROL para multiplicar por 2        ;pero se limpia antes la bandera de acarreo para evitar        ;que se sume y entregue valores erróneos.        fila0:            ldi temp,0x00            add tempscan,temp            rjmp fincol         fila1:            ldi temp,0x04            add tempscan,temp            rjmp fincol                fila2:            ldi temp,0x08            add tempscan,temp            rjmp fincol         fila3:            ldi temp,0x0C            add tempscan,temp            rjmp fincol        fincol:     ;Toca procesar el código temporal para sacarlo    ;por los leds, en este caso sale en 4 leds en puertoA    ;out PORT_DISP,tempscan    rcall desinvertir ;devolver los puertos al estado original    rcall scantoseven ;Mandar al display 7 segmentos    rjmp begin ;Subrutinas delay:    cli    ;Respaldar variables globales en la pila    push r16    push r17    ;Inicia secuencia de retraso    loop0: ldi r17,0x20    loop1: ldi r16,0xFF    loop2: dec r16        brne loop2        dec r17        brne loop1    sei    ;Restaurar las variables desde la pila    pop r17    pop r16ret invertir: ;Inversión de los pines    ldi temp,0b00001111    out DDR_K,temp    ;Activando las resistencias pull-up en la parte alta    ldi temp,0xF0    out PORT_K,temp    ;Ahora la parte alta es entrada con pullup y la parte    ;baja son salidas con cerosret desinvertir: ;Devolver los pines al estado inicial    ldi temp,0b11110000    out DDR_K,temp    ;Activando las resistencias pull-up en la parte alta    ldi temp,0x0F    out PORT_K,temp    ;Ahora la parte baja es entrada con pullup y la parte    ;alta son salidas con cerosret scantoseven: ;Convierte el escaneo a display 7 segmentos catodo común    ;Revisar el cableado del display en las hojas adjuntas      ;El bit mas alto va al segmento "a" hasta el "g" y luego el punto decimal.    cpi tempscan,0x00    breq cero    cpi tempscan,0x01    breq uno    cpi tempscan,0x02    breq dos    cpi tempscan,0x03    breq tres    cpi tempscan,0x04    breq cuatro    cpi tempscan,0x05    breq cinco    cpi tempscan,0x06    breq seis    cpi tempscan,0x07    breq siete    cpi tempscan,0x08    breq ocho    cpi tempscan,0x09    breq nueve    cpi tempscan,0x0A    breq letraA    cpi tempscan,0x0B    breq letraB    cpi tempscan,0x0C    breq letraC    cpi tempscan,0x0D    breq letraD    cpi tempscan,0x0E    breq letraE    cpi tempscan,0x0F    breq letraF    rjmp guion     cero:ldi temp,0b11111100    rjmp sacarsegmentos    uno:ldi temp,0b01100000    rjmp sacarsegmentos    dos:ldi temp,0b11011010    rjmp sacarsegmentos    tres:ldi temp,0b11110010    rjmp sacarsegmentos    cuatro:ldi temp,0b01100110    rjmp sacarsegmentos    cinco:ldi temp,0b10110110    rjmp sacarsegmentos    seis:ldi temp,0b10111110    rjmp sacarsegmentos    siete:ldi temp,0b11100000    rjmp sacarsegmentos    ocho:ldi temp,0b11111110    rjmp sacarsegmentos    nueve:ldi temp,0b11110110    rjmp sacarsegmentos    letraA:ldi temp,0b11101110    rjmp sacarsegmentos    letraB:ldi temp,0b00111110    rjmp sacarsegmentos    letraC:ldi temp,0b10011100    rjmp sacarsegmentos    letraD:ldi temp,0b01111010    rjmp sacarsegmentos    letraE:ldi temp,0b10011110    rjmp sacarsegmentos    letraF:ldi temp,0b10001110    rjmp sacarsegmentos    guion:ldi temp,0b00000010     sacarsegmentos: ;enviar al display siete segmentos    out PORT_DISP,tempret ;FIN DEL PROGRAMA TECLADO MATRICIAL 
Espero el programa sea claro y cualquier duda por favor dejen un mensaje en este tema.

 :D

© Jonathan ©:
Gracias netshark por este interesante post, esta muy bien detallado y facilita mucho la construcción de la placa y la comprensión del código. Por trabajo estoy bastante ausente del foro y veo que ya no tiene la actividad que tenia hace un tiempo, al menos el subforo de microcontroladores, por eso quiero organizar algo para activar nuevamente la actividad del sitio y volver al tiempo en el que el foro se había vuelto adicción  :comp:

Comienzo agradeciendo tu aporte y te motivo a que sigas haciendo este tipo de posteos, muy bueno!  :good:

netshark:
Saludos!

Y es cierto, me ha parecido que la actividad en el foro está un poco floja, pero mi intención es ayudar poniendo mi granito de arena.

Hasta hace poco no sabía nada de electrónica, ni mucho menos de microcontroladores pero se me ha dado la programación en diversos lenguajes. Tengo compañeros en cuyas escuelas preparatorias les enseñaron a manejar PIC, AVR y otros y me imaginé que era un mundo oscuro y difícil de entender. Ahora en la universidad descubrí que es un universo bastante interesante y con un sinfín de aplicaciones.

Estoy preparando otros programas igualmente didácticos (manejo de LCD, interfaz USART con la computadora, etc) como una forma de introducirse a los microcontroladores AVR, que han tenido un increíble boom en la industria y no es para menos.

Una duda: Tengo en mi poder un fenomenal e-book sobre Lenguaje C para AVR, ¿Hay algún problema si lo subo a este foro?

© Jonathan ©:
Tal como dices, hay un sinfín de aplicaciones y los limites dependen de la imaginación de cada uno, mis felicitaciones por la voluntad para armar los documentos detallados y mas aun por compartirlos con todos nosotros.

Sobre el libro de lenguaje C para AVR, es bienvenido como todo aquello que quieras compartir, tienes a disposición el servidor FTP del foro para subir archivos de gran tamaño, los datos para el acceso los encontraras en el siguiente enlace--> viewtopic.php?t=12696  Dentro del FTP hay carpetas destinadas a las diferentes familias de microcontroladores, creo que el directorio de ATMEL esta vacio :argh: .. luego de subir el libro si quieres puedes poner el enlace en un post para un rápido acceso desde el subforo.

netshark mil gracias y un abrazo  :beer:

netshark:
En el primer post puse las fotos del display empleando el segundo código.

Posteriormente pondré el código para lograr esto:



Stay tuned

P.D: @Einstec: Al parecer el FTP está mal, porque intenté entrar con Filezilla y me marca que está mal el password.

Navegación

[0] Índice de Mensajes

Ir a la versión completa