|
6.7 Die Meßmittel-Lese-Routinen
Die Meßmittel-Lese-Routinen bestehen aus den Dienst-Routienen, welche von allen eigentlichen
Meßmittel-Lese-Routinen gemeinsam genutzt werden, und den eigentlichen Meßmittel-Lese-Routinen selbst. Bei den Dienst-Routinen handelt es sich um Routinen, welche die Datenspeicherbereiche löschen, die
Timerprogrammierung übernehmen, grundlegende RS232-Funktionen zur Verfügung stellen und die korrekte Fehlerbehandlung gewährleisten. Die Meßmittel-Lese-Routinen sprechen direkt das Meßmittel über das periphere
Interface an, lesen die Meßdaten ein und formen sie um, so dass sie an das Terminal gesendet werden können.
6.7.1 Die Dienstroutinen
6.7.1.1 Timerprogrammierung
Der Timer auf der MPC104 wird bei den neuen Interfaces nur zur Erkennung eines Timeout-Fehlers verwendet. Dabei wird das
Problem der Zeiterkennung wie folgt gelöst: Der Timer wird so programmiert, dass er alle 50000 (Prozessor-) Taktimpulse einen Interrupt auslöst. Da bei einer Prozessortaktfrequenz von 1MHz ein Taktzyklus genau 1ms
lang ist, ergibt dies alle 50ms einen Interrupt. Bei diesem Interrupt wird in eine Routine gesprungen, welche auch als Interruptverteiler bezeichnet wird, da sie feststellt, von welchem Busteilnehmer der Interrupt
ausgelöst wurde und die Programmausführung dementsprechend verzweigt. In der hier implementierten Interruptverteiler-Routine wird nur geprüft, ob der Interrupt vom Timerbaustein ausgelöst wurde. Ist dies nicht der
Fall, wird das unterbrochene Programm sofort weiter fortgeführt.
Wurde der Interrupt vom Timer ausgelöst (erkennbar am gesetzten Interruptbit im Timerstatusregister), so wird im Interruptverteiler der Timer
gestoppt, ein Zähler (mit dem Label COUNT) inkrementiert und der Timer anschliessend wieder gestartet. Danach kehrt das Programm sofort wieder zurück an die Stelle, an der der Interrupt auftrat.
In den
Timer-Service-Routinen wird lediglich der Timer mit JSR TIMSTRT gestartet und mit JSR TIMSTOP wieder angehalten. Mit JSR TIM_NEU wird beim Timerstarten zusätzlich noch der Zähler COUNT gelöscht, so dass praktisch
ein Neustart des Timeout-Tests vorliegt. In den Meßmittel-Lese-Routinen wird dann am Anfang mit JSR TIM_NEU der Timer neu gestartet und in den Polling-Schleifen (wo beispielsweise ein Eingangsbit immer wieder
abgefragt wird) auch der Zähler COUNT mit überprüft. Sollte sein Inhalt (16-Bit-Wert) gleich dem Inhalt des Wertes in dem Speicherplatz SECONDS sein, so gilt die Timeout-Zeit als verstrichen, das Programm bricht
dann das Polling ab und generiert einen Timeout-Fehler. Man muss nun vor der Polling-Schleife in den Speicherplatz SECONDS die gewünschte Timeout-Zeit in Sekunden*20 ablegen (*20 deswegen, da der Zähler COUNT alle
50ms weitergezählt wird und 20 Zählschritte für die Zeitdauer einer Sekunde verstreichen) und den Timer über die Dienstroutine TIM_NEU neustarten. Wenn die Daten eingelesen werden, muss mit der Timer-Dienstroutine
TIMSTOP dafür gesorgt werden, dass der Timer für die Dauer des Einlesevorgangs gestoppt wird, da sonst trotz des erfolgreichen Einlesens ein Timeoutfehler erzeugt werden könnte.
6.7.1.2 R232 - V.24 Behandlung
Es wurden zwei Dienstroutinen zur RS232-Schnittstelle implementiert: ACIA_INI initialisiert die ACIA,
während READONE ein Zeichen von der seriellen Schnittstelle liest und auf Übertragungsfehler überprüft.
In ACIA_INI wird ein programmed Reset der ACIA ausgelöst und anschliessend das ACIA-Control- und
Command-Register mit zwei über einen festen Speicherplatz übergebenen Bytewerten programmiert. Man muss in der Lese-Routine, von der ACIA_INI aufgerufen wird, vorher diese beiden Bytewerte vorbereiten und an die
definierte Übergabestelle (Label PARMS wie Parameters) speichern.
Die Bytewerte bestimmen, nachdem sie in die beiden ACIA-Steuer-Register programmiert wurden, die Baudrate und das Übertragungsprotokoll der
Schnittstelle. Nach erfolgreicher ACIA-Programmierung wird ein Flag mit dem Lable ACIA_OK auf $FF gesetzt, welches anzeigt, dass die ACIA initialisiert wurde, damit dies nur einmal beim Wechsel des Meßmittelmoduls
und nicht bei jeder Datenanforderung geschieht. Dieses Flag wird nur bei einem Reset oder bei einer Neuauswahl eines Meßmittelmoduls (über den Platinen-Auswahl-Taster) wieder gelöscht.
Die Dienstroutine
READONE dient zum Einlesen eines Bytes über die serielle RS232-Schnittstelle. Im X-Register muss beim Aufruf die Adresse übergeben werden, an die das zu lesende Byte geschrieben werden soll. Dann durchläuft das
Programm eine Polling-Schleife, in der das Statusregisterbit "Receiver Data Register full" der ACIA getestet wird, welches anzeigt, dass ein vollständiges Byte seriell in das Empfänger-Daten-Register der
ACIA eingelesen wurde. In dieser PollingSchleife wird auch wie unter 6.7.1.1 beschrieben laufend getestet, ob der Timeout-Zähler einen Wert von 40 übersteigt (entspricht einer Timeout-Dauer von 2s). Ist dies der
Fall, wird das Polling abgebrochen und ein Timeoutfehler erzeugt.
Wurde ein Byte komplett eingelesen, bricht das Programm die Polling-Schleife ab und prüft nacheinander die drei Fehlerbits "Overrun"
(gesetzt, wenn ein weiteres Byte im Receiver Datenregister auflief, ohne dass das dort schon vorhandene Byte "abgeholt" wurde), "Framing" (gesetzt, wenn Länge der Start- und Stopbits nicht
korrekt) und "Parity" (gesetzt, wenn die Paritäts-Checksumme über die Datenbits nicht stimmt) des ACIA-Statusregisters, ob ein entsprechender Fehler aufgetreten ist. Ist dies der Fall, wird die
Lese-Routine mit einem entsprechenden Fehlercode abgebrochen. Der Fehlercode wird in einer dafür vorgesehenen Speicherstelle abgelegt und wird von der in 6.7.1.3. besprochenen Fehlerroutine zur Anzeige des
aufgetretenen Fehlers verwendet. Dieser kann auch nach Rückkehr des MUX-Programms zum Terminalprogramm noch weiter verwendet werden, da er erst bei einer erneuten Datenanforderung wieder gelöscht wird.
Die
ersten vier Fehlercodes sind für alle RS232-Meßmittel-Lese-Routinen, welche READONE verwenden, gleich und lauten:
|
1
|
Tiemout-Fehler
|
|
2
|
Overrun-Error
|
|
3
|
Framing-Error
|
|
4
|
Parity-Error
|
|
Die weiteren Fehlercodes (5 und höher) können bei verschiedenen RS232-Lese- Routinen verschiedene Bedeutungen haben.
Wurde keiner der oben genannten Fehler festgestellt, so wird das empfangene Byte in der im X-Register übergebenen Adresse abgelegt, verbleibt aber bis zum Ende der Routine im
Akkumulator A, so dass es von aufrufenden Programmen sofort weiterverarbeitet werden kann. Anschliessend wird der Zähler COUNT gelöscht, so dass die Timeout-Zeit neu beginnen kann.
Zuletzt werden das B-Register und das X-Register wieder mit denen beim Aufruf der Routine READONE vorhandenen Werten beschrieben, um die eventuell von aufrufenden Programmen dort abgelegten Daten nicht zu zerstören.
In der folgenden Grafik ist das Ablaufdiagramm der Dienstroutine READONE abgebildet:
Abb. 25: Ablaufdiagramm zur Dienstroutine READONE
6.7.1.3 Fehlerbehandlung
Die Fehlerbehandlung wurde für alle Meßmittel-Lese-Routinen einheitlich organisiert, so dass
auch hier wieder (sehr speicherplatzsparend!) eine Dienstroutine von allen Meßmittel-Lese-Routinen aus im Fehlerfalle aufgerufen wird und die Fehlerabarbeitung mit
anschliessender Wiederherstellung eines definierten Zustandes übernimmt. Das Unterprogramm wird über den bezeichnenden Namen ERRBLNK (Error-blink) angesprungen.
Zuerst wird der Timer gestoppt, da sein weiterlaufen im Fehlerfall nicht mehr erforderlich ist. Nun wird der Wert in der Variable P_ERROR nach ERROR kopiert. Das hat folgende Bedeutung:
Die Leseroutinen müssen, bevor sie die Daten auf einen bestimmten Fehler testen, die Variable P_ERROR (für possible error = möglicher Fehler) mit dem Fehlercode vorbereiten, der im Falle
eines positiven Testergebnisses den betreffenden Fehler anzeigen soll. Wenn nun der Fehler festgestellt wird, kann mit JMP ERRBLNK sofort in die Fehler-Dienstroutine verzweigt werden,
ohne dass man erst noch umständlich über Zwischenlables den Fehlercode abspeichern muss. Die Fehler-Dienstroutine kopiert einfach den Wert in P_ERROR nach ERROR und zeigt damit den
Fehler sozusagen "offiziell" an. Nur der Wert in ERROR ist also der aktuell aufgetretene Fehlercode, der Wert in P_ERROR dient nur zur internen Verwaltung der Fehlercodes.
Nachdem der Fehlercode gespeichert wurde, wird getestet, ob die LED-Monitorplatine gesteckt ist. Ist sie das nicht, so wird sofort wieder zurück zum MUX-Hauptprogramm gesprungen. Wenn
die Platine vorhanden ist, so wird durch 8-maliges kurzes Aufblinken der LEDs der Fehler angezeigt. Dabei blinken nur die LEDs, welche den binären Wert des Fehlercodes darstellen. Ein
Fehlercode von 1 (immer für Timeout-Fehler benutzt) wird also nur die erste LED, welche mit dem LSB (niederwertigstes Bit) des LED-PIA-Ports korrespondiert, blinken lassen, während ein
RS232-Framing Error beispielsweise bei einem Fehlercode von 3 die ersten beiden LEDs blinken lassen würde (dezimal 3 ist binär 0000 0011). So ist schnell die Art des aufgetretenen Übertragungsfehlers festzustellen.
Nachdem nun der Fehler angezeigt wurde -oder, falls keine Monitorplatine gesteckt ist, auch sofort- wird die Fehler-Dienstroutine auf unkonventionelle Weise verlassen: Der Stackpointer
wird mit dem Wert beschrieben, der in den zwei Bytes ab der Adresse STACKSVE steht. Dorthin wurde der Stackpointer zum Start des MUX-Hauptprogramms gesichert, also hat der
Stackpointer nun den gleichen Wert, wie zu Beginn des MUX-Hauptprogramms. Dann springt die Fehler-Dienstroutine mit JMP MUX wieder an den Start des MUX-Hauptprogramms. Das hat
gegenüber RTS den Vorteil, dass man aus einer beliebig tiefen Verschachtelung von Unterprogrammen heraus jederzeit in die Fehlerroutine springen kann, ohne sich über eine
korrekte Restauration des Stackpointers bei einem Rücksprung zum Hauptprogramm Gedanken machen zu müssen. Dieser wird so nämlich immer richtig wiederhergestellt.
Auch hierzu wieder ein Ablaufdiagramm:
 |
Abb. 26: Ablaufdiagramm zur Fehlerbehandlungsroutine
6.7.1.4 Korrekte Datenübertragung
Bleibt noch eine letzte, kurze Dienstroutine zu nennen, welche bei einer korrekten Übertragung
der Meßdaten vom Meßmittel zum Interface am Ende der Meßmittel-Lese-Routinen aufgerufen wird und durch ein kurzes einmaliges Aufblinken aller 8 LEDs auf der Monitorplatine die
erfolgreiche Übertragung anzeigt. Ist die LED-Monitorplatine nicht vorhanden, passiert ausser einem RTS nichts. Man ruft diese kurze, aber für den Programmierer psychologisch doch recht
wichtige Routine mit JSR UEB_OK (Übertragung O.K.) auf.
|