Foros de Electrónica

Comunidad de discusión sobre Automatización, Electrónica industrial, Microcontroladores y electrónica digital, Robótica, Domótica, Telemática, Tecnologías móviles, y muchos temas más.




Interrupciones del puerto paralelo


       



#1  Interrupciones del puerto paralelo
MaMu
Moderador
Ubicación: Argentina - Buenos Aires - Capital Federal
Registrado: 18 Abr 2005
Mensajes: 874
citar
Bueno, no se si será la hora o que, pero mi puerto paralelo ha cobrado vida propia :D. Estoy armando un pequeño proyecto al cual no tuve la mejor idea que decidir hacerlo usando las interrupciones del puerto paralelo, en version para MS-DOS (en el queridísimo Turbo Pascal 7).
Antes que nada, empecé analizando la forma de trabajo de las interrupciones en dicho puerto. Si bien, según el estado lógico del Bit C4 (Registro de Control -> Bit 4 : este no tiene conexión externa al DB25 que todos vemos en la pc, puesto que es Lógico, es decir conmutando entre 0 y 1, se activa o desactiva la IRQ). Una vez que activamos la IRQ, la interrupción se generara a partir del S6 (Registro de Estado -> Bit 6: de esta forma, funciona de forma Lógica. Para quienes no conocen cual es el Bit, es el pin #10 del conector DB25), es decir, que se ejecutará la interrupción al detectarse un flanco ascendente o descendente (según en que norma se encuentre el LPT).
Todo esto para que, mediante un pulsador entre S6 y GND, genere una interrupción cada ves que se activa. (nada de pullup, todo digital).
Ahora bien, diganme si estoy equivocado, pero el vector de interrupción (para IRQ7) no es la INT 15 ? (INT 13 para IRQ5). En port 0x0020 ingreso mi vector, en 0x0021 lo restablezco (asi como las máscaras con las que modifico el LPT).

Saludos.

#2  
Marcelo
Colaborador
Ubicación: Venezuela
Registrado: 27 Jul 2005
Mensajes: 361
citar
Oye MaMu, cuando vas a tomar vacaciones?...te vas a volver loco.

Lo que dices es cierto si y solo si estás manejando EPP. Así es que debes declara el puerto como EPP, sino en lugar de tomarte el IRQ utilizará la señal de ACK (estamos hablando del pin 10 que es el único que usa INT en el puerto paralelo) y según tengo entendido solo funciona con flanco ascendente o Rising Edge.

Los registros para EPP son:
Puerto de direcciones: Base + 3 y es lectura/escritura
Puerto de Datos: Base + 4 y es lectura/escritura

Ahora, ¿cual es la pregunta?, porque no entendí....

La tabla de vectores de interrupción y su uso común es la anexa y según dice, si es el 15 para comunicación paralela.

(¿Por cierto, el firmware del PIC medidor de temperatura no me lo vas a mandar nunca?)

Saludos,
Marcelo.



Este mensaje contiene archivos adjuntos, para verlos debes estar registrado.

#3  
MaMu
Moderador
Ubicación: Argentina - Buenos Aires - Capital Federal
Registrado: 18 Abr 2005
Mensajes: 874
citar
Marcelo escribió:

(¿Por cierto, el firmware del PIC medidor de temperatura no me lo vas a mandar nunca?)

Saludos,
Marcelo.


hahahahha, todavia lo estoy buscando, tengo una ensalada de hdd's y cd's

:D

Saludos.

#4  
MaMu
Moderador
Ubicación: Argentina - Buenos Aires - Capital Federal
Registrado: 18 Abr 2005
Mensajes: 874
citar
Parece ser tu dia de suerte, lo encontré en el 2º CD que tenía a mano.
En realidad la pregunta era si la INT 15 era para manejar la IRQ del puerto paralelo, queria saber si era correcto.

Saludos.



Este mensaje contiene archivos adjuntos, para verlos debes estar registrado.

#5  
MaMu
Moderador
Ubicación: Argentina - Buenos Aires - Capital Federal
Registrado: 18 Abr 2005
Mensajes: 874
citar
El diseño lógico.

NOTA: en windows XP no podrá tener acceso a las interrupciones por hardware sino dispone de algun driver (como el PortTalk), ya que estas funciones estan restringidas.

Programando la IRQ

Lo que se quiere lograr, es reemplazar la IRQ del puerto (sólo cuando esta deba ser ejecutada) por otro procedimiento del tipo interrupt

Pascal

Código: Seleccionar todo
GetIntVec(vector_de_int,pointer_de_int);

Guardamos el viejo vector con la int original.
Código: Seleccionar todo
SetIntVec(vector_de_int,@mi_procedure_interrupt);

Asignamos nuestro procedure al vector como nueva interrupción.

Mis preguntas (nunca utilice la int del puerto paralelo):
(No quiero trabajar en modo EPP, ya que quiero que la interrupción se genere con la señal ACK - ver diagrama - )

1) Para leer o setear el byte del vector de interrupciones debo utilizar la dirección (port) $21 ?

