![]() |
Parellelport-Tutorial
Dieses Tutorial wird unter der freundlichen Genehmigung von Martin Vogel hier veröffentlicht. Ich habe es in die BBCode-Fassung gebracht, da ein Word-Dokument hier nicht unbedingt geeignet war. Kleinere Dinge wurden von mir angepasst und Syntax-Fehler behoben.
Das Tutorial und die Grafiken stammen von Martin Vogel. Leider funktioniert der Code nicht unter Windows 2000/XP, da diese Windows-Versionen keine direkten Port-Zugriffe gestatten. __________________________________________________ _________ Vorwort Seit langer Zeit suche ich nach einer schnellen Datenerfassung per PC. Ein USB Experimentierplatinchen von Conrad ist zwar leicht zu integrieren und lässt eine kleine Steuerung für eine Eisenbahn zu, aber soll's denn etwas einfaches und schnelles sein, dann fällt mir nur der Druckerport ein. Nix gegen Mikro-Controler, aber da hab ich noch keine Erfahrung mit und ich kann den Aufwand nicht abschätzen, um zum Ergebnis zu gelangen. Da ich auch das Problem habe, dass meine Anwendung nur bis Win98 taugt, (dann braucht's Treiber) , hab ich mich entschlossen, einen alten PC herzunehmen, ihn zu vernetzen und dann die Experimente halt auf dem "Billigteil" durchzuführen. Also, ich hätt da schon Lust, ein wenig Elektronikpraxis und auch Programmiertechnik zu vermitteln. Wobei letzteres, der Informatiker möge es mir nachsehen, nicht auf einem Studium an der Uni basiert, sondern auf autodidaktische Fleißarbeit gründet. Da sind dann schon mal kleine formelle Ausrutscher möglich. An solchen Stellen bin ich dankbar für Hinweise. Aber nun zum eigentlichen Thema. Auf der Suche nach brauchbaren Treibern für NT, XP oder 2000 hab ich die vielen Probleme beim Zugriff auf den Parallelport zu lesen bekommen und habe mich entschlossen, sowohl bei Hard- als auch bei Softwarefragen zu helfen. Allerdings. Wer von mir einen "vernünftigen" Treiber erwartet, Fehlanzeige. Im Moment bin ich nicht in der Lage, weder von der Software als auch vom Wissen her, dieses anzubieten. Daher verweise ich immer bei solchen "Experimenten" mit der Hardware, nehmt einen alten PC mit Win95 oder 98. Da gibt’s dieses Problem nicht und ihr lauft auch nicht Gefahr, euren neuesten PC zu erden. Treiber wie IOPort , IO.Dll oder ähnliche haben scheinbar ein paar Nachteile, die den Experten die Nackenhaare zu Berge stehen lassen..... , allerdings weiß ich nicht, was gegen diesen Einsatz spricht, wo die meisten doch sowieso keine professionellen Programme schreiben, bzw. dies auch aufgrund ihrer Lizenz nicht können. Und was ich privat mit meinem Blechdiener anfange.... Egal, ich wollt halt das mal kurz erwähnen, damit man mir nicht gleich mein Zusammengeschriebenes um die Ohren haut.... Dieser Text soll ja auch nur einen kleinen Einblick in die elektrischen Vorgänge und Hintergründe geben, ohne gleich mit der gesamten Bandbreite zu verwirren. Ich hoffe, doch verständlich geblieben zu sein und euch nachvollziehbare Hinweise gegeben zu haben. Falls nicht, fragt nach, aber erwartet nicht immer gleich eine Antwort, da ich nebenbei noch'n bisschen arbeiten muss..... |
Re: [c-lib] Parellelport-Tutorial
Tutorial
Etwas Theorie Der Wunsch, Experimente mit dem Druckerport durchzuführen, setzt ein wenig Kenntnis der Elektrik voraus und so werde ich mit einem kleinen Kurs die "elektrische Digitaltechnik" ansprechen. Und ohne Grundsatz geht auch da gar nix, also bitte merken:
Bevor mich die Elektriker jetzt eine dumme Nuss nennen, ich habe absichtlich Begriffe wie Plus, Minus und neutral verwendet, zumal ich nicht die Absicht habe, Wechselstromtechnik einfließen zu lassen. Die Bezeichnung aus Schaltungen wie Vcc (Plus) und Gnd (Minus) sind auch nicht unbedingt besser. Nun ein wenig Praxis: Wir nehmen einen Wechselschalter und schließen wie folgt an: ![]() Es ist erkennbar, das die Leitung S (Signal) entweder ein Plus- oder ein Minuspotential hat.Bei dieser Schalung ist es egal, wie der Schalter steht, es leuchtet immer eine Lampe, und so ist es, die Leitung S führt entweder einen H(igh) oder L(ow) Potential. Nun nehmen wir einen 3 stufigen Schalter: ![]() Und schon ist's Essig mit entweder oder.... es gibt einen Zustand, da ist nix auf der Leitung. Und So sieht's dann auch in der Praxis aus, es gibt einen Zustand, der ist nicht H(igh) oder L(ow). Der ist "neutral". Und diese 3 Schaltzustände nennt man "tristate", weil's englisch halt besser klingt. Aber warum ist nun dieser "tristate" so wichtig ? Nun, ich zeichne die Schaltung mal etwas anders: ![]() Und wir korrigieren etwas die Bezeichnungen, und schon haben wir ein tristate-Element. Egal wie der Wechselschalter steht, erst mit CS (Chipselect) wird das Signal durchgeschaltet. Aber was macht das eigentlich für einen Sinn? Nicht unbedingt beim Einmaleins des kleinen Elektrikers, aber in der Computertechnik. Ich zeig's euch: ![]() Sind zwar nur zwei Nibble, aber mit ein wenig Vorstellungskraft kann man sich bis zu ein paar Millionen solcher Schaltungen 8 Bit breit auf einem gemeinsamen Leitungsbus vorstellen, oder...... Aber wir wollen ja gar nicht Millionen Speicherzellen anschließen, lediglich mal 8 oder 16 Relais steuern und vielleicht ein paar Schalter abfragen und deshalb reicht so eine kleine Einführung auch schon fast aus, um mit der Bastelei zu beginnen. Wir kennen die Bedeutung von H(igh) und L(ow) Signalen sowie den "dritten" Signalzustand. Wir sollten uns noch merken, dass eine Anzahl von Leitungen mit gemeinsamer Bedeutung "Bus" genannt wird. z.B. Datenbus, Adressbus, Steuerbus um die wichtigsten beim Namen zu nennen. Und damit hat jede Leitung eine Wertigkeit aufgrund ihrer eigenen Position in der Rangordnung. Machen wir einen kleinen Step zur dualen Mathematik. Diese kennt nur 2 Zahlen. Die "0" und die "1" analog zu den Spannungspotentialen der Leitung L(ow) und H(igh). Gerechnet wird also mit der Basis 2 entsprechend der Potentialzustände L und H sowie dem Exponenten angegeben in der Nummer der Leitung. Und wir beginnen die Zählung der Leitungen mit "0". Eine Regel der Mathematik sagt, dass x hoch 0 immer 1 ist. So sieht die Formel für Leitung mit der Nummer 0 wie Folgt aus: 2 hoch 0 mal Signalzustand (1 oder 0). Verallgemeinern wir es etwas: Basis (ist wie wir wissen 2) hoch Leitungsnummer mal Signalzustand. Nehmen wir an: 4 Leitungen: Leitung 0 = 1, Leitung 1 = 0, Leitung 2 = 1 und Leitung 3 = 1 ('1101')
Code:
Wer Spaß an Mathe hat, der kann ja mal 8 Leitungen (ab jetzt Bit), 16 Bit oder gar 32 Bit berechnen.
So lautet die Rechnung: 2 hoch 0*1 + 2 hoch 1*0 + 2 hoch 2*1 + 2 hoch 3*1
Ist 1*1 + 2*0 + 4*1 + 8*1 = 13 So, jetzt wissen wir auch, wie die Zahlen in den Computer kommen. |
Re: [c-lib] Parellelport-Tutorial
Machen wir folgenden Versuch:
Angenommen wir haben auf die Datenbits im Parallelport Schalter angeklemmt, diese von 0 bis 7 nummeriert, und wollen nun wissen, wie ich den Schalter im Computer zuordnen kann. Gehen wir davon aus, jeder hat schon mal auf den Port zugegriffen und weiß, wie das geht und er hat nun einen Wert in der Variablen ReadLPTPort stehen. ReadLPTPort wie folgt deklariert
Delphi-Quellcode:
Kleines Beispiel:
ReadLPTPort: Byte
Delphi-Quellcode:
Natürlich kann man davon auch eine Function machen und den Wert darüber einlesen, aber das machen wir später. Hier geht es um etwas anderes.
asm
Mov DX, $378h // Portadresse in DX Register schreiben In AL, DX // Port in AL Register lesen Mov ReadLPTPort, AL // Wert aus AL Register in Variable eintragen end; Wie kann ich erkennen, welche Schalter hinter dem Wert 163 z. B. stehen. Und jetzt geb ich euch eine Function.
Delphi-Quellcode:
Na, ist das was? Na gut, geb ich euch eben den zugehörigen Quellcode.
function Byte_To_Str(ByteWert: Byte): string;
Delphi-Quellcode:
Also, die Integerzahl 163 wird durch 2 geteilt und geprüft, ob sie gerade oder ungerade war. Bei einer ungeraden Zahl ergibt sich ein Rest von 1 bzw. bei einer geraden eben ein Rest 0. Diese Werte werden von hinten in einen String eingetragen und die Rechnung mit dem ganzen halben Wert wiederholt. Solange, bis nur noch 0 übrigbleibt.
function Byte_To_Str(Byte_Val: Byte): string;
var CalcWert : Integer; Ausg : string; begin Ausg := ''; CalcWert := Byte_Val; repeat if CalcWert / 2 = Trunc(CalcWert / 2) then Ausg := '0' + Ausg else Ausg := '1' + Ausg; // Darauf achten: Der String wächst von hinten ! Calcwert := Trunc(CalcWert / 2); until Calcwert = 0; while Length(Ausg) < 8 do // Wir wollen doch den ganzen Port also 8 Bit Ausg := '0' + Ausg; Byte_To_Str := Ausg; end; Klartext:
Code:
Die Abfrage nach der Länge des String ist nur bei kleineren Zahlen notwendig, um den String mit vorstelligen "0"en aufzufüllen. Der String zeigt nun, dass Schalter S7, S5, S1 und S0 geschaltet sind. Das ist doch was, oder....
163 / 2 = 81 Rest 1 String ="1" ("1")
81 / 2 = 40 Rest 1 String = "1" + String ("11") 40 / 2 = 20 Rest 0 String = "0" + String ("011") 20 / 2 = 10 Rest 0 String = "0" + String ("0011") 10 / 2 = 5 Rest 0 String = "0" + String ("00011") 5 / 2 = 2 Rest 1 String = "1" + String ("100011") 2 / 2 = 1 Rest 0 String = "0" + String ("0100011") 1 / 2 = 0 Rest 1 String = "1" + String ("10100011") Wenn ihr wollt:
Delphi-Quellcode:
Und weil ich es schon hab und ihr es auch wollt, gleich die Kehrseite, nämlich die "1" aus einem String
Edit1.Text := Byte_To_Str(ReadLPTPort);
zum Ansteuern von irgendwas nehmen:
Delphi-Quellcode:
Funktioniert folgendermaßen:
function Str_To_Byte(Str_Val: string): Byte;
var i : Integer; Ausg : Real; begin Ausg := 0; for i := 0 to Length(Str_Val) - 1 do if Str_Val[Length(Str_Val) - i] = '1' then Ausg := Ausg + Power(2, i); // dies ist die Function 2 hoch n (uses Math) Str_To_Byte := Trunc(Ausg); end; String hat den Wert "10100011", sagen wir mal, den Wert der eingelesenen Schalter. Um ein bisschen unabhängig von der Stringlänge zu sein, lassen wir die Schleife bis zur Länge des Strings laufen, und da wir bei 0 anfangen, muss es natürlich auch Length(String)-1 lauten.
Delphi-Quellcode:
Beachte:
for i := 0 to Length(Str_Val) - 1 do ...
Bei längeren Strings ist die Function mit anderem Typ zu deklarieren, weil Bytewerte nur bis 255 gehen, nicht, dass mir dann unterstellt wird, meine Function könnte nicht rechnen.... Also: Ist das letze Zeichen-Laufzähler (im String = 1 dann ist die die Summenvariable = Summenvariable + 2 hoch Laufzähler. Dies erledigt die
Delphi-Quellcode:
Function Power(Basis, Exp).
Delphi-Quellcode:
Sie liefert allerdings einen Realwert, daher muss der Ausgang letztlich mittels Trunc-Function zugewiesen werden.
if Str_Val[Length(Str_Val) - i] = '1' then
Ausg := Ausg + Power(2, i); ... So, damit haben wir schon die Möglichkeit in einem Textfeld Bits anzusehen oder zu setzen. Vereinbaren wir nun ein Ausgabe-Byte für den Port.
Delphi-Quellcode:
Dann könnte die Ausgabe eines Textfeldes an den LPT1 folgendermaßen lauten:
WriteLPTPort: Byte;
Delphi-Quellcode:
So, hat doch was.
WriteLPTPort := Str_To_Byte(Edit1.Text);
asm Mov DX, $378 Mov AL, WriteLPTPort Out DX, AL end; Ich hab jetzt Schalter, die über einen komplizierten und teuren Rechner und einem mit einem nicht minder teuren Entwicklungstool geschriebenen Programm Relais schalten..... Wer's einfacher haben will, der sollte direkt mit den Schaltern sein Licht an- und ausknipsen.... |
Re: [c-lib] Parellelport-Tutorial
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:
Deklarieren wir weitere globale Variablen
WriteLPTPort := Str_To_Byte(Edit2.Text);
asm Mov DX, $378 Mov AL, WriteLPTPort Out DX, AL end;
Delphi-Quellcode:
So, und nun kann ich auf dem Weg, Relais anzusteuern mit den gelesenen Bit einiges anstellen....
Work_Str_In : string;
Work_Str_out : string; // In CreateForm wird Wert "00000000" zugewiesen z.B.
Delphi-Quellcode:
(neee, else hier bitte nicht, da ihr sonst u.U. aufgrund der Zeitabfrage nix zu sehen bekommt)....
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] := '1' else ... ??? besser ist da die eigene Rücksetzbedingung.....
Delphi-Quellcode:
Aber da könnt ihr euch ja nun mächtig austoben und allemöglichen Kreuz- und Knüppelschaltungen ausprobieren. Nur nicht vergessen:
if (Work_Str_In[2] = '0') then Work_Str_Out[1] := '0';
Delphi-Quellcode:
Ach ja, ich glaube, hier ist es angebracht, WriteLPTPort zur Procedure zu machen....
Edit2.Text := Work_Str_Out;
WriteLPTPort := Str_To_Byte(Edit2.Text); asm Mov DX, $378 Mov AL, WriteLPTPort Out DX, AL end;
Delphi-Quellcode:
... und ReadLPTPort zur Function
procedure WriteLPTPort(Port: Word; Byte_Out: Byte);
begin asm Mov DX, Port Mov AL, Byte_Out Out DX, AL end; end;
Delphi-Quellcode:
Jetzt heißt es :
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;
Delphi-Quellcode:
Tja, wenn da nicht...
WriteLPTPort($378, Str_to_Byte(Edit2.Text));
.......... Edit1.Text := Byte_To_Str(ReadLPTPort($378)); .......... 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
Delphi-Quellcode:
Eine Anweisung:
Edit1.Text := Byte_To_Str(ReadLPTPort($378));
Delphi-Quellcode:
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:
WriteLPTPort($37A, Str_to_Byte('00100xx1'));
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:
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
WriteLPTPort(37Ah, Str_to_Byte('00100xx1'));
Edit1.Text := Byte_To_Str(ReadLPTPort($378)); WriteLPTPort(378h, Str_to_Byte('00000xx0')); 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...... |
Re: [c-lib] Parellelport-Tutorial
Um nun nicht jedesmal alle Bits vom Eingang testen zu müssen, ist es sinnvoll, abzufragen, ob überhaupt eine Änderung stattgefunden hat. Dies erledigt eine Function und liefert die Bits, die sich geändert haben.
Wir brauchen uns nur merken, wie der alte gelesene Wert war. Für die nun kommenden Prüfungen benötigen wir weitere globale Variable
Delphi-Quellcode:
Und für die Abarbeitung und Anzeige ein paar Strings
Old_In_Val : Byte; // In CreateForm wird Wert 0 zugewiesen
Event_Byte : Byte; // In CreateForm wird Wert 0 zugewiesen Event_Flag_High : Byte; // In CreateForm wird Wert 0 zugewiesen Event_Flag_Low : Byte; // In CreateForm wird Wert 0 zugewiesen
Delphi-Quellcode:
Und nun geht es los. Mit der Function Bit_Changed bekommen wir die geänderten Bits, unabhängig von der Signallage;
High_Flag_Str : string; // In CreateForm wird Wert '00000000' zugewiesen
Low_Flag_Str : string; // In CreateForm wird Wert '00000000' zugewiesen
Delphi-Quellcode:
Beispiel:
function Bit_Changed(Old_Byte, New_Byte: Byte): Byte;
var Ausg: Byte; begin Ausg := (Old_Byte xor New_Byte); Bit_Change := Ausg; end;
Code:
Xor – Wahrheitstabelle:
alt = '10011011'
neu = '10101100'
Code:
Anhand der Wahrheitstabelle erkennt man, wie's funktioniert: nur ungleiche Bit ergeben eine '1'. Bei der Anweisung Old_Byte xor New_Byte werden beide Bytes Bit für Bit verglichen.
Bit A Bit B Ergebnis
------------------------------ 0 0 0 1 0 1 0 1 1 1 1 0 Und so sieht's aus:
Code:
Mit dem Aufruf Bit_Is_Changed ( alter gelesenen Wert , EventByte) erhalte ich die Bits 1 nach 0
alt = '10011011'
neu = '10101100' --------------------- geändert = '00110111' sowie mit Bit_Is_Changed ( neuer gelesenen Wert , EventByte) erhalte ich die Bits 0 nach 1
Delphi-Quellcode:
Auch hier wieder die Erklärung:
function Bit_is_Changed(Change_Byte, Ref_Byte: Byte): Byte;
var Ausg: Byte; begin Ausg := Change_Byte and Ref_Byte; Bit_is_Changed := Ausg; end; And – Wahrheitstabelle:
Code:
Erinnern wir uns:
Bit A Bit B Ergebnis
------------------------------ 0 0 0 1 0 0 0 1 0 1 1 1
Code:
Schauen wir mal
alt = '10011011'
neu = '10101100' geändert = '00110111'
Code:
Logisch, da 5 Bit geändert wurden muss Ergebnis Änderung '0' -> '1' und '1' -> '0' in der Summe 5 ergeben.
was ist von '0' nach '1' und von '1' nach '0' gewechselt:
neu = '10101100' alt = '10011011' geändert = '00110111' geändert = '00110111' --------------------- --------------------- Ergebnis = '00100100' Ergebnis = '00010011' Also 2 Änderungen '0' -> '1' und 3 Änderungen '1' -> '0'. Passt ! Also, das neue Bit mit '1' und dem zugehörigen Änderungs – Bit mit '1' muss einen Wechsel von logisch '0' nach '1' und das alte Bit mit '1' und dem zugehörigen Änderungs – Bit mit '1' muss einen Wechsel von logisch '1' nach '0' gehabt haben. Diese Ergebnisbytes lassen sich nun abarbeiten und die auf '1' gesetzten Bit nach Bearbeitung löschen. Dadurch reagiere ich nur auf die Ereignisse und kann mir ständige if... then ... Anweisungen sparen. |
Re: [c-lib] Parellelport-Tutorial
Und los geht's:
Es macht Sinn, eine globale Variable für gelesene Bytewerte zu deklarieren
Delphi-Quellcode:
Jetzt aber.... hier der relevante Teil derTimerroutine......
Work_ In: Byte;
......ein Beispiele einer solchen Ereignisbearbeitung
Delphi-Quellcode:
Mit WriteLPTPort(37Ah, Str_to_Byte('00100xx1')) wird der Port auf "lesen" geschaltet und die Harwarebausteine selektiert. xx steht hier für die Chip-Adresse (Chipselect). Anschließend wird
begin
WriteLPTPort(37Ah, Str_to_Byte('00100xx1')); Work_In := ReadLPTPort(378h); WriteLPTPort(378h, Str_to_Byte('00000xx0')); Event_Byte := Bit_Changed(Old_In_Val, Work_In); if Pos('1', Event_Byte) <> 0 then // ab hier weiß ich, aha, eine Änderung begin Event_Flag_Low := Bit_is_Changed(Old_In_Val, Event_Byte); // hier geht was aus Event_Flag_High := Bit_is_Changed(Work_in, Event_Byte); // und hier was an Work_Str_In := Byte_To_Str(Work_In); Edit1.Text := Work_Str_In; // Eingang zur Anzeige bringen Edit3.Text := ByteToStr(EventByte); // geänderte Bits anzeigen High_Flg_Str := ByteToStr(Event_Flag_High); // für Ereignisroutine High Low_Flg_Str := ByteToStr(Event_Flag_Low); // für Ereignisroutine Low Edit4.Text := High_Flg_Str; // zum Ansehen..... Edit5.Text := Low_Flg_Str; // zum Ansehen..... Old_In_Val := Work_In; // nicht vergessen, sonst funzt es nicht end; if Pos('1', High_Flg_Str) > 0 then Action_Is_High; if Pos('1',Low_Flg_Str) > 0 then Action_Is_Low; end; das Eingangsregister in die Work_In-Variable geschrieben und der Port wieder in den Ursprung zurückgesetzt. Nun kann aus dem abgelegten alten Eingangsbyte und dem Neuen ein Ereignisbyte gebildet werden. Sind in diesem Ereignisbyte einzelne Bit auf '1' gesetzt, hat eine Änderung stattgefunden. Aus der Information altes Eingangsbyte, neues Eingangsbyte und Ereignisbyte werden die Ereignisflags Wechsel von '0' -> '1' und Wechsel von '1' -> '0' gesetzt und in eine String-Variable geschrieben. Einerseits kann man leicht ein Bild der Ereignisse in einem TEdit-Objekt anzeigen lassen, andererseits ist auch eine leichte Verarbeitung in den Prozeduren Action_Is_High und Action_Is_Low möglich. Zum Zeichen der erfolgten Verarbeitung werden die '1'-Zeichen aus dem Flag-String zu '0' gesetzt. Und so sehen die entsprechenden Ereignisroutinen aus:
Delphi-Quellcode:
Und hier die andere Reaktion...
procedure Action_Is_High;
var xPos: Integer; begin repeat XPos := Pos('1', High_Flg_Str); if xPos > 0 then begin Set_ActionBit(xPos); // diese Procedure müsst ihr aber mal selber schreiben ! High_Flg_Str[xPos] := '0'; // Bit ist bearbeitet, also brauchen wir's nicht mehr end; until xpos = 0; end;
Delphi-Quellcode:
das nehm ich euch noch ab, aber den Rest macht auch mal......
procedure Action_Is_Low;
var xPos: Integer; begin repeat XPos := Pos('1', Low_Flg_Str); if xPos > 0 then begin ReSet_ActionBit(xPos); // und die auch, da steht dann drin, was geschehen soll Low_Flg_Str[xPos] := '0'; // Bit ist bearbeitet, also brauchen wir auch nicht mehr end; until xpos = 0; end;
Delphi-Quellcode:
So, das war schon eine ganze Menge Software und auch ein wenig Einleitung in Hardware. Aber wer noch nicht damit gebastelt hat, der weiß nicht, wovon ich rede. Also, Bastelexperten, ihr könnt euch nun freien Lauf der Gedanken lassen und die Umsetzung in Programmierung vollziehen.
procedure Set_ActionBit(Bit_Number: Integer);
begin end; procedure ReSet_ActionBit(Bit_Number: Integer); begin end; Jetzt gibt's wieder Bastelstunde.... Wir haben bei der Erklärung der "tristate"-Ausgänge aufgehört. Dem möchte ich noch eines hinzufügen: Leitungen, an welchen "tristate"-Ausgänge hängen, müssen mit einem Widerstand (100k) entweder an – oder + geschaltet werden. Ich nehm immer +, weil die meisten TTL-IC mehr Strom abgeben, wenn sie Low sind. Die Erklärung spar ich mir jetzt mal, es ist einfach wichtig zu wissen, bei Low kann mehr Strom fließen. Das heißt unter anderem Leuchtdioden sind heller, wenn sie gemeinsam an Plus und vom IC den Minus bekommen. Und damit sind wir mal bei etwas, was nicht zu vernachlässigen ist. Ein Standard-TTL IC Ausgang kann ca. 10 – 20 Eingänge beschalten. Werden mehr Eingänge mit einem Ausgang beschaltet, so ist es ratsam, Bustreiber zu verwenden. Diese gibt es invertierend oder direkt. Und diese Aussage trifft speziell auf den Parallelport zu. Die Schaltung funktioniert vielleicht 10..15 Minuten, dann setzt mal hier oder da was aus und plötzlich ist's Essig mit dem tollen Experiment. Also, kommt nicht auf die Idee, ein Relais direkt am Port zu schalten und Experimente mit LED, na ja, besser ist da schon, vorher zu puffern. Könnt euch ja mal ein Datenblatt eines Standard-TTL-ICs aus dem Netz laden z.B. ![]() |
Re: [c-lib] Parellelport-Tutorial
Aber da ihr ja Daten nicht nur ausgeben sondern auch einlesen wollt, müsst ihr sowieso ein klein wenig Aufwand treiben.
So eignen sich Buspuffer mit tristate-Ausgang hervorragend für einfache Zwecke: z.B. 74 LS 244 oder 74 LS 245 Schaut in die Datenblätter und überlegt, was euch mehr nutzt. Ich glaub, der 245 invertiert die Signale. Diese Bausteine beherbergen 8 tristate Buffer in einem 20 poligen Gehäuse. Die Buffer sind jeweils zu 4 Stk in 2 Gruppen selektierbar. Und damit bin ich beim CS Signal. Oft ist über der Signalbezeichnung ein Strich. Dieser bedeutet, das ein Low-Signal die Funktion auslöst. (Low-aktiv) CS ist in vielen Fällen eines dieser Signale, die einen Datenübertrag vom Eingang (Dn) zum Ausgang (Qn) bei Low-Pegel (0-Signal) freigeben. Um den Parallelport von der Eingabe und Ausgabe zu trennen, braucht man für alle 8 Bit 2 Bausteine, wobei die Struktur des 74 LS 244 genau diese Funktion unterstützt. ![]() Die Skizze zeigt zwei gegensinnig geschaltete Buffer. Man stelle sich vor, 4 solcher Gruppen sind in einem Baustein vorhanden, CS 1 geht auf alle in Richtung "Auf" und CS 2 auf alle in Richtung "Ab". ![]() Nun muß ich nur noch CS1 mit '0' und CS2 mit 1 belegen, um Daten zum Port zu schalten und umgekehrt CS1 mit '1' und CS2 mit '0' um den Ausgang zu schalten. Da der Ausgang hier ein tristate ist, sollte man ihn vor Weiterverarbeitung mit einem Widerstand 100 K an + schalten. ![]() Nun wollen wir ein CS-Signal erzeugen. Sinnvoll ist es, ein Bit zu nehmen und festzulegen: bei '1' will ich lesen, bei '0' schreiben. Da ich dafür nicht den Datenbus benutzen möchte, bietet mir die parallele Schnittstelle ein paar weitere Signale, die sie sonst zum Handshaking mit dem Drucker benutzt. Ein Signal ist Strobe auf Pin 1. Dieses Signal bedeutet, es liegen Daten zur Ausgabe an z.B. Drucker bereit. Dieses Strobe-Signal kann über die Portadresse 37Ah zum Parallelport Pin 1 ausgegeben werden. Das zugehörige Registerbit ist Bit 0. Und genau dieses benutzen wir zur Selection der Ein- oder Ausgabe (Bit 0 = 0 -> Daten zur Ausgabe bereit). Hinweis: Dieses Bit wird Invers zum logischen Zustand geschaltet, d.h. wenn Bit = 0 dann Leitung (Pin) = 5V und wenn Bit = 1 dann Leitung (Pin) = 0V! Schließe ich nun CS1 direkt und CS2 über einen Inverter an Pin 1 vom Parallelport, habe ich schon einmal ein Richtungsbit. Mit
Delphi-Quellcode:
wird Pin 1 vom Parallelport auf '0' gelegt.
WriteLPTPort(37Ah, Str_To_Byte('xxxxxxx1')); // 'xx1xxxx1' Bit 5 ist Steuerbit für Bidirektional
Somit wird CS1 = '0' und dadurch der Eingabekanal durchgeschaltet. Mit
Delphi-Quellcode:
wird Pin 1 vom Parallelport auf '1' gelegt.
WriteLPTPort(37Ah, Str_To_Byte('xxxxxxx0')); // 'xx0xxxx0'
CS1 bekommt High-Pegel und durch den Inverter CS2 Low-Pegel. Der Ausgabekanal wird durchgeschaltet. Es lassen sich nun mit den ersten 3 Bits der Portadresse bis zu weiteren 8 CS Signale erzeugen, die sowohl Ein- oder Ausgabekanäle freigeben können. Das heißt im Klartext: ich kann eine Schaltung entwerfen, die mir 8 Kanäle mit jeweils 8 Bit also 64 Ein- und 64 Ausgänge bietet. Ein wenig beachten sollte man die Signallage zu Potentiallage. Dies ist beim Steuerregister nicht immer gleich und deshalb werde ich jetzt Pin 1 und 14 mit Invertern Beschalten. Damit habe ich wieder Bit = Signallage. (siehe Hinweis !) ![]() Diesen 3 Leitungen kann ich eine diskrete Schaltung verpassen, oder einen 3 zu 8 Decoder benutzen. SN 74 irgendwas, ich krieg das noch heraus. Nun Kann ich wirklich sagen:
Code:
und:
'00000000' schreibt Kanal 0
'00000010' schreibt Kanal 1 '00000100' schreibt Kanal 2 '00000110' schreibt Kanal 3 '00001000' schreibt Kanal 4 '00001010' schreibt Kanal 5 '00001100' schreibt Kanal 6 '00001110' schreibt Kanal 7
Code:
'00010001' liest Kanal 0
'00010011' liest Kanal 1 '00010101' liest Kanal 2 '00010111' liest Kanal 3 '00011001' liest Kanal 4 '00011011' liest Kanal 5 '00011101' liest Kanal 6 '00011111' liest Kanal 7 |
Re: [c-lib] Parellelport-Tutorial
Wer nicht gleich so riesig aufbauen will, hier eine Schaltung mit einem 74LS00 (4 -fach Nand) und 2 zusätzlichen Invertern 74LS06 (6-fach Inverter) zum Beispiel für 4 Kanäle In und 4 Kanäle Out.
Na ja, Zeichnungstechnisch nich so pralle, aber was nutzt euch eine tolle Zeichnung in EPlan oder Autosketch, wenn ihr dafür diese Zeichnung nicht zu Gesicht bekommt. Ich glaube auch so, das ihr erkennen könnt, worauf es ankommt. Auch hier gibt's für die NAND eine Wahrheitstabelle:
Code:
Hier die Wahrheitstabelle für die gesamte Schaltung und den Bits 1 und 2 des Steuerregisters:
Bit A Bit B Ergebnis
------------------------------ 0 0 1 1 0 1 0 1 1 1 1 0
Code:
In den Ausg. Sel 0 bis Sel 3 ist dem Eingangsbitmuster entsprechend immer nur 1 Ausgang auf Low und damit habe ich das benötigte CS invers Signal.
Bit 1 Bit 2 Sel 0 Sel 1 Sel 2 Sel 3 Sel 0 Sel 1 Sel 2 Sel 3
Reg Pin Reg Pin A B A B A B A B Ausg Ausg Ausg Ausg --------------------------------------------------------------------------------- 0 1 0 1 1 1 1 0 0 1 0 0 0 1 1 1 1 0 0 1 0 1 1 1 0 0 1 0 1 0 1 1 0 1 1 0 1 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 0 0 0 1 1 0 1 1 1 1 1 1 ![]() Dieses muss nur noch mit dem Bit 0 für Ein- oder Ausgabe verknüpft werden um eine saubere Trennung der Ein- und Ausgangskanäle zu bekommen. So, das war ja nun eine Menge Theorie, und vielleicht fragt sich der ein oder andere, toll, aber wie bastel ich nun die Elemente auf eine Platine und wie löte ich die Verbindungen zusammen. Also, auch ich ätz nich gleich ein paar Leiterbahnen aus einem Kupferblech. Für sowas, wo man noch gar nicht so richtig weiß, ob das überhaupt das ist, was man will und ob's so funzt, wie man es sich vorstellt, nehme ich eine Lochrasterplatine mit nur Lötaugen. Da kommen dann entsprechend der Schaltung, die ich mir ausgedacht habe, Fassungen drauf. Nicht zu eng, ruhig ein bißchen Luft lassen. Die Verdrahtung (na ja, vielleicht nicht unbedingt der Bringer, aber durchaus praktikabel) ist die Verwendung einer alten Trafowicklung. Der dünne Kupferdraht ist durch seine Lackierung isoliert, lässt sich auch ganz gut löten und durch die freien Löcher der Lochrasterplatine stecken. Allerdings gibt's auch Kupferlackdraht in verschiedenen Stärken bei Conrad oder anderen Elektronikhändlern. Zum Lötkolben, da benutze ich eine Lötstation von Obi. Die Temperatur der Lötspitze lässt sich gut regeln, und die Spitzen verbrauchen sich nicht zu schnell. Ganz wichtig ist ein gutes Lötzinn. Lasst die Finger von Lötpasten aller Art. Saubere Lötstellen werden mit einem guten dünnen Elektroniklot mit eingebetteten Fließmittel erreicht. Es ist zwar nicht billig, aber man muss eh nicht sonderlich damit umherschlampen und weniger ist oft Masse genug. Wenn die Lötspitze an einem nassen Silikonschwamm regelmäßig gereinigt wird, gibt es auch fast immer gleich einen sauberen Wärmeschluß und man kann das Lötzinn für die Lötstelle exakt dosieren. Jetzt die Frage: Welche Spannungen werden für Experimente benötigt und wo baue ich die Schaltung hin. Also, da die alten Rechner sowieso nicht viel bringen, wenn man diese loswerden will, habe ich sie erstmal behalten. Mit dem Erfolg, nun gleich 3 alte Schätzchen herumstehen zu haben. Aber selbst, wenn kein Alter mehr verfügbar ist, die Zeitungen bieten immer mal einen ausrangerten Oldie. So habe ich meine Schaltung auf alte Slotabdeckungsbleche sowie den 25pol. Verbindungsstecker für den Parallelport geschraubt. Muss man aber nicht, nur meine Slotbleche hatten bereits die Stecker vorgesehen. Platz ist auch für einen Haufen an Relais und sonstigem Schnickschnack und eine pannungsversorgung für 12 V und 5 V ist auch greifbar. Und wenn der max. Ausbau für den LPT Port nich reicht, dann rüstet eben einen 2. 3. oder 4. nach. Vielleicht gibt es noch welche, aber bitte, betreibt damit kein Kernkraftwerk..... oder ein Fließband einer Autoproduktionsanlage..... Hier eine Darstellung der Anschaltung an den Parallelport mit dem Datenbusbuffer SN 74 LS 244. Auch die Anschaltung der Ein- oder Ausgabebausteine ist in der nachfolgenden Skizze angegeben. Bei den Selektions-Signalen der Ausgabe ist es notwendig, diese mit der Schreibrichtung zu verknüpfen. ![]() ![]() So, noch ein bißchen Schalttechnik. Also, TTL-Signale können wir ja schon ganz gut erzeugen, aber wie steht es mit Ansteuerungen von Relais oder Motoren. Wie bringe ich Signale in den Rechner, die nicht von einem Schalter stammen, so z. B. Licht oder Wärme. Wie sieht's aus mit analogen Werten so im Bereich von 0 bis 10 V oder gar negative Potentiale –10 V bis +10 V. Genug der Frage, fangen wir an, Probleme zu lösen. Also, mal ganz ehrlich, anloge Werte über Parallelport würd ich nicht machen, da geb ich den Ball ganz gern an weitere Experten, die vielleicht schon mal was mit den seriellen Port angestellt haben. Vielleicht werd ich zum Schluß eine kleine Applikation bringen.... Ich liebe die Digitaltechnik. Da weiß man, was einem blüht. Entweder geht oder geht nicht, ein geht vielleicht oder nur ein bißchen ist da ausgeschlossen. Licht an oder aus. So isses. So können wir jetzt ohne Probleme sagen, komm PC, mach mal den Pin 3 vom LPT auf 5 V und die Pin's 2, 4, 5, 6, 7, 8, 9 auf 0 V. Das geht. Aber um ein Relais zu schalten, grad die, die in der Bastelkiste sind oder ein Elektronikladen für'n €uro fünfzig im Sonderangebot verscherbelt mit 12 V Spule, ne das geht nich. Oder nur durch Vorschalten eines schweineteuren 5V TTL-Relais, welches trotzdem noch sowas wie'n Treiber vorgeschaltet kriegen sollte. Ich kann euch nur sagen, wenn ihr sowieso schon bei den Elektronikbuden einkauft, dann schaut euch mal richtig um. Es braucht für das Schalten einer 12 V Spule lediglich ein paar Cents für einen Transistor, eine Diode (Freilauf, ich erklär's später) und einen Widerstand. In der Regel reicht's schon. Aber wie krieg ich 5 V TTL Pegel auf 12 V für'n Relais. Dafür nun nochmal zurück zum Anfang...
Ich will euch nicht schon wieder mit viel Theorie zuquatschen, aber schaut euch mal folgende Schaltung an: Gut, nix besonderes, aber sie funktioniert. Die Stromkreise mit dem 5 V TTL-Pegel und der 12 V Lastspannung sind verbunden mit einer gemeinsamen Masse. Der Transistor kann leitend werden, wenn in seinem Emitter ein Strom fließt und das Relais zum anziehen bringen. Oder so ähnlich. Auch hier sind bestimmt nicht alle meiner Meinung, aber so komplizierte Dinge wie Arbeitspunkt und Emitter-Basisstrom und was so ein Transistor sonst noch so alles hat, ich lass es hier weg. Wer will, der kann da gern ein paar Zeilen zu schreiben. Mir geht's nur darum: Das Relais muss anziehen, wenn ein High TTL-Pegel anliegt und bei Low TTL-Pegel V abfallen oder evtl. umgekehrt. Wichtig ist, mein Relais reagiert auf meine Ausgabe per Programm auf die Signale am Port. Da ein Relais eine Spule hat, in der ein Magnetfeld erzeugt wird, wird auch vom Relais eine Spannung erzeugt, wenn der Magnet sich abschaltet. Und die ist nicht zu ignorieren. Sie kann ein vielfaches von dem haben, was die Elektronik dieser Schaltung abkann. (Kein Mensch käme auf die Idee, diese Schaltung an 50, 80 oder gar 120 V zu hängen....) Tja, die arme Diode, sie ist nun dazu da, diese Spannung kurzzuschließen und unwirksam zu machen. Gut, sie kann es und der Rest der Schaltung erfreut sich eines ungestörten Elektroniklebens.... |
Re: Parellelport-Tutorial
Natürlich haben sich die Experten der Halbleiterindustrie auch da etwas einfallen lassen.
Der ULN 2803 beherbergt 8 Schaltkreise, die mit TTL- Pegeln versorgt und im Ausgang Relais bis 30V schalten können. Freilaufdioden sind schon drin. Damit nun die Ausgänge bei einer Selektierung eines anderen Kanales nicht ihren Wert verlieren, ist für Ausgänge ein 8-Daten-Latch geeignet. Man legt die Daten 8 Bit breit an und schickt einen Schreibimpuls über die Lesen/Schreiben Leitung. Fedisch. Es ist für Experimente sowieso besser, man teilt die Hardware auf. Z.B. In eine Portkarte mit der Aufbereitung der Kanalselektion und einen Portpuffer, um den LPT vor unbeabsichtigter Zerstörung zu sichern. Nun können simple Relaiskarten gebaut werden, die am Portpuffer hängen, eine Selektion erhalten und das Schreibsignal für die Data-Latches. Die Ausgänge der Data-Latches können direkt auf den ULN und an diesen wiederum direkt die Relais. Nun noch Klemmen für die Relaikontakte und ab geht er der Peter...... Eingangsmäßig ebenso. Hier verwenden wir keine Data-Latches sondern die Portpuffer. Jeder wird komplett als Eingang geschaltet, d.h. CS1 und CS2 kommen an die gleiche Kanal-Selektion. Wichtig ist: Alle Eingänge sind mit 100k an + zu binden, da sonst unbeschaltete Eingänge kein eindeutiges Logiksignal liefert. Dies kann die gesamte Schaltung beeinflussen, ja sogar Bausteine zerstören. Jeder Eingangskanal kann nun den Bedürfnissen angepasst werden. Z.B. ein Analog-Digitalwandler, eine Anpassung um einen Hell-Dunkel-Wechsel auf einem LDR(Lichtempfindlicher Widerstand) einzulesen oder ganz einfach eine Abfrage eines mechanischen Kontaktes. Wichtig ist: Der Signalpegel zur Schnittstelle ist TTL Norm (Low = 0 V, High = 5 V) Es sei noch bemerkt, das ein Low-Pegel nicht ganz 0 V hat und ein High-Pegel auch nicht ganz 5 V, nur dass ihr euch beim Messen nicht wundert........ Sollte es euch nun gelungen sein, mit Hilfe meiner "flachmännischen" Beratung doch tatsächlich Werte aus- bzw. in den Computer zubekommen, und zwar über eine eigens dafür zurechtgestrickte Hardware, fernab von Tastatur und Monitor, ja dann werdet ihr auch Vertrauen haben in die weiteren Programmfragmente, welche ich euch noch vorstellen möchte. Aber zuerst ein paar Gedanken dazu: Was will ich mit den eingelesenen Informationen in Form von Bits und Bytes anfangen und was mit der Möglichkeit, doch das ein oder andere Relais zum anziehen zu bringen ? Machen wir wieder ein paar kleine Steps und versuchen, visuelle Objekte zu indizieren. So z.B. eine TCheckbox einem Bit im String zuzuordnen. Z.B. Durch Anklicken erreichen, das ein Relais schaltet. Natürlich kann ich hergehen und im Code fest verankern
Delphi-Quellcode:
Nehmen wir einen String mit Namen Work_Out, der in Formcreate mit '00000000' initialisiert ist.
Tcheckbox.Name = 'CB_Bit_0';
Durch die Abfrage
Delphi-Quellcode:
Etc.
if CB_Bit_0.Checked then
Work_Out[8 - 0] := '1' else Work_Out[8 - 0] := '0'; if CB_Bit_1.Checked then Work_Out[8 - 1] := '1' else Work_Out[8 - 1] := '0'; // ... Sehr mühselig und steif. Auch eine Schleife bringt so nicht viel:
Delphi-Quellcode:
Viel eleganter ist doch dies....
for i := 0 to Length(Work_Out) - 1 do
begin if i = 0 then if CB_Bit_0.Checked then Work_Out[8 - i] := '1' else Work_Out[8 - i] := '0'; if i = 1 then if CB_Bit_0.Checked then Work_Out[8 - i] := '1' else Work_Out[8 - i] := '0'; // ... end;
Delphi-Quellcode:
Klar ist natürlich, das die Checkboxobjekte auch entsprechend angeordnet sind, damit auch Bit 0 zur Checkbox mit dem Namen 'CB_Bit_0' passt.
for i := 0 to Length(Work_Out) - 1 do
begin if TCheckbox(FindComponent(' CB_Bit_' + IntToStr(i))).Checked then Work_Out[8 - i] := '1' else Work_Out[8 - i] := '0'; end; Geht natürlich auch umgekehrt, um die "gesetzten Bit" in einem String in Checkboxen zu übertragen:
Delphi-Quellcode:
Ah ja, jetzt können wir auch direkt über einen Index auf ein visuelles Objekt zugreifen, bzw. dessen Eigenschaften ändern.Zum Beispiel die Farbe von TPanel ändern:
for i := 0 to Length(Work_In) - 1 do
begin if Work_In[8 - i] = '1' then TCheckbox(FindComponent('CB_Bit_' + IntToStr(i))).Checked := true else TCheckbox(FindComponent('CB_Bit_' + IntToStr(i))).Checked := false; end;
Delphi-Quellcode:
Manch einem erzähl ich hier nix neues, nun ja, für Fortgeschrittene sollte dieser kleine Kurs ja auch nicht sein, da brauch ich selber einen. Aber so ein paar Raffinessen und Zugriffsmethoden, nun, die möchte ich hier schon erklären, weil ich gleich so richtig ausholen werde.......
for i := 0 to Length(Work_In) - 1 do
begin if Work_In[8 - i] = '1' then TPanel(FindComponent('PN_Bit_' + IntToStr(i))).Color := clRed else TPanel(FindComponent('PN _Bit_' + IntToStr(i))).Color := clGreen; end; Also, wir haben eine Hardware gebastelt. Wir haben ein Programmrumpf, um Informationen über den Parallelport zu lesen und zu schreiben. Wir können Relais schalten. Und nun...... Schreiben wir für jede Anwendung ein Programm in Delphi. Jedesmal, wenn ein Relais geschaltet werden soll, rufe ich ein Programm x, y oder z auf ? Geht es nicht eleganter ? Jo, es geht...... Vielleicht in einem späteren Beitrag |
Re: Parellelport-Tutorial
Hi Matze
Vielen Dank für deine Mühe. Ich hoffe, es wird einigen eine Hilfe sein. Gruß oldMax |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:27 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