Hardware Access/hu
│
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) │
Hardver hozzáférés
Á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 macOS/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 macOS 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:
- http://en.wikipedia.org/wiki/Serial_port#Speed
- http://www.lvr.com/jansfaq.htm - Jan Axelson's Parallel Port FAQ
- http://en.wikipedia.org/wiki/USB#Transfer_Speed
- http://en.wikipedia.org/wiki/PCI#Conventional_PCI_bus_specifications
Soros Kommunikációval kapcsolatos hivatkozások:
- UNIX-on: [1]
- Windows-on: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp
- Synaser komponens: http://synapse.ararat.cz/
- 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/