Ganz generell wuerde ich dir empfehlen mit NASM zu assemblieren und den weltweiten Pseudostandart zu verwenden.
Sonst ist es btw doch etwas uebertrieben fuer soetwas ASM zu benuetzen. Such dir lieber einen C-Codefetzen der ueber die API den Port anspricht. So wird es auch fuer dich verstaendlicher, denke ich. Mit Hochsprachen scheinst du ja besser vertraut zu sein.
So, da es eine Gruppenarbeit ist und sich jeder um einen anderen Ansatz zum Auslesen der seriellen Schnittstelle kümmert (damit wir am Ende ein möglichst breites Spektrum an Möglichkeiten zumindest untersucht haben), arbeite ich trotz der gut gemeinten Ratschläge, das Problem mit einer höheren Sprache zu lösen, vorerst weiter mit Assembler (Aber zumindest den vorgeschlagenen Netwide Assembler).
Ich habe dieses Programm geschrieben:Es überprüft, ob an der seriellen Schnittstelle Daten vorhanden sind und gibt sie aus. Wenn keine Daten vorhanden sind, wird der "D"-Befehl an das Gerät geschickt, der nach dem >> Informationsblatt des Gerätes (PDF, ~600 kB), (siehe Seite 3) die Datenübertragung aktivieren soll.
Allerdings werden neben dem Status der seriellen Schnittstelle keine Daten ausgegeben, sondern nur "D"s, bzw, wie ich inzwischen herausgefunden habe, das, was gerade im AL-Register (und damit wegen einer Zuweisung in der Variable "zeichen") steht, in ASCII. Dabei sollte die Funktion "zeichen_empfangen" eigentlich das an der Schnittstelle vorhandene Zeichen in AL speichern (siehe >> Interrupt 14).
Ist das Gerät kaputt (die Anzeige am Gerät selber funktioniert noch problemlos und richtig, es ist eben nur ein bischen älter) oder habe ich irgendetwas falsch gemacht?
Nun habe ich mich 10 Minuten lang darüber geärgert, dass das Programm nicht funktioniert, bis mir einfiel, dass ich an diesem Computer gar keinen COM-Port habe. -_-
Naja, das Messgerät ist leider Eigentum der Schule, wo es aus diesem Grund auch momentan steht, aber ich werde das Programm Montag in einer Freistunde mal ausprobieren, um zu sehen, ob das Gerät überhaupt funktioniert. Danke für den Link.
Um mich etwas genauer mit der Funktionsweise der seriellen Schnittstelle zu beschäftigen und mir nicht bloß von Microsoft und ihrem Interrupt 14h den Arsch hinterhertragen zu lassen habe ich versucht, die serielle Schnittstelle mit einer Anleitung aus dem Internet selber zu initialisieren. Allerdings habe ich Probleme mit einem Assembler-Befehl. Es geht um out.
Die allgemeine Syntax lautet:Kann mir jemand Folgendes erklären:Sowohl AL als auch AH sind doch 8-Bit-Register, warum verhalten sie sich dann an dieser Stelle unterschiedlich?
Damit kann ich allerdings noch leben. Was mir merkwürdig vorkommt ist allerdings, dass folgende Syntax des out-Befehls einen Fehler verursacht:
Out akzeptiert als zweiten Operanden prinzipiell nur al. Das hat vermutlich intern einige Vorteile und man muss sich einfach daran halten. Die Adresse darf, soweit ich weiß, bis 255 als Direktwert angegeben werden. Danach sollte man dafür das dx Register nutzen und und keine Variable.
Danke, das erwähnen viele Quellen, die ich im Internet gefunden habe, gar nicht.
[FONT="Courier New"]out [com1], whatever[/FONT] wäre so schön anschaulich gewesen. Dadurch, dass ich nun vorher den zu versendenden Wert an AL und die Port-Adresse an DX senden muss, verdreifacht sich die Schreibarbeit und der Quelltext wird recht unübersichtlich, aber dagegen lässt sich wohl nicht viel machen.
Gibt es eigentlich irgendeine Möglichkeit, einen Timer unter Assembler einzusetzen? Ich würde die Schleife, die auf Daten von dem Gerät wartet, ganz gerne unterbrechen, wenn nach beispielsweise 2 Sekunden noch keine Daten gesendet worden sind.
Gibt es eigentlich irgendeine Möglichkeit, einen Timer unter Assembler einzusetzen? Ich würde die Schleife, die auf Daten von dem Gerät wartet, ganz gerne unterbrechen, wenn nach beispielsweise 2 Sekunden noch keine Daten gesendet worden sind.
...
Du könntest dir ja selbst einen kleinen Timer schreiben. Wie man die Uhrzeit ausliest etc. dürfte man mit Google schnell finden. Oder du nutzt einen fertigen, wie zum Beispiel den Timer der WinAPI. Am einfachsten wäre es aber, eine Schleife zu schreiben, die immer überprüft, ob ein neues Zeichen da ist, und nur dann vom Port liest, wenn ein neue Wert vorhanden ist.
Am einfachsten wäre es aber, eine Schleife zu schreiben, die immer überprüft, ob ein neues Zeichen da ist, und nur dann vom Port liest, wenn ein neue Wert vorhanden ist.
...
Das habe ich ja getan. Die Schleife bricht im Moment nur dann ab, wenn 14 Bytes von dem Gerät empfangen wurden (14 hängt mit dem Datenformat des Multimeters zusammen). Aber es kann ja auch vorkommen, dass das Gerät aus irgendeinem Grund nichts sendet, dann muss die Schleife nach einer gewissen Zeit auch abgebrochen und eine Fehlermeldung ausgegeben werden. Dafür brauche ich den Timer.
Naja, ich werde einfach mal suchen, dafür gibt es sicher fertige DOS-Interrupts, die man aufrufen kann. Aber nicht mehr heute. ^^
Ich habe das von Crash-Override gepostete Programm mal ausprobiert und festgestellt, dass das Gerät funktioniert. Man sendet ein großes "D" und das Gerät gibt die derzeitige Messwertanzeige zurück.
Mein Programm funktioniert allerdings nicht, es gibt nichts aus und wird einfach kurz nach dem Start beendet (nichteinmal eine halbe Sekunde). Ich habe keine Ahnung, wo der Fehler liegt.
Die Empfangsschleife wird mehrfach durchlaufen, dass habe ich schon überprüft. Genaueres kann ich nicht sagen, da das Gerät in der Schule steht und ich es hier (zuhause) nicht testen kann.
Nachtrag:
Ok, ich habe bei der Initialisierung vergessen, die Interrupts richtig einzustellen, das habe ich jetzt geändert (allerdings nicht im obigen Quelltext). Ich werde es morgen erstmal ausprobieren.
Nachtrag #2:
Es hat zwar noch nicht funktioniert, aber ich bin auf dem richtigen Weg. ^^
Ich habe jetzt verschiedene Fehler beseitigt, aber das Programm läuft immernoch nicht. Irgendwas stimmt noch nicht. Ich überprüfe im Programm den Status der seriellen Schnittstelle und bekomme einen Apostroph raus (ASCII-Codierung des Statusbytes). Allerdings gibt es im ASCII-Zeichensatz 4 oder 5 verschiedene Apostrophen, die in meinen Augen alle relativ gleich aussehen, aber eben durch unterschiedliche Bitkombinationen codiert werden. Weiß zufällig jemand, wie ich die einzelnen Bits eines Bytes direkt ausgeben kann?
Ja, ich bin tatsächlich skrupellos genug für einen tripple post.
Nachtrag:
Oh, vergesst es, ist nicht so wichtig. 3 der 5 möglichen Zeichen fallen raus, weil das höchste Bit, das eigentlich immer 0 ist, dann 1 sein müsste. Es gibt also noch zwei mögliche Statusmöglichkeiten:
00100111 >> Daten vorhanden, Überlauf, Paritätsfehler, Senderegister enthält noch Daten
01100000 >> Senderegister enthält noch Daten / sendet gerade Daten
Zu deiner Frage nach den einzelnen Bits abfragen ... sowas macht man idR mit AND und einer Konstanten.
Das AND wird bitweise auf die ganze Zahl angewendet.
Zur Erinnerung: 0 AND 0 = 0, 1 AND 0 = 0; 0 AND 1 = 0; 1 AND 1 = 1
Wenn die verwendete Konstante nun gerade die Zweierpotenz ist, die dein Bit repraesentiert (z.B. 1 SHL 5 = 32 = 00100000b = nur bit 5 gesetzt [merke nullindexiert]) und man diese Konstante mit der Zahl AND verknuepft, dann kommt nur dann ein Ergebniss ungleich 0 raus, wenn das entsprechende Bit gesetzt ist.
10110110b AND 00100000b
00100000b
01011010b AND 00100000b
00000000b
Das geht natuerlich auch, wenn du mehere Bits gleichzeitig abfragen willst. Hierbei treten dann 3 verschiedenen Faelle ein
a) Zahl AND Konstante == Konstante -> alle Bits aus Konstante sind gesetzt
b) Zahl AND Konstante != 0 -> mindestens ein Bit stimmt ueberein, Wert sind die uebereinstimmenden Bits
c) Zahl AND Konstante == 0 -> keines der Bits ist gesetzt.
Und um die Sache komplett zu machen: mit OR kann man Bits in einem Wert setzen und mit XOR abwechselnd an und aus stellen.