Actividad 5:
Acceso avanzado al puerto paralelo con TurboC

 

Acceso directo al puerto paralelo

Consúltese la sección correspondiente  de El Puerto Paralelo del PC para conocer los detalles acerca de cómo determinar cuántos puertos se hallan instalados y qué direcciones de E/S ocupan.

Pulse aquí para comprobar cómo se programa en TurboC el acceso al puerto.

Volver al principio de página

 

Detección del tipo de puerto

En esta sección indicaremos la sistemática para detectar el modo del puerto paralelo, es decir si el puerto es:

Cabe aclarar que se detectará el modo actual, es decir no el hardware real. Si tenemos un puerto con capacidad ECP y lo configuramos como SPP, se detectará un SPP.

Para ello, se realiza una prueba en orden descendente de complejidad, es decir, primero ECP, luego EPP, SPP y, finalmente, bidireccional PS/2. Se realiza en este orden porque los puertos ECP y EPP pueden emular perfectamente un SPP o bidireccional, por lo que obtendríamos una información inexacta. Además, se prueba al final la capacidad bidireccional porque es equivalente a probar la no existencia de un puerto (cuidado en este sentido: conviene deshabilitar el modo bidireccional con C5=0 y, una vez que se verifique que realmente hay un puerto, activarlo para saber si es bidireccional).

Pulse aquí para comprobar cómo se programa en TurboC la detección del tipo de puerto directo al puerto.

 

Detección de ECP

Este es el método que recomienda Microsoft:

 

Detección de EPP

Además de los tres registros de un puerto SPP, un puerto EPP tiene cinco registros más mapeados desde LPT_BASE+3h hasta LPT_BASE+7h. Estos registros adicionales proporcionan una manera de probar la presencia de un EPP escribiendo ciertos valores y leyendo el resultado (de la misma manera que se detecta un puerto SPP). Para ello se recomienda:

Hay que asegurarse de poner S0 a 0 (EPP timeout), antes de leer o escribir a estas direcciones extendidas.

Otro dato importante es que no existen puertos EPP en la dirección base 03BCh.

 

Detección de SPP

Para detectar si el puerto es SPP, realizamos el procedimiento que lleva acabo la BIOS en el arranque, es decir, verificar la retención del puerto, que es posible en un puerto SPP. Para ello:

 

Detección de puerto bidireccional (PS/2)

La idea es verificar que el puerto no retenga datos (al contrario que un puerto SPP, el cual tiene retención). Entonces:

Volver al principio de página

 

Acceso y detección del tipo de puerto en TurboC

A continuación aparece un ejemplo de cómo identificar los puertos paralelos instalados en un PC utilizando TurboC.

/****************************************************************/
/*								*/
/*	Identificación de los puertos paralelos del PC		*/
/*	2002 Víctor R. González					*/
/*								*/
/****************************************************************/

#include <stdio.h>
#include <dos.h>

#define TRUE  1
#define FALSE 0

/* dirección base del primer puerto paralelo */
#define LPT_BASE	LptDir[1]

/* registros del puerto estándar (SPP) */
#define DATOS       LPT_BASE
#define ESTADO      LPT_BASE + 1
#define CONTROL     LPT_BASE + 2

/* primer y último registros adicionales del puerto EPP */
#define REG_EPP_PRI LPT_BASE + 3
#define REG_EPP_ULT LPT_BASE + 7

/* registro de control extendido (ECR) del puerto ECP */
#define CONTROL_EXT LPT_BASE + 0x402

unsigned int LptDir[4];	/* Contenedor de las direcciones de los puertos */

