Nachdem ich schon serielle Daten einer RS232 mit dem
Trigger-Oszilloskop
im Testlab ansehen konnte, kommt nun der nächste Schritt: Programmieren
eines Software-UART, erstmal nur in Empfangsrichtung. Für den
ersten Versuch wurde eine Übertragungsgeschwindigkeit von 100 Baud
gewählt, weil das gut zum Timing in PicoBasic passt. Das Ziel war, dass
ich beliebige Bytes vom PC abschicke, die dann an acht LEDs angezeigt
werden. Sinnlos, könnte man denken, weil der Controller das ja über USB
und seinen Hardware-UART schon kann. Aber das Fernziel ist eine
Kommunikation zwischen zwei Controllern ohne Umweg über den PC.
Als Eingang verwende ich AD0, damit alle acht Bits des Ausgabeports
frei bleiben. Dadurch wird zwar mehr Zeit verbraucht, aber das spielt
keine Rolle, solange ich das Timing im Millisekundentakt halten kann.
Zur Erkennung der Pegel verwende ich Vergleiche mit 128. B = 128 kann
dann im ganzen Programm stehen bleiben und dient auch dazu, das höchste
Datenbit zu setzen, wenn der entsprechende Pegel zur passenden Zeit
erkannt wird. Die RS232 sendet zwar Bit 0 zuerst, aber die Daten
wandern Schritt für Schritt nach rechts, sodass das zuerst empfangene
Bit am Ende bei Bit 0 steht.
Rem RX100Bd
0x09FF Pdir = 255
L1:
0x2105 Call L2:
0x4500 Pout = A
0x4200 Print A
0x2001 Jmp L1:
L2:
0x0280 B = 128
0x3C00 A = AD0
0x2405 If A<B Jmp L2:
0x190F Delay ms = 15
0x0400 D = 0
0x0307 C = 7
L3:
0x3900 A = D
0x3200 A = A Shr 1
0x3800 D = A
0x3C00 A = AD0
0x2313 If A>B Jmp L4:
0x3900 A = D
0x2A00 A = A + B
0x3800 D = A
L4:
0x3900 A = D
0x190A Delay ms = 10
0x250B C*Jmp L3:
0x4800 Ret
Jedes Bit benötigt bei 100 Baud eine Zeit von 10 ms. Zuerst wird
auf das Startbit gewartet. Dazu dient eine schnelle Schleife ohne
Wartezeiten. Solange A kleiner B ist, also die Spannung unter 128
erscheint, wird nach L2 gesprungen. Sobald eine positive Flanke erkannt
wurde, geht es weiter. Zuerst wird aber 15 ms gewartet, damit die
nächste Abfrage mitten im ersten Datenbit landet. Ein Low-Pegel
bedeutet ein 1-Bit, dann wird B zu A hinzuaddiert, also das höchste Bit
gesetzt. Beim nächsten Durchlauf der Empfangsschleife werden zuerst alle
Bits um eine Stelle nach rechts geschoben. Immer wieder muss A in D
zwischengespeichert werden, weil A auch für die Spannungsmessung
gebraucht wird. Die Zählschleife wird mit C = 7 gestartet, weil ja der
erste Durchlauf dazukommt und so insgesamt acht Bits gelesen werden.
Das sieht alles ganz einfach aus, aber ich habe mehrere Tests und
Korrekturen gebraucht, bis alles richtig funktionierte. Als ich dann
mit meinem Terminal alle acht LEDs steuern konnte, war das ein
Erfolgserlebnis wie vor Jahrzehnten, als sich das zum ersten Mal mit
einem 8048 in Assembler geschafft habe, damals mit 1200 Baud. In
Assembler muss ich genau die pro Befehl verbrauchten Taktzyklen
addieren, um ein korrektes Timing zu erreichen. Das ist diesmal etwas
einfacher, weil Delay ms das Programm in einen Millisekundentakt zwingt
und die Programmlaufzeiten deutlich unter einer Millisekunde bleiben.