notas técnicas de uso y aplicación - ceres...

52
F.I.E., C.D.P., 2005 NT1009 NT1009 Quizá uno de los elementos más comunes para control de respuestas del usuario, adquisición o depósito de datos, es el teclado. Por su utilidad en faxes, cajeros automáticos, cerraduras codificadas de ingreso por motivos de seguridad, controles de juegos de video, es el elemento más utilizado para navegar por un menú o desplegar información solicitada por el usuario. La siguiente nota explica una de las tantas formas de decodificar un teclado matricial de 16 teclas, ordenadas en una matriz de 4 x 4 teclas, pero el mismo se puede configurar para un teclado mayor de hasta 8 x 8 (aunque limitado por el mismo microcontrolador, PTA[0:6] hasta 7 x 8). Utilizando también, lo aprendido en la NT1008 – LCD, se utilizará la rutina reusable para realizar una simulación a cerradura codificada. Una característica importante de todo el programa, para la aplicación, es la capacidad de almacenar las teclas, por medio de buffer o almacenador intermediario que acepta solo las teclas deseadas por el código y admite hasta la capacidad deseada. Notas Técnicas de Uso y Aplicación 3.9 DECODIFICACIÓN DE UN TECLADO MATRICIAL 4 X 4 INGRESO DE CÓDIGO A UNA CERRADURA ELECTRÓNICA Preparado por: Rangel Alvarado Estudiante Graduando de Lic. en Ing. Electromecánica Universidad Tecnológica de Panamá Panamá, Panamá “e-mail”: [email protected] “web site”: http://www.geocities.com/issaiass/ 3.9.1 Introducción ÏNDICE 3.9.1 Introducción 495 3.9.2 Materiales 496 3.9.3 Descripción Física del “Hardware” 497 3.9.4 Descripción Interna y Conexiones 498 3.9.5 “Buffer” Anillo 500 3.9.6 Esquemático de Aplicación 501 3.9.7 Diagrama de Flujo 502 3.9.8 Código 510 3.9.9 Conclusión 545 3.9.10 Referencias 546 3.9.11 Problemas Propuestos 546

Upload: ngolien

Post on 26-Sep-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

F.I.E., C.D.P., 2005 NT1009

NT1009 Quizá uno de los elementos más comunes para control de respuestas del usuario, adquisición o depósito de datos, es el teclado. Por su utilidad en faxes, cajeros automáticos, cerraduras codificadas de ingreso por motivos de seguridad, controles de juegos de video, es el elemento más utilizado para navegar por un menú o desplegar información solicitada por el usuario. La siguiente nota explica una de las tantas formas de decodificar un teclado matricial de 16 teclas, ordenadas en una matriz de 4 x 4 teclas, pero el mismo se puede configurar para un teclado mayor de hasta 8 x 8 (aunque limitado por el mismo microcontrolador, PTA[0:6] hasta 7 x 8). Utilizando también, lo aprendido en la NT1008 – LCD, se utilizará la rutina reusable para realizar una simulación a cerradura codificada. Una característica importante de todo el programa, para la aplicación, es la capacidad de almacenar las teclas, por medio de buffer o almacenador intermediario que acepta solo las teclas deseadas por el código y admite hasta la capacidad deseada.

Notas Técnicas de Uso y Aplicación

3.9 DECODIFICACIÓN DE UN TECLADO MATRICIAL 4 X 4 INGRESO DE CÓDIGO A UNA CERRADURA ELECTRÓNICA Preparado por: Rangel Alvarado Estudiante Graduando de Lic. en Ing. Electromecánica Universidad Tecnológica de Panamá Panamá, Panamá “e-mail”: [email protected] “web site”: http://www.geocities.com/issaiass/

3.9.1 Introducción

ÏNDICE 3.9.1 Introducción 495 3.9.2 Materiales 496 3.9.3 Descripción Física del “Hardware” 497 3.9.4 Descripción Interna y Conexiones 498 3.9.5 “Buffer” Anillo 500 3.9.6 Esquemático de Aplicación 501 3.9.7 Diagrama de Flujo 502 3.9.8 Código 510 3.9.9 Conclusión 545 3.9.10 Referencias 546 3.9.11 Problemas Propuestos 546

NT1009

Rev. 1 del 07.08.05

496 Nota Técnica

1. Microcontrolador: JL3 / JK3 / GP32 2. Potenciómetro: 10k @ 20k, Jameco Part No: 43001 3. Display LCD: LCD 16 X 4, Jameco Part No: 210761 4. Tarjeta de Desarrollo TD68HC908JL3 o similar y su microcontrolador 5. Plantilla de proyectos: Breadboard JE27, Jameco Part No: 20811 6. Fuente de Poder 7. Alambres AWG 20 8. Pelador de Alambres 9. Teclado: Matriz de 16 teclas (4 x 4), Jameco Part No: 196171, 152063

(1) (2) (3) (4)

(5) (6) (7) (8)

(9)

Figura 214. Listado de Materiales a Utilizar para la Experiencia de Decodificación de Teclado Matricial

3.9.2 Materiales

Nota Técnica Interfase a Teclado Matricial

497

Figura 215. Descripción Física del Teclado Adquirido. (a) Conjunto de teclas primarias del teclado. Serigrafía de teclas a decodificar o devolver si son presionadas. (b) Pines de Teclado Adquirido. La mayor parte del problema de la circuitería está reducido por el módulo adquirido y solo salen

fuera del mismo ocho (8) que corresponden al conjunto de teclas más el pin del chasis. (c) Conexión de interruptores a un puerto de microcontrolador. Una de las maneras correctas de conectar un interruptor. Un interruptor es un dispositivo mecánico que al presionarse genera

estados inciertos antes de estabilizar su señal, luego de esto ud puede leer el estado del interruptor, por lo general este tiempo dura alrededor de los 20 a 100 ms.

Carácter Designado Pines unidos al presionar 1A 1 – 5 2B 1 – 6 3C 1 – 7 4D 2 – 5 5E 2 – 6

↑← 1 – 8 ↓→ 2 – 8 2ND 3 – 8 6F 2 – 7 7C 3 – 5 8H 3 – 6 9I 3 – 7 0J 4 – 6

CLEAR 4 – 5 HELP 4 – 7

ENTER 4 – 8 ESD SHIELD 9

Nota: Un teclado solo es el conjunto de interruptores.

Para el siguiente párrafo, ayudarse por medio de la figuras y tablas de esta sección. En aspectos generales, el teclado adquirido ya posee la mayor parte del problema de circuitería eliminado. Al exterior salen solamente los pines necesarios para realizar conexión inmediata con el “hardware”, ver figura 215(b). Visto desde la parte inferior, el teclado posee ocho (8) pines de los cuales el último es el chasis del teclado y debe ser conectado a masa o tierra. Como se verá más adelante en la siguiente sección, un teclado está conformado por ”grupos de interruptores”, así cuando se presiona una tecla, luego de los rebotes (ver NT0108 – KBI), este une dos de los ocho pines, que representa la tecla presionada, ver tabla 78. Tabla 78. Descripción de Pines del Teclado Matricial (a) (c)

(b) Teclas y pines que se unen al ser presionado un botón

3.9.3 Descripción Física del “Hardware”

498

Figura 216. Teclado Matricial de 16 Teclas. (a) Teclado Unido a Puertos de Entrada/Salida. Un teclado matricial es un conjunto de interruptores configurados de tal manera que al presionar, se unen una fila con una columna. (b) Modo a Utilizar el Teclado. Indiferentemente, el teclado

puede ser filas-columnas o columnas-filas, quien decide como decodificar el teclado será el programa estipulado por el diseñador, en este caso, para que el “software” detecte las teclas se debe seguir el patrón estipulado en

la nota.

3.9.4.1 El Teclado Matricial Cuadrado de Teclas Para esta aplicación se decodifica un teclado matricial de 16 teclas. Un teclado matricial esta compuesto por un arreglo, generalmente una matriz cuadrada. Esto se debe a que es más eficiente tener, por ejemplo, un arreglo 4 x 3 (12 teclas), que un arreglo 5 x 2 (10 teclas). Como se experimenta, se tiene mayor oportunidad de opciones si se hacen parecer los números del arreglo. Para conectar un teclado matricial a un microcontrolador, se necesitan conectar a los puertos de entrada (filas) resistores a “pull-ups” y los puertos de salida (columnas) cuyo estado actual será un nivel lógico bajo, a los otros extremos del teclado. Cuando se presiona una tecla, se une una fila con una columna y es tarea del programador determinar que tecla fue presionada leyendo los estados de los puertos. (b) (a)

3.9.4 Descripción Interna y Conexiones

Nota Técnica Interfase a Teclado Matricial

499

Figura 217. Decodificación del Teclado. (a) Técnica de Decodificación del Teclado. A grandes rasgos, para decodificar un teclado se debe adquirir la fila, luego la columna y

aplicar la ecuación 18 para encontrar el índice al cual corresponde el carácter presionado. (b) Reconocimiento del Caracter Tecleado. Luego de encontrar el índice al cual

