Difference between revisions of "Hardware Access/es"

From Free Pascal wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(33 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
{{Hardware Access}}
 
{{Hardware Access}}
__TOC__
+
[[category:Castellano]][[category:Español]]
==Overview==
+
 
 +
==Descripción==
  
 
Esta página es el comienzo de un tutorial que trata del acceso a dispositivos hardware. Estos dispositivos incluyen entre otros: ISA, PCI, USB, puerto paralelo, puerto serie, etc.
 
Esta página es el comienzo de un tutorial que trata del acceso a dispositivos hardware. Estos dispositivos incluyen entre otros: ISA, PCI, USB, puerto paralelo, puerto serie, etc.
Line 8: Line 9:
 
a hardware en las diferentes plataformas. El código puede ser compilado en diferentes entornos utilizando compilaciones condicionales, como las siguientes:
 
a hardware en las diferentes plataformas. El código puede ser compilado en diferentes entornos utilizando compilaciones condicionales, como las siguientes:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  uses
 
  uses
 
   Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
 
   Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
Line 17: Line 18:
 
   ports;
 
   ports;
 
  {$ENDIF}
 
  {$ENDIF}
</code>
+
</syntaxhighlight>
  
 
No se sabe todavía, hasta el momento, si MAC OS X/x86 permitirá el acceso hardware. Puede que lo permita, por lo que puede que con el tiempo aparezcan drivers como io.dll.
 
No se sabe todavía, hasta el momento, si MAC OS X/x86 permitirá el acceso hardware. Puede que lo permita, por lo que puede que con el tiempo aparezcan drivers como io.dll.
  
==Parallel and Serial Comparison==
+
==Comparación entre serie y paralelo==
  
 
Las tarjetas ISA, PCI y el puerto paralelo se comunican con el ordenador utilizando un protocolo
 
Las tarjetas ISA, PCI y el puerto paralelo se comunican con el ordenador utilizando un protocolo
Line 66: Line 67:
 
|}
 
|}
  
==Parallel Communication==
+
==Comunicación Paralelo==
 +
 
 +
===Usando inpout32.dll para Windows===
  
===Using inpout32.dll for Windows===
+
Windows tiene diferentes modos de acceder a los dispositivos hardware en las series 9x y NT. En las series 9x (95,98,Me) los programas pueden acceder al hardware directamente, al igual que se hacía en DOS. En las series NT (Windows NT y XP), no es posible tal acceso directamente, por lo que se hace necesario un driver de dispositivo que permita el acceso a los puertos como un mecanismo de seguridad. Esto ocasiona que el desarrollo de un driver implique un aumento significativo en costes y tiempo empleado.
Windows has different ways to access hardware devices on the 9x series and on the NT series. On the 9x series (95, 98, Me) programs can access the hardware directly, just like they did on DOS. The NT series (Windows NT and XP), however, don't allow this approach. On this architecture, all communication with hardware ports must be throught a device driver. This is a security mechanism, but developing a driver can cost too much in terms of time and money for small projects.
 
  
Happily there is a library that solves this problem. If Windows NT is detected, it decompresses HWInterface.sys kernel device driver and installs it. If Windows 9x is detected, it simply uses assembler opcodes to access the hardware.
+
Afortunadamente existe una librería que resuelve este problema. Si se detecta un sistema con Windows NT se descomprime un controlador de dispositivo del kernel (HWInterface.sys) y lo instala, mientras que si detecta un sistema Windows 9x, entonces simplemente utiliza código en ensamblador para acceder al hardware.
  
But how do I use the library? Simple! It has only two functions, Inp32 and Out32, and their use is quite intuitive.
+
Pero, ¿Como utilizo esta librería?, ¡Simple!, tiene solamente dos funciones, Inp32 y Out32, y su uso es muy intuitivo.
  
