Hardware Access/hu

From Free Pascal wiki
Jump to: navigation, search

Deutsch (de) | English (en) | Español (es) | Français (fr) | Magyar (hu) | 日本語 (ja) | 한국어 (ko) | Polski (pl) | Português (pt) | Русский (ru) | ‪中文(中国大陆)‬ (zh_CN)


Hardver hozzáférés


Contents

Áttekintés

Ezen az oldalon a hardverek Lazarus által megvalósítható eléréséről olvashatsz. Ezek az eszközök a következők: ISA, PCI, USB, párhuzamos port, soros port, stb.

Egységes több-platformos elérés a hardver eszközökhöz nincs kidolgozva a Free Pascal Runtime Library-ban vagy az LCL-ben. Ezért ez az oldal megpróbálja összefoglalni a hardverek elérésének módjait különböző platformokon. A kód lefordítható különböző környezetekben a feltételes fordítási lehetőséget használva, így:

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


Jelenleg nem ismert hogy a Mac OS X/x86 engedi-e a hardverek elérését. Mivel megakadályozhatja, ezért javaslom olyan driver-ek használatát mint az io.dll.

Párhuzamos és Soros kommunikáció összehasonlítása

Az ISA kártyák, a PCI kártyák és a Parallel Port a számítógéppel párhuzamos protokollal kommunikál. A Serial Port és az USB eszközök soros protokolt használnak. Mivel a processzor és így a programozási nyelvek is az adatok elérésének párhuzamos módját alkalmazzák, ezért e protokolok használata jóval egyszerűbb a szoftverekben. Amikor egy Integer típusú változót kezelsz, annak értékét egyetlen utasítással elérheted. A soros protokollal azonban egyszerre csak egy bitet szerezhetsz meg, és ezt követően össze kell fűznöd azokat hogy megismerd a tényleges adatot.

A soros kommunikációt bonyolultabb kidolgozni, de viszonylag egyszerű ha egy előre elkészített komponenst használsz. A hardver oldalán is nehéz a megvalósítás, ezért sok hardver speciális integrált áramköröket vagy mikrokontrollereket tartalmaz erre a célra.

Íme egy összefoglaló táblázat a hardver hozzáférési protokolokról:

Sebesség Hardver kialakítás nehézsége
Serial Port Nagyon lassú (< E5 bit/s) Közepes
Parallel Port Lassú (~ E6 bit/s) Könnyű
ISA Card Közepes (~ E7 bit/s) Közepes
USB Közepes (~ E7 bit/s) Nehéz
PCI Card Nagyon gyors (> E9 bit/s) Nagyon nehéz

Párhuzamos kommunikáció

Az inpout32.dll használata Windows-on

Windows 9x és NT kiadásaiban különböző módok léteznek a hardverek eléréséhez. A 9x sorozatban (95, 98, ME) a programok közvetlenül hozzáférhetnek a hardverekhez, mint a DOS esetén tehették. Az NT sorozatban (Windows NT és XP) azonban ez nem lehetséges. Ezeken a rendszereken minden kommunikációt a hardverekkel eszközmeghajtókkal kell megvalósítani. Ez biztonsági szempontból jó, de eszköz-meghajtó programokat fejleszteni sok idejébe és pénzébe kerülhet a kis vállalkozásoknak.

Szerencsére van egy függvénytár ami megoldja ezt a problémát. Ha Windows NT rendszert érzékel kicsomagolja a HWInterface.sys kernel szintű eszközmeghajtót és telepíti azt. Ha Windows 9x rendszert érzékel akkor egyszerűen gépi kódú utasításokat használ a hardver eléréséhez.

Hogyan használható a függvénytár? Egyszerűen! Csak két eljárás van: Inp32 és Out32, használatuk pedig magától értetődő.

Dinamikusan lesz betöltve a függvénytár, ezért először definiálni kell mindkét funkciót:

 type
   TInp32 = function(Address: SmallInt): SmallInt; stdcall;
   TOut32 = procedure(Address: SmallInt; Data: SmallInt); stdcall;
  • Address mutatja a port címét amit el akarsz érni
  • Out32 elküldi Data tartalmát az Address által mutatott portra
  • Inp32 kiolvas egy bájtot az Address által mutatott portról

Most betöltheted a függvénytárat. Ezt megteheted ott ahol a programod főablakának OnCreate metódusát deklarálod:

 type
   TMyForm = class(TForm)
   .........
   private
     { private declarations }
     Inpout32: THandle;
     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;

