Vienet.de Sponsored by
Die Anpassung der RS232 Schnittstellensignale
auf TTL-Pegel mit dem Integrierten Schaltkreis MAX232.
von
Heiko H. / Olaf K. / Jan L.
nähere Informationen beim Webmaster.
Für die serielle Datenübertragung verfügt der Computer über eine Schnittstelle, mit welcher er in der Lage ist mit anderen Geräten zu kommunizieren. Die serielle Datenübertragung ist in der Norm RS232 festgelegt. Danach können über die Datenleitungen TxD (Transmit Data) und RxD (Receive Data) Bytes als Folge von Bits digital übertragen werden. Für die Übertragung der Daten werden noch Parameter wie z.B. die Anzahl der pro Sekunde folgenden Bits (Baudrate) benötigt. Diese Parameter werden mit Hilfe entsprechender Software an den seriellen Ein-Ausgabe-Baustein (UART-Universal Asynchronous Receive and Transmit) übermittelt, der die Datenübertragung an der seriellen Schnittstelle (COM) steuert.
er UART-Baustein gibt die Daten, die er über den internen Bus geliefert bekommt, als invertiertes schwaches Signal aus, was zur Folge hat, daß es noch einmal durch einen invertierenden Treiber verstärkt werden muß. Dies ist notwendig, damit ein Signal mit einer Amplitude von ± 15V bzw. ± 10V erzeugt werden kann.
Da diese Spannungspegel in der TTL-Technologie nicht verwendbar sind, muß eine Anpassung erfolgen.
In dem Projekt geht es nun darum die Anpassung des Pegels der seriellen Schnittstelle an die Pegel der TTL-Technologie zu verwirklichen. Um diese uns gestellte Aufgabe in die Tat umzusetzen, ist es Sinn dieses Projektes eine geeignete Schaltung zu entwickeln, welche die Funktion übernimmt.
Parallel zur Projektarbeit wurde ein C++ Testprogramm erstellt, mit dem während der Inbetriebnahme gearbeitet wurde.
Serielle Datenübertragung:
Bei der seriellen Datenübertragung unterscheidet man zwischen synchronem und asynchronem Datenaustausch. Der Unterschied liegt darin, daß bei der synchronen Übertragung über eine getrennte Leitung noch ein oder mehrere Signale übertragen werden, welche angeben, wann das nächste Bit auf der Datenleitung gültig ist. Der Vorteil der synchronen Variante liegt in der Tatsache, daß der Empfänger auf unterschiedliche Taktraten reagieren kann, solange eine maximal Frequenz nicht überschritten wird.
Bei der asynchronen Variante (der am häufigsten verwandten) wird die Synchronisationsinformation direkt in die Datenbits implementiert. Dies setzt voraus, daß Empfänger und Sender mit der gleichen Taktfrequenz arbeiten müssen. Die implementierte Synchronisationsinformation besteht zum einen aus einem Startbit, welches den Beginn einer Dateneinheit, und zum andern aus einem Stopbit, welches das Ende einer Dateneinheit beschreibt. Eine serielle Dateneinheit SDU (Serial Data Unit) besteht, wenn man die Paritätsinformation, die auch vielfach in der parallelen Datenübertragung vorkommt, noch hinzu nimmt aus einem Startbit, den Datenbits, einem eventuell vorhandenen Paritätsbit und mindestens einem Stopbit.
Bei der Parität handelt es sich um einen zwar einfachen aber wenig effektiven Schutz gegen Übertragungsfehler. Dies liegt darin begründet, daß durch die Parität nur einfache Bitfehler sicher und Bündelfehler mit mehreren gestörten Bits nur mit einer 50% Wahrscheinlichkeit erkannt werden können. Daher ist die Parität hauptsächlich für kurze und störunanfällige Übertragungswege geeignet. Auf Grund der hardwaremäßigen Unterstützung seitens der seriellen Schnittstellenbausteine ist sie gegenüber den zuverlässigeren aber auch komplizierter zu berechnenden Alternativen wie dem CRC-Code im Vorteil. Man unterscheidet bei Parität fünf verschieden Varianten:
- keine Parität: es wird kein Paritätsbit eingefügt
- gerade Parität: das Paritätsbit wird so gesetzt, daß in den Datenbits und dem Paritätsbit zusammen eine gerade Anzahl von 1-en vorkommt
- ungerade Parität: das Paritätsbit wird so gesetzt, daß in den Datenbits und dem Paritätsbit zusammen eine ungerade Anzahl von 1-en vorkommt
- Mark: das Paritätsbit wird stets auf den Wert "1" gesetzt
- Space: das Paritätsbit wird stets auf den Wert "0" gesetzt
Die beiden Paritätszustände Mark und Space haben an sich keinen großen Nutzen, da sie nur einen Fehler im Paritätsbit selber erfassen können. Über die Richtigkeit der Datenbits kann nichts ausgesagt werden, denn wenn das Paritätsbit unbeschädigt ist merkt der Empfänger nichts von eventuell zerstörten Datenbits.
Ein wirksamer Schutz vor Übertragungsfehlern ist der Signal-Loop, bei dem das empfangene Datenwort ohne Veränderung zum Sender zurückgeschickt wird und dort von der Software auf Übertragungsfehler kontrolliert wird. Wird ein Fehler im zurück geschickten Datenwort erkannt, so kann das Datenwort erneut gesendet werden.
Eine weitere Größe bei der seriellen Datenübertragung ist die Baudrate, welche immer wieder zu Mißverständnissen führt. Sie ist benannt nach dem französischen Mathematiker J.M.E. Baudot und bedeutet lediglich die Anzahl der Signaländerungen eines Übertragungkanales je Sekunde. Bei den üblich verwendeten seriellen Schnittstellen sind die Signaländerungen zeitlich äquidistant und die binäre Datencodierung sehr einfach, in diesem Fall ist die Baudrate, wenn man die Steuerbits mit berücksichtigt, gleich der Anzahl der übertragenen Bits pro Sekunde (bps). Es ist jedoch mit Hilfe von Datenkompression und leistungsfähigen Codierungen möglich Datenraten (in bps) zu erzielen die deutlich über der Baudrate liegen.
Der UART:
Der UART (UART steht für Universal Asynchronous Receiver and Transmitter ) ist der zentrale Baustein innerhalb des PC, der die Umwandlung von seriellen oder in serielle Daten übernimmt. Die Ansteuerung des UART erfolgt durch die CPU des Motherboards über die Busschnittstelle. Über diese werden auch die Daten, welche in Form von einzelnen Bytes vorliegen an den UART übertragen. Im Falle der seriellen Übertragung wandelt er, im Gegensatz zur parallelen Übertragung, das Byte in einen Strom von seriellen Bits um. Somit ist das Übertragen der Daten über eine Leitung möglich.
In den PC/XT wurde früher der UART 8250 eingesetzt.
Ab der AT–Serie und auf den heutigen Schnittstellenkarten werden fast nur
noch die verbesserten Versionen UART 16450 und UART 82450 verwendet.
Abb. 1 Anschlußschema des UART 8250/16450.
Die Urversion 8250 erreichte nur eine maximale Übertragungsrate
von 9600 Baud. Erstmals in der AT-Serie eingesetzt, war der verbesserte
Typ 16450 in der Lage bis zu 115200 Baud zu verarbeiten. Diese 115200 Baud
werden aber nur bei direkter Registerprogrammierung erreicht.
Der UART 8250/16450 gibt die seriellen Datensignale in
normaler Form, die RS-232C–Steuersignale in invertierter Form aus. Da der
Baustein nur mit einer Spannung von +5V Vcc versorgt wird, ist ein EIA-Pegel
von ± 12V nicht ohne Verstärkung
möglich. Für diese wird dem UART ein sogenannter EIA-Leitungsverstärker
nachgeschaltet, der die ausgangsseitigen Signale auf einen Pegel von ±
12V anhebt. Eine weitere Eigenschaft des Verstärkers ist es, daß
er als Inverter ausgelegt ist, um am Schnittstellenausgang die richtigen
Signale ausgeben zu können.
Auf Grund seiner vielfältigen Funktionen ist der
Aufbau durchaus als komplex zu bezeichnen. Deshalb auch nur eine kleiner
Einblick in die Architektur und die Funktion dieses Bausteins. Der UART
besitzt ein eigenständiges Empfangs- sowie Sendeteil, welche als Besonderheit
die Eigenschaft haben mit unterschiedlichen Baudraten betrieben werden
zu können. Der UART ermittelt die Sendebaudrate durch Teilung der
Bezugsfrequenz durch den Faktor 16. Diese wiederum, wird durch die Teilung
der Hauptfrequenz, welche beim PC von einem externen Schwingkreis erzeugt
wird und 1,8432 MHz beträgt, durch einen 16-Bit-wertigen Divisor,
der im Teiler-Latch-Register abgelegt ist, bestimmt. Die Bezugsfrequenz
wird als komplimentiertes Signal am Pin BAUDOUT ausgegeben. Die Empfangsbaudrate
hingegen wird extern erzeugt und dem Anschluß RCLK als 16-facher
Wert zugeführt. Wenn man jetzt wie beim PC üblich den Ausgang
der Sendebaudrate mit dem Eingang der Empfangsbaudrate verbindet, arbeiten
Sender und Empfänger mit derselben Baudrate.
Abb.2 Blockdiagramm des UART 8250/16450
Beim Empfang von Daten werden die über den Pin SIN in das Empfängerschieberegister einlaufenden seriellen Bits durch die Empfängersteuerung von den Start-, Stop-, Paritätsbits befreit, so daß nur noch die Datenbits übrig bleiben. Sobald das Empfängerschieberegister alle Datenbits empfangen hat, leitet es das gesamte Datenbyte an das Empfängerpufferregister weiter. Beim Sendevorgang wird das zu versendende Datenbyte aus dem Sendehalteregister von der Sendesteuerung in das Sendeschieberegister übertragen, wo es dann automatisch mit den Steuerbits versehen wird. Die Bits aus dem Sendeschieberegister werden dann mit der programmierten Sendebaudrate am Ausgang SOUT abgegeben.
Die RS-232C-Schnittstelle:
Für die serielle Datenübertragung verfügt der Computer über eine Schnittstelle, mit welcher er in der Lage ist mit anderen Geräten zu kommunizieren. In den PC werden fast ausschließlich Schnittstellen für die serielle Datenübertragung eingebaut , die dem RS-232C-Standard der EIA genügen. Der Begriff EIA ist die Abkürzung für Electronic Industries Association, welche der Herausgeber der RS-232C-Spezifikation ist. In Europa findet man auch häufig die Bezeichnung V.24, die mit der RS-232C-Spezifikation vollkommen konform geht, jedoch von CCITT herausgegeben wird. Der Standard RS-232C, auf den wir uns im weiteren beziehen werden, definiert die mechanische, elektrische sowie logische Schnittstelle zwischen einer Datenendeinrichtung DTE (Data Terminal Equipment) und einer Datenübertragungseinrichtung DCE (Data Carrier Equipment). Da die RS-232C-Signale im Gegensatz zu normalerweise verwendeten Logikpegeln bipolar sind, entspricht nicht ein Pegel von 0V der Masse GND, sondern ein negativer Spannungswert. Daraus folgt, daß eine "1" als positive Spannung und eine "0" als negative Spannung gegenüber der Masse dargestellt wird. Im ausgangsseitigen Bereich liegt der Spannungswert für eine "1" zwischen +5V und +15V und für eine "0" zwischen –5V und –15V. Bei den Eingangssignalen liegen die Spannungswerte zwischen +3V und +15V für eine "1" und zwischen –3V und –15V für eine "0". Diese Werte werden auch als EIA-Signalpegel bezeichnet. Auf Grund der Tatsache, daß die Netzteile von PCs nur Spannungspegel von ± 5V und ± 12V herausgeben, kann auch die serielle Schnittstelle des PC maximal einen Spannungspegel von ± 12V abgeben. Bei der Datenendeinrichtung DTE handelt es sich in der Regel um einen Computer (PC) und bei der Datenübertragungseinrichtung DCE um ein Modem. In dem RS-232C-Standard sind für die Verbindung zwischen DTE und DCE 25 Leitungen vorgesehen, wobei aber ein Großteil für synchrone Datenübertragung reserviert ist. Auf diese Form der seriellen Datenübertragung wollen wir aber nun nicht näher eingehen, sondern uns auf die im PC-Bereich typische asynchrone seriellen Datenübertragung konzentrieren. Für diese Art der Übertragung sind jedoch nur 11 der 25 vorhandenen Leitungen notwendig. Seitens der Firma IBM wurde für ihre Schnittstelle ein 9-poliger Anschluß definiert, bei dem die Schutzerde und das Signal der Datensignalrate fehlen. Dies ist jedoch nicht weiter von Nachteil, da die verbleibenden 9 Leitungen für einen Datenaustausch zwischen DTE und DCE nach RS-232C-Standard ausreichen. Maßgeblich an der Steuerung für einen Datenaustausch zwischen DTE und DCE sind jedoch nur die 5 Steuersignale: RTS, CTS, DCD,DSR und DTR, welche im nachfolgenden erläutert werden. Über die Datenleitungen TxD (Transmit Data) und RxD (Receive Data) werden die Bytes als Folge von Bits digital übertragen.
Beschreibung MAX232A:
Die in den EIA/TIA-232E- und V.28 spezifizierten hohen Spannungspegel der seriellen RS232-Schnittstelle können vom MAX232A im Treiber erzeugt und im Empfänger in TTL- und CMOS- Pegel gewandelt werden. Im MAX232A sind drei Sektionen integriert: Eine Duale Ladungs-Pumpe DC/DC-Konverter, zwei invertierende RS232 Treiber und zwei invertierende RS232 Empfänger.
Duale Ladungs-Pumpe DC/DC-Konverter:
Der MAX232A hat zwei interne Ladungs-Pumpen, die +5V in
±
10V für den RS232 Treiber
wandeln. Der erste Konverter nutzt die Kapazität
C1 um die +5V zu +10V zu doppeln. Diese +10V werden durch C3 gepuffert
und an PIN V+ ausgegeben. Über C2 werden im zweiten Konverter die
+10V in –10V an C4 und Ausgang V- invertiert. Eine kleine Leistung kann
den Ausgängen +10V (V+) und –10V (V-) zur externen Beschaltung entnommen
werden. V+ und V- sind nicht geregelt, die Ausgangsspannungen sinken mit
zunehmendem Entladestrom. Durch die externe Belastung von V+ und V- dürfen
±
5V am RS232-Treiberausgang nicht unterschritten werden.
RS232 Treiber:
Der MAX232A stellt zwei unabhängige Treiberausgänge zur Verfügung. Die typische Treiberausgangsspannung ist bei Belastung mit nominal 5k? und Vcc=+5V bei ± 8V angegeben. Damit werden die EIA/TAI-232E und V.28-Spezifikationen mit minimaler Ausgangsspannung ± 5V im "Worst-Case" eingehalten. Der "Worst-Case" wird von MAXIM bei maximaler Arbeitstemperatur mit minimaler Belastung von 3k und Vcc=+4,5V angegeben. Die zugehörigen Treibereingänge sind TTL- und CMOS-kompatibel. Nicht genutzte Treibereingänge können durch die interne Beschaltung mit 400k? nach Vcc unbeschaltet bleiben. Durch diese "Pull-Up-Widerstände" wird der invertierende Treiberausgang auf Low gehalten. Der interne Strom nach Vcc wird mit 12µA angegeben.
RS232 Empfänger:
Die EIA/TIA-232E und V.28 Spezifikation definieren einen größeren Spannungspegel +3V als logische 0. Der RS232-Empfänger invertiert das empfangene Signal. Durch die auf 0,8V und 2,4V gesetzten Schaltschwelle wird das RS232-Signal logisch gleich auf TTL-Pegel gewandelt.
Schaltungsfunktion:
Die Spannungsversorgung VCC wird extern erzeugt und ist kein Bestandteil unserer Schaltung. Eine typische Eingangsspannung von +5V und die Betriebsmasse werden dem Stecker J3 zugeführt. Die Bauteile IC1, IC2 und die LED D1 werden direkt von VCC versorgt. Die Dimensionierung der gewählten Bauteile erlaubt eine maximale Abweichung der Betriebsspannung von ± 10%. Die maximale Stromaufnahme überschreitet nicht 20mA, so kann ein stabilisiertes Kleinnetzteil verwendet werden. Beim Anschluß der externen Spannungsversorgung ist auf die Polung zu achten.
Die RS232-Schnittstelle des Test-PC wird über ein 9pol. Schnittstellenkabel mit dem SUB-D-Stecker J1 verbunden. Das verwendete Kabel wird als V24-Verbindungskabel 1:1 beschrieben.
Beschreibung der Bauteile:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Mit dem Jumper J2 wird die TTL-Schleife zurück zum MAX232 Treiber geschlossen. Hier kann der Jumper zur Kontrolle der Schleife unterbrochen werden. Das TTL-Signal wird über J2 an den MAX232 PIN11 übergeben und im internen negierenden RS232-Treiber auf den nötigen Spannungspegel der seriellen Schnittstelle angepaßt.
Dieses RS232-Signal wird J1 PIN2 zurückgeführt und gelangt so über die RXD-Leitung des Schnittstellenkabel an die RS232-Schnittstelle des Test-PC. Die Spannungen ± 10V für die RS232-Treiberstufe des MAX232 werden intern über die externen Kapazitäten C1-C4 erzeugt und stehen der Treiberstufe zur Verfügung.
Die nicht genutzten UND-Gatter des IC2 74LS08 sind nicht beschaltet.
Ein Abgriff des TX- und RX-Signals zur weiteren Verarbeitung im TTL-Pegel ist auch über J2 möglich. Der Jumper kann so gegen ein 2 poligen Jumper-Stecker ersetzt werden.
Stromlaufplan:
Der Stromlaufplan und daraus resultierende Pläne wurden mit CADDY EDS Demo V7.0 erstellt. Der abgebildete Stromlaufplan wurde übersichtlich gehalten und beschreibt die entwickelte RS232-TTL-Anpassung. Die eindeutige Kennzeichnung des erstellten Stromlaufplans im Legendenfeld wurde vorgenommen, um den Titel, die Versionsnummer, das Erstelldatum und den Bearbeiter zu verdeutlichen.
Abb.4 Stromlaufplan
Layout:
Das Platinenlayout wurde mit CADDY EDS Demo V7.0 erzeugt und kann als Gerber-Ausgabedatei zur späteren Produktion verwendet werden. Ein Designcheck der Bauteile wurde durchgeführt. Aus der Realisation ergab sich, daß ein einseitiges Platinenlayout gewählt werden konnte. Um die fertiggestellte Platine dem entsprechenden Stromlaufplan und Layout zuzuordnen, wurde die Platine mit dem Titel, der Versionsnummer, den Bearbeitern und dem Erstelldatum in einer Kupferschrift auf der Lötseite versehen. Außerdem wurde die Polung und Betriebsspannung gekennzeichnet.
Die Platinenabmaße wurde so gewählt, daß die Produktion im 3er-Nutzen auf produktionsüblichen Eurokarten im Format 100x60mm gefertigt werden können. Der zusätzliche Arbeitsaufwand des Trennens wurde in der Stück-Kostenrechnung berücksichtigt.
Abb. 5 Platinenlayout
Inbetriebnahme:
Nach einer optischen Prüfung der Platine wurde diese zur Inbetriebnahme mit dem Test-PC vorbereitet. Um Schäden an der Platine und der einzelnen Komponenten zu vermeiden, wurde die Strombegrenzung des verwendeten Netzteiles (Statron Typ 2225.2) auf max. 50mA eingestellt. Das in Reihe geschaltete Multimeter (FLUKE 87) wurde zur direkten Strommessung der Schaltung verwendet. Die Versorgungsspannung VCC +5V wurde über dem Platinenstecker J3 der Platine zugeführt. Dabei wurde besonders auf die richtige Polung des Steckers geachtet. Zur Erstinbetriebnahme wurde der Test-PC nicht mit der Platine verbunden. So konnten Spannungsmessungen der TXD- und RXD-Anschlüsse in der Schaltung vorgenommen werden, ohne die Eingangsstufe der RS232-Schnittstelle des Test-PC zu belasten. Weiterhin wurden die Spannungspotenziale der Kapazitäten zur internen Spannungsversorgung des IC1 MAX232A überprüft. Die Spannungen wurden mit dem Multimeter (HWH M8906) an der Platine gemessen.
Messungen mit Spannungsbezug auf Masse:
| Bauteil | PIN | Meßwert | Einheit | Meßergebnis / OK. |
| J1 SUB-D | 2 | -10,0V | Volt | OK |
| J1 SUB-D | 3 | 0V | Volt | OK |
| IC1 MAX232A | 1 | +8,4V | Volt | OK |
| IC1 MAX232A | 2 | +10,2V | Volt | OK |
| IC1 MAX232A | 3 | +3,2V | Volt | OK |
| IC1 MAX232A | 4 | +5,0V | Volt | OK |
| IC1 MAX232A | 5 | -5,8V | Volt | OK |
| IC1 MAX232A | 6 | -10,3V | Volt | OK |
| IC1 MAX232A | 7 | -10,2V | Volt | OK |
Ruhestrom-Messung:
| Bauteil | PIN | Meßwert | Einheit | Meßergebnis / OK. |
| J3 - Anschlußleitung | 1 | 7,4mA | Ampere | OK |
Es wurde eine Stromaufnahme von 7,4mA im Ruhezustand der Schaltung gemessen. Eine überhöhte Stromaufnahme durch einen Fehler wurde damit ausgeschlossen. Die Spannungspegel an den TXD- und RXD-Anschlüssen der Schaltung lagen im zulässigen Bereich der RS232-Schnittstelle. Die Spannungsquelle wurde ausgeschaltet, um den Test-PC an COM1 mit der Platine am Stecker J1 über das V24-Verbindungskabel spannungsfrei verbinden zu können. Die Spannungsquelle und der Test-PC wurden wieder eingeschaltet. Für die weiteren Messungen wurde der Test-PC mit der Bootdiskette und dem Programm SER.EXE gestartet. Als Testeinstellung wurde im Menü COM1 und eine Übertragungsrate von 1200Baud ausgewählt. Das ausgegeben Datenwort wurde durch Betätigen der Taste "i" am Test-PC erzeugt.
Aktivstrom-Messung:
| Bauteil | PIN | Meßwert | Einheit | Meßergebnis / OK. |
| J3 - Anschlußleitung | 1 | 18,2mA | Ampere | OK |
Abb. 6 Signal am Eingang des MAX232A
Mit dem Oszilloskop (Tektronix 100Mhz Handheld) wurde
kontrolliert, ob sich das vom PC gesendete Signal TXD am MAX232A PIN 13
einstellt. Die in Abbildung 6 gezeigte Schirmdarstellung
des Oszilloskop wurde unter der Verwendung der Software WAVEWORK4.1 erstellt.
Die Abbildung zeigt das RS232-Datenwort am Eingang des MAX232A. Das RS232
Signal erreichte den MAX232A mit einem Signalpegel von ±
10 Volt.
Abb. 7 TTL-Signal am Jumper
Um festzustellen ob der IC1 MAX232A das Signal in ein
TTL - Signal wandelt, erfolgte die nächste Messung am entsprechenden
Ausgang PIN 12. Ein dem TTL-Pegel entsprechendem Signal ±
5 Volt wurde mit dem Oszilloskop (Tektronix 100Mhz Handheld) gemessen.
Abbildung 7 wurde unter der Verwendung der Software WAVEWORK4.1 erstellt.
Abb. 8 Signal am Ausgang vom MAX232
Der TTL – Loop – Jumper J2 wurde auf der Platine geschlossen um das TTL-Signal zurück zum RS232-Treiber des IC1 MAX232A zu schleifen. Der Pegel vom Ausgangssignal RXD des IC1 MAX232A wurde mit +8 Volt und –9 Volt gemessen. Dieser Pegel entspricht immer noch den V24-Normen der RS232-Schnittstelle. Das vom IC1 MAX232A erzeugte und in Abbildung 8 gezeigte RXD-Signals wurde unter der Verwendung der Software WAVEWORK4.1 erstellt. Das RXD-Signal wurde vom Testprogramm dem UART-Register entlesen und als Zeichen "i" auf den Monitor geschrieben. Das ursprünglich vom Test-PC gesendete Datenwort wurde somit in der Schleife richtig übertragen.
Das Programm zur Steuerung der Seriellen Schnittstelle wurde in der Programmiersprache C++ auf einem AMD K6 266MHz mit dem Betriebssystem DOS 6.22 geschrieben.
Es erfüllt folgende Funktionen:
Die Version des C++ Compilers ist 3.1. Das Betriebssystem ist willkürlich gewählt, der Compiler wäre auch unter WIN95 lauffähig gewesen. Damit das Demonstrationsprogramm, im folgenden SER genannt, möglichst ohne Konflikte arbeiten kann, wurde von uns eine Bootdiskette erstellt, die auf der Basis des MS-DOS 6.22 läuft. Somit ist gewährleistet, daß kein anderes Betriebssystem unser Programm stören kann. SER ist auch unter WIN95 und WIN98 lauffähig, hier wird allerdings die DOS 7.X Oberfläche zur Ausführung benutzt.
Erstellen der Programm-Bootdiskette:
Die Bootdiskette wurde mit einem DOS 6.22 System erstellt. Hierzu reicht der Befehl FORMAT A: /S aus. Das Betriebssystem formatiert dann die Diskette im Laufwerk A und schreibt die zum Booten benötigten Dateien in den Startbereich. Danach wurde das Programm SER1 auf die selbe Diskette kopiert und eine AUTOEXEC.BAT geschrieben , die nach dem Booten des Rechners das Programm SER sofort startet.
Die Register des UART und Datenwortbildung:
Die Steuerung des UART und damit der seriellen Schnittstelle wird durch verschiedene Register des UART realisiert , deren Wertigkeit darüber entscheiden , welche Funktionen der UART ausführt. Die Register beziehen sich auf die Basisadresse des anzusprechenden seriellen Ports. Die Basisadressen für COM1 und COM2 sind auf IBM kompatiblen Rechnern immer gleich , sofern sie nicht absichtlich vom Benutzer verändert wurden. Für COM3 und COM4 gilt keine feste Basisadresse (darauf wollen wir hier nicht eingehen). Die Basisadresse für COM1 ist HEX:3F8/DEZ:1016 und für COM2 HEX:2F8/DEZ:7060. Durch das Addieren auf die Basisadresse sind die einzelnen Register zu erreichen.
Möchte man z.B. das SCRATCH Register (ein Puffer Register) der COM1 erreichen, so ist zu der Basisadresse von COM1 das Register als Offset zu addieren ; bedeutet COM1 + Register 7 (DEZ:1016 + DEZ:7 = 1023). Jede Basisadresse hat 8 Register zu je 8 Bit, von denen 2 umgeschaltet werden können. So erhöht sich die Anzahl der Register virtuell um 4 auf 12. Die Umschaltung erfolgt mit dem Divisor Latch Access Bit (DLAB) , das im Line Control Register als Bit 7 zu finden ist. Wird dieses Bit 7 logisch High (Dezimaler Wert 128) gesetzt, so werden damit den Registern 0 , 1 andere Fähigkeiten zugewiesen. Ebenso hat das Register 2 zwei mögliche Bedeutungen. Hier kommt es darauf an, welcher Wert in Register 1 bei DLAB=0 steht. Ist hier eine logische 0 geschrieben, so steht Register 2 als FIFO Steuerregister zu Verfügung, ansonsten werden die auslösbaren Interrupts mit Register 1 und 2 eingestellt.
Die folgende Beschreibung der Register bezieht sich ausschließlich auf die für dieses Projekt wichtigen Register. Wir beginnen mit Register 3, da hier das Umschaltbit für DLAB gesetzt wird.
Register 3:
Das Register 3 ist das Line Control Register. Hier wird
die Wortlänge und Eigenschaft des zu verarbeitenden Datenbits eingestellt.
(Abb. 9 und Abb. 10)Es können Datenwörter von 5 bis 8 Bit, das
Stopbit, das Paritätsbit und Pausen eingestellt werden. Für unser
Projekt verwenden wir das Format: 8 Datenbits und ein Stop Bit. Der Dezimalwert
für diese Einstellung beträgt Dezimal 3 (Binär 00000011).Außerdem
wird hier bei Bedarf mit dem
Bit 7 die Funktion DLAB ein-/ ausgeschaltet, welche Register
0 und 1 umschaltet.
Register 0:
Das Register 0 ist das Receiver Buffer Register und gleichzeitig
das Transmitter Holding Register wenn DLAB gleich Null ist. Entweder werden
Daten die gesendet werden sollen von einem Programm in dieses Register
hineingeschrieben, oder es werden Daten von einem Programm aus dem Register
gelesen. Das Register schaltet sich entsprechend der Programmanfrage selbständig
um. Wenn DLAB gleich logisch Eins ist, wird das Register 0 umgeschaltet
und dient dann als Divisor Latch zum Programmieren der Baudrate.
(Abb. 9 und Abb. 11)
Register 1:
Das Register 1 ist das Interrupt Identifikation Register,
wenn DLAB gleich Null ist. Hier können mögliche Interrupts eingestellt
werden, die allerdings in unserem Projekt keine Rolle spielen. Wir nutzen
nur die Funktion Divisor Latch bei DLAB gleich logisch Eins um die Baudrate
einzustellen. (Abb. 9)
Register 2:
Das Register 2 steuert den FIFO des UART. Er wird allerdings
ebenfalls nicht in diesem Projekt benötigt und ist daher ausgeschaltet.
(Abb. 9)
Register 5:
In dem Register 5 (Line Status Register) zeigt das erste
Bit (Bit 0) an, ob ein Zeichen im Lesepuffer des UART zur Abholung bereitsteht
oder nicht. Die anderen Register werden hier nicht benötigt.
Bildung eines Datenwortes für ein Register:
Um in ein Register eine bestimmte Information zu schreiben
, benötigt man die in Abb. 9 abgebildeten Informationen. In unserem
Projekt wird das Übertragungsformat 8 Bit , kein Paritätsbit
und ein Stopbit genutzt. Diese Informationen werden dem UART durch das
Line Control Register (Register 3) zugeführt. In Abb. 1.1 ist nun
aufgeschlüsselt, wie Bit 0 und 1 gesetzt sein müssen, damit ein
8 Bit langes Datenwort zustande kommt. Sie müssen beide auf logisch
High gesetzt sein. Zusätzlich verlangen wir ein Stopbit, das bei einem
8 Bit Wort automatisch gesendet wird. Also wird Bit 2 auf logisch Low gesetzt.
Das Paritätsbit und alle anderen Einstellungen sind unerwünscht
, also logisch Low. Es ergibt sich nun das Bild, Bit 0 und Bit 1 von Register
3 sind logisch High. Dezimal ist es eine 3.
|
|
|
|
|
|
|
|
|
|
|
|
Register |
Holding Register |
(Low Byte) |
(High Byte) |
Register |
Register |
Register |
Register |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 Bits 7 Bits 8 Bits |
1 0 1 |
0 1 1 |
| Baud Rate | Dezimal Teiler | High Byte Binär | Low Byte Binär |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Wir verzichten darauf, das ganze Programm SER.EXE zu erläutern
hier nur die wichtigsten Funktionen.
Von besonderer Bedeutung sind die folgenden Programmabschnitte:
Bevor die Schreib-/Lese-Routine auf den Seriellen Port
zugreifen kann, werden zuerst die Interrupt und FIFO Register ausgeschaltet.
Dies geschieht mit
outportb(po + 1 , 0);
outportb(po + 2 , 0);
wobei die Variable po die Basisadresse des anzusprechenden
COM Portes ist.
Jetzt erfolgt die Programmierung der Baudrate. Hierzu
wird zuerst im Register 3 (Line Control Register) dasBit 7 gesetzt, um
DLAB einzuschalten. Hiermit wird bewirkt, daß Register 0 und 1mit
dem Divisor Latch (Low Byte / High Byte) beschrieben werden können.(Abb.
9)
outportb(po + 3 , 128);
outportb(po + 0 , bdlow);
outportb(po + 1 , bdhigh);
In der Variable bdlow ist das Low Byte und in der Variable
bdhigh ist das High Byte gespeichert. Die Bedeutung der Variablen ist in
Abb. 11ersichtlich.
Nun wird DLAB wieder gelöscht. Damit erreichen wir,
daß die Teiler für die Baudrate vom UART und Register 0 und
1 übernommen werden.
outportb(po + 3 , 0);
Das Baudregister (intern) ist programmiert.
Jetzt kann das Register 3 (Line Control Register) zum
Festlegen des Datenwortes beschrieben werden. Wie wir eben festgestellt
haben, muß dieses Register mit dem Wert 3 beschrieben werden.
outportb(po + 3 , 3);
Mit dem nächsten Befehl wird ein eventuelles ESC, das durch Beenden des Programmes SER.EXE bei einem Loop im Empfangspuffer stehen bleiben kann, gelesen und damit gelöscht.
c=inportb(po);c=0;
Jetzt folgt die eigentliche Schreib-/Lese-Routine. Hier
wird in einer do - while Schleife immer wieder abgefragt, ob ein Zeichen
im Empfangspuffer des UART angekommen ist. Wenn ja, wird es gelesen und
auf dem Bildschirm ausgegeben. Das Bereitstehen eines Zeichens erfährt
das Programm indem es den Wert des
Registers 5 in die Variable c übergibt und mit 1
bitweise vergleicht. Ist diese Bedingung erfüllt, so wird das Zeichen
aus dem Eingangspuffer gelesen. Betätigt man eine Taste, so wird das
Zeichen dieser Taste als ASCII-Format von der Tastatur gelesen und in den
Sendepuffer des UART geschrieben. Der UART sendet dieses Zeichen dann mit
den eben festgelegten Kriterien. Betätigt man die ESC Taste, so erkennt
der Rechner die Wertigkeit 27 der ESC Taste und bricht diese Routine ab.
do {
c = inportb(po + 5);
if (c&1) {ch = inportb(po);
printf("%c",ch);}
if (kbhit()){ch = getch();
printf("%c",ch);outportb(po, ch);}
}
while (ch !=27);
C++ Quelltext
#include <dos.h>
#include <stdio.h>
#include <conio.h>
main(ser) {
int c,po,ch,bdlow,bdhigh; float bdanz; char abfr1,abfr2;
textbackground(BLACK); textcolor(LIGHTGREEN); clrscr();
printf("\n\n *** Test-Terminal-Programm **\n\n\n");
printf(" Bitte wählen sie die Schnittstelle ..\n\n");
printf(" '1' - COM1 (Adresse Hex:3F8 Dez:1016)\n");
printf(" '2' - COM2 (Adresse Hex:2F8 Dez:760)\n");
printf("\n\n\n\n\n\n\n\n Alle anderen Tastatureingaben
- ENDE");
printf("\n\n\n--------------------------------------------------------------");
printf("\nVersion1.1 7.11.99 ohne FIFO / Interrupt");
printf("\n--------------------------------------------------------------");
po=0;
abfr1=getch();
if(abfr1=='1') po=1016;
if(abfr1=='2') po=760;
if(po==0) return(0);
clrscr();
printf("\n\n *** Test-Terminal-Programm **\n\n\n");
printf(" Bitte wählen sie die Baudrate ..\n\n");
printf(" '1' - 115,200 KBPS \n");
printf(" '2' - 56,700 KBPS \n");
printf(" '3' - 38,400 KBPS \n");
printf(" '4' - 19,200 KBPS \n");
printf(" '5' - 9,600 KBPS \n");
printf(" '6' - 4,800 KBPS \n");
printf(" '7' - 2,400 KBPS \n");
printf(" '8' - 1,200 KBPS \n");
printf(" '9' - 0,600 KBPS \n");
printf(" '0' - 0,300 KBPS \n");
printf(" 'a' - 0,050 KBPS \n");
printf("\n\n Alle anderen Tastatureingaben - ENDE\n");
bdlow=0;bdhigh=0;
abfr2=getch();
if(abfr2=='1') {bdlow=1; bdhigh=0; bdanz=128.000;}
if(abfr2=='2') {bdlow=2; bdhigh=0; bdanz=56.000; }
if(abfr2=='3') {bdlow=3; bdhigh=0; bdanz=38.400; }
if(abfr2=='4') {bdlow=6; bdhigh=0; bdanz=19.200; }
if(abfr2=='5') {bdlow=12; bdhigh=0; bdanz=9.600; }
if(abfr2=='6') {bdlow=24; bdhigh=0; bdanz=4.800; }
if(abfr2=='7') {bdlow=48; bdhigh=0; bdanz=2.400; }
if(abfr2=='8') {bdlow=96; bdhigh=0; bdanz=1.200; }
if(abfr2=='9') {bdlow=192; bdhigh=0; bdanz=0.600; }
if(abfr2=='0') {bdlow=184; bdhigh=1; bdanz=0.300; }
if(abfr2=='a') {bdlow=0; bdhigh=9; bdanz=0.050; }
if(bdlow==0&bdhigh==0) return(0);
outportb(po + 1 , 0); outportb(po + 2 , 0);
clrscr();
printf("Dieses Programm sendet die Eingegebenen Zeichen
und erkennt Eingaben .");
printf("\n\nTerminalprogramm an : COM %c bei %6.3f KBPS
.",abfr1,bdanz);
printf("\nDas Datenformat : 8 Bits , Kein Paritätsbit
, 1 Stop Bit");
printf("\n\n'ESC' - Ende - wird ebenfalls gesendet\n\nREADY.\n\n");
outportb(po + 3 , 128);
outportb(po + 0 , bdlow);
outportb(po + 1 , bdhigh);
outportb(po + 3 , 0);
outportb(po + 3 , 3);
c=inportb(po);c=0;
do { c = inportb(po + 5);
if (c&1) {ch = inportb(po); printf("%c",ch);}
if (kbhit()){ch = getch(); printf("%c",ch);outportb(po,
ch);}
}
while (ch !=27);
printf("\n\nSER-Programm Ende oder Neustart mit 'n'\n");
ch=getch();
if (ch=='n') main(ser);
printf("\n Auf Wiedersehen.\n");
return(0);
}
-- Ende des HTML-Dokumentes
Copyright HLK 1999