Interfaces


Introducción
 Interfaz.
Conexión e interacción entre hardware, software y el usuario. El diseño y construcción de interfaces constituye una parte principal del trabajo de los ingenieros, programadores y consultores. Los usuarios “conversan” con el software. El software “conversa” con el hardware y otro software. El hardware “conversa” con otro hardware. Todo este “diálogo” no es más que el uso de interfaces. Las interfaces deben diseñarse, desarrollarse, probarse y rediseñarse; y con cada encarnación nace una nueva especificación que puede convertirse en un estándar más, de hecho o regulado.
1

5.1 Conceptos básicos

Interfaz: dispositivo electrónico que se conecta entre el PC y los elementos a ser controlados (actuadores, interruptores, pulsadores, relés, circuitos, motores, etc.).Su misión es garantizar el correcto aislamiento eléctrico entre los puertos del PC y los dispositivos externos.

Bus: Normalmente se refiere al conjunto de señales con las que se comunica el microprocesador con el entorno: memoria o periféricos (a través de las interfaces).:
Figura 1. Representación lógica de una interfaz
Las funciones más importantes de un interfaz son:

Interpretar las órdenes que recibe de la CPU y transmitirlas al periférico

Controlar las transferencias de datos entre la CPU y el periférico (convertir formatos, adaptar velocidades,..).

Informar a la CPU del estado del periférico.

Detección de errores (defectos mecánicos o eléctricos en el funcionamiento del dispositivo. Ejemplos: atasco de papel, cambio de un bit, etc.)Los interfaces también se denominan controladores, interfaces o tarjetas de E/S.
2

5.2 Clasificación
En una primera aproximación, los puertos y los interfaces del computador se pueden clasificar en función del tipo de transmisión de información que permitan:


Serie

Puerto serie: Interfaz RS-232.

Puerto/interfaz USB.

Puerto Fire Wire: Interfaz IEEE1394.

Paralela

Puerto paralelo: Interfaz Centronics ó IEEE 1284.



De igual forma, las interfaces que interrelacionan en el diálogo entre usuario-máquina son periféricos que se pueden clasificar según el sentido de la comunicación:
 Dispositivos de entrada: usuario-Máquina.
 Los dispositivos de entrada son los que se utilizan para introducir información en el ordenador. Los sensores del dispositivo transforman la información en señales físicas que envían a un controlador o programa del sistema operativo para su interpretación.


Los dispositivos de entrada más populares son: teclados, ratones, escáneres, micrófonos, cámaras, monitores táctiles, joysticks, lectores de tarjetas, códigos de barras, etc.

 Dispositivos de salida: máquina-usuario
Los dispositivos de salida son los que generan, a partir de una orden de un usuario, unidades de significado mediante formas y símbolos empleados en la representación gráfica de la información, o el sonido en el caso de la representación auditiva. Los dispositivos de salida más populares son: monitores, impresoras, altavoces, cascos, etc.


5.3 Programación de bajo nivel
Lenguaje de bajo nivel Un lenguaje de programación de bajo nivel es el que proporciona poca o ninguna abstracción del microprocesador de un ordenador. Consecuentemente es fácilmente trasladado a lenguaje de máquina. La palabra "bajo" no implica que el lenguaje sea inferior a un lenguaje de alto nivel; se refiere a la reducida abstracción entre el lenguaje y el hardware.

Perifericos

El modelo de Entrada/Salida de UNIX/Linux

UNIX supuso una revolucion por muchas razones. Sin embargo, una de las mas importantes fue, sin duda, su modelo de Entrada/Salida. En UNIX, los perifericos se encuentran representados como simples ficheros del sistema de archivos. De esta forma, si se quiere enviar datos a, por ejemplo, la pantalla, basta con abrir el fichero asociado a ella y escribir con las funciones de siempre. El resultado aparecera en el monitor. Lo mismo ocurre con los puertos serie, paralelo, etc.
El hecho de que se acceda a todos los perifericos de igual forma simplifica notablemente la programacion en un sentido, pues el programador no necesita aprender cientos de funciones especificas para cada dispositivo, y a fin de cuentas, en el 99% de los casos no se pretende hacer filigranas con los perifericos, sino simplemente enviar algo y nada mas. Sin embargo ¿que ocurre cuando sí hace falta enviar opciones especificas a un dispositivo? ¿Que hago para indicar, por ejemplo, la velocidad de transmisión de un puerto serie, o las coordenadas de impresion si se trata de un adaptador de video?