2) En el reemplazo de la int del puerto paralelo, debo tomarla de (port) $20? (de forma standard devuelve un 1 en el bit 5 cuando se produce la interrupción ACK pin 10 - "S6")



Este mensaje contiene archivos adjuntos, para verlos debes estar registrado.

#6  
Marcelo
Colaborador
Ubicación: Venezuela
Registrado: 27 Jul 2005
Mensajes: 361
citar
MaMu, creo que esta página te podría aclarar algunas dudas.

http://www.beyondlogic.org/spp/parallel.htm#5

Sino, mandas un mensaje para ponerme a buscar en mis libros.

En Windows XP deberías progamar un DCOM para poder variar los permisos desde las "Herramientas Administrativas". Creo que allí puedes permitir el uso completo del hardware variando los defaults de permisología mediante "Directivas de seguridad" y "Servicios de componentes", pero eso es programación bien avanzada.

¿Pero no estabas haciendo el driver en DOS?

No entiendo algo; al decir:

Cita Lo que se quiere lograr, es reemplazar la IRQ del puerto (sólo cuando esta deba ser ejecutada) por otro procedimiento del tipo interrupt


¿Deseas simular una interrupción? es decir, físicamente ningún dispositivo genera la interrupción pulsando el pin 10 sino que la "seteas" por software.

Lo que dices parece lógico: Lees Base+0 = $20 o lo que es lo mismo, monitoreas el registro de estados del paralelo y cuando el bit ACK se va a 1, se produjo la interrupción.

Y para activar la interrupción por vía ACK debes colocar a 1 el bit 4 del registro de control (Base+2).

Cuando digo "Base" me refiero al DataPort o al Data Register que es lo mismo. Y lo que te digo es si el puerto es bidireccional, que es cuando puedes recibir datos de esa direccion Base pues en modo unidireccional solo puedes escribir en ella.

Bueno, lee la página que te digo a ver si estamos hablando de lo mismo.

Saludos.
Marcelo.

#7  
MaMu
Moderador
Ubicación: Argentina - Buenos Aires - Capital Federal
Registrado: 18 Abr 2005
Mensajes: 874
citar
Si, mi idea es setear por software la interrupción. Con respecto a las funciones de privilegio, tan solo lo aclaré, ya que al trabajar en MS-DOS no le doy importancia. Lo que quiero hacer es algo sencillo, a modo de ejemplo te pongo esto:

- quiero que al accionarse el pulsador, imprima en pantalla "Pulsador Accionado" (interrumpiendo la tarea en curso). La idea es hacerlo utilizando la interrupción ACK habilitada por el C4. Si bien existen formas mucho más sencillas de realizar esta operación, la idea es generarla mediante la interrupción, ya que el programa correrá otras tareas simultaneamente (sin hacer un polling del estado). Lo que queria saber, como vos bien me aclaraste lo del DataPort, es si estoy utilizando bien los offsets, que son :

1) 0x0021h -> 021h -> $21 -> Para setear IRQ7
(bit 7 en 0=habilitado / 1=deshabilitado)
2) 0x0020h -> 020h -> $20 -> Acá se lee la interrupción que se produce, ya que cambia el estado del bit 5 a 1. (Y ésta es la que quiero reemplazar por mi "procedimiento").

Ej:

Código: Seleccionar todo

program irq_test;

uses dos,crt;

const DirIRQ=$21;
         DirBase=$20;
          DirLPT=$378;
var old_vector:pointer;

{Manejo del Vector de IRQs}
procedure irq7(estado:integer);
begin
   case estado of
    0 :      begin
                   {código deshabilita DirIRQ=$21;}
              end;
    1 :      begin
                   {código habilita DirIRQ=$21;}
               end;
   eng;
end;

{mi procedure de interrupción}
{+M}
procedure estado_pulsador; interrupt;
begin
  writeln('Pulsador Accionado');
end;
{-M}     

{habilitador de interrupción ACK}
procedure ACK(estado:integer);
begin
   case estado of
    0 :      begin
                   {código deshabilita DirLPT+2}
              end;
    1 :      begin
                   {código habilita DirLPT+2}
               end;
   eng;
end;