corresponde el caracter, simplemente se busca en la tabla en la correspondiente posición, el carácter adquirido, debe ser igual al tecleado.

3.9.4.2 Decodificación del Teclado Una técnica común para decodificar el teclado es por medio de sucesivas lecturas a los puertos, pero si su módulo posee interrupciones, ud. puede realizar la lectura del puerto en el momento justo. De cualquier forma, se debe: (a) Revisar las filas (que fila o bit del puerto posee un valor de cero (0) lógico en este caso). (b) Revisar las columnas (que bit del puerto de columnas fue presiona revisando cada bit del puerto de filas).

(c) Retornar el índice o desfase de la tecla presionada (corresponde al desfase o posición a desviarse en la tabla). (d) Buscar en la tabla la tecla presionada (cargar el valor dependiendo del índice, corresponde a la tecla presionada).

columna Filas de Fila Índice +×= Máximo Ecuación 18. Determinación del Índice Decodificado para Teclado (a)

(b.1) (b.2)

500

Figura 218. “Buffer” Anillo Estilo FIFO. (a) Inicializado el “Buffer”. La cabeza y la cola apuntan a la primera posición, el contador es iniciado. (b) Insertado un

caracter. La cabeza cambia a la siguiente posición y el contador es incrementado. (c) Insertados más caracteres. (d) Extracción de caracteres.

Cada vez que se extrae, se decrementa el contador y se incrementa la cola. (e) “Buffer” vacío. El “buffer” está vacío si el contador es cero. (f) “Buffer” Lleno. El “buffer” estará lleno si la cabeza o la cola apuntan más allá de la capacidad del

“buffer” y deberán de ser reiniciados a la posición cero del “buffer”.

Un “buffer” anillo o circular es un almacenador intermediario de información, se le dice circular pues la información fluye solo en ese pedazo de memoria reservada. El “buffer” implementado en esta ocasión, es estilo FIFO (“First-In-First-Out”) y como su nombre dice, existe un cierto orden en ingreso y extracción de caracteres. El primer caracter en entrar al almacenador, es el primero en salir. Por lo general, se implementa utilizando un contador de caracteres ingresados o extraídos, un apuntador de cabeza para caracteres insertados y un apuntador de cola para caracteres a extraer. Inicialmente la cabeza y cola apuntan a la posición inicial del buffer y el contador es iniciado a cero. Las condiciones de un buffer FIFO son: (1) Si se inserta un caracter al “buffer” el contador es incrementado indicando que existe un nuevo caracter en el “buffer” y el apuntador de cabeza se mueve a la siguiente posición. (2) Si se extrae un caracter del “buffer” el contador es decrementado indicando que se remueve un caracter del “buffer” y el apuntador de cola se mueve a la siguiente posición. (3) El “buffer” estará lleno cuando el contador esté al límite de la capacidad de caracteres a almacenar en el “buffer”. (4) El “buffer” estará vacío cuando el contador sea nulo (0). (5) Si la cabeza o la cola exceden la posición final del “buffer”, es decir, exceden la capacidad, el respectivo apuntador (cabeza o cola) será reiniciado. (b) (d) (a) (c) (e) (f)

3.9.5 “Buffer” Anillo

Nota Técnica Interfase a Teclado Matricial

501

22pF

22pF

4.9152MHz

5V

0.1uF

1IRQ2PTA03VSS4OSC15OSC26PTA17VDD8PTA29PTA310PTB711PTB612PTB513PTD714PTD615PTB416PTD017PTB318PTB219PTD120PTB121PTB022PTD323PTA424PTD225PTD526PTD427PTA528RST

CLEAR 0 HELP ENTER

2ND987

4 5 6 DOWN

UP321

VssVddVoRSE R/w_7D0

8D1

14D713D612D511D410D39D2

6 5 4 123

U1

10k 40%

5V 10M

10k

1314

1211

DATA

64CTRL

3

2

1

0

COL

32

1

0FILAS

0 1 2 3COL

3

FILAS

2

1

0

46CTRL

11121314

DATA

DATA

CTRL

COL

FILAS

COL

FILAS

CTRL

DATA

(1) LCD en modo de 4 bits (2) Los resistores de “pull-ups” están internamente (3) Esquema al microcontrolador en el microcontrolador

Figura 219. Esquema de Aplicación de Teclado Matricial. Para los microcontroladores JL3/QT/QY y GP32, los resistores de “pull-ups” vienen incluidos internamente para facilitar el “hardware” y coneccionamiento al microcontrolador. La pantalla LCD se hace trabajar en modo de 4 bits a manera de ahorrar pines de los puertos de entrada/salida; y el esquema del microcontrolador prácticamente no necesita de “hardware” adicional a

excepción de los módulos a trabajar.

3.9.6 Esquemático de Aplicación

502

Figura 220. NT1009 – KBD. (a) Programa Principal. El programa despliega mensajes de texto sobre la LCD la cual cuestiona sobre un código a introducir para comparar y simular una cerradura codificada. (b) Vector de Reinicio. Al presionar el botón RST, el sistema es reiniciado.

El siguiente diagrama de flujo representa la rutina principal de un programa que actúa como cerradura codificada, pero simulada. Al insertar un código incorrecto de cuatro (4) dígitos y luego presionar “ENTER”, el sistema compara el código ingresado con el residente en la memoria y si ambos códigos coinciden despliega el mensaje “Code Is OK”, de lo contrario, despliega “Miss Code”. Luego despliega un menú en el cual aguarda la tecla 1. “Press: 1 – Repeat”. Nota: Solo se listarán de los archivos, las rutinas necesarias por el programa principal y sus subrutinas. Se recomienda leer las notas técnicas, NT0009, NT010, NT0108, NT1008 para un mejor entendimiento de la aplicación, además de los Apéndices D, K y L. (a) (b) (a) (b) (c) (d)

3.9.7 Diagrama de Flujo

Nota Técnica Interfase a Teclado Matricial

503

(a) (b) (c) (d)

Figura 221. NT1009 – KBD – Subrutinas. (a) KbdBufInit. Inicializa el buffer anillo. Cabeza y cola a la posición inicial del “buffer”, contador en cero. (b) KbdBufEmpty. Verifica si el “buffer” tiene un dato que se pueda extraer. (c) KbdBufFull. Verifca si el “buffer” está lleno. (d) KbdBufPut.

Verifica si existe espacio en el “buffer” y deposita un carácter.

504 (a) (b) (c) (d)

Figura 222. NT1009 – KBD – Subrutinas - Continuación. (a) KbdBufGet. Recoge un carácter del “buffer” anillo, si existe alguno. (b) KbdBufClr.

Recoge todos los caracteres insertados, limpia el “buffer”. (c) KbdChkRow. Verifica que fila fue presionada. (d) KbdInit. Inicializa el teclado matricial.

Nota Técnica Interfase a Teclado Matricial

505

(a) (b) (e)

Figura 223. NT1009 – KBD – Subrutinas - Continuación. (a) KbdDecode. Decodifica el teclado y retorna el carácter presionado. (b) KbdChkSelCol. Verifica fila por fila, empezando por la primera columna, y retorna el índice de la columna presionada.

506

Figura 224. NT1009 – KBD – Subrutinas - Continuación. (a) KbdCmpCode. Esta rutina no forma parte del módulo, fue creada para comparar dos cadenas en la librería user.inc. (b) KbdChkCol. Verifica que columna fue presionada. (c) KbdScan. Rutina que decodifica dos veces y elimina el

rebote producido por las teclas.

(a) (b) (c)

Nota Técnica Interfase a Teclado Matricial

507

Figura 225. NT1009 – KBD – Subrutinas - Continuación. (a) LCDInit. Inicializa la pantalla en modo de cuatro bits, dado por un macro definido internamente en las rutinas. (b) LCDWrChar. Escribe un solo carácter ASCII en la pantalla. (c) LCDClr. Rutina que limpia la pantalla.

LCDWrMsgXY. Rutina que se posiciona en la fila-columna y escribe una cadena ASCII. (e) LCDSel. Rutina que selecciona entre el modo de comandos o de escritura.

(a) (b) (c) (d) (e)

508 (a) (b) (c)

Figura 226. NT1009 – KBD – Subrutinas - Continuación. (a) LCDWr. Rutina que escribe el comando o el caracter dependiendo del estado de entrada. (b) LCDSetXY. Rutina que se posiciona en la fila-columna. (c) LCDWrMsg. Rutina que escribe una cadena desde la posición en cual se

encuentre.

Nota Técnica Interfase a Teclado Matricial

509

(a) (c) (d) (e) (f) (b)

Figura 227. NT1009 – KBD – Subrutinas - Continuación. (a) RAMClr. Rutina que borra todo el contenido de la RAM y registros del CPU. (b) Delay. Rutina de retardo de tiempo programable de 0 a 65.535 segundos. (c) DelayNus. Rutina de retardo programable de microsegundos. (d)

KBIAck. Reconoce la interrupción del módulo de teclado del microcontrolador. (e) KBIInit. Inicializa el módulo de teclado del microcontrolador. (f) KBINTL. Rutina de interrupción; tarea de escaneo del teclado y reconocimiento de la interrupción de teclado.