La funcion IOCTL

Todo driver soporta una serie de funciones basicas. En concreto ha de soportar: apertura, lectura, escritura y cierre. Estas funciones (junto a alguna que otra mas) son las que permiten acceder a los dispositivos como si de ficheros se tratara. Sin embargo, existe una quinta funcion que nos permite enviar comandos especificos para cada periferico. Es la funcion IOCTL (Input/Output ConTroL).
Esta funcion recibe tres parametros y devuelve uno:
               #include <sys/ioctl.h>
 
               int ioctl(int d, int request, void *arg);
El primer parametro (d) es un identificador de dispositivo. Puesto que se trata de una variable de tipo int y no de tipo FILE, el fichero del dispositivo ha de abrirse usando la funcion open() en lugar de fopen(). Por la misma razon, para leer o escribir en el ha de usarse read() y write() en vez de fread() o fwrite(), y para cerrarlo se usara close() en vez de fclose(). Como siempre, una mirada a las paginas del manual resolveran cualquier duda sobre estas cuatro funciones.
El segundo parametro (request) especifica el comando que se ha de enviar al dispositivo. Estos comandos dependen del periferico con el que se este tratando. Asi pues, el comando 1 hara cosas distintas si lo enviamos a un puerto serie o a uno paralelo.
El tercer parametro (arg) es siempre un puntero al/los parametros que se le han de pasar al driver, o bien en donde ha de retornar este los resultados. Como tipo de puntero he puesto void simplemente porque dependiendo del comando que se envie habra que poner un puntero a int, a char, o incluso a una estructura.
Por ultimo, ioctl() nos devuelve un valor que sera cero si la funcion se ha ejecutado con exito, o -1 si ha habido algun problema. En este caso, el tipo de error lo podremos ver en la variable global errno (para ello no hay que olvidarse de hacer un #include <errno.h> al principio del codigo).

El puerto serie

Los puertos serie tienen asociados una serie de ficheros en el directorio /dev. En versiones antiguas de Linux estos eran los ficheros
/dev/cua
seguidos de un numero que especificaba que puerto era cada uno. Asi pues, /dev/cua0 seria el COM1 de MS-DOS.
En las versiones mas recientes del nucleo (versiones 2.x) los puertos serie tienen asociados los ficheros
/dev/ttyS
seguidos tambien de un numero. Asi pues, /dev/ttyS0 es el COM1 de MS-DOS. Por razones de compatibilidad con viejos programas, se siguen soportando los viejos ficheros cua, pero no se recomienda su uso en programas nuevos.

Cambiando los permisos de acceso

Para poder acceder a un periferico es preciso que su fichero asociado tenga permisos de acceso adecuados, igual que ocurre con el resto de los ficheros normales del disco duro. Puesto que el dueño de los ficheros de dispositivo es el usuario root, es necesario hacer el cambio entrando como el. Asi, para permitir que cualquiera pueda leer y escribir en cualquier puerto serie, se debe hacer (siempre como root):
chmod 666 /dev/ttyS*
Si se quiere permitir que cualquiera acceda al segundo puerto serie, se hara:
chmod 666 /dev/ttyS1

¿De que entradas y salidas dispongo?

Un puerto serie dispone de los siguientes pines, cuyo numero en el conector es el siguiente:
 Nombre   Sentido    Conector 25 pines    Conector 9 pines
 
  TXD     salida            2                  3
  RXD     entrada           3                  2
  RTS     salida            4                  7
  CTS     entrada           5                  8
  DTR     salida           20                  4
  DSR     entrada           6                  6
  DCD     entrada           8                  1
  RI      entrada          22                  9
  GND     masa              7                  5
TXD y RXD son respectivamente la salida y la entrada de datos serie. Estos datos se envian en el siguiente formato:
Por defecto, TXD se encuentra a -12 voltios (nivel alto). Cuando se quiere enviar un byte, la linea se pone a 12 voltios (nivel bajo) durante el tiempo de un bit. Es el bit de inicio, que marca el comienzo de una transmision. A continuacion se envian los bits del dato, empezando por el menos significativo. El cero (nivel bajo) se representa con 12 voltios, y el uno (nivel alto) se representa con -12 voltios. Por ultimo se envian uno o dos bits de parada a -12 voltios (nivel alto) antes de iniciar la transmision del siguiente.
Vemos que los niveles de tension se encuentran invertidos con respecto a lo que cabria esperar (el 0 son 12 voltios y el 1 son -12 voltios). Esto solo ocurre en estas dos lineas. En el resto, el cero son -12 voltios y el uno son 12.
Todas las lineas estan limitadas en corriente a unos 200mA. Esto protege al puerto en caso de que ocurra cualquier cortocircuito. Esta caracteristica tambien es aprovechada por muchos circuitos simples que se conectan al puerto serie, de modo que se consigue una notable economia de componentes.
Debido a que las lineas TXD y RXD son controladas por el propio puerto serie y no por el procesador, en principio no resulta posible indicar directamente un valor de tension en TXD o leer el que se encuentre en RXD. Todo lo que podemos hacer es enviar un byte al puerto para que este lo envie por si mismo en el formato indicado. Sin embargo, en la practica, las UARTs disponen de un bit que, al activarlo, fuerzan un cero (+12 voltios) en dicho pin.

Funciones IOCTL disponibles para el puerto serie

Seis son las funciones ioctl que nos interesan para el control de las lineas del puerto serie: TIOCMGET, TIOCMBIS, TIOCMBIC, TIOCMSET, TIOCSBRK y TIOCCBRK. Para disponer de estas definiciones es necesario hacer:
               #include <asm/ioctls.h>
La funcion TIOCMGET precisa que se le pase un puntero a int como argumento de la funcion ioctl(). Asi pues, hariamos:
               retorno=ioctl(fichero,TIOCMGET,);
En 'argumento' nos almacenara un patron de bits indicando el estado de las distintas entradas y salidas del puerto serie.
La funcion TICMBIS tambien precisa de un puntero a int como argumento de la funcion ioctl(). Asi pues:
               retorno=ioctlfichero,TIOCMBIS,);