We will load the library dynamically, so let's define both functions first:
+
Cargaremos la libreria dinámicamente, por lo que definiremos ambas funciones primero:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  type
 
  type
 
   TInp32 = function(Address: SmallInt): SmallInt; stdcall;
 
   TInp32 = function(Address: SmallInt): SmallInt; stdcall;
 
   TOut32 = procedure(Address: SmallInt; Data: SmallInt); stdcall;
 
   TOut32 = procedure(Address: SmallInt; Data: SmallInt); stdcall;
</code>
+
</syntaxhighlight>
  
* Address represents the address of the port you desire to access
+
* Address representa la dirección del puerto que se desea acceder
* Out32 sends Data to the port you specify by Address
+
* Out32 envía datos al puerto que se especifica como dirección (Address)
* Inp32 returns a byte from the port you specify by Address
+
* Inp32 retorna un byte desde el puerto que se especifica como dirección (Address)
  
Now we can load the library. This can be implemented in a place like the OnCreate method of your program's main form:
+
Ahora ya podemos cargar la librería. Esto puede implementarse en una sección como por ejemplo en el método OnCreate dentro del form principal:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  type
 
  type
 
   TMyForm = class(TForm)
 
   TMyForm = class(TForm)
 
   .........
 
   .........
 
   private
 
   private
     { private declarations }
+
     { declaraciones privadas }
     Inpout32: THandle;
+
     Inpout32: THandle; { tipo manejador para el puerto }
 
     Inp32: TInp32;
 
     Inp32: TInp32;
 
     Out32: TOut32;
 
     Out32: TOut32;
Line 116: Line 118:
 
  {$ENDIF}
 
  {$ENDIF}
 
  end;
 
  end;
</code>
+
</syntaxhighlight>
  
If you load the library on OnCreate just don't forget to unload it in OnDestroy:
+
Si se carga la librería en la sección OnCreate no se debe olvidar descargarlo en la sección OnDestroy:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  procedure TMyForm.FormDestroy(Sender: TObject);
 
  procedure TMyForm.FormDestroy(Sender: TObject);
 
  begin
 
  begin
Line 127: Line 129:
 
  {$ENDIF}
 
  {$ENDIF}
 
  end;
 
  end;
</code>
+
</syntaxhighlight>
  
Here is a simple example of how to use Inp32 function:
+
Este es un simple ejemplo de como utilizar la función Inp32:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  {$IFDEF WIN32}
 
  {$IFDEF WIN32}
 
   myLabel.Caption := IntToStr(Inp32($0220));
 
   myLabel.Caption := IntToStr(Inp32($0220));
 
  {$ENDIF}
 
  {$ENDIF}
</code>
+
</syntaxhighlight>
  
This code was tested with a custom ISA card on port $0220, using Lazarus 0.9.10 on Windows XP. Of course you will need to have Windows on your uses clause in order for this code to run. For deployment you only need to include "inpout32.dll" in the same directory of our application.
+
Este código ha sido testeado con una tarjeta ISA en el puerto $0220, utilizando Lazarus 0.9.10 en Windows XP. Por supuesto es necesario tener Windows en la clausula uses para que funcione el código. Para el desarrollo solamente necesitas incluir "input32.dll" en el mismo directorio en que se encuentra la aplicación.
  
