Práctica 3: Uso de interrupciones
Objetivo
Diseñar un programa que implemente un cronómetro visualizable a través del display de 7 segmentos cuya actualización se realice gracias a una interrupción de nivel 1 autoprogramada.
Implementación
Para poder usar el sistema de interrupciones en el simulador, lo primero que hay que hacer es capacitarlas. La capacitación de dichas interrupciones en el simulador se realiza de forma manual seleccionando la opción Enable Exception:
Otro dato a tener en cuenta es que, para el correcto funcionamiento de las interrupciones, las subrutinas encargadas de realizar la acción asociada a cada nivel ha de estar, obligatoriamente, ubicada en una dirección de memoria específica:
068 Interrupciones de Nivel 2.
06C Interrupciones de Nivel 3.
070 Interrupciones de Nivel 4.
074 Interrupciones de Nivel 5.
078 Interrupciones de Nivel 6.
07C Interrupciones de Nivel 7.
La técnica a usar para cargar la dirección de rutina en el vector será inicializar la interrupción por programa, de forma que cada vez que se ejecute el programa se cargue el vector de interrupción con la dirección de la rutina. De este modo, si la RTI asociada a una interrupción de nivel 1, se denomina RTI1, la estructura del programa con interrupciones sería la siguiente:
START ORG $1000 jmp inicio * * inicio move.l #RTI1,$00000064 Carga el vector de interrupción de IRQ1 * * * PROGRAMA PRINCIPAL * * MOVE.B #9,D0 Fin del programa. TRAP #15 * RTI1 * CODIGO DE LA SUBRUTINA * RTE Fin de la subrutina * END START |
Para autoprogramar las interrupciones de nivel 1, se usará el temporizador incluido en el simulador. Para ello se fijará el valor de dicho temporizador y se asociará a una interrupción de nivel 1.
Observación: La activación de las interrupciones siempre se ha de realizar después de ejecutar la sentencia move.l #RTI1,$00000064, pues en caso contrario, el vector IRQ1 no estará inicializado correctamente.
Solución
*----------------------------------------------------------- * * Versión : 1.0 * Escrito por : Vidal Maté Barbero * Fecha : 30 - 4 - 2006 * Descripción : Uso de interrupciones * *----------------------------------------------------------- START ORG $1000 jmp inicio * * Constantes y variables * * Guardo la tabla con los valores (en hexadecimal), para mostrar más tarde en los displays tablaa dc.b $06,$5B,$4F,$66,$6D,$7D,$27,$7F,$67 tablab dc.b $06,$5B,$4F,$66,$6D numa ds.w 1 Variable para el contador de iteraciones de segundos numb ds.w 1 Variable para el contador de iteraciones de decenas de segundos numc ds.w 1 Variable para el contador de iteraciones de minutos numd ds.w 1 Variable para el contador de iteraciones de decenas de minutos nume ds.w 1 Variable para el contador de iteraciones de horas numf ds.w 1 Variable para el contador de iteraciones de decenas de horas * * Programa principal * inicio move.l #RTI1,$00000064 Carga el vector de interrupción de IRQ1 move.b #32,d0 Cojo la dirección del hardware move.b #0,d1 trap #15 Muestro la ventana de hardware move.b #9,d3 Muevo el número tope de iteraciones del bucle al registro 3 move.b #5,d5 Muevo el número tope de iteraciones del bucle (decenas de todo) al registro 5 * Inicialización de las variables move.w #0,numa move.w #0,numb move.w #0,numc move.w #0,numd move.w #0,nume move.w #0,numf lea tablaa,a0 Pone el primer valor de la tabla a (segundos) en el registro de direcciones 0 lea tablab,a1 Pone el primer valor de la tabla b (decenas de segundos) en el registro de direcciones 1 lea tablaa,a2 Pone el primer valor de la tabla a (minutos) en el registro de direcciones 2 lea tablab,a3 Pone el primer valor de la tabla b (decenas de minutos) en el registro de direcciones 3 lea tablaa,a4 Pone el primer valor de la tabla a (horas) en el registro de direcciones 4 lea tablaa,a5 Pone el primer valor de la tabla a (decenas de horas) en el registro de direcciones 5 move.b #$40,$E00004 Coloco el guión en el tercer display move.b #$40,$E0000A Coloco el guión en el tercer display * Inicializo a ceros todos los displays (por estética) * move.b (a0),d4 Coloco en d4 al valor correspondiente de la tabla * move.b d4,$E0000E Coloco el valor adecuado en la posición de memoria adecuada * add #1,a0 Paso a la siguiente posición de memoria en a1 * move.b (a1),d4 Coloco en d4 al valor correspondiente de la tabla * move.b d4,$E0000C Coloco el valor adecuado en la posición de memoria adecuada * add #1,a1 Paso a la siguiente posición de memoria en a1 * move.b (a2),d4 Coloco en d4 al valor correspondiente de la tabla * move.b d4,$E00008 Coloco el valor adecuado en la posición de memoria adecuada * add #1,a2 Paso a la siguiente posición de memoria en a2 * move.b (a3),d4 Coloco en d4 al valor correspondiente de la tabla * move.b d4,$E00006 Coloco el valor adecuado en la posición de memoria adecuada * add #1,a3 Paso a la siguiente posición de memoria en a3 * move.b (a4),d4 Coloco en d4 al valor correspondiente de la tabla * move.b d4,$E00002 Coloco el valor adecuado en la posición de memoria adecuada * add #1,a4 Paso a la siguiente posición de memoria en a4 * move.b (a5),d4 Coloco en d4 al valor correspondiente de la tabla * move.b d4,$E00000 Coloco el valor adecuado en la posición de memoria adecuada * add #1,a5 Paso a la siguiente posición de memoria en a5 move.b #$3f,$E0000E move.b #$3f,$E0000C move.b #$3f,$E00008 move.b #$3f,$E00006 move.b #$3f,$E00002 move.b #$3f,$E00000 jmp bucle decs lea tablaa,a0 Pone de nuevo el primer valor de la tabla a (segundos) en el registro de direcciones 0 lea numa,a6 Pone la dirección de memoria del contador de iteraciones de segundos en a6 move.w #0,(a6) Pongo a 0 el contador de iteraciones de segundos move.b (a1),d4 Coloco en d4 al valor correspondiente de la tabla move.b d4,$E0000C Coloco el valor adecuado en la posición de memoria del display add #1,a1 Paso a la siguiente posición de memoria en a1 (siguiente valor de la tabla) move.b #$3f,$E0000E Pongo un cero en el primer display (siempre empezando por la derecha) lea numb,a6 Pone la dirección de memoria del contador de iteraciones de decenas de segundos en a6 add.w #1,(a6) Añado una unidad al contador cmp.w (a6),d5 Comprobación de continuación del bucle bge.w sig1 Salta al final de la subrutina si no se ha alcanzado el tope de iteraciones jsr min Salto a la subrutina de los minutos sig1 rts min lea tablab,a1 Pone el primer valor de la tabla b (decenas de segundos) en el registro de direcciones 1 lea numb,a6 Pone la dirección de memoria del contador de iteraciones de decenas de segundos en a6 move.w #0,(a6) Pongo a 0 el contador de iteraciones de decenas de segundos move.b (a2),d4 Coloco en d4 al valor correspondiente de la tabla move.b d4,$E00008 Coloco el valor adecuado en la posición de memoria del display add #1,a2 Paso a la siguiente posición de memoria en a2 (siguiente valor de la tabla) move.b #$3f,$E0000C Pongo un cero en el segundo display lea numc,a6 Pone la dirección de memoria del contador de iteraciones de minutos en a6 add.w #1,(a6) Añado una unidad al contador cmp.w (a6),d3 Comprobación de continuación del bucle bge.w sig2 Salta al final de la subrutina si no se ha alcanzado el tope de iteraciones jsr decm Salto a la subrutina de las decenas de minutos sig2 rts decm lea tablaa,a2 Pone el primer valor de la tabla a (minutos) en el registro de direcciones 2 lea numc,a6 Pone la dirección de memoria del contador de iteraciones de minutos en a6 move.w #0,(a6) Pongo a 0 el contador de iteraciones de minutos move.b (a3),d4 Coloco en d4 al valor correspondiente de la tabla move.b d4,$E00006 Coloco el valor adecuado en la posición de memoria del display add #1,a3 Paso a la siguiente posición de memoria en a3 (siguiente valor de la tabla) move.b #$3f,$E00008 Pongo un cero en el cuarto display lea numd,a6 Pone la dirección de memoria del contador de iteraciones de decenas de minutos en a6 add.w #1,(a6) Añado una unidad al contador cmp.w (a6),d5 Comprobación de continuación del bucle bge.w sig3 Salta al final de la subrutina si no se ha alcanzado el tope de iteraciones jsr hor Salto a la subrutina de las horas sig3 rts hor lea tablab,a3 Pone el primer valor de la tabla b (decenas de minutos) en el registro de direcciones 3 lea numd,a6 Pone la dirección de memoria del contador de iteraciones de decenas de minutos en a6 move.w #0,(a6) Pongo a 0 el contador de iteraciones de decenas de minutos move.b (a4),d4 Coloco en d4 al valor correspondiente de la tabla move.b d4,$E00002 Coloco el valor adecuado en la posición de memoria del display add #1,a4 Paso a la siguiente posición de memoria en a4 (siguiente valor de la tabla) move.b #$3f,$E00006 Pongo un cero en el quinto display lea nume,a6 Pone la dirección de memoria del contador de iteraciones de las horas en a6 add.w #1,(a6) Añado una unidad al contador cmp.w (a6),d3 Comprobación de continuación del bucle bge.w sig4 Salta al final de la subrutina si no se ha alcanzado el tope de iteraciones jsr hor Salto a la subrutina de las decenas de horas sig4 rts dech lea tablaa,a4 Pone el primer valor de la tabla a (horas) en el registro de direcciones 4 lea nume,a6 Pone la dirección de memoria del contador de iteraciones de las horas en a6 move.w #0,(a6) Pongo a 0 el contador de iteraciones de horas move.b (a5),d4 Coloco en d4 al valor correspondiente de la tabla move.b d4,$E00000 Coloco el valor adecuado en la posición de memoria del display add #1,a5 Paso a la siguiente posición de memoria en a5 (siguiente valor de la tabla) move.b #$3f,$E00002 Pongo un cero en el septimo display lea numf,a6 Pone la dirección de memoria del contador de iteraciones de minutos en a6 add.w #1,(a6) Añado una unidad al contador cmp.w (a6),d3 Comprobación de continuación del bucle bge.w sig5 Salta al final de la subrutina si no se ha alcanzado el tope de iteraciones jmp fin Finaliza el programa cuando las horas alcanzan el tope sig5 rts bucle jmp bucle fin MOVE.B #9,d0 TRAP #15 Parada del simulador RTI1 move.b (a0),d4 Coloco en d4 al valor correspondiente de la tabla move.b d4,$E0000E Coloco el valor adecuado en la posición de memoria del primer display add #1,a0 Paso a la siguiente posición de memoria en a0 (siguiente valor de la tabla) lea numa,a6 Pone la dirección de memoria del contador de iteraciones de segundos en a6 add.w #1,(a6) Añado una unidad al contador cmp.w (a6),d3 Comprobación de continuación del bucle bge.w ret Salta al final de la interrupción si no se ha alcanzado el tope de iteraciones jsr decs Salto a la subrutina de las decenas de segundo ret RTE Fin de la subrutina END START |