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:

No es posible acceder a la imagen

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:

064 Interrupciones de Nivel 1.
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.

No es posible cargar la imagen.


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
	

vidalmb_admin – Jue, 26/07/2007 – 01:57