NT1009

Rev. 1 del 07.08.05

510 Nota Técnica En el código se agregaron todas las rutinas de uso de teclado y todos los archivos que se utilizan en esta aplicación. Para un mejor entendimiento de la aplicación, se recomienda utilizar las NT0009, NT010, NT0108, NT1008 y Apéndices D, K y L.. ;================================================================= ; ARCHIVO : NT1009 - KBD - 06 12 04.asm ; PROPÓSITO : Control de una pantalla LCD y decodificación de teclado ; para ejecutar el simulado de una cerradura electrónica ; codificada. ; Si el código es correcto, despliega en pantalla un ; mensaje "Code Is OK"; de lo contrario, despliega ; "Miss Code". ; Luego despliega un menú en el cual se elige si desea ; repetir o esperar ; "Press : " ; "1 - Repeat" ; ; ; REFERENCIA : NT1009 - KBD - 06 12 04.doc ; ; LENGUAJE : IN-LINE ASSEMBLER ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 26 05 03 Creado. ; 06 12 04 Modificado. ;================================================================= ;============================================= ; Cabecera de Macros, Const. y Memoria ;============================================= $include '\MAP\includes.equ' ; Definiciones de usuario y mapa de memoria

3.9.8 Código

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

511

;============================================= ; OBJETIVO : Inicio de Codif. del Ensam- ; blador en Memoria FLASH. ;============================================= org FLASH_START ; Inicio Mem. FLASH ;============================================= ; OBJETIVO : Despliega caracteres en una ; pantalla de cristal líquido ; y utiliza el teclado para ; adquirir un código de acceso. ;============================================= START

rsp ; Inic.Stack = $00ff bset BIT0,CONFIG1 ; Desactiva Watchdog jsr RAMClr ; Borra RAM y registros jsr LCDInit ; Inicia pantalla clrx ; Reconoce una tecla a la vez jsr KbdInit ; Inicia teclado KBDRPT0106.A7

jsr LCDClr ; Borra pantalla clra ; Fila 0

ldx #4T ; Columna 4 pshx ; Empuja columna ldhx #LCDMESSAGE00 ; Puntero de mensaje jsr LCDWrMsgXY ; Escribe pula ; Reposiciona pila lda #1T ; Fila 1 clrx ; Columna 0 pshx ; Empuja columna ldhx #LCDMESSAGE01 ; Puntero de mensaje jsr LCDWrMsgXY ; Escribe pula ; Reposiciona pila clra ; Contador temporal KBDLOOP1009.A2

psha ; Empuja a pila jsr KbdBufEmpty ; Hay tecla en el buffer pula ; Recupera contador bne KBDLOOP1009.A2 ; NO, esperar nuevamente psha ; Empuja contador jsr KBdBufGet ; SI, Recoge la tecla jsr LCDWrChar ; Escribir caracter pula ; Recupera contador inca ; Incrementa contador cmp #KBD_MAX_KEY ; ¿Código totalmente ingresado? blo KBDLOOP1009.A2 ; NO, Siguiente tecla sta KBD_FIFO_CTR ; SI, Hace ver el buffer lleno clr KbdLastKey ; Borra última tecla KBDLOOP1009.A3

lda KbdLastKey ; Lee el último caracter presionado cmp #KBD_ENTER ; ¿Fue ENTER?

NT1009

Rev. 1 del 07.08.05

512 Nota Técnica bne KBDLOOP1009.A3 ; NO, Seguir preguntando ldhx #KBDKEYCODE ; Carga Dir. Código en Flash pshx ; Empuja Dir. Baja pshh ; Empuja Dir. Alta ldhx #KBD_FIFO ; Carga Dir. Código Insertado jsr KbdCmpCode ; Compara el código con el ingresado ais #2T ; Reposiciona pila beq KBDFALSE1009.A4 ; ¿Código incorrecto?, SI, Desplegar Falla lda #2T ; NO, fila 2 ldx #3T ; Columna 3 pshx ; Empuja columna ldhx #LCDMESSAGE02 ; Carga mensaje jsr LCDWrMsgXY ; Escribe bra KBDMENU1009.A5 ; Despliega el menu KBDFALSE1009.A4

lda #2T ; Fila 2 ldx #3T ; Columna 3 pshx ; Empuja columna ldhx #LCDMESSAGE03 ; Carga mensaje jsr LCDWrMsgXY ; Escribe KBDMENU1009.A5

ldhx #3000T ; A demora 3seg jsr Delay ; Retarda jsr LCDClr ; Borra pantalla ldhx #LCDMESSAGE04 ; Carga mensaje jsr LCDWrMsg ; Escribe lda #1T ; Fila 1 clrx ; Columna 0 pshx ; Empuja columna ldhx #LCDMESSAGE05 ; Carga mensaje jsr LCDWrMsgXY ; Escribe clr KbdLastKey ; Borra la última tecla KBDLOOP1009.A6

lda KbdLastKey ; Carga última tecla cmp #'1' ; ¿'1' Presionado? bne KBDLOOP1009.A6 ; NO, Repetir acción jsr KbdBufInit ; Si, reiniciar el buffer jmp KBDRPT1009.A7 ; Repetir de nuevo ;============================================= ; Declaración y definición de funciones ;============================================= $include '\FUNCTIONS\INCLUDES.inc' ; Incluye Funciones ;============================================= ; Declaración y Definición de interrupciones ;============================================= $include '\INTERRUPTS\interrupt.inc' ; Incluye interrupciones del microcontrolador Listado 62. NT1009 – KBD. Utiliza una pantalla de cristal líquido y un teclado de 16

teclas, despliega en pantalla una ventana de código donde el usuario inserta los cuatro campos y luego verifica si el código ingresado es correcto o no.

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

513

;================================================================= ; ARCHIVO : KBD.inc ; PROPÓSITO : Librería para utilidad de Teclado hasta 8 x 8. ; LENGUAJE : IN-LINE ASSEMBLER ; NOTAS : LA LIBRERÍA KBD.INC UTILIZA LA LIBRERÍA KBI.INC Y ; DELAY.INC ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 26 05 03 Creado. ; 06 12 04 Modificado. ;================================================================= ; INICIALIZACIÓN ; : Esta rutina puede utilizarse con cualquier teclado ; matricial y sirve hasta un teclado de 8 X 8 teclas ; Para utilizar esta rutina usted deberá inicializar ; el módulo de la siguiente manera. Configurar: ; 1 - Puerto de Filas de Teclado: KBD_ROW_PORT ; 2 - Reg. de direccionamiento de filas: KBD_ROW_DDR ; 3 - Cantidad de filas a utilizar: KBD_MAX_ROW ; 4 - Puerto de Columnas de Teclado: KBD_COL_PORT ; 5 - Reg. de direccionamiento de columnas: KBD_COL_DDR ; 6 - Cantidad de columnas a utilizar: KBD_MAX_COL ; 7 - Posición en RAM de la última tecla: KbdLastKey ; 8 - Máximo de teclas del buffer: KBD_MAX_KEY ; 9 - Lugar en RAM del Contador de buffer: KBD_FIFO_CTR ; 10 - Lugar en RAM de la cabeza del buffer: KBD_FIFO_HD ; 11 - Lugar en RAM de la cola del buffer: KBD_FIFO_TL ; 12 - Lugar en RAM del inicio del buffer: KBD_FIFO ; ; NOTA : Por el momento, solo se tiene la rutina para interrup- ; ciones para microcontroladores con puerto de teclado. ; Modificaciones futuras incluirán configuración para ; decodificación de teclado para microcontroladores sin ; este módulo. ; ;=================================================================

NT1009

Rev. 1 del 07.08.05

514 Nota Técnica ;============================================= ; Constantes & Macros ;============================================= ;============================================= ; DEFINA PUERTOS DE TECLADO ;============================================= KBD_ROW_PORT equ PORTA ; Puerto de Filas KBD_ROW_DDR equ DDRA ; Registro de Filas KBD_MAX_ROW equ 4T ; Máximo de Filas KBD_COL_PORT equ PORTD ; Puerto de Columnas KBD_COL_DDR equ DDRD ; Registro de Columnas KBD_MAX_COL equ 4T ; Máximo de Columnas KBD_MAX_SW equ {(KBD_MAX_ROW - 1) * KBD_MAX_ROW + (KBD_MAX_COL - 1)} ; Máximo de elementos de el teclado KBD_NO_KEY equ $FB ; Resultado de una tecla no presionada ; ROW = COL = FF; ROW*KBD_MAX_ROW +