{Programa Principal}
Begin
    irq7(1);
    ACK(1);
    GetIntVec(DirBase,old_vector);
    SetIntVec(DirBase,@estado_pulsador);
   {...........................}
   {sentencias}
   {...........................}
   keep(0); {sino hay error lo mantengo en memoria}
   {restablesco todo cuando sale de la aplicación}
   ACK(0);
   SetIntVec(DirBase,@old_vector);
   irq7(0);
end. 


Ahi volque el ejemplo, he omitido las rutinas de comprobaciones y máscaras ya que es secundario.

Quizas con este ejemplo, se entienda más mi duda.

Saludos.

#8  
Marcelo
Colaborador
Ubicación: Venezuela
Registrado: 27 Jul 2005
Mensajes: 361
citar
Acuérdate que recién he empezado con el Pascal. Aunque entiendo el código, al no tener todas las rutinas me enredo un poco.

Lo que puedo hacer es decirte como lo veo en pseudo código. (Nota aparte: en el código que anexastes, ¿ "eng" es una instrucción o un error ?)

Si me equivoco por favor me perdonas, pues la programación de interrupciones la hacía para el 6510 de una commodore 128 para manejar scrolling y sprites, así es que hace bastante que no refresco esto.
Lo que voy a tratar de hacer es escribirte un algoritmo (que va a ser largo), de como haría yo esto.

Aqui vamos:

1) La familia del 8086 tiene en total 256 interrupciones. El vector de interrupción que te interesa de la tabla de vectores que contiene las ISR (Interrupt Service Routines) es la INT (0F) que corresponde a la dirección de memoria que apuntará el vector cuando el IRQ 7 se habilita. Esto ya lo habíamos dicho.

2) Esta familia posee 2 PIC (Programmable Interrupt Controller) y c/u se encarga de 8 interrupciones. Estos 2 PIC están conectados en cascada.

3)PIC1 de 0 a 7 y PIC2 de 8 a 15 La interrupciones que podemos programar son 15, todas de hardware y enmascarables (que se pueden ocultar para que el microprocesador no las "vea"). La tabla de vectores para estos 15 IRQ de los 256 existentes, te la anexé en un post más arriba.

4) Tenemos 2 "comandos" o registros principales para controlar las interrupciones: OCW1 (Operation Control Word 1) y OCW2. OCW1 se utiliza para enmascarar o no los IRQ y el OCW2 sirve para seleccionar como FINALIZAR la interrupción (EOI). También existen las palabras OCW3, ICW1(Initialization Command Word), ICW2, ICW3 , ICW4 pero creo que estas no las voy a tocar. Estas palabras son las que se envían a los PIC y eso se hace almacenándo el valor deseado en las direcciones de memoria o registros establecidos para cada una de estas palabras.

5)Primero se define la OCW1 para decirle al micro cual interupciones vamos a enmascarar y cuales no.

6) Debemos saber cual PIC tenemos que usar porque cada uno está en direcciones de memoria distintas. El PIC1 está en 0x20h y el segundo en 0x0Ah.

7) Como te interesa el IRQ7 entonces tu base es 0x20h. Hasta aquí vamos bien. El byte a enviar al PIC1 pareciera ser 10000000. Aquí hay algo importante. El bit 2 de este byte (el que está en negrita), es el que enlaza o conecta el PIC1 con el PIC2. Como lo estamos enmascarando, deberás desactivar también los IRQ 8 al 15 del PIC2.

8) OCW1 incide en parejas de IRQ por bit. Por ejemplo el bit7 actúa sobre los IRQ 7 y 15. La diferencia radica en que si OCW1 la mandas a la dirección 0x21h (0x20h - PIC1) se actúa sobre el 7 y si la "pokeas" en la dirección 0x0Bh (0x0Ah - PIC2) sobre el IRQ15. El bit 0 de OCW1 va con los IRQ 0 y 8, el 1 con los IRQ 1 y 9 y así sucesivamente. Ahora te explico por qué en 0x21h y 0x0Bh.

9) Los bits de OCW1 funcionan en complemento, lo que quiere decir que cuando los bit están a 0, los IRQ están activados (a 1 se enmascaran). Por lo tanto si queremos activar el IRQ 7, deberemos definir OCW1 complementado. Habíamos dicho que el supuesto byte era 10000000 (128 = 0x80h) , entonces en OCW1 deberemos poner: 01111111 (127 = 0x7Fh) para dejar activo solo el IRQ7 (recuerda lo que te dije antes, en 0x0B deberas colocar 11111111=255=0xFFh).

