Problema :temporizador 8254 del pc como controlador de int

Mi intensión: es a partir del temporizador de la cpu (temporizador 8254) controlar una interrupcion de 0,5 seg (solo puede hacerse as por exigencia del profesor)para que cada medio segundo se enciendan las luces siguiendo la tabla.

LA Forma: Modifico la tabla de interrupciones donde esta la interrupcion de reloj, y hago que apunte a mi rutina retardo, la cual me reduce en 1 el contador cada vez que entra(28 veces cada vez que se enciende una luz segun la rutina secuen1, de manera que 28 *18,9ms(interrupcion cpu)=509ms).

PROBLEMA: Nunca me entra en la rutina retardo

NOTA:FALTAN MUCHAS LINEAS DE CODIGO QUE NO VIENEN AL CASO, PERO EL ARCHIVO ESTA ADJUNTO

Mi programa es el siguiente:


Stkseg SEGMENT PARA STACK 'STACK'
DB 100h DUP (?)
Stkseg ENDS

Data SEGMENT WORD 'DATA'


tiempo DB 00h

intseg DW 00h

intoff DW 00h

Texto1 DB ' Prueba Finalizada'
DB '$'
Text2 DB 'Empieza la Prueba de Luces'
DB '$'
Text3 DB 13,'Prueba de Tecla producto. **Pulse cada tecla una sola vez**'
DB '$'

Tabla DB 5d
DB 11111111b
DB 11100111b
DB 11000011b
DB 10000001b
DB 00000000b

Tabla2 DB 2d
DB 00000101b
DB 00001010b


Data ENDS

Code SEGMENT WORD 'CODE'
ASSUME CS:Code,DSata
..
....
call noint ;Cancelamos posibles interrupciones mientras cambiamos la tabla de vectores
call vectorint ;Modifica el vector interrupcion
call siint ;habilita la interrupcion IRQ0 (que es nuestro timer)

corre:
mov al,tiempo
or al,al
jnz nosecuen ;Siel tiempo no se ha terminado hacemos tiempo hasta interrupcion
call secuen1 ;Llamamos a la secuencia de luces solo cuando tiempo de interrupcion terminado 0,5s
nosecuen:
call tecla ;veamos si hay tecla
jz corre ;si no hay tecla seguimos haciendo tiempo para interrupciones
call intcar ;Nos quedamos en espera de que se introduzca caracter TODO PARADO, HASTA INT

...





;******Secuencia de luces producto******

secuen1 proc

push ax
push ds
push bx
push dx

mov ax,data
mov ds,ax
mov bx,OFFSET tabla ;Primera DIRECCION de la tabla
mov dx,378h ;Nos situamos en la direccion de datos
add bx,cx
mov ax,[bx]
out dx,ax
inc cx
cmp cx,05h
jbe continua ;salta si son menores que 5
mov cx,0d ;si es mayor que 5 lo vuelve a poner a cero


continua:
mov tiempo,28d ;Restauramos el tiempo para interrupciones 18.2ms*28=0,5s

pop dx
pop bx
pop ds
pop ax
ret


secuen1 endp



;*********Retardo de perdida de tiempo poco mas de 0.5s*****

retardo proc far

push ax
push bx
push ds

mov ax,data ;
mov ds,ax ;Apuntamos a Data, para la variable tiempo
mov al,tiempo
cmp al,00h
jz final
dec al ;Decrementamos en 1 el tiempo
mov tiempo,al

final:
mov al,20h ;Fin de Interrrupcion
out 20h,al ;Direccion de pic maestro IR0

pop ds
pop bx
pop ax

IRET

retardo endp





;*********Procedimiento para nuestra interrupcion de reloj modificacion en la tabla******

vectorint proc

push ax
push dx
push ds

mov ah,35h ;Interrupcion del DOS
mov al,08h ;num de vector
int 21h

mov ax,es ;Guardamos el Manejador de puntero
mov intseg,ax
mov intoff,bx

;Vamos a cargar en su lugar la interrupcion que queremos

mov ax,seg retardo ;segmento del programa CS:IP (nuestro programa
mov ds,ax
lea dx,retardo; calcula el offset de retardo y lo mete en dx CS:[DX](retardo)
mov al,08h
mov ah,25h
int 21h ;Establece el puntero de interrupcion

pop ds
pop dx
pop ax

ret
 

Adjuntos

  • prueba_172.txt
    10.4 KB · Visitas: 11
Puede que te este jodiendo Windows.
En lugar de redireccionar Int08 (Timer Interrupt) , redirecciona la Int 1Ch (User Timer Tick).

Int 1Ch no es una interrupcion por hardware, es llamada en cada ciclo por Int 08 y normalmente apunta a un IRET.
Es una interrupcion mas 'legal' y no necesita enmascarar interrupciones ni el out2020 final.
 
no trabajo bajo windows en la simulacion, trabajo bajo ms-dos, pero de todas formas probare, aun asi puede ser que haya algo raro en el programa, si lo veis decidmelo
 
Hago correr tu programa en una ventana de XP y entra lo mas bien en la rutina de retardo.
El unico desliz es que lo hace cada 1.5" porque esta mal el valor de reinicio del contador (ahi esta mal pero en otra parte esta bien)
 
Los has conseguido? :eek: y cual es mi problema entonces, yo uso el debugger del tasm, tu como lo has hecho? ¿es que he puesto varios reinicios de contador?, puede ser lo cambie un par de veces
 
Al Turbo Debugger no le gusta que le cambien 'algunos vectores' y le modifiquen 'algunas direcciones de memoria'.
Hace mucho que no programo bajo DOS asi que no me pidas detalles porque no me acuerdo, tampoco investigue mucho, a medida que me encontraba con algo y concluia que era el debugger veia como esquivarlo.
Donde mas jode es con las ejecuciones pasa a paso, ahi en general zafas ejecutando de corrido el bloque problematico con un breakpoint al final, despues seguis paso a paso.
Con las interrupciones, lo que usaba era insertar rutinas auxiliares que me escribieran algo en pantalla o en memoria.

En tu programa puse un macro sencillo que incrementa un numero decimal en pantalla, (no usa el DOS), si ves actividad, es porque esta pasando por ahi.
El macro que use fue:
Flash_Dec MACRO Ypos,Xpos ; Ypos,Xpos posicion en pantalla
LOCAL flash, skip
jmp $+3
flash db '0'
push es di ax
mov ax,0B800h
mov es,ax
mov di, 2*(80*Ypos+Xpos)
inc flash
mov al,flash
cmp al,'9'
jbe skip
mov al,'0'
mov flash,al
skip: mov es:[di],al
pop ax di es
ENDM



A la rutina retardo le inserte el macro en dos puntos:

retardo proc far

push ax
push bx
push ds

mov ax,Data ;
mov ds,ax ;Apuntamos a Data, para la variable tiempo

Flash_Dec 10,1

mov al,tiempo
cmp al,00h
jz final

Flash_Dec 14,1

dec al ;Decrementamos en 1 el tiempo
mov tiempo,al
...........................................................



Lo ejecuto y los contadores se van incrementando --> OK --> se pueden borrar.



El error de reinicio estaba en secuen1
mov tiempo,28d ;Restauramos el tiempo para interrupciones 18.2ms*28=0,5s

Y estaba bien en secuen2
mov tiempo,10d ;Restauramos el tiempo para interrupciones 54.92ms*10=0,5s
 
Atrás
Arriba