Ha a függvénytárat az OnCreate-ben töltöd be akkor ne felejtsd el befejezni a használatát az OnDestroy-ban:

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

Itt egy egyszerű példa az Inp32 funkció használatára:

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

Ez a kód egy ISA kártyával lett tesztelve a $0220-as porton, Lazarus 0.9.10 használatával Windows XP rendszeren. Természetesen a Windows unit-nak a uses részben szerepelnie kell hogy futtthasd ezt a kódot. Használatához az "inpout32.dll" állományt ugyanabba a könyvtárba kell telepíteni ahol az alkalmazásod található.

A függvénytár honlapja itt található: www.logix4u.net/inpout32.htm *lásd: discussion*

Assembler használata Windows 9x rendszeren

Windows 9x rendszeren használhatsz assembler kódot is. Tegyük fel hogy a $320-as portra a $CC értéket akarod írni. A következő kód ezt teszi::

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

Hibaelhárítás Windows-on

Egy léehetséges hibaforrás hogy olyan párhuzamos hardvert használsz amely nem támogatja a "Plug And Play" rendszert Windows-on és így annak portjait a Windows egy másik eszközhöz kapcsolja. A következő hivatkozáson információkat találsz arról hogy miként utasíthatod a Windows-t arra hogy ne használja a hardvered portjait "Plug And Play" eszközökhöz:

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

Folyamatban...

Az IOPerm használata portok eléréséhez Linuxon

A hardverek elérésének legjobb módja Linux-on az eszközmeghajtók használata, azonban a meghajtókészítés folyamatának bonyolultsága miatt néha egy gyorsabb megoldás kézenfekvőbb. Ahhoz hogy a "ports" unit-ot használhasd Linux-on a programodat rendszergazdaként kell futtatni, és az IOPerm segítségével a port eléréséhez megfelelő jogosultságokat kell beállítani.. A "ports" unit dokumentációját itt találod.

Az első teendő a Libc linkelése és azIOPerm meghívása. Van egy unit a free pascalban ami linkeli a meglévő (g) libc-t, azonban ez hibát okoz ha közvetlenül hívjuk meg az alkalmazásból és statikusan kerül felhasználásra, mivel a verziók közötti változások kompatibilitási problémákat okozhatnak. A függvények mint az ioperm valószínűleg nem változnak.


 {$IFDEF Linux}
 function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
 {$ENDIF}
  • "from" az első port amelyet el akarsz érni.
  • "num" a portok száma az elsőtől amelyeket el akarsz érni, az IOPerm($220, 8, 1) hozzáférést biztosít a program számára az összes porthoz beleértve a $220 és $227 portokat is.

Az IOPerm meghívása után a port[<cím>] forma használható.

 {$IFDEF Linux}
   i := ioperm($220, 8, 1);
   port[$220] := $00;
   myLabel.Caption := 'ioperm: ' + IntToStr(i);
   i := Integer(port[$220]);
   myOtherLabel.Caption := 'response: ' + IntToStr(i);
 {$ENDIF}

Ez a kód egy általános ISA kártya $0220-as portján lett kipróbálva, a Lazarus 0.9.10 változatával Mandriva Linux 2005 és Damn Small Linux 1.5 rendszereken.

Általános UNIX Hardver Elérés

{$IFDEF Unix}
Uses Clib;   // kinyeri a libc könyvtár nevét
{$ENDIF}
 
{$IFDEF Unix}
function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external clib;
{$ENDIF}


Az FPC egy absztrakt hívással az "fpioperm" -el éri el az ioperm-t ez a x86 unit-ban található, és szintén definiálja az fpIOPL-t és az out-/inport függvényeket. Ezek a függvények állnak rendelkezésre jelenleg a Linux/x86 és a FreeBSD/x86 rendszerben.

Ennek a linkelése nem ajánlott a libc-hez csak ha a telepítés és a hordozhatóság megvalósítható.

A libc kézi linkelése (pl a libc függvényeinek ad-hoc deklarásával amelyek valahol fellelhetőek) szintén kerülendő (illetve a libc import sor szükségszerűen hibát dob, mivel a standard C lib nem hívja meg a libc-t, továbbá pl. a libroot a BEos vagy más platformokon nem szabványos C szimbólumokat használ). Egyszóval kompatibilitási hibákat okoz.