; COL ;============================================= ; DEFINA UBICACIÓN DE LA ÚLTIMA TECLA ;============================================= KbdLastKey equ $80 ; Última tecla presionada ;============================================= ; TECLAS ESPECIALES DEL TECLADO ;============================================= KBD_UP equ 'U' ; Arriba KBD_DN equ 'W' ; Abajo KBD_LT equ 'L' ; Izquierda KBD_RT equ 'R' ; Derecha KBD_2ND equ 'S' ; Secundario KBD_HLP equ 'P' ; Ayuda KBD_ENTER equ 'N' ; Enter ;============================================= ; DEFINA TAMAÑO Y UBICACIÓN DEL BUFFER TECLADO ;============================================= KBD_MAX_KEY equ 4T ; Máximo de Teclas del buffer KBD_FIFO_CTR equ $A1 ; Contador de bytes del buffer KBD_FIFO_HD equ $A2 ; Cabeza del Buffer KBD_FIFO_TL equ $A4 ; Cola del Buffer KBD_FIFO equ $A6 ; Dirección Inicial del Buffer Anillo KBD_FIFO_MAX equ {KBD_FIFO+KBD_MAX_KEY}

; Máximo Puntero del buffer

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

515

;============================================= ; KBDBUFINIT : Inicializa el buffer anillo ; OBJETIVO : Cabeza y cola en posición i- ; nicial; contador en cero ; ENTRADA : Ninguna ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : CCR, H:X ;============================================= KbdBufInit

sei ; Deshabilita interrupciones ldhx #KBD_FIFO ; Apunto al buffer sthx KBD_FIFO_HD ; Cabeza y cola apuntando... sthx KBD_FIFO_TL ; ... al inicio del buffer cli ; Habilita interrupciones clr KBD_FIFO_CTR ; Borra contador rts ; Retorna ;============================================= ; KBDBUFEMPTY ; : Verifica si el buffer está ; vacío ; OBJETIVO : Pregunta si hay un nuevo con- ; tenido del buffer ; ENTRADA : Ninguna ; SALIDA : A = 1 si el buffer está ; vacío. ; A = 0 si el buffer no está ; lleno. ; REGISTROS ; AFECTADOS : ACCA ;============================================= KbdBufEmpty

lda KBD_FIFO_CTR ; Carga contador de bytes del buffer bne KBD1009.A ; No es 0?, SI, salir lda #1 ; Carga 1, buffer vacío bra KBD1009.B ; Salir KBD1009.A

clra ; NO, Carga 0, buffer no vacío KBD1009.B

rts ; Retorna

NT1009

Rev. 1 del 07.08.05

516 Nota Técnica ;============================================= ; KBDBUFFULL ; : Verifica si el buffer está ; lleno. ; OBJETIVO : Verifica si se agotó la capa- ; cidad del buffer. ; ENTRADA : Ninguna ; SALIDA : A = 1 si el buffer está ; lleno. ; A = 0 si el buffer no está ; lleno. ; REGISTROS ; AFECTADOS : ACCA ;============================================= KbdBufFull

lda KBD_FIFO_CTR ; Carga contador de bytes del buffer cmp #KBD_MAX_KEY ; Compara con la capacidad máxima del buffer bge KBD1009.C ; Sobrepasa?, SI, activar bandera clra ; NO, Carga 0, buffer no lleno bra KBD1009.D ; Salir KBD1009.C

lda #1 ; Carga 1, buffer lleno KBD1009.D

rts ; Retorna ;============================================= ; KBDBUFPUT : Impone 1 byte en el buffer ; OBJETIVO : Arroja 1 byte en el bufer ; ENTRADA : A es el dato a enviar al ; buffer ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : ACCA, H:X, CCR ;============================================= KbdBufPut

tax ; Transfiere SCI_SCDR a X jsr KBDBufFull ; Verifica capacidad del buffer bne KBD1009.E ; Si está lleno, salir inc KBD_FIFO_CTR ; incrementa contador txa ; Recupera el dato ldhx KBD_FIFO_HD ; Apunta al lugar a trasferir al buffer sta ,x ; Almacena en la posición apuntada aix #1 ; incrementa el puntero sthx KBD_FIFO_HD ; Actualiza cabeza cphx #KBD_FIFO_MAX ; Compara con la capacidad máxima bne KBD1009.E ; NO, no son iguales, salir ldhx #KBD_FIFO ; SI, Carga posición inicial sthx KBD_FIFO_HD ; Apunta cabeza al inicio nuevamente KBD1009.E

rts ; retorna

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

517

;============================================= ; KBDBUFGET : Recoge 1 byte en el buffer ; OBJETIVO : Arroja 1 byte en el bufer ; ENTRADA : Ninguna ; SALIDA : A = 0 si no se recupera ; del buffer... ó ; A contiene el byte re- ; cuperado del buffer ; REGISTROS ; AFECTADOS : ACCA, H:X, CCR ;============================================= KbdBufGet

sei ; Deshabilita interrupciones jsr KBDBufEmpty ; Verifica si hay un nuevo dato en el buffer bne KBD1009.F ; Si está vacío, salir dec KBD_FIFO_CTR ; decrementa contador ldhx KBD_FIFO_TL ; Apunta al lugar a remover el byte del buffer lda ,x ; Recupera de la posición apuntada aix #1 ; incrementa el puntero sthx KBD_FIFO_TL ; Actualiza cola cphx #KBD_FIFO_MAX ; Compara con la capacidad máxima bne KBD1009.G ; NO, no son iguales, salir ldhx #KBD_FIFO ; SI, Carga posición inicial sthx KBD_FIFO_TL ; Apunta cola al inicio nuevamente bra KBD1009.G ; salir KBD1009.F

clra ; si el buffer está lleno, retorna 0 KBD1009.G

cli ; Habilita interrupciones rts ; retorna ;============================================= ; KBDBUFCLR : Vacía el buffer ; OBJETIVO : Saca todos los caracteres del ; buffer de teclado ; un contenido nulo ; ENTRADA : Ninguna ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : ACCA ;============================================= KbdBufClr

sei ; Inhabilita interrupciones lda KBD_FIFO_CTR ; Carga contador del buffer beq KBDOUT1009.H ; SI es 0, salir jsr KBDBufGet ; NO, Recoger el caracter bra KbdBufClr ; Seguir hasta vaciar KBDOUT1009.H

cli ; Habilita interrupciones rts ; Retorna

NT1009

Rev. 1 del 07.08.05

518 Nota Técnica ;============================================= ; KBDINIT : Configura puertos de filas y ; columnas. ; OBJETIVO : Configura las filas y columnas ; especificadas por el macro. ; ENTRADA : X contiene el tipo de ; reconocimiento de ; teclas. ; X = 1, Continua ; X = 0, Una a la vez ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : ACCA, X ; NOTAS : La rutina KBDInit no verifica ; si configuro adecuadamente ; el módulo de teclado. ;============================================= KbdInit

lda #{1 < KBD_MAX_ROW - 1} ; Configura filas a usar jsr KBIInit ; Configura Filas y el tipo de interrupción lda #{1 < KBD_MAX_COL - 1} ; Configura columnas a usar ora KBD_COL_DDR ; Puerto, bit "n" es salida en bajo sta KBD_COL_DDR ; Configura como salidas lda #{1 < KBD_MAX_COL - 1} ; Configura columnas a usar coma ; 0s las columnas a usar and KBD_COL_PORT ; preserva bits sta KBD_COL_PORT ; Almacena en el puerto jsr KbdBufInit ; Inicia el buffer e interrupciones globales

rts ; Retorna

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

519

;============================================= ; KBDCHKROW ; : Verifica que fila fue activa ; da al presionarse la tecla. ; OBJETIVO : Sensa del puerto de filas la ; línea que está en estado ; lógico bajo. ; ENTRADA : Ninguna ; SALIDA : ACCA es el número de la ; fila decodificada ; REGISTROS ; AFECTADOS : CCR_C, X, A, KBD_ROW_PORT ; NOTAS : Si no se ha detectado tecla ; carga caracter de error #$FF ;============================================= KbdChkRow

clc ; CCR_C = 0 clrx ; Contador de filas = 0 lda KBD_ROW_PORT ; Carga contenido del puerto de filas KBDLOOP1009.J

rora ; Rota el contenido del puerto bcc KBDOUT1009.I ; ¿CCR_C = 0?, SI, Salir incx ; Incrementa contador de filas cpx #KBD_MAX_ROW ; ¿Hubo sobreflujo de filas? bne KBDLOOP1009.J ; NO, Siguiente fila ldx #$FF ; SI, Carga caracter de error, no hay tecla KBDOUT1009.I

txa ; Transfiere al acumulador rts ; Retorna

NT1009

Rev. 1 del 07.08.05

520 Nota Técnica ;============================================= ; KBDCHKCOL : Verifica que columna fue ac- ; tivada al presionarse la te- ; cla. ; OBJETIVO : Sensa del puerto de columnas ; la línea que ocasionó el ; estado lógico bajo. ; ENTRADA : Ninguna ; SALIDA : ACCA contiene la decodi- ; ficación del valor ; registrado del te- ; clado ; REGISTROS ; AFECTADOS : ACCA ;============================================= KbdChkCol

lda KBD_COL_PORT ; Carga el contenido del puerto psha ; Salva el contenido del puerto lda #{1 < KBD_MAX_COL - 1} ; Configura columnas ora KBD_COL_PORT ; Preserva bits del puerto

sta KBD_COL_PORT ; Almacena en el puerto jsr KbdChkSelCol ; Devuelve la columna presionada pula ; Recupera Estado de puertos sta KBD_COL_PORT ; Almacena estado rts ; Retorna

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

