![]() |
Hardware Portansteuerung
Hallo,
ich möchte gern die E/A-Pins des LPT1-Ports aus Delphi 5 ansteuern, leider sind die Befehle aus Turbo nichtmehr die Richtigen, kann mir jemand mit seiner Erfahrung helfen??? - Danke |
Auf was für einen Betriebssystem soll das laufen? Unter Windows2000 und höher brauchen wir gar nicht weiterreden, da brauchst du einen Treiber, der sich mit Delphi nicht schreiben lößt. Da müßtest du dann auf Komponenten bei Torry umsteigen.
|
Ist kein Problem, muss nur unter 98 laufen.
Johannes |
Zitat:
![]() ...:cat:... |
Und wie ist das bitte sehr zu verstehen?
Zitat:
|
Hi,
ich kenne NicoDE auch noch ;) Ich stimme zu, dass Delphi bestimmt nicht das optimale Tools zur Erstellung von Treibern ist, aber ich bleibe bei der Aussage, dass es nicht unmöglich ist. ...:cat:... |
OK ich glaube, da kommen wir zu einer Einigung. Es ist nicht unmöglich, aber mehr als blödsinning es zu machen. Desweiteren dürfte man als otto-normal Programmierer keine Chance haben es zu schaffen.
|
Hallo jwhm,
zum Parallel-Port kann ich nichts sagen, aber vielleicht kannst Du Dein Problem ja durch Nutzung der seriellen Schnittstelle lösen. Eine Kassenschublade läßt sich zumindest durch direktes Anspechen des COM-Ports öffnen. mfg eddy |
Danke, aber nach der Diskussion habe ich mich entschieden, doch wieder das gute alte Turbo unter Dos zu verwenden, da kenn ich alle Ansteuerungen, das passt auf eine Diskette und kann auf jedem PC laufen.
Johannes |
Für den Parallelport habe ich eine Unit.
Delphi-Quellcode:
unit LPTPort;
{.$define WINIO} // WinIo nutzen um auf den ParPort zuzugreifen {.$define USERPORT} // UserPort.sys nutzen um auf den ParPort zuzugreifen {$ifdef WINIO} {$ifdef USERPORT} Es kann nur ein Kernel Mode Treiber genutzt werden {$endif} {$endif} {$ifdef USERPORT} {$ifdef WINIO} Es kann nur ein Kernel Mode Treiber genutzt werden {$endif} {$endif} { Beschreibung: Parallel Port Objekt mit direktem Hardwarezugriff } interface uses Windows, SysUtils, Classes{$ifdef WINIO}, WinIo{$endif}; const PortNames: array [0..2] of string = ('None', 'LPT1', 'LPT2'); PortAddress: array[0..2] of Word = (0, $378, $278); STB = $01; AUTOFD = $02; INITL = $04; SLCI = $08; IRQEN = $10; ERR = $08; SLCO = $10; PE = $20; ACK = $40; BSY = $80; type TPortNumber = (portNone, portLPT1, portLPT2); TParPort = class(TObject) private FPort: TPortNumber; FPortAddress: Word; PortHandle: THandle; FData, FControl, FStatus: Byte; FStrobe, FAutoFd, FInit, FSlctIn, FError, FSlct, FPaperEnd: Boolean; FAcknlg, FBusy: Boolean; procedure SetPort(Value: TPortNumber); function GetData: Byte; procedure SetData(Value: Byte); function GetControl: Byte; procedure SetControl(Value: Byte); function GetStatus: Byte; function GetStrobe: Boolean; procedure SetStrobe(Value: Boolean); function GetAutoFd: Boolean; procedure SetAutoFd(Value: Boolean); function GetInit: Boolean; procedure SetInit(Value: Boolean); function GetSlctIn: Boolean; procedure SetSlctIn(Value: Boolean); function GetError: Boolean; function GetSlct: Boolean; function GetPaperEnd: Boolean; function GetAcknlg: Boolean; function GetBusy: Boolean; public constructor Create; destructor Destroy; override; function OpenPort(PortNo: Byte): Boolean; function ClosePort: Boolean; property Control: Byte read GetControl write SetControl; public property Port: TPortNumber read FPort write SetPort; property BaseAddress: word read FPortAddress; property Status: Byte read GetStatus; property Data: Byte read GetData write SetData; property Strobe: Boolean read GetStrobe write SetStrobe; property AutoFeed: Boolean read GetAutofd write SetAutofd; property Initialize: Boolean read GetInit write SetInit; property SlctIn: Boolean read GetSlctIn write SetSlctIn; property Error: Boolean read GetError; property Slct: Boolean read GetSlct; property PaperEnd: Boolean read GetPaperEnd; property Acknlg: Boolean read GetAcknlg; property Busy: Boolean read GetBusy; end; implementation { ************************************************************************* } { Get a Byte from the port } function InPort(PortAddr: Word): Byte; stdcall; begin {$ifdef WINIO} Result := WinIo_GetPort(PortAddr) {$else} try asm mov dx, PortAddr in al, dx mov Result, al end; except Result := 0; end; {$endif} end; { ************************************************************************* } { Write a Byte to the port } procedure OutPort(PortAddr: Word; DataByte: Byte); stdcall; begin {$ifdef WINIO} WinIo_SetPort(PortAddr, DataByte) {$else} try asm mov al, DataByte mov dx, PortAddr out dx, al end; except end; {$endif} end; { ************************************************************************* } { Do (Action) to b(Bit) of (PortAddr) } procedure SetBitState(PortAddr: Word; Action: Boolean; Bit: Byte); begin if Action = True then OutPort(PortAddr, InPort(PortAddr) or Bit) else OutPort(PortAddr, InPort(PortAddr) and not Bit); end; { ************************************************************************* } { Return status of b(Bit) of (PortAddr) } function GetBitState(PortAddr: Word; Bit: Byte): Boolean; begin Result := (InPort(PortAddr) and Bit) <> 0; end; {---------- TParPort ----------} { ************************************************************************* } constructor TParPort.Create; begin inherited Create; FPort := portNone; FPortAddress := 0; PortHandle := 0; end; { ************************************************************************* } destructor TParPort.Destroy; begin ClosePort; inherited Destroy; end; { ************************************************************************* } function TParPort.OpenPort(PortNo: Byte): Boolean; var s: string; begin ClosePort; s := ''; Result := False; if (PortNo < 1) or (PortNo > 2) then exit; s := '\\.\LPT' + IntToStr(PortNo); PortHandle := CreateFile(PChar(s), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0); if PortHandle = INVALID_HANDLE_VALUE then PortHandle := 0; if PortHandle <> 0 then begin case PortNo of 1: FPort := portLPT1; 2: FPort := portLPT2; end; FPortAddress := PortAddress[PortNo]; { Output data = 0 } OutPort(FPortAddress, 0); { Control reg = 0c } OutPort(FPortAddress + 2, (InPort(FPortAddress + 2) and $F0) or $0C); Result := True; end; end; { ************************************************************************* } procedure TParPort.SetPort(Value: TPortNumber); begin if Value <> FPort then begin { Set default output data } OpenPort(Ord(Value)); end; end; { ************************************************************************* } function TParPort.GetData: Byte; begin { Get a Byte from the data port } if PortHandle <> 0 then FData := InPort(FPortAddress) else FData := 0; Result := FData; end; { ************************************************************************* } procedure TParPort.SetData(Value: Byte); begin { Send a Byte to the data port } if PortHandle <> 0 then OutPort(FPortAddress, Value); end; { ************************************************************************* } function TParPort.GetControl: Byte; begin { Get a Byte from the control port } if PortHandle <> 0 then FControl := InPort(FPortAddress + 2) else FControl := 0; Result := FControl; end; { ************************************************************************* } procedure TParPort.SetControl(Value: Byte); begin { Send a Byte to the control port } if PortHandle <> 0 then OutPort(FPortAddress + 2, (InPort(FPortAddress + 2) and $F0) or (Value and $0F)); end; { ************************************************************************* } function TParPort.GetStatus: Byte; begin { Read port status, inverting B7 (busy) } if PortHandle <> 0 then FStatus := InPort(FPortAddress + 1) else FStatus := 0; Result := FStatus; end; { ************************************************************************* } function TParPort.GetStrobe: Boolean; begin { Read the STROBE output level } if PortHandle <> 0 then FStrobe := not GetBitState(FPortAddress + 2, STB) else FStrobe := False; Result := FStrobe; end; { ************************************************************************* } procedure TParPort.SetStrobe(Value: Boolean); begin { Condition the STROBE output } if PortHandle <> 0 then SetBitState(FPortAddress + 2, not Value, STB); end; { ************************************************************************* } function TParPort.GetAutoFd: Boolean; begin { Read the AUTOFD output level } if PortHandle <> 0 then FAutoFd := not GetBitState(FPortAddress + 2, AUTOFD) else FAutoFd := False; Result := FAutoFd; end; { ************************************************************************* } procedure TParPort.SetAutoFd(Value: Boolean); begin { Condition the STROBE output } if PortHandle <> 0 then SetBitState(FPortAddress + 2, not Value, AUTOFD); end; { ************************************************************************* } function TParPort.GetInit: Boolean; begin { Read the INITIALIZE output level } if PortHandle <> 0 then FInit := GetBitState(FPortAddress + 2, INITL) else FInit := False; Result := FInit; end; { ************************************************************************* } procedure TParPort.SetInit(Value: Boolean); begin { Condition the INITIALIZE output } if PortHandle <> 0 then SetBitState(FPortAddress + 2, Value, INITL); end; { ************************************************************************* } function TParPort.GetSlctIn: Boolean; begin { Read the SLCTIN output level } if PortHandle <> 0 then FSlctIn := not GetBitState(FPortAddress + 2, SLCI) else FSlctIn := False; Result := FSlctIn; end; { ************************************************************************* } procedure TParPort.SetSlctIn(Value: Boolean); begin { Condition the SLCTIN output } if PortHandle <> 0 then SetBitState(FPortAddress + 2, not Value, SLCI); end; { ************************************************************************* } function TParPort.GetError: Boolean; begin { Read the ERROR input level } if PortHandle <> 0 then FError := GetBitState(FPortAddress + 1, ERR) else FError := False; Result := FError; end; { ************************************************************************* } function TParPort.GetSlct: Boolean; begin { Read the SLCT input level } if PortHandle <> 0 then FSlct := GetBitState(FPortAddress + 1, SLCO) else FSlct := False; Result := FSlct; end; { ************************************************************************* } function TParPort.GetPaperEnd: Boolean; begin { Read the PE input level } if PortHandle <> 0 then FPaperEnd := GetBitState(FPortAddress + 1, PE) else FPaperEnd := False; Result := FPaperEnd; end; { ************************************************************************* } function TParPort.GetAcknlg: Boolean; begin { Read the ACK input level } if PortHandle <> 0 then FAcknlg := GetBitState(FPortAddress + 1, ACK) else FAcknlg := False; Result := FAcknlg; end; { ************************************************************************* } function TParPort.GetBusy: Boolean; begin { Read the inverted BUSY input level } if PortHandle <> 0 then FBusy := not GetBitState(FPortAddress + 1, BSY) else FBusy := False; Result := FBusy; end; { ************************************************************************* } function TParPort.ClosePort: Boolean; begin { Close currently open LPT } if PortHandle <> 0 then begin { Output data = 0 } OutPort(FPortAddress, 0); { Control reg b0..3 = $0C } OutPort(FPortAddress + 2, (InPort(FPortAddress + 2) and $F0) or $0C); Result := CloseHandle(PortHandle); end else Result := False; PortHandle := 0; FPort := portNone; FPortAddress := 0; end; {$ifdef USERPORT} procedure StartUserPortDriver; var hUserPort : THandle; begin hUserPort := CreateFile('\\.\UserPort', GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ); CloseHandle(hUserPort); // Activate the driver Sleep(100); // We must make a process switch end; function IsWinNT: Boolean; var OSVersionInfo: TOSVersionInfo; begin OSVersionInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); GetVersionEx(OSVersionInfo); Result := OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT; end; initialization if IsWinNT then StartUserPortDriver; {$endif} {$ifdef WINIO} initialization WinIo_InstallAndStart; finalization WinIo_ShutDown; {$endif} end. |
also, dieser code funktioniert, bei allen Checkboxen wird OnClick die prozedur ausgeführt.
Delphi-Quellcode:
Jo[allesmussman(n)selbermachen]hannes
unit Unit1;
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) CheckBox1: TCheckBox; CheckBox2: TCheckBox; CheckBox3: TCheckBox; CheckBox4: TCheckBox; CheckBox5: TCheckBox; CheckBox6: TCheckBox; CheckBox7: TCheckBox; CheckBox8: TCheckBox; procedure CheckBox1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.DFM} procedure port(x:byte); begin asm mov dx,378h mov al,x out dx,al end; end; procedure TForm1.CheckBox1Click(Sender: TObject); var a:byte; begin a:=0; if CheckBox1.Checked=True then a:=a+1; if CheckBox2.Checked=True then a:=a+2; if CheckBox3.Checked=True then a:=a+4; if CheckBox4.Checked=True then a:=a+8; if CheckBox5.Checked=True then a:=a+16; if CheckBox6.Checked=True then a:=a+32; if CheckBox7.Checked=True then a:=a+64; if CheckBox8.Checked=True then a:=a+128; port(a); end; end. |
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab dir mal was angehängt. Das funzt! Ich hatte es für Technik in der Schule geschrieben. Du kannst es verändern wie du willst. Ist ganz einfach! Du legst durch umschalten im zweiten Fenster den ersten Datenpin auf "High". Wunder dich nicht über das Design! Als Delphi-Newbie kann man halt noch nicht alles. :wink: Schick mir mal das fertige Ergebnis.
Thx! :D |
Zitat:
Grüsse, Daniel :hi: |
Zitat:
|
Zitat:
Ich kann mir nicht ganz vorstellen das es was mit der Kompilierzeit zutun hat. Aus dem einfachen Grund, ich benutze eine solche Software in der Arbeit an verschiedenen Rechnern, alle mit NT, und jedesmal ein anderer Login. Grüsse, Daniel :hi: |
Moin Daniel B,
nur noch einmal zum Verständnis: Ihr sprecht über in und out Befehle unter NT direkt die Schnittstellen an? |
Moin Christian,
Zitat:
Womit man Adressen direkt ansprechen konnte. Jedenfalls die der Schnittstellen. Grüsse, Daniel :hi: |
Auch als Admin kann man nicht direkt, sondern nur mittels eines Treibers auf die Hardware zugreifen.
Das liegt an der hal.dll (Hardware abstarct layer) diese DLL liegt zwischen den Treiber-Routinen des Kernes und der Hardware und kontrolliert alle Hardwarezugriffe. Und verbiete direkte Zugiffe auf eben diese. Ein schönes Diagramm findet man hier auf der zweiten Seite: ![]() Oder hier ganz unten: ![]() |
Zitat:
Grüsse, Daniel :hi: |
Das kann natürlich sein. Da will ich mich jetzt nicht festlegen.
|
Zitat:
Die Meldung im Anhang. Grüsse, Daniel :hi: Nachtrag: Ich hab nur ME! |
nt lpt
Liste der Anhänge anzeigen (Anzahl: 1)
ich habe das gleiche problem mal gehabt den lpt über NT (xp) anzusteuern
dann hab ich mal gegoogled und hab gefunden: lpt komponente ( naja eher so nen riesen codeschnipsel ) mit ASM code drin und das alles ganz ohne DLLs oder calls zu denen :) also ein asm treiber für NT :) geht übrigends auch ohne admin login es heist: ZLPortIO hat auch eine demo exe dabei.. ich häng das teil mal an :) |
Zitat:
Das dürfte die Treiber DLL sein, die von dem Code gekapselt wird. Unter ME geht das so wohl auch gar nicht. Da kann man noch direkt auf die Hardware zugreifen. |
ich habe das Prog unter XP als Computeradmin ausprobiert, nix is, der erlaubt keinen Zugriff auf LPT1.
Johannes |
Zitat:
Grüsse, Daniel :hi: |
der Comp hat nur eine Ausschrift "I/O Zugriffsverletzung"(manchmal denk ich windows hat zum auswählen der Fehlermeldung einen Zufallsgenerator) gebracht, also sowas hab ich mit Kylix noch nich gehabt, ich brauchs aber nur unter 98.
Mich würde aber noch interessieren, wie ich Daten vom Port importieren(von Port 379 Pin 3-6) kann, mir fehlt der ASM-Befehl zum einlesen, das out läuft. Jo[unterLINUXundDOSläuftsschonlange]hannes |
LPT
naja bei mir läuft das prog unter xp( auch mit sp1 ), 2k und unter win98 / win95 ( sogar auf nem alten simens notebook wo das win95 druff is )
hab allerdings die sources verwendet und selber nen prog damit gecoded.. das mir meine LEd anzeige ansteuert ( auf meiner webseite zu betrachten ) so zugriffsverletzungen sind mir nochnicht unter gekommen.. ka ihr macht da irgend was falsch ?! :) :coder: |
Moin Johannes,
das Gegenstück zu out ist in. |
nagut, darauf hätte ich vieleicht selber kommen können. :(
@supermuck'l: welchen code?(asm?) hast du den progcode irgendwo, zum vergleichen??? Johannes |
Liste der Anhänge anzeigen (Anzahl: 1)
Scheisse! Ihr habt recht! Das Problem hatte ich auch. Ich hab mal die QTINTF70.dll angehängt. Wenn ihr die nach C:\Windows\System kopiert funktioniert es.
Mein Fehler! :( :( :( MfG Florian P.S.: Cooler Wortfilter! |
@ jwhm
der code steht im sourcecode :) die komponente gibts übrigends bei torry achja.. das teil geht bei mir immer noch.. unter 2k und xp und win98 / win95 hab ichs nochmal ausprobiert.. das teil funzt und funzt.. ich kann dagegen nichts tun :hello: |
Zitat:
Naja, is ja auch egal! Sacht mal: Was haltet ihr von meinem Programm??? Gefällt es euch? :D |
Sorry wenn ich jetzt "dumm" frage, aber ich hab das Posting mal so überflogen, aber hab nicht so recht ne Antwort gefunden.
Ich hab WinXP und bekomme immer ne Fehlermeldung: "Privilegierte Anweisung". Der Fehler kommt nur, wenn ich in Delphi bin, ansonsten nicht. Kann mir da jemand was zu sagen? Gruß Yheeky |
Hallo Yheeky!
Wenn Du Dein Programm in der Delphi-IDE ausführst, gibt es eine Fehlermeldung, bei Start der EXE außerhalb von Delphi nicht? 1. Du hast wohl bei "Tools", "Debugger-Optionen", "Sprach-Exceptions" einen Haken in "Bei Delphi-Exceptions stoppen" - dann werden aufgetretene Exceptions auch dann gemeldet, wenn das mit einem TRY-EXCEPT oder TRY-FINALLY abgefangen ist. 2. in diesem Fall stinkt das meilenweit nach Pfusch. Statt die Plattform einmal einzulesen und passend zu programieren, wurde einfach mit TRY-EXCEPT gearbeitet nach dem Motto: "versuchen wir ASM-IN/OUT, wenns klappt is gut, wenn nicht haben wir NT/2000/XP und nutzen dann erst die nötige Umgehung" - wie war das noch mit der Regel beim Einparken? Richtig: "wenns knallt, noch 1 Meter" :mrgreen: Wie sagten schon Murphy und seine Schüler? Die Programmkomplexität wächst so lange, bis sie das Leistungsvermögen des Programmierers überschreitet. Gruß Dietmar Brüggendiek |
Yo, klingt gut, aber was willst du mir jetzt damit sagen? :roll: :wink:
|
Hallo Yheeky!
Der Entwickler der Komponente hat gepfuscht (oder war überfordert). Korrekt ist Folgendes:
Delphi-Quellcode:
Offensichtlich kannte der Programmierer jedoch nicht den Code der ersten Zeile (bei Initialisierung der Unit aufzurufen), der das W9xFlag setzt, wenn wir ein DOS-basiertes Windows haben und damit die ASM-Befehle IN und OUT benutzen dürfen. Also wurde so programmiert:
W9xFlag := not (Win32Platform = VER_PLATFORM_WIN32_NT);
.. if W9xFlag then begin // Code für Win95/98/ME end else begin // Code für NT/2000/XP end;
Delphi-Quellcode:
also umgangssprachlich ausgedrückt: wenn es knallt, geht es nicht!
try
// Code für Win95/98/ME except // Code für NT/2000/XP end; Ist nun die Anzeige von Exceptions in der IDE aktiviert, gibt es eine Ausgabe - natürlich nur, wenn das Programm in der IDE läuft. Gruß Dietmar Brüggendiek |
Zitat:
MfG Florian |
@flomei: doch. :)
kannst du dien prog noch mal ranhängen? irgendwie gehts bei mir nich, zeigt nur kurz die sanduhr. hab winxp |
Hallo flomei,
Zitat:
Nicht jeder hat die möglichkeit LEDs zusammen zu löten um es dann am Port anzuhängen. Ob man das Programm an sich starten kann ist glaub ich erledigt. Aber was sollen die Leute damit, wenn sie keine "entsprechende Harware" dazu haben? Es geht hier nicht ums mögen, sondern um keine Testmöglichkeiten haben! Grüsse, Daniel :hi: |
Hm. Das sehe ich ein. Böses Kind, dass so etwas vermutet :wall:
Ein einziges Mal noch für alle die nicht richtig gelesen haben : Das funktioniert NICHT unter Win 2000 oder XP!!! Naja. Ich hab dafür meine 1 in Technik bekommen und dann soll es auch gut sein |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:51 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz