HSG |
|
Bei der seriellen Schnittstelle wird gewöhnlich das RS-232 -Protokoll zur Datenübertragung benutzt. Wir wollen eine stark vereinfachte Variante, miniRS232 benutzen.
In einem ersten Schritt soll das Bitmuster '01000101' mit der festen Bitlänge von 0.2s gesendet werden. Die Aufgabe dient als 'Fingerübung' und soll möglichst einfach realisiert werden. Unter Python wird man ein kleines Programm ohne GUI schreiben. Die sleep-Anweisung ist auch in Python verfügbar. Zur Kontrolle soll das Gesendete mit einem Oszilloskop-Programm empfangen werden. Bitte bedenken, dass das Protokoll mit der steigenden Flanke des Startbits beginnt. Will man das sicherstellen, so ist die Leitung zunächst auf Null zu setzen. send0qd.py
Aufgabe 1 soll nun so strukturiert gelöst werden, dass eine Übertragung auf unterschiedliche Schnittstellen, verschiedene Bitzeiten und beliebige Byte-Folgen möglich ist. Dazu könnte man eine Prozedur - in Python eine Funktion ohne Rückgabe - sendbyte schreiben, die das zu sendende Byte, die Bitzeit und Funktion, die die Leitung setzt, als Parameter hat. Eine Funktion ByteToBin, die ein Byte in die Einzelbits zerlegt, könnte als Teillösung nützlich sein. send1.py
Wer ein Byte senden kann, kann natürlich auch eine Bytefolge senden. Die Bytefolge könnte dabei ein codierter String sein. So sendet z.B.
>>> for b in bytes('Hallö','utf8'): sendbyte(b,0.1,s.setRTS)
die utf8-codierte Nachricht 'Hallö'. Preisfrage: Aus wie vielen Bytes besteht diese Nachricht?
Es ist wichtig sich klarzumachen, dass nur Bytes versendet und empfangen werden. Nun will man aber auch Strings der Art 'Hallö Welt!' versenden können. Dazu muss aus der Zeichenfolge eine Bytefolge gemacht werden. Bei dem Zeichen 'H' denkt man schnell an 72, das ist die ASCII-Codierung, die allen üblichen Codierungen zugrunde liegt, aber eben nur für Zeichen bis zur Nummer 127. Wie soll man aber z.B. ein 'ö' codieren? Das 'ö' hat die Unicodenummer 246. Ein Zeichen mit der Nummer 246 wird aber in utf8 mit 2 Bytes codiert. Werden solche Folgen in einem Bit gestört, so sind sie schnell nicht mehr decodierbar, was zu Abbrüchen führt. Wählt man eine 1-Byte-Codierung, so gibt es keine Abbrüche, sondern nur fehlerhafte Zeichen. Ein möglicher Standard wäre dann iso-8859-1. Man könnte aber auch einfach die Unicode-Tabelle zur Codierung benutzen. Dann kommt man mit den bekannten, in den meisten Sprachen vorhandenen, Standardfunktionen ord und chr aus, muss aber auf die Zeichen jenseits der '255-Grenze' verzichten.
def codiert(s): """ wandelt einen Python-String in eine Byte-Folge um, dabei wird ein Python-Zeichen ch zu dem Byte ord(ch), falls ord(ch) > 255 ist, wird auf 255 zurueckgesetzt """ def ordx(ch): b = ord(ch) if b > 255: return 255 else: return b return bytes([ordx(ch) for ch in s]) def decodiert(bf): """ wandelt eine Bytefolge bf in einen Pythonstring um, dabei wird aus einem Byte b das Zeichen chr(b) """ return ''.join([chr(b) for b in bf])
Tests
Hier lernt man das berühmt berüchtigte Zeichen mit der Nummer 255 kennen: 'ÿ'
>>> s = 'Hallö Welt!' >>> bf = codiert(s) >>> bf b'Hall\xf6 Welt!' >>> s1 = decodiert(bf) >>> s1 'Hallö Welt!' >>> s = '^³€ß' >>> bf = codiert(s) >>> bf b'^\xb3\xff\xdf' >>> s1 = decodiert(bf) >>> s1 '^³ÿß'
Es soll nun ein Programm mit GUI geschieben werden, das komfortabel das Senden von Text-Nachrichten ermöglicht. Für die Auswahl der Schnittstelle bietet sich ein Optionmenü, für die Eingabe der Bitzeit ein Entry-Feld, für die Eingabe der Nachricht ein Text-Feld an.
Entwickle in verschiedenen Schritten ein Programm, das zunächst nur das Bitmuster '01000101' mit der festen Bitlänge von 20ms sendet. Dann soll im nächsten Schritt die Baudrate und das Zeichen eingelesen werden. Schließlich soll im dritten Schritt ein String aus einem Memo-Feld mit der eingelesenen Baudrate gesendet werden. Es soll ein Startbit und ein Stoppbit verwendet werden. Die Zeichen sollen mit Hilfe der eingebauten Zeichentabelle kodiert und mit dem höchstwertigen Bit voraus gesendet werden. Ein Paritätsbit soll nicht verwendet werden. Die Klasse TNetzHW steht zur Verfügung und soll der Ansteuerung der seriellen Schnittstelle COM1 verwendet werden. Zum Test kann z.B. ein Null-Modem-Kabel und ein zur Verfügung gestelltes Oszilloskop-Programm benutzt werden. Die Oberfläche soll der Vorgabe entsprechen. Das Programm benötigt keine Threads und kein MVC! Die gemachten Tests sind zu dokumentieren.
procedure TForm1.bSende1Click(Sender: TObject); begin // Startbit NetzHW.SetAus(true); sleep(20); // Datenbits NetzHW.SetAus(false); sleep(20); NetzHW.SetAus(true); sleep(20); NetzHW.SetAus(false); sleep(20); NetzHW.SetAus(false); sleep(20); NetzHW.SetAus(false); sleep(20); NetzHW.SetAus(true); sleep(20); NetzHW.SetAus(false); sleep(20); NetzHW.SetAus(true); sleep(20); // Stoppbit NetzHW.SetAus(false); sleep(20); end;
Zumindest auf einigen Rechnern kann man wesentlich höhere Baud-Raten erreichen, wenn man am Anfang des Programms die Zeitauflösung von sleep mit
... uses ...., mmsystem, ... ... TimeBeginPeriod(1);
auf eine große Granularität schaltet und am Schluss mit
TimeEndPeriod(1);
wieder ausschaltet.