521

;============================================= ; KBDDECODE : Rutina de decodificación ; OBJETIVO : Decodifica el teclado encon- ; trando las fila, columna y ; luego buscando en una tabla ; el valor ASCII correspon- ; diente al teclado. ; ENTRADA : Ninguna ; SALIDA : ACCA contiene el caracter ; decodificado ; REGISTROS ; AFECTADOS : A, H, X, SP ; NOTAS : Si en segunda instancia, se ; detecta la tecla 2ND, la ; rutina suma un offset que la ; traslada a la siguiente ; tabla de búsqueda. ;============================================= KbdDecode

jsr KBDChkRow ; Verifica la fila psha ; Empuja fila a la pila

jsr KBDChkCol ; Verifica la columna pula ; Recupera la fila pshx ; Empuja columna a la pila ldx #KBD_MAX_ROW ; Carga máximo de filas mul ; A = ROW*KBD_MAX_ROW add 1,SP ; A = A + COL pulx ; Reposiciona pila cmp #KBD_NO_KEY ; ¿Tecla no presionada? beq KBDOUT1009.K ; SI, Salir cmp #{KbdTblTop - KbdTbl} ; ¿Pasa del límite de decodificación? bhi KBDOUT1009.K ; Si, salir clrh ; SI, Borra H tax ; NO, Apunta a la tabla lda KBDLastKey ; Cargo la última tecla presionada cmp #KBD_2ND ; ¿Última tecla fue 2ND? bne KBDNOOFFSET1009.L ; NO, Saltar a buscar caracteres primarios aix #{KBD_MAX_SW + 1} ; Añade el offset KBDNOOFFSET1009.L lda KBDTbl,x ; Carga Caracter primario o secundario KBDOUT1009.K

rts ; Retorna

NT1009

Rev. 1 del 07.08.05

522 Nota Técnica ;============================================= ; KBDCHKSELCOL ; : Verifica columna presionada ; OBJETIVO : Configura cada puerto de te ; clado en bajo, los demás en ; alto y verifica la columna ; correspondiente a ver si ; fue presionada ; ENTRADA : Ninguna ; SALIDA : ACCA contiene los bits a ; configurar como sali- ; das para columnas ; REGISTROS ; AFECTADOS : A, X, SP ;============================================= KbdChkSelCol

lda #1T ; Carga máscara inicial clrx ; Contador temporal = 0 KBDLOOP1009.O

coma ; 1s por 0s, cambia máscara psha ; Empuja máscara pshx ; Empuja contador temporal and KBD_COL_PORT ; Enmascara la columna sta KBD_COL_PORT ; Columna actual en estado bajo jsr KBDChkRow ; Verifica si alguna fila está en bajo cmp #$FF ; ¿Tecla no presionada? pulx ; Recupera contador temporal pula ; Recupera máscara bne KBDOUT1009.M ; Si la tecla no fue presionada, cpx #KBD_MAX_COL ; ¿Máximo de columnas? bge KBDOUT1009.N ; SI, Cargar caracter de error incx ; Incrementa contador de columnas coma ; Conmuta máscara asla ; Siguiente columna bra KBDLOOP1009.O ; Busca en la siguiente columna KBDOUT1009.N

ldx #$FF ; Devuelve error de rutina KBDOUT1009.M

rts ; Retorna

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

523

;============================================= ; KBDSCAN : Verifica el estado del tecla ; do ; OBJETIVO : Decodifica teclado, almacena ; en buffer si hay espacio, ; almacena la última tecla ; presionada y reconoce la ; Interrupción ; ENTRADA : Ninguna ; SALIDA : KbdLastKey última tecla ; presionada ; REGISTROS ; AFECTADOS : ACCA, H:X ;============================================= KbdScan

jsr KbdDecode ; Decodifica el teclado cmp #KBD_NO_KEY ; ¿No hay tecla? beq KBDOUT1009.P ; SI, no hay, salir ldhx #4T ; Carga retardo jsr Delay ; Elimina rebote jsr KbdDecode ; Decodifica el teclado cmp #KBD_NO_KEY ; ¿No hay tecla? beq KBDOUT1009.P ; SI, no hay, salir sta KbdLastKey ; HAY, Almacena como última tecla jsr KbdBufPut ; Almacena si hay espacio KBDOUT1009.P

jsr KBIAck ; Reconoce interrupción rts ; Retorna ;============================================= ; KBDTBL : Tabla de decodificación ; OBJETIVO : Muestra la tabla de filas, ; columnas y número decodifi- ; cado. ;============================================= KbdTbl ; X = KeyDecodeIx = ROW*KBD_ROW_MAX

, + COL ; ROW COL KbdPrimary KbdSecondary db '1' ; 0 0 1 A db '2' ; 0 1 2 B db '3' ; 0 2 3 C db KBD_UP ; 0 3 UP LT db '4' ; 1 0 4 D db '5' ; 1 1 5 E db '6' ; 1 2 6 F db KBD_DN ; 1 3 DN RT db '7' ; 2 0 7 G db '8' ; 2 1 8 H db '9' ; 2 2 9 I db KBD_2ND ; 2 3 2ND 2ND db ' ' ; 3 0 CLR CLR db '0' ; 3 1 0 J

NT1009

Rev. 1 del 07.08.05

524 Nota Técnica db KBD_HLP ; 3 2 HLP HLP

db KBD_ENTER ; 3 3 ENTER ENTER db 'A','B','C',KBD_LT ; Tabla de caracteres Secundarios db 'D','E','F',KBD_RT db 'G','H','I',KBD_2ND db ' ','J',KBD_HLP KbdTblTop

db KBD_ENTER Listado 63. NT1009 – KBD – KBD.inc. Archivo de funciones del módulo de teclado.

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

525

;================================================================= ; ARCHIVO : KBI.inc ; PROPÓSITO : Inclusión de la función de inicialización del módulo de ; teclado ; LENGUAJE : IN-LINE ASSEMBLER ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 10 09 04 Creado. ; 10 09 04 Modificado. ;================================================================= ;============================================= ; KBIINIT : Inicializa registro de inte- ; rrupción de teclado. ; OBJETIVO : Teclas PTA como interrup- ; tores de teclado. ; ENTRADA : A teclas a inicializar ; como teclado ; X valor booleano del ; bit MODEK ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : KBSCR, KBIER ;============================================= KBIInit

tsta ; prueba ACCA beq KBIOUT0108.A ; Si es cero, salir bset BIT1,KBSCR ; IMASK = 1, Enmascaro interrupción de

; teclado sta KBIER ; Escribo en KBIER y habilito las teclas ; Se generó una falsa interrupción. txa ; Transfiere MODEK a ACCA ora #ACKK ; Reconoce la interrupción sta KBSCR ; Almacena en el registro KBIOUT0108.A

rts ; Retorno de la subrutina

NT1009

Rev. 1 del 07.08.05

526 Nota Técnica ;============================================= ; KBIACK : Borra Interrupción de Tecla ; OBJETIVO : Reconoce IRQF del KBSCR ; ENTRADA : Ninguna ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : KBSCR, A ;============================================= KBIAck

lda #MODEK ; A = MODEK and KBSCR ; Preservo bit MODEK ora #ACKK ; Cargo ACCK + A sta KBSCR ; Borro falsa interrupción rts ; Retorna Listado 64. NT1009 – KBD – KBI.inc. Archivo de funciones del módulo de teclado del

microcontrolador.

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

527

;================================================================= ; ARCHIVO : LCD.inc ; PROPÓSITO : Librería para pantalla LCD ; LENGUAJE : IN-LINE ASSEMBLER ; NOTAS : LA LIBRERÍA LCD.INC UTILIZA LAS FUNCIONES DE LA ; LIBRERÍA DE FUNCIONES DE RETARDO DELAY.INC. ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 05 11 04 Creado. ; 11 11 04 Modificado. ;=================================================================; INICIALIZACIÓN ; : Esta rutina puede utilizarse con cualquier LCD con ; driver Hitachi HD44780. ; Para utilizar esta rutina usted deberá inicializar ; el módulo de la siguiente manera. Configurar: ; 1 - Puerto de datos: LCD_DATA_PORT ; 2 - Reg. de direccionamiento para datos: LCD_DATA_DDR ; 3 - Pines de salida de datos a utilizar: LCD_DATA_OUTPUT ; 4 - Puerto de la señal RS: LCD_RS_PORT ; 5 - Reg. de direccionamiento de la señal RS: LCD_RS_DDR ; 6 - Pin del puerto para señal RS: LCD_RS_PIN ; 7 - Puero de la señal E: LCD_E_PORT ; 8 - Reg. de direccionamiento de E: LCD_E_DDR ; 9 - Pin del puerto para E: LCD_E_PIN ; ; 0,0 ; +-> (Columna) ; | Pantalla LCD de 16 X 4 Caracteres ; U (Caracteres Visibles) ; (Fila) ; ; 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 ; +******************************************************************* ; 00* A B C D E F G H I J K L M N O P ; 01* Q R S T U V W X Y Z 0 1 2 3 4 5 ; 02* 6 7 8 9 a b c d e f g h i j k l ; 03* m n o p q r s t u v w x y z # ! ; +******************************************************************* ; ; ;=================================================================;$SET LCD_8BIT_MODE_EN ; Configura para 8 Bits $SETNOT LCD_8BIT_MODE_EN ; Configura para 4 Bits