activara aquellas salidas que le indiquemos, dejando inalteradas el resto. Por su parte, la funcion TICMBIC hace lo contrario: desactiva (pone a cero) las salidas que le indiquemos, sin modificar el resto. La usariamos asi:
               retorno=ioctlfichero,TIOCMBIC,);
La funcion TIOCMSET activa las salidas que le indiquemos y desactiva el resto. Precisa tambien un puntero a int como argumento de la funcion ioctl(). Asi pues:
               retorno=ioctl(fichero,TIOCMSET,);
activara las salidas que le indiquemos en funcion del patron de bits que contenga 'argumento'.
El bit que corresponde a cada entrada y salida viene definido tambien en el fichero ioctl-types.h. Este fichero se incluye automaticamente con ioctl.h.
En concreto, estan las definiciones:
               TIOCM_DTR   DTR    0x002
               TIOCM_RTS   RTS    0x004
               TIOCM_CTS   CTS    0x020
               TIOCM_CAR   DCD    0x040
               TIOCM_CD    DCD    0x040
               TIOCM_RNG   RI     0x080
               TIOCM_RI    RI       0x080
               TIOCM_DSR   DSR    0x100
Por ultimo, las funciones TIOCSBRK y TIOCCBRK permiten poner a cero (+12 volts) o devolver al estado normal, respectivamente, el pin TXD. Como dicho estado de reposo es un uno, estas funciones nos permiten controlar a voluntad dicha salida.
               retorno=ioctl(fichero,TIOCSBRK,);
               retorno=ioctl(fichero,TIOCCBRK,);
El puntero no es modificado, por lo que se puede dar cualquiera.
Por supuesto, existen otras muchas funciones IOCTL para el puerto serie (man ioctl-list), pero todo lo que se puede hacer con ellas tambien resulta factible hacerlo con la libreria TERMIOS.

No hay comentarios:

Publicar un comentario