Einzelnen Beitrag anzeigen

Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.929 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: [c-lib] Parellelport-Tutorial

  Alt 15. Jun 2006, 18:04
Wir haben aber noch lange nicht fertig, denn jetzt wird's ja erst interessant......
Zuerst trennen wir mal den gelesenen Wert und den Ausgabewert, indem wir für den Ausgabewert ein zweites Editfeld einbauen und der Ausgabe dieses übergeben:

Delphi-Quellcode:
WriteLPTPort := Str_To_Byte(Edit2.Text);
asm
  Mov DX, $378
  Mov AL, WriteLPTPort
  Out DX, AL
end;
Deklarieren wir weitere globale Variablen

Delphi-Quellcode:
Work_Str_In : string;
Work_Str_out : string; // In CreateForm wird Wert "00000000" zugewiesen
So, und nun kann ich auf dem Weg, Relais anzusteuern mit den gelesenen Bit einiges anstellen....
z.B.

Delphi-Quellcode:
Work_Str_In := Edit1.Text;

if ((Work_Str_In[2] = '1') and (Work_Str_In[5] = '1') or (Work_Str_In[7] = '1')) and (FormatDateTime('hh:nn:ss', Time) = '11:00:00') then Work_Str_Out[1] := '1else ... ???
(neee, else hier bitte nicht, da ihr sonst u.U. aufgrund der Zeitabfrage nix zu sehen bekommt)....
besser ist da die eigene Rücksetzbedingung.....

if (Work_Str_In[2] = '0') then Work_Str_Out[1] := '0'; Aber da könnt ihr euch ja nun mächtig austoben und allemöglichen Kreuz- und Knüppelschaltungen ausprobieren. Nur nicht vergessen:

Delphi-Quellcode:
Edit2.Text := Work_Str_Out;
WriteLPTPort := Str_To_Byte(Edit2.Text);

asm
  Mov DX, $378
  Mov AL, WriteLPTPort
  Out DX, AL
end;
Ach ja, ich glaube, hier ist es angebracht, WriteLPTPort zur Procedure zu machen....

Delphi-Quellcode:
procedure WriteLPTPort(Port: Word; Byte_Out: Byte);
begin
  asm
    Mov DX, Port
    Mov AL, Byte_Out
    Out DX, AL
  end;
end;
... und ReadLPTPort zur Function

Delphi-Quellcode:
function ReadLPTPort(Port: Word): Byte;
begin   
  asm
    Mov DX, Port // Portadresse in DX Register schreiben
    In AL, DX // Port in AL Register lesen
    Mov ReadLPTPort, AL // Wert aus AL Register in Variable eintragen
  end;
end;
Jetzt heißt es :

Delphi-Quellcode:
WriteLPTPort($378, Str_to_Byte(Edit2.Text));
  ..........
Edit1.Text := Byte_To_Str(ReadLPTPort($378));
  ..........
Tja, wenn da nicht...
Der Parallelport von Hause aus ein Ausgabeport wäre und es ist nicht immer gesagt, das ReadLPTPort

($378)
das gewünschte Ergebnis bringt. Aber der Hersteller hat sich etwas einfallen lassen und in

den meisten Fällen sollte es funktionieren....
Man setze Bit 5 im Steuerregister auf '1'. Nicht jedes teure Buch verrät diesen Trick, aber wie sonst sollte ein Scanner der alten Generation z. B. Daten über den Parallelport in den PC schieben...

So setzt man vor die Zeile

Edit1.Text := Byte_To_Str(ReadLPTPort($378)); Eine Anweisung:

WriteLPTPort($37A, Str_to_Byte('00100xx1')); Diese 2 'x' sind Bits, mit denen ich den Eingabekanal adressiere, also das CS-Signal bilde, und die Portbuffer in Richtung zum Parallelport durchschalte. Um zu verhindern, das der Portbuffer gegen den Parallelport durchschaltet, gibt es 2 Möglichkeiten:
Einmal: Ich schalte den Portbuffer immer auf Ausgabe, nur für die kurze Zeit zum Einlesen gebe ich die
Richtung zum Port frei, oder ich lege 100 Ohm – Widerstände in die Datenleitung zwischen Portbuffer und Parallelport. Das brät mir wenigstens den Portbaustein nicht weg, falls die Signale mal gegeneinander stehen....

So, nun mal ein kompletter Einlesevorgang:

Delphi-Quellcode:
WriteLPTPort(37Ah, Str_to_Byte('00100xx1'));
Edit1.Text := Byte_To_Str(ReadLPTPort($378));
WriteLPTPort(378h, Str_to_Byte('00000xx0'));
Aber wieso muss nun Bit 5 und Bit 0 gesetzt, bzw. zurückgesetzt werden. Ganz einfach, Bit 5 steht am Parallelport nicht zur Verfügung und ist intern zur Steuerung im Portchip verschaltet. Bit 0 hat aber für Drucker die Bedeutung, dass Daten abgeholt werden können. Wir müssen dem Portchip sagen, es kommen
Daten von außen und die Portbuffer in die Richtung schalten.
Also, Bit 5 für den Portchip und Bit 0 für die Portbuffer.
Mit den Bit 1 und 2 werden die Kanäle selektiert. Die Erklärung und Beispiele folgen später.

Da es mit einem Interrupt auf dem LPT-Port nicht ganz so einfach ist, muss die Funktion ReadLPTPort zyklisch von einer Timerroutine aufgerufen werden. Also, 10ms sollten nicht unterschritten werden, damit das Programm nicht zu sehr ausgebremst wird. Für viele Anwendungen reicht
eine 100ms Abtastung völlig aus. Die Zuweisung eines Ausgangs wird vom Programm ausgelöst.

Um mal ein Beispiel zu nennen, Steuerungen von Maschinen lesen zuerst die Eingangskarten und legen die Information in einem Speicher ab. Dann erfolgt die Bearbeitung mit Ablage der Ergebnisse in einem weiteren Speicherbereich. Nach Abarbeitung wird der gesamte bearbeitete Speicher zu den Ausgangskarten
übertragen.

Kurz:
- Eingänge lesen
- Programm bearbeiten
- Ausgänge schreiben

Und wieder erneut
- Eingänge lesen
...........

und genau dies können wir auch mit einem Programm erreichen, aber ein PC ist nun mal keine Maschinensteuerung und da kommt's schon mal vor, die Festplatte möchte sich mal wieder drehen, die Grafik hätte auch gern wieder etwas Bewegung im Speicher und auch sonst sind diverse nützliche und unnütze Treiber lustig dabei, Zeit für sich zu beanspruchen. Aus diesem Grund ist es Sinnvoll, einen Timer zu benutzen und in regelmäßigen Zeitspannen auf Änderungen der gelesenen Information zu reagieren.
Schließlich soll der Zug ja im Bahnhof anhalten und nicht zufällig auf irgendeinem Teilstück der riesigen Modelbahnanlage......
  Mit Zitat antworten Zitat