NT1009

Rev. 1 del 07.08.05

528 Nota Técnica ;============================================= ; Constantes & Macros ;============================================= ;============================================= ; DEFINA EL PUERTO DE DATOS ;============================================= LCD_DATA_PORT equ PORTD ; Puerto de Salida de la Información LCD_DATA_DDR equ DDRD ; Registro de dir. del Puerto de Salida

; de la Información $IF LCD_8BIT_MODE_EN LCD_DATA_OUTPUT equ $FF ; Puertos a Utilizar en el LCD ($FF =

; Todos son utilizados, modo 8bits) $ELSEIF LCD_DATA_OUTPUT equ $F0 ; Puertos a Utilizar en el LCD ($F0 =

; Solo nibble alto) $ENDIF ;============================================= ; DEFINA PUERTO DE REGISTRO/INSTRUCCIÓN LCD ;============================================= LCD_RS_PORT equ PORTB ; Puerto de Registro/Instrucción del

; LCD LCD_RS_DDR equ DDRB ; Registro de dir. del Puerto del RS del

; LCD LCD_RS_PIN equ BIT4 ; Pin del Puerto ;============================================= ; DEFINA PUERTO HABILITADOR DE INSTRUCCIÓN ;============================================= LCD_E_PORT equ PORTB ; Puerto de Habilitador de Instrucción

; del LCD LCD_E_DDR equ DDRB ; Registro de dir. del Puerto de RS LCD_E_PIN equ BIT6 ; Pin del Puerto ;============================================= ; DEFINA MÁXIMO DE FILAS Y COLUMNAS DE SU LCD ;============================================= LCD_MAX_ROW equ 4T ; Máximo de filas LCD_MAX_COL equ 16T ; Máximo de columnas ;============================================= ; INSTRUCCIONES DEL LCD ;============================================= LCD_CLR equ %00000001 ; Borra pantalla y ubica en posición inicial izq. LCD_HOME equ %00000010 ; Regresa a posición inicial LCD_INC equ %00000010 ; Incremento de Cursor LCD_SHIFT equ %00000001 ; Cambio extremo activado LCD_ON equ %00000100 ; Enciende el LCD LCD_CSR equ %00000010 ; Enciende el Cursor LCD_BLINK equ %00000001 ; Parpadea LCD LCD_RT equ %00000100 ; Display Shift Derecho

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

529

LCD_SET equ %00001000 ; Cursor Encendido LCD_8BIT equ %00010000 ; LCD de 8 bit LCD_2LINE equ %00001000 ; LCD 2 líneas LCD_5X11 equ %00000100 ; LCD 5X11 Puntos LCD_CSR_RT equ %00010100 ; Mueve el cursor a la derecha LCD_CSR_LT equ %00010000 ; Mueve el cursor a la izquierda LCD_MOVE_RT equ %00011100 ; Mueve la pantalla a la derecha LCD_MOVE_LT equ %00011000 ; Mueve la pantalla a la izquierda ;============================================= ; CONSTANTES DE RETARDO E INHERENCIAS ;============================================= LCD_RS_HIGH equ 1T ; Comando de escritura LCD_SPACE_CHAR equ $20 ; Caracter de espacio LCD_CLR_DLY equ 5T ; Retardo de estabilidad de comando CLR LCD_ROW1 equ 1T ; Comprobante de fila 1 LCD_ROW2 equ 2T ; Comprobante de fila 2 LCD_ROW0_OFFSET equ $80 ; Desfase hacia fila 0 ($80 + $00) LCD_ROW1_OFFSET equ $C0 ; Desfase hacia fila 1 ($80 + $40) LCD_ROW2_OFFSET equ $90 ; Desfase hacia fila 2 ($80 + $10) LCD_ROW3_OFFSET equ $D0 ; Desfase hacia fila 3 ($80 + $50)

NT1009

Rev. 1 del 07.08.05

530 Nota Técnica ;============================================= ; LCDINIT : Inicializa el módulo LCD ; OBJETIVO : Configura el LCD en modo de ; 8bits, 2 líneas, matriz de ; 5 X 11 puntos si existe en el ; LCD, Incremento ; ENTRADA : Ninguna ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : PORTX, DDRX, A ;============================================= LCDInit

clrh ; Borra H ldx #40T ; A retardar 40 ms jsr Delay ; Retarda clr LCD_DATA_PORT ; DATA = LOW mov #LCD_DATA_OUTPUT,LCD_DATA_DDR ; DDR_DATA = OUTPUT bset LCD_E_PIN,LCD_E_DDR ; DDR_E = OUTPUT bset LCD_RS_PIN,LCD_RS_DDR ; DDR_RS = OUTPUT bclr LCD_RS_PIN,LCD_RS_PORT ; RS = LOW bclr LCD_E_PIN,LCD_E_PORT ; E = LOW clra ; A = 0 jsr LCDSel ; RS = LOW $IF LCD_8BIT_MODE_EN

lda #{$20|LCD_8BIT|LCD_2LINE|LCD_5X11} ; LCD 8bits, 2 líneas y 5 X 11 $ELSEIF

lda #LCD_HOME ; Regresa a Casa jsr LCDWr ; Ejecuta comando lda #{$20|LCD_2LINE|LCD_5X11} ; Dos líneas, 5X11, si posee y 4 bits $ENDIF jsr LCDWr ; Ejecuta comando lda #{$08|LCD_ON|LCD_CSR|LCD_BLINK} ; Enciende LCD, Cursor, Parpadeo. jsr LCDWr ; Ejecuta comando jsr LCDClr ; Borra pantalla lda #{$04|LCD_INC} ; Modo incremental jsr LCDWr ; Ejecuta comando rts ; Retorna

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

531

;============================================= ; LCDCLR : Borra la pantalla ; OBJETIVO : Borra completamente el LCD ; y ubica cursor en la parte ; superior izquierda ; ENTRADA : Ninguna ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : A, H:X ;============================================= LCDClr

clra ; RS = LOW jsr LCDSel ; Cambia estado de RS a bajo lda #LCD_CLR ; Comando borrar jsr LCDWr ; Ejecuta comando ldhx #LCD_CLR_DLY ; A retardar 5 ms jsr Delay ; Ejecuta retardo rts ; Retorna ;============================================= ; LCDWRCHAR : Escribe un caracter en la ; posición actual del cursor ; OBJETIVO : Escribe un caracter en cual ; quier posición de la LCD ; ENTRADA : A es el caracter a enviar ; al LCD ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : A, SP ;============================================= LCDWrChar

psha ; Empuja caracter a pila lda #LCD_RS_HIGH ; A ejecutar comando jsr LCDSel ; RS = LOW pula ; Recupera caracter de pila jsr LCDWr ; Escribe caracter rts ; Retorna

NT1009

Rev. 1 del 07.08.05

532 Nota Técnica ;============================================= ; LCDWRMSG : Escribe una cadena de carac- ; teres ; OBJETIVO : Escribe una cadena dada por ; la dirección de una tabla ; ENTRADA : H:X contiene la dirección ; de la cadena a enviar ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : CCR, A, H:X ;============================================= LCDWrMsg

sei ; Inhabilita interrupciones lda #LCD_RS_HIGH ; Comando RS = 1 jsr LCDSel ; RS = 1 LCDWRITE1008.I

lda ,x ; Carga caracter beq LCDOUT1008.J ; ¿Cero?, salir pshx ; Empuja a pila jsr LCDWr ; Envía al LCD pulx ; Recupera de pila aix #1 ; Incrementa puntero bra LCDWRITE1008.I ; Siguiente caracter LCDOUT1008.J

cli ; Habilita interrupciones rts ; Retorna ;============================================= ; LCDWRXY : Ubica el cursor y escribe ; OBJETIVO : Ubica cursor en posición X-Y ; y escribe un caracter ; ENTRADA : A (PUSH) ; es el dato a desplegar ; en la pantalla ; A es la fila en número de- ; cimal ; X es la columna en número ; decimal ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : CCR, SP, A ;============================================= LCDWrXY

jsr LCDSetXY ; Posiciona en X-Y lda #LCD_RS_HIGH ; A = 1 jsr LCDSel ; RS = HIGH lda 3,SP ; Recupera dato jsr LCDWr ; Escribe el dato rts ; Retorna

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

533

;============================================= ; LCDWRMSGXY ; : Escribe un mensaje en la po- ; sición X-Y ; OBJETIVO : Escribe un conjunto de carac- ; teres en la posición X-Y ; ENTRADA : A es la fila del mensaje ; X (PUSH) ; es la columna del men- ; saje ; H:X es la dirección del ; mensaje a escribir ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : X, SP, CCR ;============================================= LCDWrMsgXY