int main(void)
{
	unsigned int PuertoNum, Puerto;
	unsigned int far *LptDirPnt;
	unsigned int Byte, tmp;
	char PuertoEPP;

/* Busca la dirección de E/S de los puertos instalados */

	/* Una opción: usando <peek> */
	for (PuertoNum=1; PuertoNum<=3; PuertoNum++) {
		LptDir[PuertoNum] = peek(0x0040,0x0008 + (PuertoNum-1)*2);
		if (LptDir[PuertoNum] == 0)
			printf("No se encuentra puerto asignado a LPT%d \n", PuertoNum);
		else
			printf("La dirección asignada a LPT%d es 0x%X\n", PuertoNum, LptDir[PuertoNum]);
	}

	/* Otra opción: mediante puntero <far> */
	LptDirPnt=(unsigned int far *)0x00000408;
	for (PuertoNum=1; PuertoNum<=3; PuertoNum++){
		if (*LptDirPnt == 0)
			printf("No se encuentra puerto asignado a LPT%d \n", PuertoNum);
		else
			printf("La dirección asignada a LPT%d es 0x%X\n", PuertoNum, *LptDirPnt);
		LptDirPnt++;
	}

/* Detecta el tipo de puerto del primero hallado */

	/* Prueba puerto ECP */
	Byte = inportb(CONTROL_EXT) & 0x03; /* toma bits 0 y 1 de CONTROL_EXT */
	if (Byte==1) {
		Byte = inportb(CONTROL);
		tmp  = Byte;
		outportb(CONTROL, Byte ^ 0x03);    /* pone a cero los bits 0 y 1 de CONTROL */
		Byte = inportb(CONTROL_EXT) & 0x03;
		if (Byte==1)
			printf ("El puerto es ECP\n");
		else
			printf ("El puerto no es ECP\n");
		outportb(CONTROL, tmp);          /* restaura CONTROL */
	}
	else
		printf("El puerto no es ECP\n");

	/* Prueba puerto EPP */
	PuertoEPP = FALSE;
	if (LPT_BASE != 0x03bc) {
		Byte = inportb(ESTADO);
		tmp  = Byte;
		outportb(ESTADO, Byte & (~0x01)); /* Pone a 0 el bit 0 de ESTADO */

		for (Puerto=REG_EPP_PRI; Puerto<=REG_EPP_ULT; Puerto++) {
			outportb(Puerto, 0x55);
			Byte = inportb(Puerto);
			if (Byte == 0x55) {
				outportb(Puerto, 0xAA);
				Byte = inportb(Puerto);
				PuertoEPP = (Byte == 0xAA);
				if (!PuertoEPP) break;
			}
		}
		outportb(ESTADO, tmp); /* restaura bit 1 de ESTADO */
	}
	if (PuertoEPP)
		printf("El puerto es EPP\n");
	else
		printf("El puerto no es EPP\n");

	/* Prueba puerto SPP */
	Byte = inportb(CONTROL);
	tmp=Byte;
	outportb(CONTROL, Byte | 0x20 ); /* Pone a 1 el bit 5 de CONTROL */
	outportb(DATOS, 0x55);
	Byte = inportb(DATOS);
	if (Byte == 0x55) {
		outportb(CONTROL, Byte | 0x20 ); /* Pone a el 1 bit 5 de CONTROL */
		outportb(DATOS, 0xAA);
		Byte = inportb(DATOS);
		if (Byte == 0xAA) printf("El puerto es SPP\n");
	}
	else
		printf("El puerto no es SPP\n");
	outportb(CONTROL, tmp); /* Restaura el bit 5 de CONTROL */

	/* Prueba puerto bidireccional */
	Byte = inportb(CONTROL);
	tmp=Byte;
	outportb(CONTROL, Byte | 0x20 ); /* Pone a 1 el bit 5 de CONTROL */
	outportb(DATOS, 0x55);
	Byte = inportb(DATOS);
	if (Byte != 0x55) {
		outportb(CONTROL, tmp | 0x20 ); /* Pone a 1 el bit 5 de CONTROL */
		outportb(DATOS, 0xAA);
		Byte = inportb(DATOS);
		if (Byte != 0xAA) printf("El puerto es bidireccional\n");
	}
	else
		printf("El puerto no es bidireccional\n");
	outportb(CONTROL, tmp); /* Restaura el bit 5 de CONTROL */

	return(0);
}

Volver al principio de página

 

Actividades

Impleméntese en TurboC el código de la sección anterior en una función denominada ParaleloIni (que pueda ser utilizada en posteriores programas de control) que retorne los valores:

Inclúyanse, asimismo, las definiciones relativas al puerto paralelo que se hallan en la cabecera del programa en un archivo include denominado paralel.h.

Volver al principio de página

volver a Inicio