PROYECTO DE INVESTIGACION I Y I1 LICENCIATURA EN COMPUTACION TRANSMISION Y RECEPCION DE ARCHIVOS ENTRE UNA COMPUTADORA PERSONAL NO COMPATIBLE Y UNA COMPATIBLE MEDIANTE EL USO DE LOS PUERTOS SERIALES PROFESOR: MARIKO NAKANO ALUMNO: MARISOL JARAMILLO GOMEZ MATRICULA: 89323700 INTRODUCCION Posiblemente no existe otro dispositivo estándar que dé más problemas al programador que el puerto serie asíncrono. Se diferencia del puerto paralelo, que es mucho más simple, en que el puerto serie da más erroes de transmisión. Para complicar las cosas, lasposibilidades de diálogo del puerto serie, que aseguran una buena comunicación no se suelen tener en cuenta al conectar los hilos que ligan el puerto serie con el dispositivo externo. Pero a pesar de estas dificultades, el puerto serie se usa mucho,alserel medio más barato de conectar dos dispositivos separados. Este proyecto pretende la transmisión / recepción de información entre dos computadoras compatibles y no compatibles, por lo que se explicarán las bases para el manejo del puerto serie, incluyendo la inicialización, transmisión y recepción de datos y el tratar algunos de los errores que ocurren más a menudo. Una vez cubierta la forma de trabajar con el puerto serie, se desarrollará un sistema de transferecnia de archivos que se podrá usar para transferir cualquier tipo de archivo ( incluso archivos binarios ) entre dos computadoras. PARTE UNO. - Transmisión Asíncrona en serie de datos. - El estándar RS-232. - Problemas con la comunicación entre computadoras compatibles. PARTE DOS. - Programade compatibles. - Conclusión. - Bitácora. transmisión/recepción de archivos entre computadoras PARTE TRES. - Programa de compatibles. transmisión/recepción de archivos entre computadoras no - Conclusión. - Bitácora. Trar~srnisiórl/recepriórlde archir~oserrfre cornpufadom ( ) I O ) co~npntibles Proyecto Terminal I y I1 1 PARTE I = Transmisión Asíncrona en serie de datos. El estándar RS-232. Problemas con l a comunicación entre computadoras compatibles Tratrsrnisiótr /recepciórr de arclrivos etltre cotrrprltndoras (HO) cornpntrbles Proyecto Terminal I y I1 L TRANSMISION ASINCRONA EN SERIE DE DATOS. Antes de estudiar en sí mismo el puerto serie asíncrono, necesita entender quesonlas comunicaciones asíncronas.(De ahora en adelante, el puerto serie asíncrono se llamará simplemente << puerto serie >>.)A través de un puerto serie los datos se transmiten bit a bit, uno en cada momento. En esto se diferencia de la transmisión a través de un puerto paralelo, que envía unbyte cada vez. La transmisión se denomina clsíncroncl si el tiempo entre la transmisión de un byte de los datos (bit a bit) es indiferente. Sin embargo, tanto el tiempo de transmisión como el orden de losbits, que componen un byte más otra información, es crítico. Cadabyte de datosquese transmite a través del puerto serie, usa esta secuencia de señales: 1. Un bit inicial. 2. Ocho bits de datos (siete enalgunas circunstancias). 3. Un bit deparidad de fin de transmisión. 4. Uno o dos bits de fin de transmisión. Puede transcurrir cualquier tiempo entre la transmisión de un par de bytes cualquiera. El estado de la línea de transmisión cuando no está ocupada es en alto.Un bit puesto a cerohace que la línea esté en bajo, un bit puesto a uno hace que la línea esté en alto. El bit inicial que marca el principio de la transmisión de un nuevo byte lleva la líneaacero por un ciclo.Se transmiten entonces los bits de datos. Finalmente se envían uno o dos bits de parada que corresponden a estados de la línea en nivel bajo. Los bits de parada determinan el tiempo más corto entre el envío de dos bytes. En general, no tiene importancia el usar uno o dos bits de parada, siempre y cuando los dos puertos, tanto el que envía como el que recibe, utilicen el mismo número. El bit de paridad, si se usa, sirve para detectar los errores de transmisión.La paridad puede ser par o impar. Si se elige la paridad par, el bit de parada se le da un valor de forma que el byte transmitido más el bit de paridad dé un número par.Si se usa la paridad impar, el byte más la paridad darán un número impar. La velocidad a la que se transmiten los bits se mide en baudios ( bits por segundo ). La velocidad más baja que se usaes de 300 baudios, que se utiliza fundamentalmente en los modems más viejos y lentos. (La mayoría de los modems actuales van a1200 o 2400 baudios). Trarzsrrlisidrf/recepcidrr de nrchiz~osertfre corrrprrtadovns ( m ) compatibles Proyecto Terminal I y I1 3 EL ESTANDAR RS-232 La configuración de la mayoría de los puertos serie se basa, aunque relajada, en el estándar RS-232 (EIA RS-232) usando un conector de 25 pins, sin embargo también es posible encontrar conectores : EIA 574 de 9 pins y el EIA 561 de 8 pins, el cual es un conectorestilo telefónico. RAPIDEZ Y POTENCIA. El estándar RS-232 permite la transmisión y recepción a velocidades desde cero hasta 20,000 bits por segundo.En el caso del EIA 561 (conector de 8 pins) se pueden tener velocidades hasta de 38,400 bps.Ambas dependen de la longitud del cable. DESCRIPCION MECANICA DE LA INTERFACE ENTRE CIRCUITOS. LOS El estándar RS-232 es un conector hembra para dispositivos como el modem y un conector macho para un equipo terminal. Las funciones del RS-232 se dividen en filnciones de datos y funciones de control. FUNCIONES DE DATOS. 1. Transmisión de datos ( PIN 2 ) 2. Receptor de datos ( PIN 3 ) FUNCIONES DE CONTROL. 1. 2. 3. 4. 5. 6. 7. Tierra de Protección ( PIN 1 ). Preparado para enviar ( recibir ) ( PIN 4 ). Línea de control ( PIN 5 ). Datos preparados ( PIN 6 ) Tierra ( PIN 7 ). Detector de acarreo ( PIN 8 ). Terminal de datos preparada ( PIN 20 ) 4 Sin embargo, una gran cantidad de los puertos serie no emplea todas las señales especificadas en el estándar RS-232.Algunas de estas señales no se usan por no tener utilidad en la aplicación prevista; otras no se emplean debido a que el fabricante prefiere ofrecer un conjunto mínimo, en lugar de suministrar soporte completo para RS-232. La existencia de tantas señales se debe al hecho de que el puerto serie se diseño inicialmente para soportar un modem.Porello, cuando se usa con otros dispositivos, muchasde esas señales no sirven de nada.Esas señales se utilizan normalmente para establecer unprotocolode hardware entre el modem y la computadora, de forma que ésta: 1) no le envíe información antes de que pueda transmitirla, o 2) nolea información del modem antes de que esté lista. Los conectores EIA 572 y 561 son lógicamente y eléctricamente compatibles con el RS-232, a excepción de que el EIA 561 permite velocidades de transmisión y recepción hasta de 38,400 bps.Estos son mostrados a continuación. Trnrzsrnisiórl /recepciórr de nrchiuos erltre corwprrtndorns (110) corrrpntlbles Proyecto Terminal I y I1 5 PROBLEMAS CON LA COMUNICACION ENTRE COMPUTADORAS COMPATIBLES. Para permitir la comunicación vía modem, se usan varias señales para determinar cuándolos datos están listos o cuándo se puede enviar el próximo byte.Sin embargo, cuando la comunicación se lleva a cabo entre computadoras, es posible (aunqueno recomendable) el usar las señales de tierra, transmisión y recepción.La razón que hay detrás de ésto es que tender tres cables es bastante más barato quetender cinco o seis.Si dos computadoras del mismo tipo están en comuniccación entre sí, cuando una está lista para enviar datos, la otra lo está, en teoría, para recibirlos.sin embargo, al obviar el protocolo de señales inmerso en el estándar RS-232, da inicio a los problemas.El peor de éstos es el error de sincronización. Sobreescribiendo el registro de recepción. Cuando se usan solo tres hilos para conectar entre sí dos puertos serie, es necesario <<engañar>> al puerto que transmite, haciéndole creer que el puerto receptor está siempre 1isto.Esto se lleva a cabo puenteando las patillas 6, 8 y 20 del conector de 25 patillas.Desafortunadamente, este método hace que aparezca muy a menudo un error de sobreescritura.Supongamos que la computadora A es más rápida que la B. Si no se utiliza diálogo hardware, posiblemente la compuatadora A puede enviar a la B un segundo byte antes de que ésta haya leído la información del registro de entrada de su puerto serie. Este es el denominado error de sincronización. Este tipo de error se puede producir incluso siendo la computadora B más rápida que la A, si el software de la B fuera demasiado lento. Este problema aparece debido a que las patillas 6, 8 y 20 se han ligado entre sí y por tanto el puerto transmisor cree que el receptor está listo para recibir datos siempre. ACCESO A LOS PUERTOS SERIE DEL PC A TRAVES DEL BIOS. A los puertos serie de un PC o compatible se puede acceder a através del DOS, delaROM-BIOS o bien sin pasar por el DOS y la BIOS controlando directamente el hardware. En general, el acceso a los puertos serie a través del DOS no es una buena idea, ya que el DOS no provee de posibilidad de realimentación con el estado del puerto, sólo nos brinda lecturas o escrituras ciegas en el puerto. Por ello no se usarán las interrupciones del DOS. Trnrlsrnisiórr / recepciórl de nrrlriuos errtre corrlprrtndor~s(rro) c-orrryntlhles Proyecto Terminal I y I1 h Cuatro rutinas de la ROM-BIOS permiten el acceso a los puertos serie.Estas rutinas se lanzan a través de la interrupción 14H. Inicialización delpuerto. Antes de utilizar el puerto serie, probablemente se deseen inicializar los valores característicos con valores distintos de los dados por defecto. (Los valores de trabajo dados para el puerto serie son normalmente 2,400 baudios, sin paridad, ocho bits de datos y un bit final.) La rutina de servicio O de la interrupción 14H se utiliza para inicializar un puerto serie.Comoconlas otras interrupciones de la BIOS, se usa el registro AH para suministrar el número de la rutina de servicio.En el registro AL se suministran los parámetros de inicialización que se codifican en un byte tal y como semuestra a continuación. número de bit baudios paridad fin de trans bits datos de tabla: 7/65 4,3 2 LO La velocidad de transmisión se codifica como se muestra en la siguiente I I I 9600 4800 2400 1200 600 300 150 110 I I I 111 110 1o1 100 o13 o1o O01 O00 I I I 7 Los bits de paridad se codifican según se ve en la siguiente tabla: I No Paridad I O0 ó 10 I o1 Imparcial I 11 El número de bits de fin de transmisión viene dado en el bit 2 del byte de fin de inicialización de puerto serie. Si el bit 2 está a 1, se usan dosbitsde transmisión; en otro caso se usaría un solo bit de fin de transmisión.Fina1mente el número de bits de datos viene dado por los bits 1 y O del byte de inicialización.De los cuatro posibles valores, sólo dos son válidos. Si los bits 1 y O contienen el par << 1 O>>, se usarán siete bits de datos. Si muestran el par << 1 1 >> se utilizarán ocho bits de datos. Por ejemplo si se desea configurar el puerto a 2,400 baudios, sin paridad, un bit final y ocho bits de datos, se tendrá que utilizar el formato que sigue. Baudios : Paridad : Fin de transmisión : Bits datos : 101 O0 O 11 y se expresa en binario: ( Baudios I Paridad I Fin de Trans I Bits Datos ) En forma decimal, su valor es 163. En un PC estándar puede haber hasta 7 puertos serie. Se especifica el puerto a usar en el registro DX.El primer puerto serie es el O, el segundo el 1, y así sucesivamente. La función que sigue denominada inicializaPwerto() se utiliza para inicializar los parámetros de cualquier puerto serie. 8 e puerto /" Inicialización del puertode comunicaciones serial */ void inicializapuerto(puerto,valor) int puerto; unsigned char valor; { union REGS inregs; integs.x.dx = puerto; /*puerto serie*/ inregs.h.ah. = O; /*Inicializa la función*/ inregs.h.al = valor; /"Código de Inicialización*/ int86(0~14,&inregs,&inregs); 1 Esta función se basa en la función int860, que existe en muchos compiladores, entre ellos Turbo C y Microsoft C, aunque la función puede recibir algún otro nombre si se utiliza otro compilador distinto. También puede ocurrir que exista unafunción específica que inicialice el puerto serie. Los valores de la velocidad, la paridad, el bit de parada y los bits de datos, se pueden asignar mediante el uso de un menú que permita seleccionar entre distintas cantidades. Las funciones para tal elección son: /.De acuerdo a la opcion seleccionada en la opción del menu: Baudios /.se asigna un valorequivalente en hexadecimal.Este valor forma partedel inicializacion del /.codigo de */ *I */ Bauds ( Bps, selection ) int "Bps, selection; { switch ( selection ) { case 0 : *Bps = OxEO ; /* 9600 baudios */ break; case 1: *Bps = 0xC0 ; /* 4800 baudios */ break; case 2 : *Bps = OxAO ; /* 2400 baudios */ break; case 3 : *Bps = 0x80 ; /* 1200 baudios */ break; 9 case 4 : *Bps = 0x60 ; /* 600 baudios break; case 5 : case 6 : case 7 : */ *Bps = 0x40 ; /* 300 baudios */ break; *Bps = 0x20 ; /* 150 baudios */ break; *Bps = Ox00 ; /* 110 baudios break; */ /*De acuerdo a la opcionseleccionadaenlaopcióndelmenu: Parada /*se asigna un valor equivalente en hexadecimal.Este valor forma parte del seriepuerto /*codigo inicializacion del de */ */ *I BitStop ( Parada, selection ) int "Parada, selection; { switch ( selection ) { case O : *Parada = Ox00 ; / * Un bit de fin de transmisión */ break; case 1 : I I "Parada = 0x04 ; /* Dos bits de fin de transmisión*/ break; /*Deacuerdoa la opcionseleccionadaenlaopcióndelmenu:Paridad /*se asigna un valor equivalente en hexadecimal.Este valor forma parte del seriepuerto rcodigo inicializacion del de */ */ */ BitParity ( Parity, selection) int *Parity, selection; f switch ( selection ) 1 case O : *Parity = Ox00 ; /* No paridad */ break; case 1 : *Parity = Ox08 ; /* Desigual */ break; case 2 : Trmsrnisiórl/ recepciórl de nrckir~oserltre corr~p~rtndorns (110) corrrpntibles Proyecto Terminal I y I1 10 *Parity = Ox18 ; /* Imparcial */ break; /,De acuerdo a la opcion seleccionada en la opción del menu: Palabra*/ /,se asigna unvalor equivalente en hexadecimal.Este valor forma partedel*/ /,codigo inicializacion del de puerto serie *I BitDatos( Datos, selection ) int *Datos, selection; { switch ( selection ) ( case O : case 1 : *Datos = 0x02 ; /* Siete Bits de datos */ break; *Datos = 0x03 ; /* Ocho Bits de datos*/ break; Transmisión de bytes. L a rutina de servicio 1 de la interrupción 14H del BIOS transmite un byte a través del puerto serie especificado en DX. El byte que se desea enviar debe estar en AL. El estado de la transmisión se devuelve en el registro AH.Dicho estado se verifica en el bit 7, si su valor es de O (cero) entonces no hubo error, en caso contrario, los bits O a 6 muestran la causa de la falla (veáse Tabla 1) La función mandaserialo que sigue envía un byte a través del puerto serie especificado. 7'rarrsmisiór~/ recepciórr de arclmos entre corlrprrtndorns (rroi corrrpntihles Proyecto Terminal I y I1 11 Tabla 1. Envía un caracter al puerto serial especificado y devuelve el estado de éste.Antes de llamar a esta función, asegurese de usar Int 14/00 para preparar el puerto*/ /" void mandaSerial(puerto,car) int puerto; char car; { union REGS inregs; inregs.x.dx = puerto; /"Puerto serie*/ inregs.h.al = car; /"Caracter a enviar*/ inregs.h.ah = 1; /"Función que envía un carácter*/ int86(0~14,&inregs,&inregs); if(inregs.h.ah & 128) { /"Comprueba el bit 7.Siel bit 7=0 no hubo error*/ gotoxy(1,q; cprintf("Error de transmisión en el puerto serie."); cprintf("%d",statusPuerto(puerto)); delay(500); gotoxy(L1); 1 Aunque ahora mandaserialo se limita a salir ante un error, se podría escribir una rutina de control de errores queintentase recuperar cierto tipo de errores. Trarlsrnisidrl,' recepciórl de nrcInz1os rrltre corrrprrtariorns (110) corrrpntibles Proyecto Terminal I y 11 12 Comprobación del estado de un puerto. La rutina deservicio 3 de la interrupción 14H del BIOS sirve para comprobar el estado del puerto. El puerto a comprobar se especifica en el registro DX. A la vueltade la interrupción, AH y AL contendrán el estado del puerto codificado como se muestra en la Tabla 1. El valor de estado que es importante es el de << Datos preparados >>.Comprobandoestevalor,se puede determinar si se ha recibido unbytede datos en un puerto y si está listo para leerlo. La función recibeserialo, usada para leer datos de un puerto, muestra el uso del valor de estado << Datos preparados >>, como verá en el próximo apartado. Recepción de unbyte. La rutina de servicio 2 de la interrupción 14H se utiliza para leer un byte en un puerto serie. Una vez más elpuerto serie a usar se especifica en DX.A la vuelta de la interrupción, el carácter leído se encuentra en AL. Y de idéntica forma a como ocurría en la transmisión, al acabar, el bit 7 de AH indica el éxito o el fracaso de la operación. La función recibe Serial(), que sigue, lee un byte en un puerto dado. /* Lee un carácter del puerto serial especificado y devuelve el estado del puerto.Antes de llamar aesta función debe prepararse el puerto.*/ recibeSerial(puert0) int puerto; { union REGS inregs; /* Espera por el carácter*/ while (!(statusPuerto(puerto) & 256)) if (kbhit())( /* Termina si se pulsa una tecla*/ getch(); clrscr(); exit(1); 1 inregs.x.dx = puerto; /*PuertoSerie*/ inregs.h.ah = 2; /*FuncióndeLecturade un carácter*/ int86(0~14,&inregs,&inregs); if (inregs.h.ah & 128)( gotoxy(1,I); cprintf("Error de lectura en el puerto serie."); delay(500);) return inregs.h.al; \ Trnr~strrisiót~ / rereepcidrl de nrchir1os erltre corr~plrtndorm( r m ) corrrpnfihle~ Proyecto Terminal I y I1 13 La interrupción de lectura de un puerto espera hasta que se ha recibido un byte en el puerto serie antes de retornar.Sin embargo, cierto tipo de errores, como uncable mal conectado, pueden bloquear la computadora. Paraevitareste problema, recibeserialo lee el estado del puerto especificado, comprobando el bit de datos listos. Simultáneamente, la función kbhit() controla si se pulsa una tecla. Si se pulsase alguna, el control abandona la tarea. ( En algunos casos, se puede llamar a una función de control de errores específica.) Esto le permite terminar si no se recibiera ningún dato. Tan pronto como se recibe un dato, se llama a la rutina de servicio 2 de la interrupción 14H y se lee el byte. Una vez más, se comprueba el bit 7 de A H para ver si la operación fue exitosa.Finalmente la función devuelve el byte leído. Diálogo Software. Cuando el diálogo hardware no es posible, o está dañado, la cínica forma de asegurar que no va haber errores de sobreescritura durante la transmisión es el de implementar un diálogo software. El diálogo software funciona de la siguiente forma: la computadoraque transmite envía el primer bytey espera aquela computadora receptora le envíe un byte de contestación. Una vez que ha recibido lacontestación,el transmisor envía el siguiente byte y espera de nuevo la contestación.Este proceso continúa hasta que se haya transferido todo el archivo.En pseudocódigo C, las rutinas emisora y receptora tienen este aspecto: enviar() { while (hay bytes por enviar){ enviar(un byte); esperar; I 1 recibir() { do{ recibe-byte(); envia(reconocimiento); }while(haya bytes por leer); 1 Trnrlslrlisiórl,’ reccpciórl de arclliuos crrtre c-orrrprrtndorns (110) corrryntiblcs Proyecto Terminal I y I1 14 De esta forma el emisor nunca sobreescribe en el puerto receptor, independientemente de lo distintas que sean las velocidades de trabajo. El Único inconveniente de este tipo de diálogo esque la velocidad de transmisión se divide por dos, ya que se deben transmitir dos bytes por cada byte de información que se transfiere. Siete u ocho bitsde datos. Si sólo desea transferir archivos de texto, necesita sólo siete bits de datos, ya que las letras y símbolos de puntuación no requieren el octavo bit ( a diferencia de lo que ocurre en lengua inglesa, en lengua castellana hay una serie de caracteres que sí necesitan el octavo bit: las vocales acentuadas y la ñ). Enviando sólo siete bits, aumenta un poco la velocidad de transmisión, pero aparecen problemas cuandose intenta enviar un archivo que no sea de texto,como un archivo ejecutable de programa. Todos los archivos de programa y algunos de datos contienen información que usan los ochobits completos. Por ello, el programa de transferencia de archivos deberá enviar los ocho bits. Sin embargo, aparece un pequeño problema cuando se envían archivos binarios: la marca EOF no se puede usar como señal que marque el fin de archivo. Para resolver este problema, el número de los bytes a enviarse deberá ser transferido al receptor antes de enviar el archivo. Envío de un archivo. La primera rutina que se necesita es una función que transmita un archivo porel puerto serie. En general, deberá abrir el archivo a transmitir, calcular su tamaño,enviarelvalor del tamañoy finalmente enviar el archivo. La función mandArchivo0, que sigue, lleva a cabo estas tareas. '~rauarlsunisldn/recepridrr de arclriuos entre colnpufadorns (110) compatibles Proyecto Terminal I y I1 15 /* Transmite el archivoespecificado*/ void mandArchivo(archivoNom) char *archivoNom; { FILE "fp; char car; union( char c[2]; unsigned int contador; }contar; if ((fp = fopen(archivoNom,"rb")) == NULL){ gotoxy(l,l); cprintf("Imposib1e abrir archivo: %s",archivoNom); delay(500); gotoxy(L1); cprintf(1inea); return; 1 mandaNomArchivo(archivoNom ); /*Envía el nombre del archivo*/ esperaRespuesta(puert0); /"Espera el reconocimiento del receptor*/ contar.contador = archivoTamano(fp); /*Se determina el tamaño del Archivo*/ mandaSerial(puert0, contar.c[O]); /*Envia la longituddel archivo*/ esperaRespuesta(puert0); mandaSerial(puerto,contar.c[l]); /*Envia la longitud del archivo*/ do { car = getc (fp); if ( ferror(fp) ){ gotoxy(l,l); cprintf("Error de lectura en el archivo."); delay(500); gotoxy(l,l); cprintf(1inea); break; 1 /*Espera hasta que el receptor esta preparado*/ if (!feof(fp)){ esperaRespuesta(puert0); mandaSerial(puerto,car); I ]while(!feof(fp)); esperaRespuesta(puert0); fclose(fp); gotoxy(l,l); /*Lee el último punto delpuerto*/ 1 La función mandaNomArchivo(), que sigue, establece la conexión con el receptor y transmite el nombre del archivo. 7'rur1srr~isidrl /recepcidrl de nrchivos entre coruprrtndorns ()lo) corrrpntihks Proyecto Terminal I y 11 16 PTransmite el nombre del archivo*/ void mandaNomArchivo(archivoNom) char *archivoNom; { gotoxy(L1); cprintf("Transmision en espera..."); do { mandaSerial(puerto,'?'); }while(!kbhit() && !(statusPuerto(puerto) & 256)); if (kbhit()){ getch(); clrscr(); exit(1); I esperaRespuesta(puert0); /*Espera el reconocimiento del receptor*/ gotoxy(1J); cprintf("Transmitiendo : %s",archivoNom); while (*archivoNom){ mandaSerial(puerto,*archivoNom++); esperaRespuesta(puert0); /*Espera el reconocimiento del receptor*/ 1 I mandaSerial(puerto,'\O'); La función mandaNomArchivo() tiene dos objetivos. El primero es establecer comunicación con elreceptor, enviando una marca de interrogación hastaque el receptor responda con un punto.(El punto es el símbolo de reconocimiento de transferencia de programas, pero se puede usar el valor que se desee). Una vez que se ha establecido la comunicación, se transmite el nombre del archivo.Téngase en cuenta que esta función puede terminarse pulsando cualquier tecla. La función esperaRespuesta() usada por la función mandaNomArchivo() devuelve el estado del puerto especificado. El código de la función statusPuerto() se verá en el listado general. continuación, espera para un La función esperaRespuesta(), quesevea reconocimiento del receptor; de esta forma se implementa el diálogo software. Trorrsrwisidrl/vecepcidrr de nrclrims erltve corrrptntforns ( m ) c-orrrpatibl~s Proyecto Terminal I y I1 17 /* Revisa si se recibio el caracter verificador, correcto.Dicho caracter es el ,,"'*/ int puerto; { void esperaRespuesta(puert0) if (recibeSerial(puert0) != '.'){ gotoxy(Lq; cprintf("Error de comunicación"); delay(500); exit(1); 1 1 Si esta función detecta error, en caso de que laaplicación lo requiera, podría sustituirse por un controlador específico de errores. La función archivoTamano() nos devuelve el tamaño del archivo en bytes. Es posible que el compilador suministre una función que dé la longitud de los archivos;portanto, siéntase libre de sustituirla.La variable union contar se necesita, ya que el tamaño del archivo es un valor dado en dos bytes, pero solo se puede enviar un byte en un ciclo por el puerto serie. Recepción de un archivo. La recepción deun archivo es justo lo contrario a enviarlo. Primero la función receptora espera hasta que recibe una marca de interrogación. Responde con un punto ( el símbolo de reconocimiento). Entonces lee el nombre del archivo. Recuérdese que cada vez que se recibe un byte, se envía un reconocimiento.Esto constituye el diálogo software. Es posible que el usuario indique que tipo de archivo va a recibir, de esa forma se podrá optimizar el número de accesos a disco.De lo anterior obtenemos que si el archivo a recibir es de texto entonces los carácteres se almacenarán en un arreglo, el cual vaciará su contenido a una unidad de almacenamiento secundario una vez lleno o terminado el archivo, en caso contrario los carácteres se guardarán conforme se reciban. La función para realizarlo es recibeArchivo() : 78 PRecepcion de un archivo*/ void recibeArchivo(TipoArchivo) char TipoArchivo; { FILE *fp; char car; char archivoNom[l4], GuardaDato[150]; int cuenta=O; union{ char c[2]; unsigned int contador; )contar; memset(archivoNom,",14); memset(GuardaDato,",l50); recibeNomArchivo(archivoNom); /*Lee nombre eldel gotoxy(L1); cprintf("E1archivo recibido es: % S ",archivoNom); remove(archivoNom); archivo*/ switch(TipoArchivo){ case 'B': ( if ((fp = fopen (archivoNom, "wb"))== NULL){ gotoxy(1,l); cprintf("1mposible abrir el archivo de salida"); delay(500); cprintf(1inea); return; 1 break; 1 case IT':{ if ((fp = fopen (archivoNom, "wt"))== NULL){ gotoxy(L1); cprintf("1mposible abrir el archivo de salida"); delay(500); cprintf(1inea); return; 1 break; 1 1 mandaSerial(puerto,'.'); contar.c[O] = recibeSerial(puert0); mandaSerial(puerto,'.'); contar.c[l] = recibeSerial(puert0); /" Leelongitud la del archivo*/ /* Lee lalongituddel archivo*/ mandaSerial(puerto,'.'); Trmsrwisidrr / recepcidrr de archivos rrztre cornprrtndoras ( m ) corrrpntibk.5 Proyecto Terminal I y I1 19 /" Escribe el contenido del archivo enviado */ for (;contar.contador; contar.contador--)( car = recibeSerial(puert0); GuardaDato[cuenta]=car; /*Si es texto almacena datos en un arreglo para disminuir el número de accesos a disco*/ switch(TipoArchivo){ case 'B': {putc (car, fp); /" Si es un archivo Binario*/ break;} case IT': /" Si es un archivo Texto*/ { if ((contar.contador==l) I I (car==l\n') I I (feof(fp))) { fputs(GuardaDat0,fp); cuenta=0; 1 else cuenta++; break; 1 1 if ( ferror(fp) ){ gotoxy(1J); cprintf("Error de escritura en el archivo."); delay(500); cprintf(1inea); return; 1 mandaSerial(puerto,'.'); /" Envia reconocimiento*/ 1 fclose(fp); 1 La función recibeNomArchivo() se muestra a continuación. /" Recibe el nombre del archivo */ void recibeNomArchivo(archivoNom) char *archivoNom; { gotoxyp,q; cprintf("Recepcion en espera..."); while(recibeSerial(puerto) != I ? ' ) ; mandaSerial(puerto,'.'); /" Envia el reconocimiento*/ while ((("archivoNom= recibeSerial(puerto)))!= NULL) { i f (*archivoNom != I ? ' ) { archivoNom++; mandaSerial(puerto,'.'); /* Enviaelreconocimiento*/ I 1 1 Trnrlsirrisiórr/recepciórr de nrchiz1os erltre corrrpufndoms ( m ) c-orrrpntibles Proyecto Terminal I y II 20 PARTE I1 9 9 9 Programa de transmisión/recepción de archivos entre computadoras compatibles Conclusión Bitácora Trarlsrnisidrl /recepcidr~de archivos errfre corrrprrtadoras ()lo) cor~rpnt~blc~s Proyecto Terminal I y I1 21 PROGRAMA DE TRANSMISION/RECEPCION ARCHIVOS ENTRE COMPUTADORAS COMPATIBLES. DE A continuación se lista el programa de transferencia de archivos, incluyendo las funciones necesarias. Tal como se muestra, se usa el puerto O (el primer puerto serie); sinembargo, se puede cambiar la definición del puertoauna posición cercana al inicio delprograma si se desea utilizar un puerto diferente. /+Transferencia de archivos usando dialogo software. Puerto inicializado COMl : O, sin paridad, ocho bits de datos, dos bits de parada*/ #define PUERTO O #define cad1 "Inicializacion" #define cad4 "Baudios." #define cad16 "9600 bps." #define cad17 "4800 bps." #define cad18 "2400 bps." #define cad19 "1200 bps." #define cad20 "600 bps." #define cad21 "300 bps." #define cad22 "150 bps." #define cad23 "110 bps." #define #define #define #define cad5 "Paridad." cad24 "Sin paridad" cad25 "Impar." cad26 "Par." #define cad14 "Parada." #define cad27 "1 bit de parada." #define cad28 "2bits de parada." #define cad15 "Palabra." #define cad29 "7 bits de datos." #define cad30 "8bits de datos." #define #define #define #define cad2 cad3 cad6 cad7 "Ayuda." "Salida." "Salida." "Archivos." 22 #define cad8 "Transmision." #define cad9 "Recepcion." #define NUMV 7 #define NUMM 7 #define NMOPC 8 /*Numero de ventanas*/ /*Numero de menues*/ /*Numero de opciones*/ #include "std1ib.h" #include "conio.h" #include "a1loc.h" #include "stdio.h" #include "string.h" #include "dos.h" #include "ventanas.h" #include "menus.h" # include <bios.h> # include <dir.h> # include <ctype.h> #include <a:\helptran.c> /* Archivo que contiene los enunciados de Ayuda*/ unsigned int archivoTamano(); void mandaserial(), mandArchivo(), recibeArchivo0, mandaNomArchivo(); void recibeNomArchivo(), inicializaPuerto(), esperaRespuesta(); void goto-xy(), cls(); char far "vid-mem; /*Inicializa las funciones deapertura de ventanas. /*Las funciones iniclzvent(), caractvent(), iniclzmenu(), llenamenu(), /,forman parte de una libreria que incluye codigo para la creacion de /"de menues void ventanilla(void) *I */ */ *I 1 iniclzvent(0,1,1,80,25,0,'I'); iniclzvent(l,5,4,75,23,1,'L'); iniclzvent(2,1,1,80,4,O,'I'); iniclzvent(3,2,6,16,14,1,"); iniclzvent(4,16,7,28,18,1,'P'); iniclzvent(5,16,7,34,13,1,'P'); iniclzvent(6,15,6,30,12,l,'L'); iniclzvent(7,10,20,70,23,1,'L'); caractvent(0,l,l5,15,15,"BC","TRANSMISION DE ARCHIVOS"); caractvent(l,l,l5,15,15,"DC",""); caractvent(2,1,15,15,15,"DC","TRANSMISION DE ARCHIVOS"); 7rarrsrnisidrI / recepcidrl de archioos errtre corrrputnrloras Proyecto Terminal I y I1 (110) corrrpntrbks 23 caractvent(3,1,15,15,15,"DC"," caractvent(4,1,15,15,15,"CC"," caractvent(5,1,15,15,15,"CC"," caractvent(6,1,15,15,15,"DC"," caractvent(7,1,15,15,15,"DC"," "); "); "); "); "); iniclzmenu(0,4,WHITE,O); /, Menu principal */ Ilenamenu(O,O,l,2,cadl); Ilenamenu(O,1,20,2,cad7); llenamenu(0,2,40,2,cad2); llenamenu(0,3,60,2,cad3); iniclzmenu(l,5,WHITE,O); /, Menu para seleccionar las caracteristicas del puerto serie*/ Ilenamenu(l,0,1,2,cad4); llenamenu(l,l,l,3,cad5); Ilenamenu(l,2,1,4,cad14); llenamenu(l,3,1,5,cadl5); Ilenamenu(l,4,1,6,cad6); iniclzmenu(2,3,WHITE,O); /,Menu para seleccionar Transmision/Recepcion*/ llenamenu(2,0,1,2,cad8); llenamenu(2,1,1,3,cad9); Ilenamenu(2,2,1,4,cad6); iniclzmenu(3,8,WHITE,O); /, Menu Para seleccionar los baudios*/ Ilenamenu(3,0,1,2,cad16); llenamenu(3,1,1,3,cadl7); llenamenu(3,2,1,4,cad18); llenamenu(3,3,1,5,cad19); llenamenu(3,4,1,6,cad20); llenamenu(3,5,1,7,cad21); llenamenu(3,6,1,8,cad22); llenamenu(3,7,1,9,cad23); iniclzmenu(4,3,WHITE,O); /, Menu para seleccionar la paridad */ llenamenu(4,0,1,2,cad24); llenamenu(4,1,1,3,cad25); llenamenu(4,2,1,4,cad26); iniclzmenu(5,2,WHITE,O); /, Menu para seleccionar los bits de parada llenamenu(5,0,1,2,cad27); llenamenu(5,1,1,3,cad28); */ iniclzmenu(6,2,WHITE,O); /, Menu para seleccionar la longitud palabra*/ llenamenu(6,0,1,2,cad29); llenamenu(6,1,1,3,cad30); Vtermina ventanilla*/ 24 ............................................................................. / *I *I PCreacion /*El numero opciones se de cuenta desde cero /*Las funciones crear-v(), ciema-v(), activa-v(), crea-opcvnt() forman parte */ /" de una librería que incluyecódigos para la creación, activación y cierre de*/ *I /*ventanas. ............................................................................ / void menues(void) { short opc, opcl, opc2, opcbaud, opcparity, opcstop, opcdata; int cant; int register Settings; int Bps = 0x00, Parity = 0x00, Parada = 0x00, Datos = 0x00; char archivoNom[l4]; char *NombreArchivo; char TipoArchivo="; Settings = ( Bps clrscr(); ventanilla(); crear-v(0); activa-v(O); crear_v(l); activa-v(1); Portada(); cierra-v(1); clrscr(); do{ I Parity I Parada I Datos ); /"Variable a la que se asigna el codigo de inicializacion*/ /" Se encuentra enel archivo He1pTran.C */ crear-v(2); activa-v(2); opc=crea-opcvnt(0,2); switch(opc){ case O: { /* OPCION: MENUInicializaciondel puerto */ do{ ~rear~v(3); activa~v(3); opcl=crea-opcvnt(l,3); switch(opcl){ case O: { crear-v(4); /" OPCION: SeleccionBPS */ activa-v(4); clrscr(); opcbaud=crea-opcvnt(3,4); Bauds(&Bps,opcbaud); cierra-v(4); break;] 25 case 1: { crear-v(5); /" OPCION:Seleccion Paridad*/ activa-v (5); opcparity=crea_opcvnt(4,5); BitParity(&Parity,opcparity); cierra-v(5); break;} { crear-v(5); /" OPCION:SeleccionParada activa-v(5); case2: opcstop=crea-opcvnt(5,5); BitStop(&Parada,opcstop); cierra~v(5); break;} ( crear~v(5); /" OPCION:SeleccionBitsde activaxv(5); opcdata=crea_opcvnt(6,5); BitDatos(&Datos,opcdata); cierra_v(5); break;] case3: */ Datos*/ 1 cierra-v(3); }while(opcl!=4); if ((Parity I Datos == OxOB) 1 Parity = 0x00; Datos = 0x02; 1 (Parity I Datos == OxlB)){ 1 . Settings = ( Bps I Parity I Parada I Datos );/"Codigo de Inicializacion*/ break; }/*case*/ case 1: { /" OPCION: MENU Transmision, recepcion */ do{ crear-v(6); activa-v(b); opc2=crea_opcvnt(2,6); switch(opc2)( case O: ( /" OPCION:Transmision deArchivos */ inicializaPuerto(COM1,Settings); crear~v(7); activa-v(7); gotoxy(1,l); cprintf("Nombre Archivo : "); cscanf("%s",archivoNom); mandArchivo(archivoNom); cierra-v(7); break;] case1: { /" OPCION:Recepcion deArchivos */ inicializaPuerto(COM1,Settings); crear~v(7); activa-v( 7); do{ gotoxy(13); cprintf(" Tipo Archivo: (T)exto, (B)inario: It); Tratmtisiórl /recepción de archivos entre cornputadoras (no) co~npntibles Proyecto Terminal I y I1 26 cscanf("%c",&TipoArchivo); TipoArchivo=toupper(TipoArchivo); }while (TipoArchivo!='T'&& TipoArchivo!='B'); clrscr(); recibeArchivo(TipoArchivo); cierra-v(7); break;} )/%witch()*/ cierra-v(b); ]while(opc2!=2); break; }/*case 1*/ case 2: /* OPCION: Ayuda */ { crear-v(1); activa-v(1); Ayuda(); /*Se encuentra en el archivo HelpTran.c*/ cierra-v(1); break; 1 1 cierra-v(2); }while(opc!=3); cierra-v(O); clrscr(); main() 1 I clrscr(); menues(); clrscr(); 7ralmzisiál~ /recepciórrde nrchivos entre cornplttndarns (110) corrlpntibles Proyecto Terminal I y I1 27 /*De acuerdo a la opcion seleccionada en la opción del menu: Baudios /+se asigna un valor equivalente en hexadecimal.Este valor forma parte del /*codigo de inicializacion del puerto serie Bauds ( Bps, selection ) int *Bps, selection; { switch ( selection ) { case O : *Bps = OxEO ; /* 9600 baudios */ break; case 1 : *Bps = OxCO ; /*4800 baudios */ break; case 2 : *Bps = OxAO ; / * 2400 baudios*/ break; case 3 : *Bps = Ox80 ; /* 1200 baudios */ break; case 4 : *Bps = 0x60 ; / * 600 baudios */ break; case 5 : *Bps = 0x40 ; /* 300 baudios */ break; case 6 : *Bps = 0x20 ; / * 150 baudios */ break; case 7 : *Bps = Ox00 ; /* 11O baudios */ break; /*De acuerdoa la opcionseleccionadaenlaopcióndel menu: Parada /*se asigna un valor equivalente en hexadecimal.Este valor forma parte del epuertoinicializacion del de/*codigo BitStop ( Parada, selection) int *Parada, selection; switch ( selection ) { case O : case 1 : 1 *I */ "I *Parada = Ox00 ; /*Un bit de fin de transmisión*/ break; *Parada = 0x04 ;/*Dos bits de fin de transmisión*/ break; 1 Trnrlslnisióll/recepciótl de archivos etltre comprrtadoras (110) corr~patibles Proyecto Terminal I y I1 28 /*De acuerdoa la opcionseleccionadaenlaopcióndelmenu:Paridad /*se asigna un valor equivalente en hexadecimal.Este valor forma parte del seriepuerto /*codigo inicializacion del de BitParity ( Parity, selection) int *Parity, selection; { switch ( selection ) { case O : case 1 : case 2 : */ */ *I *Parity = Ox00 ; /* Sin paridad*/ break; “Parity = Ox08 ; / * Desigual */ break; *Parity = Ox18 ; /* Imparcial */ break; /.De acuerdo a la opcion seleccionada en la opción del menu: Palabra*/ /,se asigna un valor equivalente en hexadecimal.Este valor forma parte del*/ serie /*codigo puerto inicializacion del de “1 BitDatos( Datos, selection) int *Datos, selection; { switch ( selection ) { case O : case 1 *Datos = 0x02 ; /*Siete bits de datos*/ break; *Datos = 0x03 ; /*Ocho bits de datos*/ break; Trurlsrnisiórl,’ recepciórl de nrchiuos erltre cotrryufndorns (110) corwpnfibles Proyecto Terminal I y I1 29 /* Transmite elarchivo especificado*/ void mandArchivo(archivoNom) char *archivoNom; { FILE *fp; char car; union( char c[2]; unsigned int contador; }contar; if ((fp = fopen(archivoNom,"rb")) == NULL){ gotoxy(L1); cprintf("1mposible abrir archivo: %s",archivoNom); delay(500); gotoxy(L1); cprintf(1inea); return; 1 mandaNomArchivo( archivoNom ); /*Envía el nombre del archivo*/ esperaRespuesta(puert0); /*Espera el reconocimiento del receptor*/ contar.contador = archivoTamano(fp); /*Se determina el tamaño del Archivo*/ mandaSerial(puert0, contar.c[O]); /*Envia lalongituddel archivo*/ esperaRespuesta(puert0); mandaSerial(puerto,contar.c[l]); /*Envia la longitud del archivo*/ do 1 car = getc (fp); if ( ferror(fp) ){ gotoxy(L1); cprintf("Error de lectura en el archivo."); delay(500); gotoxy(L1); cprintf(1inea); break; 1 /*Espera hasta que elreceptor esta preparado*/ if (!feof(fp))( esperaRespuesta(puert0); mandaSerial(puert0,car); 1 }while(!feof(fp)); esperaRespuesta(puert0); fclose(fp); /*Lee el último punto del puerto*/ Tmr~smisidrz/recepczdrlde archivos erltre corrrplrfadoras ( I Z O ) rorrrpatzbles Proyecto Terminal I y I1 30 PRecepcion deun archivo*/ void recibeArchivo(TipoArchivo) char TipoArchivo; FILE "fp; char car; char archivoNom[l4], GuardaDato[l50]; int cuenta=0; union{ char c[2]; unsigned int contador; }contar; memset(archivoNom,",14); memset(GuardaDato,",l50); recibeNomArchivo(archivoNom); /*Leenombre el del gotoxy(1,l); cprintf("E1archivo recibido es: % S ",archivoNom); remove(archivoNom); archivo*/ switch(TipoArchivo){ case 'B': 1 if ((fp = fopen (archivoNom, "wb"))== NULL){ gotoxy(L1); cprintf("1mposible abrir el archivo de salida"); delay(500); cprintf(1inea); return; 1 break; 1 case 'TI:{ if ((fp = fopen (archivoNom, "wt"))== NULL){ gotoxy(L1); cprintf("1mposible abrir el archivo de salida"); delay(500); cprintf(1inea); return; 1 break; 1 1 mandaSerial(puerto,'.'); contar.c[0] = recibeSerial(puert0); mandaSerial(puerto,'.'); contar.c[l] = recibeSerial(puert0); mandaSerial(puerto,'.'); Trarzsrnisiórr/ reccpciórr de archivos errtre corrrplrtadoras (no) corrrpatiblcs Proyecto Terminal I y I1 /* Lee longitud la del archivo*/ /* Lee lalongituddel archivo*/ 31 /, Escribe el contenido del archivo enviado */ for (;contar.contador; contar.contador--)( car = recibeSerial(puerto); /,Si es texto almacena datos en un arreglo GuardaDato[cuenta]=car; para disminuir el número de accesos a disco*/ switch(TipoArchivo)( case 'B': (putc (car, fp); /, Si es un archivo Binario*/ break;} case 'TI: /* Si es un archivo Texto*/ if ((contar.contador==l) II (car=='\nl) II (feof(fp))) { fputs(GuardaDat0,fp); cuenta=O; 1 else cuenta++; break; 1 1 if ( ferror(fp) ){ gotoxy(L1); cprintf("Error de escritura en el archivo."); delay(500); cprintf(1inea); return; } mandaSerial(puerto,'.'); /* Envia reconocimiento*/ 1 fclose(fp); 1 /,Determina la longitud del archivo unsigned int archivoTamano(fp) FILE *fp; { unsigned long inti; i = o., do { getc(fp); i++; }while (! feof(fp)); rewind(fp); return i - 1; /*No cuenta el caracter EOF*/ Trn~~sfnisidrr/recepciÓrr de nrchiuos entre compufndorns (m) corrrpnfibles Proyecto Terminal 1 y 11 32 /"Transmite el nombre delarchivo*/ void mandaNomArchivo(archivoNom) char *archivoNom; 1 gotoxy(1,l); cprintf("Transmision en espera..."); do { mandaSerial(puerto,'?'); ]while(!kbhit() && !(statusPuerto(puerto)& 256)); if (kbhit())( getch(); clrscr(); exit(1); I esperaRespuesta(puert0); /*Espera elreconocimientodel gotoxy(1,l); cprintf("Transmitiendo : %s",archivoNom); receptor*/ while (*archivoNom)( mandaSerial(puerto,*archivoNom++); esperaRespuesta(puert0); /"Espera el reconocimiento del receptor*/ I mandaSerial(puerto,'\O'); I /" Recibe el nombre del archivo */ void recibeNomArchivo(archivoNom) char *archivoNom; { gotoxy(L1); cprintf("Recepcion en espera..."); while(recibeSerial(puert0) != mandaSerial(puerto,'.'); /* Envia reconocimiento*/ el while (((*archivoNom = recibeSerial(puert0))) != NULL)( if (*archivoNom != archivoNom++; mandaSerial(puerto,'.'); /* Envia reconocimiento*/ el I?'); '?I)( I I 1 /" Revisa si se recibio elcaracter verificador, correcto.Dicho caracter es el"."*/ void esperaRespuesta(puert0) int puerto; { if (recibeSerial(puert0) != '.')( gotoxy(1,l); cprintf("Error de comunicación"); delay(500); exit(1); ] I Envía un caracter al puerto serial especificado y devuelve el estado de este.Antes de llamar a esta función,asegurese de usar Int 14/00 para preparar el puerto*/ /* void mandaSerial(puert0,car) int puerto; char car; union REGS inregs; inregs.x.dx = puerto; /*Puerto serie*/ /*Caracter a enviar*/ inregs.h.al = car; inregs.h.ah = 1; /*Función que envía un carácter*/ int86(0~14,&inregs,&inregs); if(inregs.h.ah & 128) [ /"Comprueba el bit 7.Si el bit 7=0 no hubo error*/ gotoxy(L1); cprintf("Error de transmisión en el puerto serie."); cprintf("%d",statusPuerto(puerto)); delay(500); gotoxy(1,l); 1 /* Lee un carácter del puerto serial especificado y devuelve el estado del puerto.Antes de llamar a esta función debe prepararse el puerto.*/ recibeSerial(puert0) int puerto; { union REGS inregs; /" Espera por el carácter*/ while (!(statusPuerto(puerto) & 256)) if (kbhit())( /" Termina si se pulsa una tecla*/ getch(); clrscr(); exit(1); } inregs.x.dx = puerto; /*Puerto Serie*/ inregs.h.ah = 2; /*Función de Lectura deun carácter*/ int86(0~14,&inregs,&inregs); if (inregs.h.ah & 128)( gotoxy(111); cprintf("Error de lectura en el puerto serie."); delay(500);) return inregs.h.al; 1 Trarwnisión / recepción de archivos entre conzprrtndoras (no) cornpntibles Proyecto Terminal I y I1 34 /"Revisa el estado del puertoserie*/ statusPuerto(puerto) int puerto; 1 I union REGS inregs; inregs.x.dx = puerto; inregs.h.ah = 3; int86(0x14, &inregs, &inregs); return inregs.x.ax; /* Inicialización del puertode comunicaciones serial */ void inicializapuerto(puerto,valor) int puerto; unsigned char valor; 1 union REGS inregs; integs.x.dx = puerto; /*puerto serie*/ inregs.h.ah. = O; /*Inicializa la función*/ inregs.h.al = valor; /*Código de Inicialización*/ int86(0~14,&inregs,&inregs); 1 Trarlsrnisiórr / recepciórl de archivos errtre computadoras (no) compntibles Proyecto Terminal I y I1 35 CONCLUSION. La transmisión / recepción de archivos entre dos computadoras compatibles solo es posible cuidando aspectos como la inicialización, sincronización, la revisión del estado del puerto, etc., Se observa además que es necesario elusode algoritmos para diálogo software, el presentado en este documento es solo una pequeña idea para tal acción, sin embargo dicho diálogo es el que nos permite trabajar de una forma sincronizada sin la necesidad de controlar el hardware. Transmisión / recepciórl de nrchiuos entre corrrprrtadoras (HO) corlrpatiblrs Proyecto Terminal I y I1 36 BITACORA. A continuación se presentan los diversos problemas que se presentaron durante el desarrollo del proyecto. SOLUCION No se conocen características de los uuertos No se reciben todoslos caracteres. (Sincronización) No transmite ni recibe. Uso de la aplicación NCC de Norton Utilities. Uso de Diálogo Software. Inicialmente se pensó que eran problemas debidos a la versión de DOS. Sin embargo estos se deben a la no adecuada inicialización del puerto. Se debe verificarque los puertos funcionen correctamente. 37 BIBLIOGRAFIA C, Guía para usuarios expertos. Osborne / McGraw-Hill. 1989. Schildt Herbert Trnrfsrrfisidtf/recepcidrl de archivos entre cornputadoras Proyecto Terminal I y I1 (110) cornpntibles 38 PARTE I11 = Programa de transmisión/recepción de archivos entre computadoras no compatibles Conclusión Bitácora 39 INTRODUCCION ~~ ~ ~~ ~~~ ~ ~ La computadora personal considerada en esta sección pertenece a la serie 9800 de la marca NEC, caracterizada por: a) No es compatible con una PC-IBM b) El diseño del hardware es diferente c) Utiliza una versión Kanji de MS-DOS d) La mayoría de los programas DOS no se ejecutan porque el BIOS es diferente e) Las principales diferencias en hardware son: reclado ’loppy Xsco Duro 3uertos Paraleloy Serial BIOS El tablero de una PC-9800 tiene teclas equivalentes con diferentes nombres y algunas adicionales no se localizanen un teclado compatible. Adicionalmente los códigos regresados a la unidad central son diferentes Los discos de 5 Y4 y 3 Y2 son utilizables. Puede accesar discos conformato norteamericano Soportadiscos duros; SASI,SCSI e IDE desde 20MB a 2GB. Cada PC-9800 incluye un puerto serial y uno paralelo. Sin embargo, pPC-9800 usa un dispositivo 8251AA como controlador mientras que un PC-IBM el estándar 8250 y 16450 ó 16550. Los registros de entrada - salida, deben de manejarse de forma diferente Las llamadas al BIOS son diferentes en el PC-9800. BIOS Interrupciones IBM-PC BIOS Nombre 0x09 & 0x16 Teclado Ox10 Video 0x13 Disco 0x14 Comunicación serial 0x15 Servicios 0x17 Impresora Trmsrrrisiórl,’ recepciórl de archivos errtrr corrrprrfndorns (110) cornpntibks Proyecto Terminal I y I1 Interrupciones PC-9800 BIOS OX18 0x18 OxlB 0x19 Varios OxlA 40 f) DOS. El DOS utilizado es una licencia OEM de Microsoft DOS,por lo que funciones como int21 y int2F se ejecutan sin problema alguno. Los comandos de DOS norteamericano son utilizables en el DOS-NEC, pero algunos tienen diferentes nombres, los cuales pueden ser consultados en el archivo comparativo proporcionado por NEC. g) Mapa Memoria. En la PC-9800 existen dos tipos de arquitectura, lade resolución normal y el modo de alta resolución, la diferencia entre éstas reside en el video y el mapa de memoria. El modo de alta resolución fue hecho para usos especiales (CAD), sin embargo, puede ser alcanzado usando un acelerador de gráficos sobre un modo de resolución normal. El mapa de memoria presenta las siguientes diferencias con una PC-IBM: oooo:oooo Vector Interrupción Vector Interrupción A400:OOOO , _, . _ " . ,._^,, ,, CG Window VGA Transruisiórl /recepridrr de archioos errtre cornputadoras Proyecto Terminal I y I1 Bios (110) corrlpntibles I/O 41 , CONSIDERACIONES Inicialización del puerto Antes de utilizar el puerto serie se inicializa con un parámetro que se codifica en dos bytes (una palabra) como se muestra a continuación: Número de bit Baudios Fin de transmisión Paridad Bits datos 8,9,10,11 67 4,5 32 La longitud de datos secodifica como se muestra en la siguiente tabla: O O 5 bit O 1 O 6 bit I ~rnrrsrrrisiórr/recepciórr de nrchivos etltre cornputndorns (110) cotrrpntlbles Proyecto Terminal I y I1 1 7 bit 1 I 18 bit 42 El número de continuación: bits de fin de transmisión se codifica como se muestra a O deshabilitado 1 2 bit 1 1.5 bit O 1 bit La velocidad de transmisión se codifica como se muestra en la siguiente tabla: I I I I I I I I BAUDIOS 9600 4800 2400 1200 600 300 150 75 Incorrecto I I I I I I I I Valores de bits 1000 0111 0110 o1o1 o1O0 O011 O010 O001 O000 I I I I I I I I Por ejemplo si se desea configurar el puerto a 1200 bps, fin de transmisión a 1 bit, con paridad par, verificación de paridad (ON), longitud dedatosde 8 bits y parámetro OFF, se utilizará el formato siguiente: Baudios : Fin transmisión : Paridad par : Verificación paridad : Longitud datos : Parámetro OFF : 0101 o1 1 1 11 O Trarfsrrrisiórl/recepciórl de archiuos eiltre corrrprltadorns (IKJ) corrrpntibles Proyecto Terminal I y I1 I; 43 Estado del puerto La verificacih condiciones: b=bii ___ b7 - b6 DSR SYN DET del puerto se realiza considerando cualquiera delas siguientes b5 FE b4 OE b3 PE 3 2 21 - TxE Rx RDY __ rx RDY I 1 1 1 1 1 1 1 SIGNIFICADO bO - 0:Envio Desocupado 1:Envio Ocupado 0:Recepción Desocupada 1:Recepción Ocupada O: Búfer de envío ocupado 1: Búfer de envío desocupado Error de paridad. O: Sin error de paridad 1 : Error de Daridad localizado Error de ejecución. O: Sin error 1: Error de ejecución localizado cuando el CPU no termina de leer el carácter actual antes del simiente Error válido solo en modo asincrono O: Sin error 1: Error localizado cuando el bit de fin de transmisión no es detectado al final Detección "break' O: OFF 1: ON O: DSR OFF 1: DSR ON Adicionalmente: a) Debe modificarse el archivo Config.sys, registrando : DEVICE = RSDRV.SYS b) Durante la inicialización se copiará el contenido de una dirección de memoria a otra: movedata(sseg, soff, dseg, doff, n) Sseg Soff Dseg Doff N Source segment Source offset Destination segment Destination offset Número de bytes c) Uso de versiones compatibles de MS-DOS y lenguaje C. Trunsmisiór~/recepciórc de archim~serctre cornpcttndorns ()IO) cotrrpafihles Proyecto Terminal I y I1 44 PROGRAMA TRANSMISION/RECEPCION DE DE ARCHIVOS ENTRE COMPUTADORAS NO COMPATIBLES. A continuación se lista el programa de transferencia de archivos, incluyendo las funciones necesarias. Tal como se muestra, se usa el puerto COMl (el primer puerto serie); sin embargo, se puede cambiar ladefinición del puerto. Programa para recepciónde datos binarios. /* * " " " " " " " " " " " " " " * Librería rs232c.h */ #include <stdio.h> #include <dos.h> union REGS inregs, outregs; struct SREGS segregs; /* Inicializa el puerto serial*/ rs-init(bandera) int bandera; { segread(&segregs); inregs.h.ah=O; movedata(segregs.ds,&bandera, 0x0060,0x0068,2); segregs.ds = 0x0060; int86x(Ox19,&inregs, &outregs, &segregs); 1 /* Verifica el estado del puerto */ stat2320 { inregs.h.ah = 3; segregs.ds = 0x0060; int86x(Ox19, &inregs, &outregs, &segregs); return(Ox00ff & 0utregs.h.d) 1 7rnnsrrrisión / recepciórl de arcl~ir~os erltre corrrplrtndorns (110) corrrpntibles Proyecto Terminal I y I1 45 /* Leer un carácter deRS-232C */ m-auxin() { return(bdos(3)); 1 /* Escribir un carácter enRS-232C */ m-auxout(c) char c; { I return(bdos(4,c)); /*Mandar señal "break"- break: ON */ breake-on() { 0utp(0x32,0x3f); 1 /*Regresar a condición normal*/ breake-off() { 0utp(0x32,0x37); 1 Trmsmisión / recepciórl de arcki7)osentre corrrplrtndoras (IZO) cornpatibles Proyecto Terminal I y I1 /'CPrograma para la recepción de datos binarios */ #include "rs232c.h" main(argc, argv) int argc; char *argv[]; { int c,s; FILE *fp; If ((fp=fopen(argv[l], "wb"))==NULL){ ptintf("No es posible abrirel archivo"); exit(); 1 rs-init(Ox087c); while (c=m-auxin(), ((s=stat232())&0~40)!=O Ox40){ printf(" %4x",c); putc(c,fp); 1 fclose(fp); 1 /"Programa para el envío dedatos binaries*/ #include "rs232c.h" main(argc, argv) int argc; char *argv[]; 1 int c,t; FILE *fp; If ((fp=fopen(argv[l], "rb))==NULL) { ptintf("No es posible abrirel archivo"); exit(); I rs-init(Ox087c); /,Inicialización del puerto*/ while ((c=getc(fp)) !=O EOF){ printf(" %4x",c); m-auxout(c); I I for (t=O; t<1000;t++); for (t=O; t<1000;t++) break-on(); break-off(); fclose(fp); /" Tiempo de espera */ 7ransmisiór~/recepción de archioos erltrc cornp~~tadoras (no) corrlpntibles Proyecto Terminal I y 11 47 CONCLUSION La transmisión / recepción de archivos entre dos computadoras no compatibles solose puede lograr considerando adicionalmente a los procesos involucrados (inicialización de puertos, sincronización, revisión del estado del puerto y algoritmos para el diálogo software), la compatibilidad de: a) Hardware con los estándares internacionales establecidos, b) Sistemas operativos, c) Lenguaje de programación d) Instrucciones, interrupciones y direcciones, así como pruebas de funcionamiento óptimo del equipo. La transmisión de los datos no se logró totalmente debido a fallas en la recepción, la causa a considerar es la no sincronización, a pesar de utilizar los parámetros indicados en el manual técnico del equipo, así como las instrucciones pertinentes. Se determinó que la versión del compilador no era la correcta y por el momento solo puede adquirirse en el país de origen del equipo (Asia). 48 BITACORA. A continuación se presentan los diversos problemas quese durante el desarrollo del proyecto. (Sincronización) Traducción de manuales Desconocimiento de comandos apropiados para su ejecución con el sistema operativo Bibliografía escasa I b) Verificación de versiones tanto del sistema operativo comodel lenguaje de programación Asignación de tiempo para traducción de manuales técnicos, ya que se encontraban en lapones Investigación de comandosnecesarios para el uso del sistema operativo (directamente) Localización de manuales técnicos y algunas fichas de información TrmsrnisiÓrl/ recepciórl de nrcllivos erltre colwpufadorns (110) corrrpntlbles Proyecto Terminal I y I1 presentaron 49 BIBLIOGRAFIA NEC PC - 9800, Manual Técnico. 1994 rrarlslrlisidrl/recepcidrz de nrchims erltre computadoros ( m )rorr~ptiblrs Proyecto Terminal I y I1 50