sei ; Inhabilita Interrupciones pshx ; Empuja parte baja de puntero a pila ldx 4,SP ; Carga Columna jsr LCDSetXY ; Posiciona en X-Y pulx ; Recupera parte baja del puntero jsr LCDWrMsg ; Escribe cadena y habilita

; interrupciones rts ; Retorna ;============================================= ; LCDSEL : Selecciona modo de instruc- ; ciones o datos ; OBJETIVO : RS = HIGH ó RS = LOW ; ENTRADA : A es el estado booleano a ; imponer para control ; de RS ; A = 1 RS = HIGH ; A = 0 RS = LOW ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : DDRX, PORTX ;============================================= LCDSel

beq LCDOUT0105.A ; A = 0, Saltar a imponer RS bajo bset LCD_RS_PIN,LCD_RS_PORT ; A = 1, Impone RS alto bra LCDOUT1008.B ; Salir LCDOUT1008.A

bclr LCD_RS_PIN,LCD_RS_PORT ; Impone RS bajo LCDOUT1008.B

rts ; Retorna

NT1009

Rev. 1 del 07.08.05

534 Nota Técnica ;============================================= ; LCDWR : Escribe un caracter ; OBJETIVO : Muestra un caracter en la ; pantalla ; ENTRADA : A contiene el caracter a ; desplegar ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : DDRDX, PORTX, A, X ;============================================= LCDWr $IF LCD_8BIT_MODE_EN

sta LCD_DATA_PORT ; Almacena dato en puerto de LCD $ELSEIF psha ; Empuja el caracter a pila and #LCD_DATA_OUTPUT ; Preserva byte alto LCD psha ; Empuja Dato LCD a pila lda LCD_DATA_PORT ; Carga Puerto LCD and #$0F ; Preserva byte bajo add 1,SP ; Añade el byte preservado sta LCD_DATA_PORT ; Almacena en puerto pula ; Reposiciona pila $ENDIF bset LCD_E_PIN,LCD_E_PORT ; Levanta pin Enable

ldx #5T ; XTAL lda #10T ; A retardar +1 us jsr DelayNus ; Retardar +1 bclr LCD_E_PIN,LCD_E_PORT ; Baja línea enable ldx #5T ; XTAL lda #60T ; A retardar +40 us jsr DelayNus ; Retarda +40 us y más $IF LCD_8BIT_MODE_EN $ELSEIF

pula ; Recupera byte caracter de pila and #$0F ; Preserva byte bajo LCD nsa ; Posiciona el byte alto

psha ; Empuja Dato LCD a pila lda LCD_DATA_PORT ; Carga Puerto LCD and #$0F ; Preserva byte bajo add 1,SP ; Añade el byte preservado sta LCD_DATA_PORT ; Almacena en puerto pula ; Reposiciona pila bset LCD_E_PIN,LCD_E_PORT ; Levanta pin Enable ldx #5T ; XTAL lda #10T ; A retardar +1 us jsr DelayNus ; Retardar +1 bclr LCD_E_PIN,LCD_E_PORT ; Baja línea enable ldx #5T ; XTAL lda #60T ; A retardar +40 us jsr DelayNus ; Retarda +40 us y más $ENDIF

rts ; Retorna

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

535

;============================================= ; LCDSETXY : Cursor de LCD ubicado en ; Posición de pantalla ; OBJETIVO : Ubica cursor en posición X-Y ; ENTRADA : A es la fila en número de- ; cimal ; X es la columna en número ; decimal ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : CCR ;============================================= LCDSetXY

cmp #LCD_MAX_ROW ; Compara A con máximo de filas bge LCDOUT1008.G ; Mayor o igual?, salir cpx #LCD_MAX_COL ; Compara X con máximo de

; columnas bge LCDOUT1008.G ; Mayor o igual?, salir psha ; Empuja fila a la pila clra ; A = 0 jsr LCDSel ; RS = LOW pula ; Recupera A pshx ; Empuja columna a pila tsta ; Comprueba si es fila 0 beq LCDOUT1008.C ; Salir si es 0 cmp #LCD_ROW1 ; Comprueba si es fila 1 beq LCDOUT1008.D ; Ir a offset de fila 1 cmp #LCD_ROW2 ; Comprueba si es fila 2 beq LCDOUT1008.E ; Ir a offset de fila 2 ldx #LCD_ROW3_OFFSET ; Carga offset de fila 3 bra LCDOUT1008.F ; Salta a posicionar en fila LCDOUT1008.C

ldx #LCD_ROW0_OFFSET ; Carga offset de fila 0 bra LCDOUT1008.F ; Salta a posicionar en fila LCDOUT1008.D

ldx #LCD_ROW1_OFFSET ; Carga offset de fila 1 bra LCDOUT1008.F ; Salta a posicionar en fila LCDOUT1008.E

ldx #LCD_ROW2_OFFSET ; Carga offset de fila 2 LCDOUT1008.F

txa ; Carga columna add 1,sp ; Suma fila + columna jsr LCDWr ; Posiciona en Fila, repite X veces pulx ; Posiciona stack LCDOUT1008.G

rts ; Retorna Listado 65. NT1009 – KBD – LCD.inc. Archivo de funciones de manejo de una LCD. Para esta nota, se hace énfasis en las funciones utilizadas y la configuración en modo

de 4 bits.

NT1009

Rev. 1 del 07.08.05

536 Nota Técnica ;=================================================================; ARCHIVO : RAM.inc ; PROPÓSITO : Funciones de uso de la RAM ; NOTAS : ADVERTENCIA - Se debe especificar el inicio y el origen de ; RAM de su microcontrolador por medio de los ; macros RAM_ORG y RAM_END ; ; LENGUAJE : IN-LINE ASSEMBLER ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 05 10 04 Creado. ; 06 10 04 Modificado. ;================================================================= ;============================================= ; CONSTANTES & MACROS ;============================================= RAM_ORG equ $0080 ; Inicio de la memoria RAM RAM_END equ $00FF-1 ; Fin de limpieza de la RAM ;============================================= ; RAMCLR : Borra la Ram utilizada y re- ; gistros inherentes ; OBJETIVO : Borra registros ; ENTRADA : Ninguna ; SALIDA : A, H:X y RAM en 0 ; REGISTROS ; AFECTADOS : RAM, H:X, A ;============================================= RAMClr ; Borra la RAM y registros

clrh ; Borra H ldx #RAM_ORG ; Carga con el origen

RAM_EMPTY0000.A clr ,x ; rellena con "0" la posición actual aix #1 ; incrementa puntero de RAM cphx #RAM_END ; Compara hasta el final deseado bne RAM_EMPTY0000.A ; Si no concuerda entonces sigue

; limpiando clra ; Borra A clrh ; Borra H clrx ; Borra X rts ; retorna

Listado 66. NT1009 – KBD – RAM.inc. RAMClr es una rutina que borra la RAM y los

registros del CPU.

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

537

;================================================================= ; ARCHIVO : DELAY.inc ; PROPÓSITO : Función de retardo de tiempo ; ARGUMENTOS ; : H:X = tiempo en milisegundos ; RETORNO : Ninguno ; LENGUAJE : IN-LINE ASSEMBLER ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 22 08 04 Creado. ; 11 11 04 Modificado. ;================================================================= ;============================================= ; CONSTANTES & MACROS ;============================================= DELAY4 equ $0079 ; Constante de Retardo a 4.0000 MHz DELAY49152 equ $0096 ; Constante de Retardo a 4.9152 MHz DELAY98304 equ $0130 ; Constante de Retardo a 9.8304 MHz DELAY128 equ $018C ; Constante de Retardo a 12.800 MHz DELAY32 equ $03E4 ; Constante de Retardo a 32.000 MHz

NT1009

Rev. 1 del 07.08.05

538 Nota Técnica ;============================================= ; DELAY : Genera un retardo de tiempo ; OBJETIVO : Retardo de tiempo, base 1ms ; ENTRADA : H:X = Retardo en ms ; SALIDA : H:X = 0 ; REGISTROS ; AFECTADOS : H:X ; USO : ; MIN = H:X = 1T ; MÁX = H:X = 65535T ; ldhx #500T ; jsr Delay ; retarda 0.5 seg ;============================================= Delay

cphx #0 ; [3] Compara con 0 beq DELAY0009.A ; [3] Salir si es 0 pshx ; [2] Salva X en la pila pshh ; [2] Salva H en la pila ldhx #DELAY49152 ; [3] Carga constante de bucle fino Delay0009.B

aix #-1 ; [2] Decrementa H:X en 1 cphx #0 ; [3] LLegó a cero (0) bne Delay0009.B ; [3] Si no es igual, salta a Delay0 pulh ; [2] Si es igual, recupera H de la pila pulx ; [2] Recupera X de la pila aix #-1 ; [2] Decrementa H:X en 1 cphx #0 ; [3] LLegó a cero (0) bne Delay ; [3] Si no es igual, salta a Delay DELAY0009.A

rts ; [4] retorna

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

539

;============================================= ; DELAYNUS : Genera un retardo de tiempo ; OBJETIVO : Retardo de tiempo, base 1us ; ENTRADA : X = Valor entero del cris- ; tal externo ; A = Tiempo a retardar en us ; SALIDA : Ninguna ; REGISTROS ; AFECTADOS : A, X ;============================================= DelayNus

tsta ; [1] Verifica estado de A beq DELAY0009.C ; [3] Salir si es cero deca ; [1] Decrementa A psha ; [2] Empuja A a pila pshx ; [2] Empuja variable X dbnzx * ; [3] Decrementa hasta 0 pulx ; [2] Recupera variable X pula ; [2] Recupera A bra DelayNus ; [3] Salta a comprobar estado de A DELAY0009.C rts ; [4] Retorna

Listado 67. NT1009 – KBD – DELAY.inc. Archivo que contiene las funciones de retardo programables.

NT1009

Rev. 1 del 07.08.05

540 Nota Técnica ;================================================================= ; ARCHIVO : USER.inc ; PROPÓSITO : Funciones de usuario ; LENGUAJE : IN-LINE ASSEMBLER ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 06 09 04 Creado. ; 05 11 04 Modificado. ;================================================================= KbdCmpCode

sei ; Inhabilita interrupciones lda #KBD_MAX_KEY ; Inicializa contador temporal psha ; Empuja a pila pshx ; Empuja Dir. RAM.LSB a pila pshh ; Empuja Dir. RAM.MSB a pila KBDLOOP1009.AD

tsx ; Transfiere SP a H:X dec 2,x ; Decrementa contador beq KBDOUT1009.AA ; SI, salir lda 0,x ; Carga Puntero RAM.MSB psha ; Empuja a pila tsx ; Transfiere SP a H:X ldx 2,x ; X = RAM.LSB pulh ; H = RAM.MSB lda ,x ; Carga contenido de puntero RAM psha ; introduce a pila tsx ; Transfiere SP a H:X lda 6,x ; Carga Puntero ROM.MSB psha ; Empuja a pila tsx ; Transfiere SP a H:X ldx 8,x ; X = ROM.LSB pulh ; H = ROM.MSB pula ; Carga Caracter RAM cmp ,x ; ¿Contenidos iguales? bne KBDOUT1009.AA ; NO, Revisar contador tsx ; SI, Transfiere SP a H:X inc 1,x ; Incrementa Puntero RAM.LSB bne KBD2NDPTR1009.AE ; No hubo sobreflujo, incrementar puntero

; ROM inc ,x ; SI, incrementar Puntero RAM.MSB KBD2NDPTR1009.AE inc 6,x ; SI, incrementar Puntero ROM.LSB bne KBDLOOP1009.AD ; No hubo sobreflujo, siguiente tecla inc 5,x ; SI, incrementa Puntero ROM.MSB bra KBDLOOP1009.AD ; Siguiente tecla KBDOUT1009.AA

tsx ; Transfiere SP a H:X tst 2,x ; ¿Iguales todos los caracteres? beq KBDOUT1009.AB ; SI, Salir con bandera levantada clra ; NO, Borra bandera bra KBDOUT1009.AC ; Salir

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

541

KBDOUT1009.AB

lda #1T ; Carga bandera KBDOUT1009.AC

ais #3T ; Reposiciona puntero cli ; Habilita interrupciones rts ; Retorna ;============================================= ; Tablas del Usuario ;============================================= $include '\USER\TABLES.inc' ; Tablas del Usuario

Listado 68. NT1009 – KBD – USER.inc. Archivo de definido por el usuario (programador). Compara dos cadenas y retorna una bandera en uno (1) si coinciden

ambas cadenas o cero (0) si no coincide alguno de los caracteres.

NT1009

Rev. 1 del 07.08.05

542 Nota Técnica ;================================================================= ; ARCHIVO : TABLES.inc ; PROPÓSITO : Tablas de búsqueda predefinidas por el usuario ; LENGUAJE : IN-LINE ASSEMBLER ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 06 09 04 Creado. ; 11 11 04 Modificado. ;================================================================= ;============================================= ; Tablas de Búsquedas ;============================================= ;============================================= ; TABLA DE MENSAJES ;============================================= LCDMESSAGE00 db 'E - Lock',0 LCDMESSAGE01 db 'Code = ',0 LCDMESSAGE02 db 'Code Is OK',0 LCDMESSAGE03 db 'Miss Code',0 LCDMESSAGE04 db 'Press: ',0 LCDMESSAGE05 db '1 - Repeat',0 KBDKEYCODE db '8749',0 Listado 69. NT1009 – KBD – TABLES.inc. que contiene los mensajes a desplegar en

la pantalla LCD y el código correcto a ingresar.

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

543

;================================================================= ; ARCHIVO : INTERRUPTSJL3.inc ; PROPÓSITO : Plantilla de Funciones de Interrupciones para ; JL3/JK1/JK3/Serie QT/QY ; LENGUAJE : IN-LINE ASSEMBLER ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 22 08 04 Creado. ; 06 12 04 Modificado. ;================================================================= ;============================================= ; Interrupción del Módulo de Teclado ;============================================= KBINTL ; Teclado (Bajo)

jsr KbdScan ; Decodifica teclado, almacena ; en buffer si hay espacio, ; almacena la última tecla ; presionada y reconoce la ; Interrupción

rti ; Retorno de la interrupción.

Listado 70. NT1009 – KBD – INTERRUPTSJL3.inc. que contiene los mensajes a desplegar en la pantalla LCD y el código correcto a ingresar.

NT1009

Rev. 1 del 07.08.05

544 Nota Técnica ;=============================================================== ; ARCHIVO : VECTORSJL3.inc ; PROPÓSITO : Definir el vector de búsqueda de cada interrupción ; LENGUAJE : IN-LINE ASSEMBLER ; --------------------------------------------------------------------------- ; HISTORIAL ; DD MM AA ; 22 08 04 Creado. ; 06 12 04 Modificado. ;=============================================================== ;============================================= ; Vector del Módulo de Teclado ;=============================================

org KBINTH ; Teclado (Alto) dw KBINTL ; Teclado (Bajo) ;============================================= ; Vector de Reinicio del Sistema ;============================================= org RESET_VEC ; Puntero Vec - RESET dw START ; al darse reset salta a Start Listado 71. NT1009 – KBD – VECTORSJL3.inc. Muestra las rutinas de interrupción

utilizadas.

Nota Técnica Interfase a Teclado Matricial

NT1009 Rev. 1 del 07.08.05

545

Como anteriormente se remarcó, el teclado es un dispositivo indispensable para entrada y captación de datos. El código ejemplificó como se puede entre una de las opciones, decodificar un teclado matricial de 16 teclas el cual se puede ajustar a las necesidades. Para efecto práctico, también se desarrolló un método poderoso de almacenamiento de variables, los “buffers”. Cada “buffer” que el programador cree posee la capacidad de extraer o insertar caracteres de manera inteligente y también, es una forma de reservar una memoria para compartir información. En este caso, es de gran utilidad en la cerradura codificada pues el mismo se tranca al estar el “buffer” lleno, y no admite más caracteres. Como ha sido costumbre, cada nota técnica posee un archivo cabecera capaz de manejar cada módulo estudiado. Para mayor información de operación de las rutinas de teclado, favor consultar la nota “Módulos” en donde se tendrá mayor información a entradas y salidas de las subrutinas.

3.9.9 Conclusión

NT1009

Rev. 1 del 07.08.05

546 Nota Técnica 3.9.10.1 “Embedded Systems Building Blocks, Second Edition” - ”Complete and

Ready-to-Use Modules in C” Autor: Jean J. Labrosse Recurso: Capítulo 03 – Keyboards 3.9.10.2 Información Avanzada sobre el Microcontrolador (a) http://www.freescale.com/files/microcontrollers/doc/data_sheet/MC68HC08JL3.pdf 3.9.10.3 Manual de Referencia del CPU (a) http://www.freescale.com/files/microcontrollers/doc/ref_manual/CPU08RM.pdf 3.9.10.4 Página web sobre esta Nota Técnica (a) http://www.geocities.com/issaiass/ NT0026 – Módulos – Rutinas reusables para programación. Apéndices en Tesis. NT0105 – LCD – Control de una Pantalla de Cristal Líquido. NT1008 en Tesis. 3.9.10.5 Displays de Cristal Líquido (a) http://x-robotics.com/rutinas.htm#Teclado Matricial 4x4 3.9.10.6 Notas de Aplicación sobre Control de Teclados (a) http://www.freescale.com/files/microcontrollers/doc/app_note/AN2205.pdf (b) http://www.freescale.com/files/microcontrollers/doc/app_note/AN2600.pdf (c) http://www.freescale.com/files/microcontrollers/doc/app_note/AN1748.pdf (d) http://mcu.st.com/devicedocs-ST72141K2-15.html 3.9.11.1 Utilice el teclado y la pantalla de cristal y haga un programa que pueda leer el contenido de los registros del microcontrolador. 3.9.11.2 Modificando ciertas rutinas del programa 3.9.11.1, cree una nueva rutina que permita escribir en los puertos del microcontrolador, desde el teclado.

3.9.10 Referencias

3.9.11 Problemas Propuestos