E. U. DE INFORMÁTICA UNIVERSIDAD POLITÉCNICA DE MADRID ARQUITECTURA DE COMPUTADORES Departamento de Informática Aplicada Motorola 68000 Ejercicios de Prácticas Octubre-2008 1 Ejercicios de la Sesión 1 (Directivas de Ensamblaje) El objetivo de la sesión es que los alumnos se familiaricen con la programación en lenguaje ensamblador y con el entorno de prácticas. Escribir el siguiente programa en un fichero y seguir su desarrollo con el profesor. * Presentacion de las DIRECTIVAS DE ENSAMBLAJE * * Calcula el mayor entre tres numeros dados: NUM1, NUM2, NUM3 ORG DC.L DC.L $0 $8000 INICIO * ZONA DE DATOS EN MEMORIA MAYOR NUM1 NUM2 NUM3 ORG DS.B DC.B DC.B DC.B $2A00 1 20 35 78 VEINTE EQU 20 * PROGRAMA PRINCIPAL INICIO COMPARA FIN MOVE.B MOVE.B MOVE.B MOVE.B CMP.B BGE MOVE.B MOVE.B MOVE.B CMP.B BGE MOVE.B MOVE.B MOVE.B MOVE.B BREAK NUM1,D0 #VEINTE,D0 NUM2,D1 NUM3,D2 D1,D0 COMPARA D0,D3 D1,D0 D3,D1 D2,D0 FIN D0,D3 D2,D0 D3,D1 D0,MAYOR ; Calcula el mayor ; Igual que la anterior END 2 Ejercicios de la Sesión 2 (Introducción al Ensamblador) Ejercicios de introducción ensamblador, para realizar en el laboratorio de prácticas con ayuda del profesor. 1. Repaso de Directivas: ORG, DC, EQU a. Indicar el contenido de las variables PER1 y PER2 una vez finalizada la ejecución del programa que aparece a continuación: * p1a ORG DC.L DC.L $0 $10000 INI TAM ORG EQU $400 $10 LAD1 LAD2 PER1 PER2 DC.B DC.B DS.B DS.B 10 $10 2 1 ORG MOVE.B ADD.B MOVE.B ADD.B MOVE.B BREAK END $500 LAD1,D0 LAD2,D0 D0,PER1 TAM,D0 D0,PER2 INI b. Utilizando las directivas del ensamblador, declarar las variables siguientes a partir de la dirección $1000 de memoria: • PAL, tamaño palabra, sin valor inicial • OCT, tamaño octeto, con valor inicial ‘A’ • LONG, tamaño doble palabra, con valor inicial 12345678 • VECTOR_PAL, array de palabras con 10 elementos, sin valor inicial • VECTOR_OCT, array de octetos con 12 elementos, con valor inicial “Arquitectura” • VECTOR_LONG, array de dobles palabras con 5 elementos, sin valor inicial 3 2. Tamaño de los Operandos a. Dado el programa siguiente, indicar el contenido de los registros D0, D1, D2, D3, A0, A1 y A2, una vez finalizada la ejecución del mismo. * p2a ORG DC.L DC.L DAT INI $0 $10000 INI ORG DC.L $400 $ABCDDCBA ORG MOVE.L MOVE.L MOVE.B MOVE.W MOVE.L EXG SWAP MOVEA.L LEA BREAK END $500 #$12345678,D0 $0,A0 D0,D1 D0,D2 D0,D3 D0,A0 D3 DAT,A1 DAT,A2 3. Declaración y Acceso a Variables Vectoriales a. Completar el programa de abajo para que realizase una copia de un vector en otro idéntico. El vector origen tiene 4 elementos de tamaño doble palabra. No se deberá utilizar ninguna instrucción de salto. * p3a VEC1 VEC2 VEC3 VEC4 ORG DC.L DC.L $0 $10000 INICIO ORG DC.L DS.L DS.L DS.L $400 5,$6,%00000110,20 4 4 4 ; Las variables a partir de $400 ORG $500 ; El codigo a partir de $500 bloque de instrucciones que hay que escribir BREAK END 4 4. Operaciones Aritméticas, Lógicas y de Desplazamiento. a. Escribir un programa que realice la suma, resta y multiplicación de dos variables (B y C), previamente declaradas como variables de tamaño palabrea e inicializadas con los valores 11 y 12 respectivamente, dejando los resultados en tres variables: SUMA (B+C), RESTA (C-B) y MULTI (B*C), declaradas como variables de tamaño palabra, sin valor inicial. b. Escribir un programa que calcule las 8 primeras potencias de 2 (20 hasta 27), utilizando, para los cálculos, exclusivamente instrucciones de desplazamiento. Los resultados deberán almacenarse en un vector de ocho elementos de tamaño octeto. 5. Bucles. a. Escribir un programa que rellene un vector con los diez primeros números naturales. Los elementos del vector son de tamaño doble palabra. Para realizar la inicialización se debe utilizar un bucle WHILE. b. Igual que en el apartado anterior, pero utilizando REPEAT. c. Escribir un programa que busque la posición del número más pequeño en un vector de 10 elementos de tipo palabra. El resultado deberá almacenarse en una variable de tipo palabra. El valor inicial del vector es: 4, 6, 5, 3, 2, 1, 9, 0, -1, -1. 6. Caracteres y Números a. Dadas las siguientes variables: CARS ORG DC.B 400 '0','1','2','3','4','5','6','7','8','9' NUMS ORG DC.B $500 0,1,2,3,4,5,6,7,8,9 STR1 ORG DC.B $600 'ARQUITECTURA' STR2 ORG DC.B $700 'A','R','Q','U','I','T','E','C','T','U','R','A' STR3 ORG DC.B $800 $41,$52,$51,$55,$49,$54,$45,$43,$54,$55,$52,$41 END Comprobar, mediante el visor de memoria del simulador, los valores almacenados en memoria a partir de las direcciones $400 y $500. ¿Cuál es la diferencia? ¿Existe alguna diferencia entre las posiciones de memoria de las direcciones $600, $700 y $800? (Al mostrar el mensaje "Fin de la Aplicación" pulsar "Aceptar" para ver el resultado). 5 b. Escribir un programa que inicialice un vector con las letras mayúsculas (desde la ‘A’ a la ‘Z’). c. Escribir un programa que a partir de los valores del vector CARS (del apartado 6a) obtenga los valores de NUMS, dejándolos en un nuevo vector de 10 elementos de tamaño palabra. 6 EJERCICIOS RECOMENDABLES PARA REALIZAR FUERA DE LA SESIÓN DE PRÁCTICAS 1. Realizar un programa que almacene en memoria RAM, a partir de la dirección $1000, los 30 primeros números múltiplos de tres. 2. Paso de parámetros en la pila. Seguir la ejecución del programa siguiente. Después, modificar los parámetros para que sean de tipo LONG y BYTE. DATOS INICIO BORRAR BUCLE ORG DC.L DC.L $0 $8000 INICIO DCB 8,$AAAA ORG MOVE.W MOVE.W MOVE.W MOVE.W BSR BREAK $2000 #DATOS,A2 ; Pasamos el 1er. Parámetro en la pila A2,-(SP) #$00,D2 ; Pasamos el 2do. parametro D2,-(SP) BORRAR MOVE.W MOVE.W MOVE.W ADDQ CMP BNE RTS END 4(SP),D0 ; Recuperamos los parámetros 6(SP),A0 D0,(A0) #2,A0 #$1010,A0 BUCLE 3. Realizar una subrutina que tenga dos parámetros de entrada (base y exponente) que calcule la función baseexponente. a. Estructurar el programa para pasar los parámetros en registros de datos. b. Estructurar el programa para pasar los parámetros en la pila del sistema. 4. Escribir un programa que calcule la función factorial por medio de una subrutina que acepte un parámetro de entrada a través de la pila. La función debe ser recursiva. 7 Ejercicios de la Sesión 3 (E/S por polling) * * * * * Fichero: sondeo.asm --- Ejemplo de E/S por polling. Este programa debe sacar la ristra de caracteres “Arquitectura de Computadores” por la ventana de E/S del simulador, mediante sondeo. No obstante, tiene algunos errores que no permiten realizar tal cometido * Arranque del 68000 ORG $0 DC.L $10000 DC.L RESET * CONSTANTES * UART EQU $EFFA01 MR1 MR2 USR CSR CR TB RB $0 $0 $2 $2 $4 $6 $6 EQU EQU EQU EQU EQU EQU EQU ; Comienzo Tabla Vectores de Interrupcion ; Valor Inicial SSP ; PC Inicial * * VARIABLES INICIALIZADAS * ORG$ 400 MENSAJE DC.B 'Arquitectura de Computadores',$0 * $A caracater Line Feed (LF) * $D caracter Carriage Return (CR) * $0 caracter NULL, indica el Final del String * BEGIN * ORG $500 BSR INI_UART MOVE.L #MENSAJE,A1 ; A1 := ADDRESS (MENSAJE) BUCLE: CMPI.B BEQ #0,(A1) SALIR ; While (A1) <> 0 do POLL: BTST.B BEQ #2,UART+USR POLL MOVE.B JMP (A1)+,UART+TB BUCLE RESET: SALIR: BREAK * PROC INI_UART() * INI_UART MOVE.L A0,-(SP) MOVE.L #UART,A0 MOVE.B #%00010000,CR(A0) MOVE.B #%00010011,MR1(A0) MOVE.B #%00000111,MR2(A0) MOVE.B #%10111011,CSR(A0) MOVE.B #%00000100,CR(A0) MOVE.L (SP)+,A0 RTS END ; Call INI_UART ; While TX-RDY = 0 do ; End While ; Enviar_Car ; End While ; End Program ; ; ; ; ; ; ; ; Push A0 A0 := USART UART.CR = Habilitar MR1 UART.MR1 = 8 bits por car. sin paridad UART.MR2 = no RTS, no CTS, 1 bit Stop UART.CSR = 9600 bps UART.CR = Habilitar Transmisor Pop A0 8 La práctica de esta sesión consta de varios apartados. En el primero hay que implementar unas subrutinas para manejar las UART mediante la técnica de entrada/salida programada o polling. En los apartados siguientes se escribirán una serie de programas que harán diversos usos de las subrutinas escritas en el primer apartado. Todos los apartados de la práctica se realizarán en el modo de funcionamiento supervisor del procesador Motorola 68000. Apartado 1. Se pide desarrollar las subrutinas siguientes para manejar las UART mediante entrada/salida programada. INI_UART (uart: WORD) Permite inicializar una UART. El parámetro uart es de tipo WORD, es decir, ocupa dos octetos y sus únicos valores posibles son: 0, 1 o 2, para referirse a cada una de las tres UARTS que se van a utilizar en el desarrollo de la práctica. Esta subrutina programa la UART indicada en el parámetro, para comunicarse a 8 bits por carácter, sin paridad, un bit de STOP y una velocidad de transmisión/recepción de 9.600 bits por segundo. Además habilitará la recepción y la transmisión de caracteres. Es posible que una misma UART pueda inicializarse varias veces durante la ejecución de un programa, por lo que conviene tener en cuenta la singularidad del funcionamiento de los registros MR1 y MR2. ENV_CAR (uart: WORD; car: BYTE) Envía un carácter por una UART. El parámetro uart es de tipo WORD, es decir, ocupa dos octetos y sus únicos valores posibles son: 0, 1 o 2, para referirse a cada una de las tres UARTS utilizadas en la práctica. El parámetro car es de tipo BYTE. Esta rutina enviará el carácter (escribir en el registro TB) cuando la UART esté preparada, y no devolverá el control hasta que el último bit del carácter haya salido por la línea de comunicaciones. REC_CAR (uart: WORD; VAR car: BYTE); Recibe un carácter de una UART. El parámetro uart es de tipo WORD y admite los mismos valores que en la subrutina ENV_CAR. El parámetro car, además de ser de tipo BYTE, es de salida (paso de parámetro por referencia). Esta subrutina no devolverá el control hasta que se reciba un carácter por la UART indicada. 9 Apartado 2 Escribir el programa ECO, que deberá enviar por el puerto de una UART todos los caracteres recibidos por su puerto, finalizando su ejecución cuando reciba el carácter asterisco (‘*’). En este apartado se utilizará únicamente la UART 0, que tiene por nombre “Port A (0)” en el entorno de prácticas. Téngase en cuenta que antes de poder enviar o recibir por una UART es necesario inicializarla. Apartado 3 Escribir un programa que escriba por las UARTS 1 (Port B) y 2 (Port C) todo lo que lea de la UART 0 (Port A). Al igual que en el Apartado 2, el programa finalizará su ejecución cuando reciba un asterisco (‘*’). 10 Ejercicios de la Sesión 4 (E/S por Interrupciones) 1. Realizar un programa que muestre por un puerto de la UART los diez primeros valores exponenciales de base 2 (20, 21, 22, …, 29). Tener en cuenta que para visualizar un valor por la ventana de la UART hay que enviar los caracteres ASCII que representan un valor, y no el valor en sí. Es decir, si queremos mostrar el valor 32, tendremos que convertir este número a los caracteres ‘3’ y ‘2’ para proceder a su envío. La conversión puede realizarse utilizando la división entera y el módulo, además de tener en cuenta que el valor ASCII del carácter ‘0’ es el $30 y que el resto tiene valores consecutivos. La transmisión debe realizarse mediante interrupciones. OPCIÓN: La llamada para la inicialización de la UART se llevará a cabo mediante un Trap. Una interrupción software o Trap es similar a una interrupción hardware, pero se produce por la ejecución de una instrucción TRAP. El 68000 dispone de 16 traps distintos, donde cada uno tiene asociado un número de vector de interrupción. Al trap #0 le corresponde el vector $20 (32 , en decimal) y al trap #15, el $2F (47, en decimal). 2. Modificar el programa “ECO” propuesto en la sesión 2 para que la recepción de caracteres se realice mediante interrupciones. 11 Tabla de Vectores de Excepción del MC68000 BERR Excepciones Interrupciones Autovectorizadas Interrupciones Software (Traps) Interrupciones Vectorizadas (Hardware) Número Vector 0 2 3 4 5 6 7 8 9 10 11 12-14 15 16-23 24 25 26 27 28 29 30 31 32-47 48-63 64-255 Dirección Dec Hex E.D. 0 0 SC 4 4 SC 8 8 SD 12 C SD 16 10 SD 20 14 SD 24 18 SD 28 1C SD 32 20 SD 36 24 SD 40 28 SD 44 2C SD 48 30 SD 60 3C SD 64 40 SD 96 60 SD 100 64 SD 104 68 SD 108 6C SD 112 70 SD 116 74 SD 120 78 SD 124 7C SD 128 80 SD 192 C0 SD 256 100 SD Excepción Reset: SSP Inicial Reset: PC Inicial Error de Bus Error de Dirección Instrucción Ilegal División por 0 Instrucción CHK Instrucción TRAPV Violación de Privilegio Traza Emulador Instrucción 1010 Emulador Instrucción 1111 Reservado Vector Int. No Inicializado Reservado Interrupción Espúrea Autovector Nivel 1 Autovector Nivel 2 Autovector Nivel 3 Autovector Nivel 4 Autovector Nivel 5 Autovector Nivel 6 Autovector Nivel 7 Instrucciones TRAP Reservado Vectores de Interrupción 1er Kbyte de memoria 256 Vectores Dirección RTI Autovectorizadas = Nº Vector * 4 Las pastillas de E/S contienen el número del vector de interrupción (8 bits) en el registro del vector de interrupción 12 Ejercicios de la Sesión 5 (Timer) 1. Escribir un programa que escriba el eco de lo que se pulsa en el teclado, de tal manera que cuando el carácter pulsado sea un dígito del 1 al 9, la presentación en pantalla se retardará tantos segundos como indique el dígito pulsado. La entrada/salida se realizará mediante sondeo (polling). 2. Escribir un programa que simule el comportamiento de un dado. Cada vez que se pulsa una tecla se visualizará un número aleatorio entre 1 y 6. Para obtener el número aleatorio podemos utilizar los bits menos significativos del contador del TIMER, habiéndolo puesto a funcionar previamente. Si dicho contador se decrementa muy rápido (por ejemplo, cada centésima de segundo) y lo leemos cada vez que se pulsa una tecla, podemos considerar este valor como aleatorio. Después bastará con transformar el valor leído al rango entre 1 y 6 (módulo 6 +1). 13 * FICHERO: timer.asm * ============== Saca "*" por la UART 0 cada segundo * ================= Definición de constantes ========================== * ---------------------- UART 68681 ---------------------------------UART EQU $EFFA01 MR1 MR2 USR CSR CR TB RB ISR IMR IVR EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU $0 $0 $2 ;SR de la UART $2 $4 $6 $6 $A $A $18 * -------------------- TIMER 68230------------------------------------TIMER EQU $10021 TCR TIVR CPRH CPRM CPRL CNTRH CNTRM CNTRL TSR EQU EQU EQU EQU EQU EQU EQU EQU EQU $0 $2 $6 $8 $A $E $10 $12 $14 NVI_TIMER EQU $70 * ==================== Vectores de interrupción ======================= ORG $0 DC.L $10000 ; Valor Inicial del SSP DC.L INICIO ORG DC.L NVI_TIMER*4 RTI_TIMER ; Dir. RTI del TIMER * -------------- Programa Principal ---------------------------------INICIO ESPERA ORG BSR BSR $400 INI_UART INI_TIMER ; Inicializa la UART ; Inicializa el TIMER ANDI.W #$F0FF,SR ; Permite interrupciones; BRA ESPERA ; Espera activa, no hace nada * -------------- SUBRUTINAS ------------------------------------------* ================= INI_UART MOVE.L MOVE.L MOVE.B MOVE.B MOVE.B MOVE.B MOVE.B MOVE.L RTS Inicializar la UART: 68681 A0,-(SP) ; Guarda registro #UART,A0 ; Direccion base #%00010000,CR(A0) ; Habilita MR1 #%00100011,MR1(A0) ; 8 bits por car, sin paridad #%00000111,MR2(A0) ; 1 bit de stop #%10111011,CSR(A0) ; 9600 bps #%00110100,CR(A0) ; Habilita TX (SP)+,A0 ; Recupera registro 14 * ================= INI_TIMER MOVE.L MOVE.L MOVE.B MOVE.B MOVE.B MOVE.B TCR_PROG * === * === * === * === * === EQU 101: 0: X: 00: 1: Inicializar Timer: 68230 A0,-(SP) ; Guarda registro #TIMER,A0 ; Dirección base #$1,CPRH(A0) ; 4.000.000/32 = $1E848 #$E8,CPRM(A0) #$48,CPRL(A0) #NVI_TIMER,TIVR(A0) ; Vector de interrupción %10100001 IRQ Vectorizada, ZD activo (Recarga), No Usado, Control de Reloj Modo 00 (Clock Sistema con preescala(32)), Activado MOVE.B #TCR_PROG,TIMER+TCR ; Para activar el TIMER MOVE.L RTS (SP)+,A0 ; Recupera registro *==================== Tratamiento de interrupción del TIMER RTI_TIMER POLL BTST.B #2,UART+USR BEQ POLL MOVE.B #'*',UART+TB MOVE.B #TCR_PROG,TIMER+TCR ; Para activar el TIMER RTE END 15 Ejercicios de la Sesión 6 (DMA) A continuación se muestra el esqueleto de un programa que, utilizando el dispositivo DMA, realiza un copia de un bloque de información de una zona de memoria a otra. Se debe completar el programa escribiendo el código necesario en las zonas sombreadas indicadas, y teniendo en cuenta las siguientes consideraciones: • Antes de realizar la copia, la zona origen se rellenará con los 2048 primeros números (0-2047), utilizando una palabra (2 octetos) para almacenar cada número. • El programa principal, una vez haya inicializado y arrancado el DMA, se quedará en un bucle mostrando repetidamente por la UART A el carácter punto (‘.’) hasta que no finalice la transferencia. La finalización de la transferencia se detectará mediante la correspondiente interrupción y se indicará mostrando el carácter asterisco (‘*’) por la misma UART. • El DMA se programará con una velocidad de transferencia de 1 octeto cada 32 ciclos de reloj. • La transmisión por la UART A se realizará mediante la técnica de sondeo (polling). 16 *************************************************** * FICHERO: DMA.asm * Ejemplo de utilización del DMA. * Realiza la copia de una zona de memoria *************************************************** ***************** * D M A ***************** DMA EQU DSR EQU DCR EQU DIVR EQU SPRH EQU SPRM EQU SPRL EQU DPRH EQU DPRM EQU DPRL EQU LPRH EQU LPRL EQU $20001 0 0 2 4 6 8 10 12 14 16 18 ; ; ; ; ; ; ; ; ; ; ; ; Dirección base del DMA DMA Status Register (solo lectura) DMA Control Register (solo escritura) DMA Interrupt Vector Register Source Preload Register (High) Source Preload Register (Medium) Source Preload Register (Low) Destination Preload Register (High) Destination Preload Register (Medium) Destination Preload Register (Low) Length Preload Register (High) Length Preload Register (Low) ***************** * U A R T ***************** DUART EQU MR1A EQU MR2A EQU SRA EQU CSRA EQU CRA EQU TBA EQU RBA EQU ACR EQU IMR EQU ISR EQU IVR EQU $EFFA01 0 0 2 2 4 6 6 8 10 10 24 ; ; ; ; ; ; ; ; ; ; ; ; Direccion base de la DUART RW Mode Register 1 canal A RW Mode Register 2 canal A R- Status Register A -W Clock-select Register A -W Command Register A -W Transmit Buffer A R- Receive Buffer A -W Auxiliary Control Register -W Interrupt Mask Register R- Interrupt Status Register RW Interrupt Vector Register DMA_IVN EQU $54 ; Nº del vector de interrupción del DMA LEN EQU $800 ; Longitud de la copia * Reset MC68000 ORG DC.L DC.L $0 $8000 INICIO ; SSP inicial ; PC inicial * Vector de interrución del DMA ORG DC.L DMA_IVN*4 RTI_DMA * RTI del DMA ORG $1000 RTI_DMA: Escribir el código necesario para la rutina de tratamiento de interrupción del DMA 17 * Inicializar la UART en modo polling INIT_UART: MOVE.L MOVE.L MOVE.B MOVE.B MOVE.B MOVE.B MOVE.B MOVE.L RTS A0,-(SP) #DUART,A0 #%00010000,CRA(A0) #%00100011,MR1A(A0) #%00010111,MR2A(A0) #%10111011,CSRA(A0) #%00000101,CRA(A0) (SP)+,A0 ; Salvar A0 ; ; ; ; ; ; Reset de MR2 A 8 bits Funcionamiento normal 9600 bps Tx & Rx Recuperar A0 * Envio de un caracter por la UART ENV_CAR: POLL: MOVE.L MOVE.L A0,-(SP) #DUART,A0 ; Salvar A0 ; Dir. Base DUART BTST BEQ MOVE.B #2,SRA(A0) ; Tx ? POLL 8(SP),TBA(A0) ; Transmitir MOVE.L RTS (SP)+,A0 ; Recuperar A0 * Programa principal INICIO: RELLENAR: ORG $2000 BSR INIT_UART CLR.L MOVE.L D0 #ORIGEN,A0 MOVE.W ADDQ.W CMP.W BNE D0,(A0)+ #1,D0 #LEN,D0 RELLENAR MOVE.W #$2300,SR MOVE.L #ORIGEN,D0 ; Utilizar Words para almacenar los números ; Carga en el DMA la direccion de origen CÓDIGO PARA ESTABLECER EN EL DMA LA DIRECCIÓN DEL ORIGEN DEL BLOQUE MOVE.L #DESTINO,D1 ; Carga la direccion destino CÓDIGO PARA ESTABLECER EN EL DMA LA DIRECCIÓN DEL DESTINO MOVE.W #LEN*2,D0 ; Carga la longitud de la transferencia en bytes CÓDIGO PARA ESTABLECER EN EL DMA EL TAMAÑO DE LA TRANSFERENCIA. 18 CÓDIGO PARA ESTABLECER EN EL DMA EL NÚMERO DEL VECTOR DE INTERRUPCIÓN QUE SE DEBE GENERAR CON LA INTERRUPCIÓN. CÓDIGO PARA INICIAR LA COPIA DE LA ZONA DE ORIGEN A LA ZONA DE DESTINO. BUCLE MOVE.B BSR ADDQ.L MOVE.B BTST.B BNE #'.',-(SP) ENV_CAR #2,SP (DMA+DSR),D0 #0,D0 BUCLE ; Envía el car. '.' ; Lee el byte de Estado del DMA ; Comprueba si aún esta copiando BREAK * * Variables * ORIGEN ORG DS.W $3000 1000 DESTINO ORG DS.W $4000 1000 END 19 Ejercicios de la Sesión 7 (Trabajo Final) Este ejercicio pretende ser una especie de “trabajo final” en el que se utilicen conceptos ya introducidos en prácticas anteriores. Por lo tanto, carece de explicaciones teóricas y deja al alumno la iniciativa sobre cómo enfocar el problema. Se plantea la realización de lo que denominaremos un “medidor de reflejos”. Se trata de implementar un bucle sin fin que visualice un estímulo visual al que el usuario deberá responder pulsando una tecla cualquiera en el menor tiempo posible. A continuación se visualizará el tiempo de reacción (el transcurrido entre la visualización del estímulo y la pulsación de la tecla). El programa utilizará el puerto A de la UART 0 como medio de entrada/salida. Comenzará visualizando un mensaje para prevenir al usuario, por ejemplo: Pulse cuando esté preparado... Cuando el usuario lo desee, pulsara una tecla cualquiera. A partir de ese instante transcurrirá un tiempo aleatorio (8 0 10 segundos como máximo) al final del cual se visualizará el estímulo, por ejemplo: ..... YA! A partir de este momento, el usuario pulsará una tecla cualquiera lo antes que pueda y ello dará lugar a la visualización del tiempo de reacción. Este tiempo se medirá en centésimas de segundo que es una escala razonable para este tipo de mediciones. El resultado podría ser algo así: Tiempo de reacción (centésimas): 68 A continuación volveríamos a repetir el ciclo visualizando nuevamente el mensaje inicial. Nuestro programa no tiene fin. Se muestra un ejemplo de lo que podría ser la salida de ejecución a través del puerto A: Pulse cuando esté preparado... <se pulsa una tecla> ..... YA! Tiempo de reacción (centésimas): 59 Pulse cuando esté preparado... <se pulsa una tecla> ..... YA! Tiempo de reacción (centésimas): 87 Pulse cuando esté preparado... 20