This is the homepage for the library: [http://www.logix4u.net/inpout32.htm www.logix4u.net/inpout32.htm]  *see discussion*
+
La página principal de esta librería se encuentra en: [http://www.logix4u.net/inpout32.htm www.logix4u.net/inpout32.htm]  *ver discusión*
  
 
===Using assembler on Windows 9x===
 
===Using assembler on Windows 9x===
  
On Windows 9x you can also use assembler code. Suppose you wish to write $CC to the $320 port. The following code will do it:
+
En Windows 9x se permite el acceso directo al hardware por lo que es posible utilizar código ensamblador para acceder al mismo. Supongamos que queremos escribir el valor $CC en el puerto $320. Lo podemos realizar con las siguientes líneas de código (este ejemplo utiliza la sintaxis ATT en lugar de la de Intel):
  
<code>
+
<syntaxhighlight lang=pascal>
 
  {$ASMMODE ATT}
 
  {$ASMMODE ATT}
 
  ...
 
  ...
Line 153: Line 155:
 
         outb %al, %dx
 
         outb %al, %dx
 
     end ['EAX','EDX'];
 
     end ['EAX','EDX'];
</code>
+
</syntaxhighlight>
  
===Troubleshooting on Windows===
+
===Resolución de problemas en Windows===
  
One possible source of trouble using parallel hardware that does not support Plug And Play on Windows is that Windows may assign the port utilized by your hardware to another device. You can find instructions on the URL below about how to tell Windows not to assign the address of your device to Plug And Play devices:
+
Una posible fuente de problemas al utilizar hardware paralelo que no soporta Plug&Play en Windows es que Windows puede asignar el puerto utilizado por el hardware a otro dispositivo. Puedes encontrar instrucciones en la siguiente URL, de como indicar a Windows que no asigne la dirección del disoositivo a dispositivos Plug&Play:
  
 
http://support.microsoft.com/kb/135168
 
http://support.microsoft.com/kb/135168
  
===Using ioperm to access ports on Linux===
+
===Utilizando ioperm para acceder puertos en Linux===
  
The best way to access the hardware on Linux is throught device drivers, but, due to the complexity of the task of creating a driver, sometimes a quick method is very useful.
+
La mejor manera de acceder al hardware en Linux es a través de drivers de dispositivos, pero, debido a la complejidad de crear un driver, algunas veces un método rápido es más útil.
  
In order to use the "[[doc:rtl/ports|ports]]" unit under Linux your program must be run as root, and IOPerm must be called to set appropriate permissions on the port access. You can find documentation about the "[[doc:rtl/ports|ports]]" unit [http://www.freepascal.org/docs-html/rtl/ports/index.html here].
+
En orden a usar la unit "[[doc:rtl/ports|ports]]" bajo Linux, el programa debe arrancarse como usuario root, y debe llamarse a IOPerm para establecer los permisos apropiados para acceso al puerto.
 +
Se puede encontrar documentación sobre la unit "[[doc:rtl/ports|ports]]" en la siguiente URL:
 +
[http://www.freepascal.org/docs-html/rtl/ports/index.html]  
  
The first thing to do is link to (g)libc and call IOPerm. A unit that links to the entire (g)libc exists on free pascal, but this unit gives problems when used directly by application and linking statically to the entire (g)libc library is not a very good idea because it changes often between version in an incompatible manner. Functions like ioperm, however, are unlikely to change.
+
Lo primero que debemos hacer es enlazar a (g)libc y llamar a IOPerm. En Free Pascal existe una unidad que enlaza enteramente a (g)libc, pero da lugar a problemas cuando se utiliza directamente por la aplicación y por tanto enlazarla estáticamente directamente a la librería (g)libc no es una buena idea porque siempre cambia de manera incomprensible entre versiones. Funciones como ioperm, como siempre, es poco probable que cambien.
  
<code>
+
<syntaxhighlight lang=pascal>
 
  {$IFDEF Linux}
 
  {$IFDEF Linux}
 
  function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
 
  function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
 
  {$ENDIF}
 
  {$ENDIF}
</code>
+
</syntaxhighlight>
  
* "from" represents the first port to be accessed.
+
* "from" representa el primer puerto a ser accedido.
* "num" is the number of ports after the first to be accessed, so ioperm($220, 8, 1) will give access for the program for all ports between and including $220 and $227.
+
* "num" es el número de puertos despueś de acceder al primero, por lo que ioperm($220, 8, 1) permitirá el accceso por parte del programa a todos los puertos entre $220 y $227, ambos inclusive.
  
After linking to IOPerm you can port[<Address>] to access the ports.
+
Después de enlazar a IOPerm se puede utiliar port[<Address>] para acceder a los puertos:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  {$IFDEF Linux}
 
  {$IFDEF Linux}
   i := ioperm($220, 8, 1);
+
   i := ioperm($220, 8, 1); { se enlaza IOPerm }
   port[$220] := $00;
+
   port[$220] := $00; { utilizamos port para escribir el valor $00 en el puerto $220 }
 
   myLabel.Caption := 'ioperm: ' + IntToStr(i);
 
   myLabel.Caption := 'ioperm: ' + IntToStr(i);
 
   i := Integer(port[$220]);
 
   i := Integer(port[$220]);
 
   myOtherLabel.Caption := 'response: ' + IntToStr(i);
 
   myOtherLabel.Caption := 'response: ' + IntToStr(i);
 
  {$ENDIF}
 
  {$ENDIF}
</code>
+
</syntaxhighlight>
  
This code was tested with a custom ISA card on port $0220, using Lazarus 0.9.10 on Mandriva Linux 2005 and Damn Small Linux 1.5
+
Este código fue testeado con una tarjeta ISA en el puerto $0220, utilizando Lazarus 0.9.10 en Mandriva Linux 2005 y Damn Small Linux 1.5.
  
===General UNIX Hardware Access===
+
===Acceso general a hardware en UNIX ===
  
 
<pre>
 
<pre>
Line 207: Line 211:
 
'''Note''' that FPC provides an abstraction for ioperm called "fpioperm" in [[doc:rtl/x86/index.html|unit x86]], and also defines out and inport functions. These functions are currently implemented for Linux/x86 and FreeBSD/x86.
 
'''Note''' that FPC provides an abstraction for ioperm called "fpioperm" in [[doc:rtl/x86/index.html|unit x86]], and also defines out and inport functions. These functions are currently implemented for Linux/x86 and FreeBSD/x86.
  
It is not recommended to link to libc unless absolutely necessary due to possible deployment and portability functions.
+
No se recomienda enlazar a libc a menos que sea absolutamente necesario debido a un posible diseño y
Also manual linking to libc (by declaring ad hoc libc imports for functions that are available elsewhere) like done above is not recommended  (e.g. the above libc import line will unnecessarily fail if the standard C lib is not called libc, like e.g. libroot on BeOS, or on platforms with a non standard C symbol mangling).
+
portabilidad de funciones.
 +
 
 +
Tampoco se recomienda el enlace manual a libc (declarando tal cual libc importado por funciones que son accesibles desde cualquier parte). Por ejemplo la línea de importación de libc fallará innecesariamente si la librería estandar no se llama desde libc, como por ejemplo libroot en BeOS, o en plataformas que no utilicen símbolos C estandar).
  
'''Note 2''' Using _unit_ libc is not recommended under any circumstances other than Kylix compability. This because the unit is relatively unportable (due to excessive exposure of structures and other private symbols) and must only be modified as little as possible out of Kylix compability issues.
+
'''Note 2''' Utilizar la unidad _unit_ libc no es recomendable bajo ninguna circunstancia salvo para compatibilidad con Kylix. Esto es debido a que esta unidad es relativamente poco portable (debido a la excesiva exposición de estructuras y otros símbolos privados) y debe modificarse solamente tan poco como sea posible fuera de lo que implique su compatibilidad con Kylix.
  
==Serial Communication==
+
==Comunicación Serie==
  
The [[Hardware Access#External Links | External Links]] section has UNIX and Windows serial port tutorials.
+
La sección [[Hardware Access#External Links | External Links]] tiene tutoriales para puertos serie bajo UNIX y Windows.
  
 
==USB==
 
==USB==
Line 220: Line 226:
 
===libusb===
 
===libusb===
  
A cross platform possibility for Linux, BSDs and Mac OS X is [http://libusb.sourceforge.net/ libusb].
+
Una posibilidad para múltiples plataformas, para Linux, BSDs y Mac OS X es [http://libusb.sourceforge.net/ libusb].
  
Headers are listed in http://www.freepascal.org/contrib/db.php3?category=Miscellaneous:
+
Las cabeceras se listan en http://www.freepascal.org/contrib/db.php3?category=Miscellaneous:
  
 
{|cellpadding="4"
 
{|cellpadding="4"
 
|-
 
|-
! name !! author !! version !! date !! link !! remarks
+
! Nombre !! Autor !! Versión !! Fecha !! Enlace !! Aclaraciones
 
|-
 
|-
 
| libusb.pp || nowrap | Uwe Zimmermann || 0.1.12 || nowrap | 2006-06-29 || http://www.sciencetronics.com/download/fpc_libusb.tgz ||  
 
| libusb.pp || nowrap | Uwe Zimmermann || 0.1.12 || nowrap | 2006-06-29 || http://www.sciencetronics.com/download/fpc_libusb.tgz ||  
Line 232: Line 238:
 
| libusb.pas || Johann Glaser ||  || nowrap | 2005-01-14 || http://www.johann-glaser.at/projects/libusb.pas ||  
 
| libusb.pas || Johann Glaser ||  || nowrap | 2005-01-14 || http://www.johann-glaser.at/projects/libusb.pas ||  
 
|-
 
|-
| fpcusb || Joe Jared || 0.11-14 || nowrap | 2006-02-02 || http://relays.osirusoft.com/fpcusb.tgz || nowrap | download link broken
+
| fpcusb || Joe Jared || 0.11-14 || nowrap | 2006-02-02 || http://relays.osirusoft.com/fpcusb.tgz || nowrap | enlace de descarga roto
 
|}
 
|}
  
 
===FTDI===
 
===FTDI===
  
If you use one of the chips from [http://www.ftdichip.com/ FTDI], you can use their pascal headers for their dll interface to the chips.
+
Si utilizas uno de los circuitos integrados (IC o chips) listados en  [http://www.ftdichip.com/ FTDI], puedes utilizar sus cabeceras pascal para el interface dllcon los chips.
  
==External Links==
+
==Enlaces externos==
  
Communication Protocols speed comparison:
+
Comparación de velocidades para protocolos de comunicación:
  
 
# http://en.wikipedia.org/wiki/Serial_port#Speed
 
# http://en.wikipedia.org/wiki/Serial_port#Speed
Line 248: Line 254:
 
# http://en.wikipedia.org/wiki/PCI#Conventional_PCI_bus_specifications
 
# http://en.wikipedia.org/wiki/PCI#Conventional_PCI_bus_specifications
  
Serial Communication Links:
+
Enlaces de comunicación serie:
  
# On UNIX: [http://www.easysw.com/~mike/serial/serial.html]
+
# Bajo UNIX: [http://www.easysw.com/~mike/serial/serial.html]
# On Windows: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp
+
# Bajo Windows: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp
# Synaser component: http://synapse.ararat.cz/
+
# Componente Synaser: http://synapse.ararat.cz/
 
# Comport Delphi package: http://sourceforge.net/projects/comport/
 
# Comport Delphi package: http://sourceforge.net/projects/comport/
  
ISA Digital Oscilloscope - A example of hardware access with full source included:
+
Osciloscopio Digital ISA - Un ejemplo de acceso a hardware con todo el código fuente incluido:[http://eletronicalivre.incubadora.fapesp.br/portal/english/oscilloscope/]
 
 
[http://eletronicalivre.incubadora.fapesp.br/portal/english/oscilloscope/]
 

Latest revision as of 13:18, 16 February 2020

Deutsch (de) English (en) español (es) français (fr) magyar (hu) 日本語 (ja) 한국어 (ko) polski (pl) português (pt) русский (ru) slovenčina (sk) 中文(中国大陆)‎ (zh_CN)

Descripción

Esta página es el comienzo de un tutorial que trata del acceso a dispositivos hardware. Estos dispositivos incluyen entre otros: ISA, PCI, USB, puerto paralelo, puerto serie, etc.

El acceso a dispositivos hardware no esta implementado en la modalidad multiplataforma ni para el Runtime ni para el LCL de Free Pascal, por lo que este tutorial básicamente cubrirá los métodos de acceso a hardware en las diferentes plataformas. El código puede ser compilado en diferentes entornos utilizando compilaciones condicionales, como las siguientes:

 uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
 {$IFDEF WIN32}
   Windows;
 {$ENDIF}
 {$IFDEF Unix}
   ports;
 {$ENDIF}

No se sabe todavía, hasta el momento, si MAC OS X/x86 permitirá el acceso hardware. Puede que lo permita, por lo que puede que con el tiempo aparezcan drivers como io.dll.

Comparación entre serie y paralelo

Las tarjetas ISA, PCI y el puerto paralelo se comunican con el ordenador utilizando un protocolo paralelo. El puerto serie y los dispositivos USB en cambio con un protocolo serie. Como tanto el procesador como todos los lenguajes de programación trabajan en una aproximación a datos en paralelo, el acceso a esta clase de protocolos es más fácil de implementar en la parte software. Por ejemplo, cuando se accede a una variable de tipo entero (Integer), es posible acceder a su valor asociado con un simple mandato. Con un protocolo serie, sin embargo, se puede conocer sólamente un bit en cada vez, y se hace necesario unir todos los bits para tener un dato con significado.

La comunicación serie es difícil de implementar directamente, pero puede resultar razonablemente sencillo si se utiliza un componente prediseñado. También se bastante difícil en la parte hardware, por lo que algunos dispositivos utilizan Cirtuitos Integrados especializados o incluso Microcontroladores para implementarlo.

A continuación se presenta una breve comparación de protocolos de acceso a hardware:


Velocidad Dificultad de implementación hardware
Puerto serie Muy lenta (< E5 bit/s) Media
Puerto Paralelo Lenta (~ E6 bit/s) Sencilla
Tarjeta ISA Media (~ E7 bit/s) Media
USB Media (~ E7 bit/s) Laboriosa
Tarjeta PCI Muy rápida (> E9 bit/s) Muy laboriosa

Comunicación Paralelo

Usando inpout32.dll para Windows

Windows tiene diferentes modos de acceder a los dispositivos hardware en las series 9x y NT. En las series 9x (95,98,Me) los programas pueden acceder al hardware directamente, al igual que se hacía en DOS. En las series NT (Windows NT y XP), no es posible tal acceso directamente, por lo que se hace necesario un driver de dispositivo que permita el acceso a los puertos como un mecanismo de seguridad. Esto ocasiona que el desarrollo de un driver implique un aumento significativo en costes y tiempo empleado.

Afortunadamente existe una librería que resuelve este problema. Si se detecta un sistema con Windows NT se descomprime un controlador de dispositivo del kernel (HWInterface.sys) y lo instala, mientras que si detecta un sistema Windows 9x, entonces simplemente utiliza código en ensamblador para acceder al hardware.

Pero, ¿Como utilizo esta librería?, ¡Simple!, tiene solamente dos funciones, Inp32 y Out32, y su uso es muy intuitivo.

Cargaremos la libreria dinámicamente, por lo que definiremos ambas funciones primero:

 type
   TInp32 = function(Address: SmallInt): SmallInt; stdcall;
   TOut32 = procedure(Address: SmallInt; Data: SmallInt); stdcall;
  • Address representa la dirección del puerto que se desea acceder
  • Out32 envía datos al puerto que se especifica como dirección (Address)
  • Inp32 retorna un byte desde el puerto que se especifica como dirección (Address)

Ahora ya podemos cargar la librería. Esto puede implementarse en una sección como por ejemplo en el método OnCreate dentro del form principal:

 type
   TMyForm = class(TForm)
   .........
   private
     { declaraciones privadas }
     Inpout32: THandle;  { tipo manejador para el puerto }
     Inp32: TInp32;
     Out32: TOut32;
   .........
 implementation
   .........
 procedure TMyForm.FormCreate(Sender: TObject);
 begin
 {$IFDEF WIN32}
   Inpout32 := LoadLibrary('inpout32.dll');
   if (Inpout32 <> 0) then
   begin
     // needs overtyping, plain Delphi's @Inp32 = GetProc... leads to compile errors
     Inp32 := TInp32(GetProcAddress(Inpout32, 'Inp32'));
     if (@Inp32 = nil) then Caption := 'Error';
     Out32 := TOut32(GetProcAddress(Inpout32, 'Out32'));
     if (@Out32 = nil) then Caption := 'Error';
   end
   else Caption := 'Error';
 {$ENDIF}
 end;

Si se carga la librería en la sección OnCreate no se debe olvidar descargarlo en la sección OnDestroy:

 procedure TMyForm.FormDestroy(Sender: TObject);
 begin
 {$IFDEF WIN32}
   FreeLibrary(Inpout32);
 {$ENDIF}
 end;

Este es un simple ejemplo de como utilizar la función Inp32:

 {$IFDEF WIN32}
   myLabel.Caption := IntToStr(Inp32($0220));
 {$ENDIF}

Este código ha sido testeado con una tarjeta ISA en el puerto $0220, utilizando Lazarus 0.9.10 en Windows XP. Por supuesto es necesario tener Windows en la clausula uses para que funcione el código. Para el desarrollo solamente necesitas incluir "input32.dll" en el mismo directorio en que se encuentra la aplicación.

La página principal de esta librería se encuentra en: www.logix4u.net/inpout32.htm *ver discusión*

Using assembler on Windows 9x

En Windows 9x se permite el acceso directo al hardware por lo que es posible utilizar código ensamblador para acceder al mismo. Supongamos que queremos escribir el valor $CC en el puerto $320. Lo podemos realizar con las siguientes líneas de código (este ejemplo utiliza la sintaxis ATT en lugar de la de Intel):

 {$ASMMODE ATT}
 ...
    asm
        movl $0x320, %edx
        movb $0xCC, %al
        outb %al, %dx
    end ['EAX','EDX'];

Resolución de problemas en Windows

Una posible fuente de problemas al utilizar hardware paralelo que no soporta Plug&Play en Windows es que Windows puede asignar el puerto utilizado por el hardware a otro dispositivo. Puedes encontrar instrucciones en la siguiente URL, de como indicar a Windows que no asigne la dirección del disoositivo a dispositivos Plug&Play:

http://support.microsoft.com/kb/135168

Utilizando ioperm para acceder puertos en Linux

La mejor manera de acceder al hardware en Linux es a través de drivers de dispositivos, pero, debido a la complejidad de crear un driver, algunas veces un método rápido es más útil.

En orden a usar la unit "ports" bajo Linux, el programa debe arrancarse como usuario root, y debe llamarse a IOPerm para establecer los permisos apropiados para acceso al puerto. Se puede encontrar documentación sobre la unit "ports" en la siguiente URL: [1]

Lo primero que debemos hacer es enlazar a (g)libc y llamar a IOPerm. En Free Pascal existe una unidad que enlaza enteramente a (g)libc, pero da lugar a problemas cuando se utiliza directamente por la aplicación y por tanto enlazarla estáticamente directamente a la librería (g)libc no es una buena idea porque siempre cambia de manera incomprensible entre versiones. Funciones como ioperm, como siempre, es poco probable que cambien.

 {$IFDEF Linux}
 function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
 {$ENDIF}
  • "from" representa el primer puerto a ser accedido.
  • "num" es el número de puertos despueś de acceder al primero, por lo que ioperm($220, 8, 1) permitirá el accceso por parte del programa a todos los puertos entre $220 y $227, ambos inclusive.

Después de enlazar a IOPerm se puede utiliar port[<Address>] para acceder a los puertos:

 {$IFDEF Linux}
   i := ioperm($220, 8, 1); { se enlaza IOPerm }
   port[$220] := $00; { utilizamos port para escribir el valor $00 en el puerto $220 }
   myLabel.Caption := 'ioperm: ' + IntToStr(i);
   i := Integer(port[$220]);
   myOtherLabel.Caption := 'response: ' + IntToStr(i);
 {$ENDIF}

Este código fue testeado con una tarjeta ISA en el puerto $0220, utilizando Lazarus 0.9.10 en Mandriva Linux 2005 y Damn Small Linux 1.5.

Acceso general a hardware en UNIX

{$IFDEF Unix}
Uses Clib;   // retrieve libc library name.
{$ENDIF}

{$IFDEF Unix}
function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external clib;
{$ENDIF}


Note that FPC provides an abstraction for ioperm called "fpioperm" in unit x86, and also defines out and inport functions. These functions are currently implemented for Linux/x86 and FreeBSD/x86.

No se recomienda enlazar a libc a menos que sea absolutamente necesario debido a un posible diseño y portabilidad de funciones.

Tampoco se recomienda el enlace manual a libc (declarando tal cual libc importado por funciones que son accesibles desde cualquier parte). Por ejemplo la línea de importación de libc fallará innecesariamente si la librería estandar no se llama desde libc, como por ejemplo libroot en BeOS, o en plataformas que no utilicen símbolos C estandar).

Note 2 Utilizar la unidad _unit_ libc no es recomendable bajo ninguna circunstancia salvo para compatibilidad con Kylix. Esto es debido a que esta unidad es relativamente poco portable (debido a la excesiva exposición de estructuras y otros símbolos privados) y debe modificarse solamente tan poco como sea posible fuera de lo que implique su compatibilidad con Kylix.

Comunicación Serie

La sección External Links tiene tutoriales para puertos serie bajo UNIX y Windows.

USB

libusb

Una posibilidad para múltiples plataformas, para Linux, BSDs y Mac OS X es libusb.

Las cabeceras se listan en http://www.freepascal.org/contrib/db.php3?category=Miscellaneous:

Nombre Autor Versión Fecha Enlace Aclaraciones
libusb.pp Uwe Zimmermann 0.1.12 2006-06-29 http://www.sciencetronics.com/download/fpc_libusb.tgz
libusb.pas Johann Glaser 2005-01-14 http://www.johann-glaser.at/projects/libusb.pas
fpcusb Joe Jared 0.11-14 2006-02-02 http://relays.osirusoft.com/fpcusb.tgz enlace de descarga roto

FTDI

Si utilizas uno de los circuitos integrados (IC o chips) listados en FTDI, puedes utilizar sus cabeceras pascal para el interface dllcon los chips.

Enlaces externos

Comparación de velocidades para protocolos de comunicación:

  1. http://en.wikipedia.org/wiki/Serial_port#Speed
  2. http://www.lvr.com/jansfaq.htm - Jan Axelson's Parallel Port FAQ
  3. http://en.wikipedia.org/wiki/USB#Transfer_Speed
  4. http://en.wikipedia.org/wiki/PCI#Conventional_PCI_bus_specifications

Enlaces de comunicación serie:

  1. Bajo UNIX: [2]
  2. Bajo Windows: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp
  3. Componente Synaser: http://synapse.ararat.cz/
  4. Comport Delphi package: http://sourceforge.net/projects/comport/

Osciloscopio Digital ISA - Un ejemplo de acceso a hardware con todo el código fuente incluido:[3]