Thema: Delphi Hardware Portansteuerung

Einzelnen Beitrag anzeigen

jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#10
  Alt 4. Feb 2003, 13:30
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.
  Mit Zitat antworten Zitat