Megjegyzés: A libc unit használata semmilyen körülmények között nem ajánlott, kivétel a Kylix kompatibilitás. Lásd: libc unit

Soros kommunikáció

Soros kommunikációt végző szoftver építése nagyon egyszerű a Synaser függvénytár használatával. A példa együtt áttekintve a Synaser dokumentációjával könnyen érthető. A leglényegesebb rész a TBlockSerial.Config mellyel beállítható a sebesség (bitek száma másodpercenként), valamint az adat bitek, az ellenörző (parity) bitek, vezérlő (stop) bitek és kapcsolódási (handshake) protokol, ha van. A következő kód egy COM 1-re sorosan csatlakozó egérrel lett tesztelve.

program comm;
 
{$apptype console}
 
uses
  Classes, SysUtils, Synaser;
 
var
  ser: TBlockSerial;
begin
  ser:=TBlockSerial.Create;
  try
    ser.Connect('COM1');
    ser.config(1200, 7, 'N', SB1, False, False);
    while True do
      Write(IntToHex(ser.RecvByte(10000), 2), ' ');
  finally
    ser.free;
  end;
end.


A következő kód a fentebbi példa egy másik változata. A fentebbi példa alapvetően hibásnak tűnik a "while true do..." ciklus használata miatt. A teszteléshez használt rendszeren (Asus A6T Laptop, Digitus USB-RS232 Adapterrel, Ubuntu 8.04.1), ez a rész a következő hibát okozta: Az alkalmazás munkamenetenként csak egyszer futott hibátlanul, amikor az alkalmazás újra lett indítva, már nem tudott csatlakozni a soros porthoz. Így a rendszer újraindítására volt szükség minden alkalommal amikor a felhasználó az alkalmazást újra használni akarta, ez pedig nagyon zavaró hiba.

program serialtest;
 
{$mode objfpc}{$H+}
 
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes,SysUtils,Synaser,Crt
  { ez után jöhetnek a unit-ok };
 
  var l:boolean;
 
  function check_affirmation():boolean;
  var k:string;
  begin
       Writeln('A kilépéshez NE használd a CTRL-C gombokat, inkább valamelyik másik gombbal állítsd le az alkalmazást! '+
       'Válassz a lehetőségek közül! '+
       '[0]=Kilépés, [1]=Rendben, folytatás! ');
       Writeln('Választás: ');
       Read(k);
       if StrtoInt(k) = 1 then
       begin
            check_affirmation:=true;
            Writeln('OK, az alkalmazás tovább fut ...');
       end
       else
       begin
            check_affirmation:=false;
            Writeln('Kilépés');
       end
  end;
 
  procedure RS232_connect;
  var
     ser: TBlockSerial;
  begin
       ser:=TBlockSerial.Create;
       try
          ser.Connect('/dev/ttyUSB0'); //ComPort
          Sleep(1000);
          ser.config(1200, 7, 'N', SB1, False, False);
          Write('Eszköz: ' + ser.Device + '   Állapot: ' + ser.LastErrorDesc +' '+
          Inttostr(ser.LastError));
          Sleep(1000);
          repeat
                Write(IntToHex(ser.RecvByte(10000), 2), ' ');
          until keypressed; //Important!!!
       finally
              Writeln('A soros port fel lesz szabadítva...');
              ser.free;
              Writeln('A soros port sikeresen fel lett szabadítva!');
       end;
  end;
 
  begin
     l:=check_affirmation();
     if l=true then
     RS232_connect()
     else
     Writeln('Kilépés a programból! ');
  end.

A külső hivatkozások részben UNIX és Windows soros port kezeléssel foglalkozó írások címei találhatók.

USB

libusb

Egy keresztplatformos lehetőség Linux, BSD és Mac OS X rendszerekhez a libusb.

A fejlécek megtalálhatók a http://www.freepascal.org/contrib/db.php3?category=Miscellaneous címen:

név szerző változat dátum link megjegyzés
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 hibás letöltési cím

FTDI

Az FTDI chip-jeinek kezeléshez használhatod az általuk kiadott pascal fejléceket a dll függvénytáruk eljárásainak hívására.

Külső hivatkozások

Kommunikációs Protokolok sebességének összehasonlítása:

  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

Soros Kommunikációval kapcsolatos hivatkozások:

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

ISA Digital Oscilloscope - Egy példa a hardverelérésre teljes forráskóddal: http://eletronicalivre.incubadora.fapesp.br/portal/english/oscilloscope/

Personal tools