10) Como no sabes en que estado se encuentran los bits de interrupción en la dirección donde hay que colocar OCW1, debemos hacer un AND con lo que hay allí de manera tal que no vayamos a "colgar" la computadora. LA DIRECCION O REGISTRO DONDE SE ALMACENA OCW1 ES EN BASE+1 (0x21h para PIC1 y 0x0B para PIC2). Entonces, antes de establecer el Byte de enmascarados hacemos esto: Leemos OCW1 -- hacemos el AND de ese Byte con nuestro Byte de enmascaramiento -- Guardamos el resultado en BASE +1 estableciendo el nuevo valor de OCW1. (lo mismo desbes aplicar para PIC2 con 11111111 porque IRQ2 está enmascarado)

Ahora estamos listo para capturar la interrupción y que la computadora haga lo que le hemos programado en nuestra rutina de servicios de interrupción. Según vi en el código en Pascal que anexastes, estás claro en como hacerlo.

11) Para poner las cosas como estaban antes de haber actuado sobre estos registros y después de haber hecho lo que queríamos en nuestra rutina de servicios de interrupción, debemos resetear al estado inicial. Para esto hacemos lo siguiente: Leemos OCW1 -- hacemos el OR de ese Byte con nuestro Byte de enmascaramiento COMPLEMENTADO (es decir el que originalmente habíamos tomado: 10000000 = 128 = 0x80h) -- Guardamos el resultado en BASE +1 reestableciendo el valor de OCW1. (lo mismo desbes aplicar para PIC2 con 00000000 porque IRQ2 estaba enmascarado)

12) Para enviar la orden de finalización de interrupción al procesador (EOI), deberemos "pokear" el valor 0x20h en la dirección 0x20h para el PIC1 o en la 0x0Ah para el PIC2.

Recuerda que si IRQ2 no lo enmascaras, entonces no hace falta actuar sobre PIC2 a no ser que también desees enmascarar IRQs en ese bloque (PIC2 = IRQ 8 a 15).
Pero para este caso del IRQ 7 que te está sacando el sueño, si lo dejas sin enmascarar, todos los IRQ desde el 8 hasta el 15 deberás tratarlos dentro de tu ISR (Interrupt Service Routine), pues alcanzarán al microporcesador y dispararán la solicitud de interrupción.

Para generar la interrupción del paralelo, debes colocar a 1 el ya famoso ACK.

Seguro que mucho de lo que te dije aquí ya lo sabías, pero tenía que explicarlo completo para hacerme entender. Me parece que con esto te indiqué más o menos como lo veo yo.

Espero que te ayude.

Saludos,
Marcelo.


Ultima edición por Marcelo el Lun Nov 07, 2005 1:11 am, editado 5 veces

#9  
MaMu
Moderador
Ubicación: Argentina - Buenos Aires - Capital Federal
Registrado: 18 Abr 2005
Mensajes: 874
citar
Marcelo : lo del eng fue un error al tipear. Todo lo que explicaste, esta perfecto y es tal cual lo entiendo yo, pero el tema es el siguiente, a la IRQ7 le corresponde el vector 0Fh (INT 15), ahora bien, en todos los listados de interrupciones me aparece como la INT 17 y no la 15. Esto es importante, ya que justamente es el vector que yo debo reemplazar por mi interrupción.

Código: Seleccionar todo
SetIntVec($17,@mi_irq);


Saludos.



Este mensaje contiene archivos adjuntos, para verlos debes estar registrado.

#10  
Marcelo
Colaborador
Ubicación: Venezuela
Registrado: 27 Jul 2005
Mensajes: 361
citar
Si, ya veo.

Eso se establece en el Bios y el paralelo que yo sepa siempre usa el IRQ7 y si tienes un LPT2 el IRQ5.

Confused

Déjame seguir buscando a ver de donde sale el 17 y el 15.

 Responder





 Otros temas de interés 
No hay mensajes nuevos Estado inicial de 555
No hay mensajes nuevos Aumentar potencia en bobina tesla de estado solido
No hay mensajes nuevos amplificador para electromiografo
No hay mensajes nuevos Detectar cambio de estado (VB)
No hay mensajes nuevos Diseño de un relé de estado solido DC

Foros de Electronica
|| Cuestiones Elementales de Electrónica || Fuentes de alimentacion || Circuitos de radio || Diseño de circuitos en general ||
|| Sistemas de Audio: Preamplificadores, Ecualizadores || Amplificadores || Reparación || Discusión ||
|| Microcontroladores y sistemas embebidos || Circuitos logicos combinacionales y secuenciales || Interfaces y Programacion || Dudas en general || Sistemas de Video || PC Hardware || Telematica y comunicaciones || Tecnologias moviles || Software Electronico || Robotica, Domotica y Mecatronica || Autotrónica || Automatizacion, Electronica industrial y de Potencia || Documentacion, circuitos y esquemas || Donde Las Ideas Convergen... || Tutoriales y Manuales || Proyectos Prácticos ||