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
ReadLPTPort: Byte
Kleines Beispiel:
Delphi-Quellcode:
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;
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.
Wie kann ich erkennen, welche Schalter hinter dem Wert 163 z. B. stehen.
Und jetzt geb ich euch eine Function.
function Byte_To_Str(ByteWert: Byte): string;
Na, ist das was? Na gut, geb ich euch eben den zugehörigen Quellcode.
Delphi-Quellcode:
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;
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.
Klartext:
Code:
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")
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....
Wenn ihr wollt:
Edit1.Text := Byte_To_Str(ReadLPTPort);
Und weil ich es schon hab und ihr es auch wollt, gleich die Kehrseite, nämlich die "1" aus einem String
zum Ansteuern von irgendwas nehmen:
Delphi-Quellcode:
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;
Funktioniert folgendermaßen:
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.
for i := 0 to Length(Str_Val) - 1 do ...
Beachte:
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
Function Power(Basis, Exp).
Delphi-Quellcode:
if Str_Val[Length(Str_Val) - i] = '1' then
Ausg := Ausg + Power(2, i); ...
Sie liefert allerdings einen Realwert, daher muss der Ausgang letztlich mittels Trunc-Function zugewiesen werden.
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.
WriteLPTPort: Byte;
Dann könnte die Ausgabe eines Textfeldes an den LPT1 folgendermaßen lauten:
Delphi-Quellcode:
WriteLPTPort := Str_To_Byte(Edit1.Text);
asm
Mov DX, $378
Mov AL, WriteLPTPort
Out DX, AL
end;
So, hat doch was.
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....