12-Bit Messwerterfassungssystem mit 32 Eingangskanälen
am Druckerport
Um Messwerte aus der "analogen Welt" zur Weiterverarbeitung in einem PC aufzubereiten, existieren auf dem Markt eine große Menge von Adapterkarten. Ob PCI- oder ISA-Bus, alle Leistungs- und Preisbereiche sind abgedeckt. Da jeder PC oder LAPTOP über eine parallele Schnittstelle verfügt, muss nicht immer ein freier Steckplatz auf dem Motherboard für ein Messwerterfassungssystem zur Verfügung stehen.
Dieses Projekt stellt ein Messwerterfassungssystem für den Druckerport auf Basis des Controllers PIC16C84 von MicroChip vor. Damit können gleichzeitig vier, des in [1] vorgestellten 8x12 Bit A/D-Wandler-Moduls, über einen Druckerport bedient werden.
Der Beitrag zeigt zum einem die Schritte der Hardwareentwicklung. Zum anderen werden in kleinen Einführungen die verwendeten Softwarewerkzeuge vorgestellt.
ELRAD stellte in Heft 10/93 ein A/D-Wandlermodul mit 8 Kanälen und 12 Bit Auflösung am Druckerport vor. Der eingesetzte A/D-Wandler MAX186 von Maxim besitzt ein serielles Interface mit einem sehr einfachen Protokoll. Das fertige Wandlermodul selbst stellt eine äußerst kostengünstige Lösung zur Erfassung von physikalischen Größen wie Druck, Temperatur und Durchfluss in unserem Prozessmesstechnik-Labor dar. Als besonders vorteilhaft erweisst sich die Tatsache, dass bei einem Rechnerwechsel lediglich das A/D-Wandlermodul von einer Druckerschnittstelle zur anderen "umziehen" muss. Aufwendige Schraub- und Einbauarbeiten von PC-Steckkarten ( ganz zu schweigen von den begrenzten Steckzyklen der direkten Steckkontakte einer ISA/PCI Adapter Karte ) können so entfallen.
Die Verwendung eines 8x12Bit Moduls
Die Messwertaufnahme erfolgt auf einem "betagten" 486er-33Mhz . Das dazu entwickelte kleine Messwerterfassungsprogramm MESS.EXE[2] setzt auf dem guten alten DOS auf. Es zeigt die Kanäle, ähnlich einem Digital-Voltmeter auf dem Bildschirm an, und speichert diese in einem File ab.
Das Programm nutzt das Echtzeit-Multi-Tasking Betriebssystem RTKernel der Firma On Time Informatik (Hamburg).
Bild 1
Struktur des RTKernel
RTKernel ist für die professionelle Softwareentwicklung z.B. in der Prozessdatenverarbeitung
entworfen. Es kann auf PC oder x86-basierenden Embedded-System eingesetzt werden.
Die RTKernel-Applikation setzt auf die in Bild 1 gezeigten Systemkomponenten
auf. Sie besteht aus einer einzigen EXE-Datei. Diese enthält den Kernel,
alle benötigten Treiber und die Applikations-Task. Es handelt sich um multitasking-
und echtzeitfähige DOS-Programme.
In der Applikation MESS.EXE[2] gewährleistet RTKernel, dass
weder Bildschirmausgaben noch das Ablegen der Messwerte im Filesystem (auf einer
Harddisk oder einem Netzwerklaufwerk) die zeitlich äquidistante Abtastung
der Sensorsignale stört. Es arbeitet mit preemptiven Multitasking, denn
so werden z.B. Leerlaufzeiten bei Festplattenzugriffen durch das DOS in den
Interrupt-Routinen erkannt und der Laufzeit des Anwenderprogrammes zugeschlagen.
Mehr-Rechner-Verarbeitung
Für die Lehrveranstaltungen in unserem Labor ist es wichtig, dass die
aktuellen Messwerte für mehrere Rechner gleichzeitig zur Verfügung
stehen. Die Messwerterfassung erfolgt mit dem RTK unter DOS. Die Messwerte werden
vom Erfassungsrechner über das Filesystem des Netzwerkes an einen oder
mehrere Rechner mit der Visualisierungs-Software weitergereicht. Die Weiterverarbeitung
der Messwerte erledigt z.B. das Softwarepaket MatLab[3]. Das Erfassungsprogramm
legt die Messwerte in tabellarischer Form im ASCII-Format in einem File ab und
die Arbeitsstation mit der MatLab-Anwendung liest diese Rohdaten zur weiteren
Analyse ein.
Der RTKernel unterstützt zudem die Möglichkeit, in NetWare-Umgebung,
IPX-Telegramme,mit den Messwerten, direkt von Rechner zu Rechner zu versenden.
Messwertverarbeitung unter Windows
Für Windows3.x/95 steht eine große Anzahl von Visualisierung-Tools
zur Verfügung. Von besonderen Interesse sind für uns solche, die über
das Dateisystem, in Fileform Messwerte aufnehmen und weiter verarbeiten können.
Dies erspart nämlich das Kopfzerbrechen, wie Fremdhardware (z.B. 12Bit
A/D-Wandler am Druckerport) an eine beliebige Visualsierung-Software anzubinden
ist.
Auch für die "Ein-Rechner-Lösung" mit einer Visualsierung
unter Windows3.x bietet der RTK eine Lösung.
Vor dem Start von Windows3.x wird speicherresident unter DOS die RTKernel-Task
mit der Messwerterfassung geladen. Nach dem Start von Windows3.x, das im Real-,
Standard- oder 386-Enhanced-Mode arbeitet, kommuniziert die Visualisierungs-Software
über einen von ihr allokierten Shared-Memory Speicherblock mit der RTKernel-Task.
Bild 2
RTK-Windows-System
Die unter DOS geladene RTK-Task liefert in einem festen Zeitraster die Werte
an die Visualisierungs-Software unter Windows3.x. Gegebenenfalls kann die RTK-Task
diese Werte auch gleich in einem File abspeichern. Nähere Einzelheiten
und kleine Anwendungsbeispiele können dem sehr hilfreichen RTKernel Handbuch
[4] entnommen werden.
Die Verwendung mehrerer 8x12Bit Module
Mit dem Anwachsen der Sensormessstellen neigte sich recht bald die Anzahl freier Kanäle der 8-kanaligen A/D-Wandlerkarte ihrem Ende zu. Eine Erweiterung sollte 32 Kanälen umfassen. Diverse Hersteller bieten derartige Adapter als PC-Einsteckkarten, wir aber wollten bei der bewährten externen Hardwarelösung bleiben.
Folgende Lösungen waren denkbar, um vier A/D-Wandlermodule gleichzeitig nutzen zu können:
|
I/O-Erweiterung des PC : |
Den PC auf vier parallele Schnittstellen aufrüsten und die gesamte Ansteuerung, wie bei einem A/D-Wandler Modul dem PC überlassen. |
|
|
CPLD oder FPGA als Multiplexer am Parallelport : |
Mit Hilfe eines CPLD's einen "Multiplexer" für die Wandler an der Drucker-, oder ECP- oder EPP-Schnittstelle realisieren. Wenn möglich, soll dieser auch gleich die "niedere" Kommunikation mit den A/D-Wandlermodulen übernehmen. Aus Sicht des PC-Programms soll nur die Kanalnummer übergeben werden und den Rest der Arbeit, bis zur Rücklieferung des erfassten Messwertes, soll der "Multiplexer" übernehmen. |
|
|
mController als Multiplexer am Parallelport : |
Einsatz eines "smarten" Single-Chip-mController (als Knecht), der eventuell bei späteren Erweiterungen eine Messwert-Vorverarbeitung zulässt. Im übrigen soll er dieselben Aufgaben wie obiges CLPD's, aber in Software realisiert, über-nehmen. |
Das dazu entwickelte kleine Messwertaufnahmeprogramm MUX.EXE[2] ist wieder ein unter DOS/RTKernel implemtiertes Tool und wird am Ende dieses Beitrags näher erläutert werden.
Lastenheft des Multiplexers (MUX)
Schließlich fiel die Entscheidung auf die unserer Meinung nach flexibelste Lösung, nämlich einen mController zur Realisierung des "Multiplexers" einzusetzen. An einem einfach zu durchschauenden Beispiel kann so der Einsatz PC-externer "intelligenter" Hardware und deren Kommunikation mit einem Host (PC) über eine standardisierte Schnittstelle gezeigt werden. Das Lastenheft sieht die in Bild 3 gezeigte Systemarchitektur vor:
Bild 3
Messwertaufnahmesystem
Kommunikation PC<-> MUX --Hardwareaufbau
Das Interface zwischen PC und dem MUX soll die Druckerschnittstelle des PC sein. Bild 4 zeigt die genutzen Signalleitungen des Druckerports des PC. Den sogenannten Standardmodus beherrschen alle Parallelschnittstellen des PC’s, egal welches Baujahr zum Einsatz kommt. Das 12-Bit breite Messergebnis wird dazu in 3 Nibble zu je 4 Bit zerlegt und über die Druckerstatusleitungen zurückgelesen. Zur vollständigen Übertragung eines 12-Bit Wertes muß folglich 3-mal auf den MUX zugegriffen werden. Eine "nibble-basierende" (langsame) Übertragung, würde natürlich bei PC’s mit modernen Parallel-Schnittstellen nicht mehr realisiert werden. Wie bereits in [5] beschrieben, unterstützen diese den ECP- bzw. EPP- Modus. Der EP-Port stellt 8 bidirektionale Ports, 4 Ausgänge und 5 Ausgänge zur Verfügung.
Bild 4
Druckerport<->MUX
Dass natürlich bei einer Datenübertragung über die Centronics-Schnittstelle für eine "sichere" Datenübertragung gewisse schaltungstechnische Massnahmen zu ergreifen sind, soll nicht verschwiegen werden. Der Abschnitt "Die Hardware des MUX" geht auf die typischen Signalverzerrungen und die Abhilfen dafür näher ein.
Kommunikations-Protokoll
Der Host (PC) sendet an den Multiplexer ein 5 Bit breites Kommandowort über die Datenleitungen:
Folgende Kommandos an den MUX sind vereinbart:
|
Commando vom Host |
Bedeutung |
||||
|
Data D4 |
Data D3 |
Data D2 |
Data D1 |
Data D0 |
|
|
|
|
|
000b....111b |
|
Conversion: Auf allen angeschlossenen Modulen wird gleichzeitig der angegebene Kanal gewandelt und in den "Messwert-Cache" des MUX geschrieben |
|
|
|
|
|
|
Ping: Kommunikationstest MUX<->Host. Der 4*12Bit "Messwert-Cache" des MUX wird mit einem Testmuster beschrieben und kann hernach vom Host ausgelesen werden. |
|
1 |
00. |
.11 |
00. |
.11 |
Lese Modul/Nibble: Host liest aus dem "Messwert-Cache" des MUX das angegebene Nibble aus |
Tabelle 1
Jedes Kommando wird vom Host per TimeOut-Zyklus überwacht, d.h. meldet sich der MUX nicht innerhalb eines definierten Zeitfensters zurück, so erkennt dies das Messwerterfassungsprogramm.
Folgende Statusmeldungen liefert der MUX in Abhängigkeit des jeweiligen Kommandos über die Statusleitungen zurück. Wird vom MUX eine TimeOut zurückgeliefert, so bedeutet dies, dass die Kommunikation
MUX<->Wandlermodul(e) gestört ist.
|
Commando vom Host |
Code |
Zurückgelieferte Werte |
Code |
|
Wandle Kanal 0 auf allen Module |
0x08 |
Okay/TimeOut |
0x3/0x5 |
|
" 1 " |
0x0C |
" |
0x3/0x5 |
|
" 2 " |
0x09 |
" |
0x3/0x5 |
|
" 3 " |
0x0D |
" |
0x3/0x5 |
|
" 4 " |
0x0A |
" |
0x3/0x5 |
|
" 5 " |
0x0E |
" |
0x3/0x5 |
|
" 6 " |
0x0B |
" |
0x3/0x5 |
|
" 7 " |
0x0F |
" |
0x3/0x5 |
|
Lese Modul 0 Nibble 0 |
0x10 |
Teilwert des gewandelten Kanals |
0x0..0xF |
|
Lese Modul 0 Nibble 1 |
0x14 |
" |
0x0..0xF |
|
Lese Modul 0 Nibble 2 |
0x18 |
" |
0x0..0xF |
|
Lese Modul 1 Nibble 0 |
0x11 |
" |
0x0..0xF |
|
Lese Modul 1 Nibble 1 |
0x15 |
" |
0x0..0xF |
|
Lese Modul 1 Nibble 2 |
0x19 |
" |
0x0..0xF |
|
Lese Modul 2 Nibble 0 |
0x12 |
" |
0x0..0xF |
|
Lese Modul 2 Nibble 1 |
0x16 |
" |
0x0..0xF |
|
Lese Modul 2 Nibble 2 |
0x1A |
" |
0x0..0xF |
|
Lese Modul 3 Nibble 0 |
0x13 |
" |
0x0..0xF |
|
Lese Modul 3 Nibble 1 |
0x17 |
" |
0x0..0xF |
|
Lese Modul 3 Nibble 2 |
0x1B |
" |
0x0..0xF |
|
Ping |
0x00 |
Okay |
0x3 |
Tabelle 2
Die Kommunikation wird mittels zweier Signale der Druckerschnittstelle gesteuert. Die Signale /STROBE (=/SELMUX) und /ACK dienen als sogenannte Hand-Shake Leitungen.
Bild 5
Kommunikation Host<->MUX
Das Bild 5 zeigt die zeitliche Abfolge der Kommunikation zwischen dem Host (PC) und dem MUX. Diese ist nach dem Master-Slave-Prinzip verwirklicht und gliedert sich in 4 Phasen:
|
Phase 1: |
Der Host (PC) sendet ein Kommando auf den Daten-Leitungen D[0..4] zum MUX. Zum Zeitpunkt der fallenden Flanke des /SELMUX-Signals müssen die Daten stabil anstehen. (Setup Zeit der Daten zu /SELMUX ¯ ist 0s). Während des folgenden Zeitraums, also bis der MUX einen Low-Pegel auf der /ACK-Leitung zurückmeldet, führt dieser das Kommando aus. |
|
Phase 2: |
Der MUX hat das Kommando ausgeführt und gibt auf der /ACK-Leitung einen Low- |
|
Phase 3: |
Der Host (PC) wiederum quittiert das Einlesen der Daten vom MUX damit, dass er das Signal /SELMUX auf High-Pegel schaltet |
|
Phase 4: |
Den Signalwechsel von /SELMUX erkennt der MUX und schaltet das Signal /ACK ebenfalls auf High-Pegel. Damit ist ein Kommunikationszyklus abgeschlossen. |
Ansteuerung der A/D Wandlermodule
Auf den A/D-Wandlermodulen kommt der in [1] beschriebene 12Bit-AD-Wandler MAX186 zum Einsatz. Auf diesem Modul wird der interne Conversion-Clock des MAX186 (1,7Mhz) genutzt. Das Bild 6 zeigt den sogenannten Internal-Clock-Mode im Diagramm.
Bild 6
Kommunikation MUX<->A/D-Wandlermodul
Nach Addition der Zeitdauer aller Signale ergibt sich eine Zykluszeit von ca.12,5ms pro Wandlung. Dies wären 80645 Wandlungen in der Sekunde. Dieser Wert ist in diesem Projekt nur theoretischer Natur. Die Übertragung der 12-Bit Wandlungsergebnisses in Nibbles á 4Bit über die Druckerschnittstelle setzt die Wandlungsrate auf etwa 2000 Wandlungen pro Sekunde herab.
Zugriffszeiten auf die A/D-Wandlermodule
Die Zeitspanne TBefehl (siehe Bild 5) ist die Zeit, die der MUX zur Abarbeitung eines Commandos vom Host benötigt. Tabelle 5 zeigt die typischen Befehlsabarbeitungszeiten für die 10Mhz-Version des PIC16C84.
|
Commando vom Host |
Abarbeitungszeit TBefehl |
|
Lesen eines beliebigen Nibbles (z.B. Lese Modul0 Nipple 0) |
60 ms |
|
Wandle beliebigen Kanal |
260 ms |
Tabelle 3
Diese Werte konnten bereits durch den im MPLAB IDE [6] integrierten Simulator ermittelt, und mittels eines Logikanalyzers an der realen Schaltung nachgemessen werden. Die Übertragungszeiten vom Host zum PC können der Tabelle 4 entnommen werden.
|
Operation |
Zugriffszeit |
|
Kanalauswahl, Wandeln und Übertragung von 1x 12-Bit |
0,55 ms |
|
Kanalauswahl, Wandeln und Übertragung von 4 x 12-Bit |
1,77 ms |
|
Kanalauswahl, Wandeln und Übertragung von 32 x 12-Bit mit 104 Zugriffen (= 8* Kanalauswahl + 96 * Lese Nibble) |
16 ms |
Tabelle 4
Eine Modifikation der Hardware für den Betrieb am EP-Port würde die Zykluszeiten natürlich drastisch senken. So könnte ein 12 Bit Wandlergebnis in einem Zyklus eingelesen werden. Es wären zum Einlesen aller 32 Kanäle nur noch 40 Zugriffe (= 8* Kanalauswahl + 32 * Lese Nibble) nötig. Dies würde die Zugriffszeit für 32 Kanäle auf ca. 8 ms absenken.
Das Innenleben des MAX186
Da der MAX186 bereits ausführlich in [1] beschrieben wurde, muss an dieser Stelle nur eine kleine Aufrischung erfolgen. Über den Din (Pin 17) erhält der MAX186 ein 8 Bit breites Kommando. (In diesem sind Betriebsbe-dingungen und Kanalnummer kodiert). Auf die acht Eingangskanäle CH0 bis CH7 des A/D-Wandlers folgt eine
Track- and Hold-Einheit in welcher der Augenblickswert des analogen Signals zwischengespeichert wird . Dahinter ist die eigentliche Wandlereinheit geschaltet. Diese arbeitet nach dem Prinzip der sukzessiven Approximation. Nach der Wandlung steht der 12-Bit lange Digitalwert im Ausgangsschieberegister gespeichert, von wo aus dieser über den Dout (Pin 15) ausgelesen werden kann. Das Interface des MAX186 ist ein serielles SPI-,QSPI-, Microwire- bzw. TMS320-kompatibles 4-Draht-Interface.
Die Hardware des MUX
Grundsätzliches
Der gewählte mController PIC16C84 von MicroChip erfüllt mit seinen integrierten Funktionseinheiten alle Anforderungen dieses Projektes. Die modifizierte Dual-Bus Harvard Architektur und der 35 Befehle umfassende RISC Befehlsatz erreicht bei 10Mhz Taktfrequenz immerhin 2,5Mips.
Die getrennten Programm-/Datenspeicherbusse und das Lesen (Fetch) der Instruktionen einen Zyklus vor ihrer Abarbeitung, machen die Befehlsausführung in einem einzigen Zyklus möglich.
Bild 7
PIC16C84 im PDIP oder SOIC
Es würde den Rahmen dieses Beitrags sprengen, den gesamten internen Aufbau des PIC16C84 hier näher zu erläutern. Die Details sind dem Datenblatt des mControllers[6] zu entnehmen. Deshalb sollen hier nur die wichtigsten Eigenschaften des PIC16C84 nocheinmal angeführt werden:Eigenschaften des mControllers PIC16C84:
|
-- |
18 pol. DIP oder 18 pol. SOIC Gehäuse |
|
-- |
Low Power, High Speed CMOS Design max. 10Mhz Taktfrequenz |
|
-- |
1024 * 14 Bit on-chip E2PROM Programmspeicher |
|
-- |
36 * 8 Bit Register (Static RAM) |
|
-- |
64 * 8 Bit on-chip E2PROM Datenspeicher |
|
-- |
8 Ebenen Hardware-Stack |
|
-- |
4 Interrupt Quellen : Externer Interrupt RB0, Timer Overflow, PORTB<7:4>, |
|
-- |
8 Bit Timer/Counter mit 8 Bit programmierbaren Prescaler |
|
-- |
4 verschiedene on-chip Oszillatortypen wählbar |
|
-- |
13 I/O Pins Strombelastung pro Pin max. 25mA sink / 20mA source |
Einziger Nachteil ist, dass der PIC16C84 für diese Anwendung eigentlich mindestenes 28 Ports benötigen würde. Bei näherer Betrachtung der Signalübertragungen über lange Leitungen (bis ca. 1m) durch die eingesetzen parallelen Schnittstellen stellt die Portanzahl des mControllers dann aber doch kein Manko dar. Betrachten wir dazu einmal die Einsatzbedingungen:
Bild 8
Systemkomponenten
In dieser Anwendung müssen die Signale vom PC <--> MUX bzw. vom MUX <--> A/D-Wandlermodulen über 0,25m bis 1,00m lange Leitungen übertragen werden. Die Ausgangssignale des in CMOS-Technologie ausgeführten PIC-Controller liegen bei etwa 5V. Verbunden mit der hohen Treiberleistung des Controllers führt dies zu kritischen Unter- bzw. Überschwingern der Signale. Der Spannungshub erzeugt im Extremfall am Leitungsende ein positives Überschwingen von 2x5V=10V. Diese Spannung überschreitet die zulässigen Werte eines jeden Logikschaltkreises und kann zu dessen Zerstörung führen. Dagegen erreichen TTL-Bausteine einen Signalhub von ca. 3V. Positive Überschwinger erreichen somit eine maximale Spannung von 2x3V=6V. Für Eingänge von TTL-Schaltungen sind diese Werte jedoch unkritisch. Um die Probleme von Reflexionen und die daraus resultierenden Signalverzerrungen zu verringern, werden als Schnittstellen-Bausteine LS-TTL Bustreiber eingesetzt.
Eine weitere Schaltungsmaßnahme ist der Abschluß einer jeden Signalleitung mit der in Bild 9 gezeigten Widerstandskombination.
Bild 9
Abschluss der Signalleitungen
Die Fehlanpassung bei dem gegebenen Wellenwiderstand Zw=100W der Leitung (220W//220W=110W,
Reflexionfaktor=0,05) ist so gering, dass die Leitungsreflexionen keine verbleibenden Signalverzerrungen mehr verursachen. Es darf natürlich nicht verschwiegen werden, dass aus dem Gleichstrompfad dieses Leitungs-abschlusses ein großer Leistungsumsatz resultiert.
Die schnellere CMOS-Logik würde nur zusätzlichen Schaltungsaufwand für eine sichere Signalübertragung mit sich bringen. Es gilt die in [7] gemachte Aussage, "dass die Geschwindigkeit der verwendeten Logikfamilien nur so schnell sein sollte, wie es die Applikation erfordert." Weitergehende, sehr interessante Informationen, liefert auch die Firmenschrift [8] von Texas Instruments.
Aus den letztgenannten Gründen wurde auf einen Wechsel, hin zu den "größeren" Brüdern aus der PICmico Familie (wie z.B. dem PIC16C74/C42) verzichtet. ( Es soll auch nicht verschwiegen werden, dass die schnelle Reprogrammiermöglichkeit des E2PROM-Programmspeicher dem PIC16C84 gerade beim Austesten eines Designs zum Vorteil gereicht.) Die Idee den recht preisgünstige "uralt" 4-Bit I/O-Expander 8243 (Intel) einzusetzen, musste (leider) verworfen werden, da dieser inzwischen auch von NEC und Thosiba abgekündigt wurde.
Bild 10
Blockschaltbild MUX
Mit Hilfe von Standard-Bustreibern wurde, wie im Blockschaltbild (Bild 10) gezeigt, ein 4-Bit breiter Datenbus geschaffen. Dieser erweitert die bestehenden Ports des PIC16C84 auf die 28 I/O-Pins, die in dieser Anwendung benötigt werden.
Simultaner Zugriff auf die A/D-Wandler
Die Hardware des MUX ist so ausgelegt, dass ein ausgewählter Kanal gleichzeitig auf allen vier A/D-Wandlermodulen gewandelt und in das RAM des PIC16C84 eingelesen wird. Der RAM-Bereich, in dem die 4x12Bit zwischengespeichert werden, wird im dazugehörigen Assemblerprogramm mit CACHE[0..11] bezeichnet.
Dem Stromlaufplan (Bild 11) sind die Schnittstellen (X[2..5]) zu den A/D-Wandlern zu entnehmen. Die Signalbezeichnungen dieser Funktionseinheit (D4, D5 und D6) sind an die Nomenklatur der Pinbezeichnung des MAX186 angelehnt deshalb wohl selbsterklärend.
Um die Qualität der Signalübertragung auf den Leitungen MUX -->A/D-Wandlern noch zu verbessern, wurde jede Leitung wie in Bild 9 gezeigt abgeschlossen. Auf den A/D-Wandlermodulen, die über kritisch lange Leitungen mit dem MUX verbunden sind, wurde chirurgisch eingegriffen, und sowohl eingehende als auch ausgehende Signale über LS-TTL Bustreiber gepuffert.
Bild 11
Stromlaufplan MUX
Schnittstelle zum PC
Die Schaltkreise D3 und D8 bilden das dem Centronics-Standard in Teilen "nachempfundene" Interface des MUX zum Host. Es werden natürlich nur die in dieser Applikation nötigen Signale zur Verfügung gestellt. Mit Verweis auf Bild 4 sind folgende Signale zu nennen. Die Daten vom PC -->MUX werden über D3 vom MUX-internen Datenbus entkoppelt. Die Daten vom MUX --> PC werden im Latch D4 gespeichert und von dort über die Statusleitungen in den PC eingelesen.
Die Software
Die Entwicklungsumgebung MPLAB
Die Softwareentwicklung erfolgte mit dem Integrated Developement Environment (IDE) MPLAB für Windows. Das kostenlos von der Firma Microchip [9] beziehbare IDE beinhaltet zunächst die "Workbench" , einen Assembler, einen Linker und einen Simulator. Desweiteren sind in MPLAB Zukaufprodukte, wie In-Circuit-Emulatoren (ICE), C-Compiler oder Programmer integrierbar. Im Vollausbau sind dann u.a. folgende Komponenten verfügbar:
|
MPASM |
Assembler für PICmicro’s wie: |
|
MPLAB-SIM |
Simulator für alle vom MPASM unterstützte Controllertypen |
|
PIC-MASTER |
In Circuit Emulator Anbindung |
|
MPLINK |
Erzeugt aus Object Modulen aus MPLab-C, Assembler MPASM und Bibliotheken einen ablauffähigen File |
|
HI-TEC-C Compiler |
ANSI-C Compiler der Firma HI-TEC[10] unterstützt PIC12Cx, PIC14000, PIC16Cx und PIC17Cx Controller |
|
MPLAB-C17 |
ANSI-C Compiler unterstützt PIC17Cx |
|
PIC Start Plus |
Programmer für PIC16Cx/17Cx Controller via RS232 |
Für dieses Projekt waren die frei verfügbaren Komponenten MPASM und MPLAB-SIM des MPLAB IDE’s vollkommen ausreichend, um mit dem am Ende generierten HEX-File einen mController zu programmieren.
Einführung in MPLAB
Die Oberfläche des MPLAB erinnert an die heute unter Windows gängigen Entwicklungsumgebungen wie z.B. auch MS-Visual C. Ein einfacher Editor und ein Projekt Manager sind integriert.
Project anlegen
Der erste Schritt zum Neuanlegen eines Projektes geschieht durch den Menübefehl Project-->New Project aus dem Bedienermenü. Nach der Festlegung des Pfades und des Projektnamens können bereits vorhandene Dateien in das Projektmanagement einbezogen werden. Das System erzeugt einen Projekt Konfigurations File PROJECTNAME.CFG und einen Projekt File PROJECTNAME.PJT.

Bild 12
MPLAB Edit Projekt
In späteren Entwicklungsstadien hinzukommende Dateien werden über Projekt-->Edit Project dem Projekt zugewiesen. Die Einstellungen des Compiler können über den Menübefehl Project-->Add/Modify Compiler (Bild 13) eingesehen und verändert werden. Als Endprodukt der Softwareentwicklung ist ein Programmierfile im Hex-Format voreingestellt. Dieses kann z.B. mit dem in [11] vorgestellten Programmiergerät in das E2PROM des PIC16C84 transferiert werden.
Bild 13
MPLAB Compiler Options
Editieren des Quellcodes
Der Menübefehl File-->Open Source... öffnet im Editor die gewünschte Quelldatei. In unserem Falle den File MUX.ASM.
|
; Kommentare ; File : MUX.ASM call HS ; Hand-Shake mit Host call HS ; Hand-Shake mit Host call HS ; Hand-Shake mit Host |
Listing 1
Rumpf des Programmes MUX.ASM
Im Listing 1 folgt nach dem sogenannten Header, dessen Zeilen immer mit einem ‘;’ als erstes Zeichen (=Kommentar) in einer Zeile beginnen, die Steueranweisung list p=16c84 . Diese gibt den zu unterstützenden Prozessor für den Assembler an. Das Statement #include "<FILENAME>" weisst, wie z.B. aus der Hochsprache C bekannt, den Übersetzungsprozess an, die nachfolgend angegebenene Datei "<FILENAME>" in die Sourcedatei einzubeziehen. In unserem Falle wird z.B. die von Microchip bereits mitgeliefert Includedatei PIC16C84.INC einbezogen. In dieser sind bereits Konfigurationen, Register oder Bitdefinitionen für Flags festgelegt.
Die Anweisungen ORG (Festlegen der Programmcode-Speicherstelle) und EQU (Konstantenzuweisung) sind wie aus anderen Assemblerprodukten bekannt, einzusetzen. Der Befehlszähler des PIC16C84 zeigt nach einem Power-On Reset bzw. einem /MCLR-Reset auf Adresse 000h. Deshalb steht vor der ersten Assembleranweisung das Statement ORG 0.
Ein Interrupt führt beim PIC16C84 immer zu einem Sprung im Code an die Adresse 4. Die Controllerarchitektur stellt nur diesen einen Interruptvektor für alle freigegebenen Interruptquellen zur Verfügung. Deshalb muss erst in der Interruptroutine durch Abfragen gewisser Flags entschieden werden, welches Ereignis den Interrupt ausgelöst hat. Der "Interruptroutine" muss das Statement ORG 4 vorangestellt werden.
Assembler starten
Nach der Programmeingabe assembliert der Menübefehl Project-->Make Project alle dem Project zugeordneten Quelldateien.
Das Projektmanagementwerkzeug (ähnliche Funktionalität wie etwa die MAKE Utilities von Borland oder Microsoft) vergleicht dazu die Erstellungzeit der Quellfiles mit dem des Projectobjektfiles (hier: MUX.COD) . Sollten die Quelldateien jünger als die Objektdatei sein, so werden die entsprechenden Dateien neu assembliert. Sollte keine Fehler aufgetreten sein, so meldet dies der Assembler wie in Bild 14 gezeigt.

Bild 14
MPLAB Compiler Status Meldung
Etwaige Fehler werden in einem seperaten Statusfenster gemeldet. Durch Anklicken der Fehlermeldung öffnet MPLAB das entsprechende File und führt den Cursor an die Fehlerstelle im Quellcode.
Die Debuggingoberfläche
Durch den im MPLAB integrierten Simulator konnte die Firmware des MUX bereits vor dem Programmieren des PIC16C84 komplett ausgetestet werden. Entsprechende Stimuli machen es im Debugmodus möglich Signale an den Pins des "virtuellen" Controllers vorzugeben und das Verhalten des Programmes im Sourcecode zu beobachten und auszuwerten. Nach dem kompletten Austesten lief der "reale" programmierte Controller auf Anhieb in der Schaltung. Um die MPLAB Oberfläche auf das Debugging vorzubereiten muss zunächst der zu simulierende Controller (Bild 15) mit dem Menübefehl Project-->Development Mode ausgewählt werden.

Bild 15
MPLAB Auswahl des Prozessortyps
Im nächsten Schritt "schneidert" sich der Benutzer die Oberfläche mit den für ihn wichtigen Informationen während des Debuggings zusammen. Der Menübefehl Window--> usw.... hält dazu die verschiedenen Informationmöglichkeiten vor. Das Bild 16 zeigt beispielhaft die geöffneten Fenster einer solchen Debuggsitzung:

Bild 16
MPLAB Beispiel einer Debug-Sitzung
Für das Beispiel sind folgende Befehle der Bedienoberfläche von MPLAB vorgenommen worden:
Window-->Project öffnet ein Fenster mit den Namen der am Projekt beteiligten Files. Durch Anklicken eines der im Fenster aufgelisteten Files öffnet das System automatisch im Editor jeweils die dazugehörige Datei.
Window-->File Register stellt den gesamten on-chip RAM- und Registerbereich dar.
Window-->Special Function Register stellt den Registerbereich nochmals, aber diesmal mit der Klartext-bezeichnung des einzelnen Registers dar.
Window-->Program Memory zeigt die Instruktionen auf den vom Assembler zugewiesenen Speicherstellen im ROM, den OpCode in hexadezimaler Darstellung und den äquivalenten Assemblerbefehl.
Window-->Stopwatch... zeigt die hilfreiche Stoppuhrfunktion, die es möglich macht die Programmlaufzeit (in Abhängigkeit der Taktfrequenz des späteren Targets) zu vermessen. Ein mühseliges Abzählen der einzelnen Instruktionen bleibt dem Benutzer so erspart.
Window-->Modify... ermöglicht das ändern von Daten, Programm, Stack und E2PROM während des Debuggings.
Entwanzen des Codes
Für den geübten Benutzer hält MPLAB eine spezielle Buttonleiste zum beschleunigten Aufruf vieler Befehle auf Knopfdruck bereit. In dieser Kurzbeschreibung werden aus Gründen der Vereinfachung nur die äquivalenten Befehle aus dem Hauptmenü beschrieben.
Zunächst wird der Befehlszähler zurückgesetzt. Der entsprechende Menübefehl Debug-->RUN-->RESET setzt das Register PCL=00h. Die entsprechende Instruktion an der Adresse 0 im Source Code Window (MUX.ASM) wird mit einem Markerbalken gekennzeichnet. Um die Abarbeitung des Codes zu beobachten steht der Einzelschrittbetrieb (Debug-->Run-->Step F7 oder Debug-->Run-->Step Over F8) und eine vom Simulator selbstständig durchgeführte langsame schrittweise Abarbeitung (Debug-->Run-->Animate CTRLF9). des Codes zur Verfügung.
Ein wichtiges Werkzeug zum Austesten von Code stellt, wie auch in anderen Debuggern, der Einsatz von Haltepunkt oder Neudeutsch Break Points dar. Anstatt den Code immerwieder schrittweise "zu durchschleichen", werden im Source Code Window (MUX.HEX Fenster im Bild 15) an den gewünschten Stellen Haltepunkte gesetzt. Dies geschieht z.B. dadurch, dass der Mauszeiger auf die entsprechende Instruktion gestellt wird. Sodann aktiviert man mit der rechten Maustaste ein Kontextmenü und setzt einen Haltepunkt gewünschten Typs.
Mit einem Haltepunkt gekennzeichnete Instruktionen stellt MPLAB in der Grundeinstellung in roter Farbe dar.
Nach der Eingabe des Menübefehls Debug-->Run-->Run F9 wird der Code bis einschließlich des durch den Break Point gekennzeichneten Befehls abgearbeitet, dann stoppt der Debugger. Nun können die Auswirkungen auf die einzelnen Register abgelesen werden.
Um Eingangsignale an Pins für ein Debugging zu manipulieren, hält der Simulator mehrere Stimulimöglichkeiten vor.
Asychronous Stimulus:
Debug-->Simulator Stimulus-->Asynchronus Stimulus.....

Bild 17
MPLAB Asynchronus Stimulus
Den einzelnen Buttons des Dialogs im Bild 17 werden bestimmte Signale (Pulse, High, Low, Toggle) und Pins der Controllers zugeordnet. Dazu wird der Mauszeiger auf den zu bearbeitenden Button gestellt und wieder mittels rechter Maustaste ein Kontextmenü aufgerufen. Der Menüpunkt Assign Pin ordnet den Button schließlich als Signalquelle einem Controllerpin zu. Ein Druck auf den so konfigurierten Funktionsbutton legt während des laufenden Debuggings das entsprechende Signal an den ausgewählten Pin und kann so die Abarbeitung der Codes beeinflussen.
Pin Stimulus:
Debug-->Simulator Stimulus-->Pin Stimulus...
Die I/O Pins werden zu bestimmten Zeitpunkten oder Schritten während der Simulation mit vom Benutzer festgelegten Signalen verbunden. Die Definitionen der Signale, der Pins und der Zeitschritte sind dazu in sogenannten Stimulusdateien (*.sti) abzulegen.
Clock Stimulus:
Debug-->Simulator Stimulus-->Clock Stimulus...
Die I/O Pins können über Taktsignale getrieben werden. Die Taktzyklen sind synchron zur PIC16 MCU.
Die Länge von High- oder Low-Zyklen werden in dezimaler Form angegeben. Die Voreinstellung (initial Phase) führt einen High-Pegel.
Register Stimulus:
Debug-->Simulator Stimulus-->Register Stimulus...
Der Registerstimulus erlaubt es Werte aus einer Datei in die Fileregister des Prozessor zu schreiben, wenn das Programm eine vom Bediener festgelegte Stelle erreicht hat. Die Funktion ist für die Simulation immer dann interessant, wenn der Controller z.B. über seine Portpins Werte einliest. In unserem Falle (MUX.ASM) wären dies z.B. die Kommandos des Hosts (PC), die während der Interruptroutine (Interruptquelle Pin RB0=/SELMUX) vom Port A in eine Speicherstelle des Controllers eingelesen werden.
Firmware- die Software im PIC
Das Assemblerprogramm des Projektes ist der Übersicht wegen auf mehrere Dateien verteilt. In den Dateien *.h befinden sich die verschiedenen Wertezuweisungen.
|
Dateiname |
Inhalt: |
|
Mux.asm |
Hauptdatei des Projektes und Assemblercode |
|
MuxComm.h |
Definitionen betreffend die Kommunikation zwischen MUX und dem Host (PC) |
|
MuxPatt.h |
Testmuster, die in den im Programm als "Cachespeicher" bezeichneten RAM-Bereich des PIC16C84 geschrieben werden |
|
Max186.h |
Steuerung des A/D-Wandlers MAX186 |
|
MuxRegs.h |
Vereinbarungen für Register, Flags, Cache und Chip-Select |
Tabelle 6
Dateien des Projektes
Die prinzipielle Struktur des Programmes MUX.ASM ist dem Bild 18 zu entnehmen. Nach einer Initialisierungsequenz INIT:, die immer nach einem Reset ausgeführt wird, sind die Signalrichtungen der I/O-Pins, der "Interrruptcontroller" und der Inhalt Commando-Register (CoR) festgelegt. In der Warteschleife MAIN: fragt das Programm den Inhalt der RAM-Zelle CoR solange ab, bis darin über die Interruptroutine INTR: ein gültiges Commando abgelegt wurde. Nach der Auswertung des Commando verzweigt das Programm in die jeweils zugehörige Subroutine.

Bild 18
MPLAB Ablaufstruktur MUX.ASM
Die Funktionen sind im Listing des Programms MUX.ASM ausführlich mit Kommentaren versehen. Deshalb folgt an dieser Stelle jeweils eine kleine Funktionsbeschreibung der Subroutinen:
|
Subroutine |
Funktionsbeschreibung |
|
Convert: |
Funktion dekodiert den zu wandelnden Kanal aus dem CommandoRegister (CoR). Die Funktion ist für das A/D-Wandler Modul MAX186 Version ELRAD entwickelt. In ADControl ist der Modus des MAX 186 definiert. (siehe auch File Max186.h). TimeOut : wenn die A/D-Wandler nicht angeschlossen sind oder die Kommunikation zu diesen gestört ist im DatenRegister (IC D8) der MUX Baugruppe zurück (siehe auch File MuxComm.h) |
|
HS: |
Zunächst wird der Inhalt des W-Reg in das Daten Register (IC D8) der MUX-Baugruppe geschreiben.. Danach folgt Hand-Shake Kommunikation mit dem Host (PC). Sobald MUX erkennt, dass /SELMUX=1 wird /ACK=1 zur Quittierung gesendet. |
|
Init: |
Initialisierung aller benötigten Register des PIC16C84 für die Applikation. Richtung der Ports festlegen, Interruptmechanismus initialisieren und freigeben. Zusätzlich schreibt die Routine nach einem Reset ein Bitmuster auf den MUX-internen Datenbus, das mit Oszilloskop oder Logikanalyzer aufgenommen werden kann. (Primitiver Test, um bei der Inbetriebnahme zu testen ob der PIC arbeitet) |
|
Ping: |
Es erfolgt das Beschreiben des "CACHE", d.h. der Speicherstellen Cache[0..11] (PIC-internes RAM) mit festgelegten Testmustern. (siehe auch File MuxPatt.h) |
|
Read: |
Lesen des angeforderten Nibbles aus "Cache[0..11]" Speicherbereich des PIC-internen RAM's. Die Funktion liefert via HS-Funktion das vom Host angeforderte Nibble zurück und schreibt dieses in das DatenRegister D8 auf der MUX Baugruppe. (siehe auch File MuxComm.h) |
Der Maschinencode des Programm belegt ca 25% des verfügbaren Programmspeiches im PIC16C84 (siehe MUX.LST). Damit ist noch genügend Raum um z.B. eine Kalibrierung der Messwerte, oder ähnliche Funktionen einzufügen.
Die Messwertaufnahme des Hosts
Die DOS/RTKernel Anwendung MUX.EXE [2] ist mit einer SAA-Oberfläche versehen. Natürlich entspricht das Programm nicht mehr den standardisierten Windows3.x/95 Bedieneroberflächen. Der Hauptgrund dieser, für den einen oder anderen sicher als antiquiert empfundenen DOS-Umgebung ist darin zu suchen, dass Windows3.x/ Windows95 nicht so ohne weiteres "echtzeitfähig" zu machen sind. In unserem Falle wollten wir sicher gehen, dass eine äquidistante Abtastung der physikalischen Signale aus dem Laborprozess gewährleistet ist. Dazu genügte uns ein kleines, wenn auch nicht mehr ganz "zukunftssicheres" DOS-Programm.
An dieser Stelle müssen natürlich die schon seit einiger Zeit existierenden Soft-[12] als auch Hardwarelösungen genannt werden, die unter Windows3.x/95 echtzeitfähige Applikationen ermöglichen.
Eine sehr interessante Hardwarelösung bietet dazu die Firma LP Elektronik [13] an. Als Basis nutzt diese den auf dem ISA-Bus brachliegenden Non-Maskable-Interrupt (NMI). Eine über den NMI ausgelöste Unterbrechungs-anforderung kann auch von Windows3.x/95 nicht ignoriert werden. Im Rahmen dieses Projektes wurden aber derlei Lösungen noch nicht weiter verfolgt.
Das Messwertaufnahmeprogramm MUX.EXE
Die Entwicklungsumgebung
Die Programmerstellung erfolgte mit dem MSC6.0a Compiler-Paket und einer ebenfalls mit diesem Compiler entwickelten C-Toolbox[14]. Durch das Echtzeit-Multitasking-System RTKernel 4.5 für C/C++ wurde die Echtzeitfähigkeit implementiert. Der Einstieg in die Programmentwicklung gestaltete sich durch die von der
Firma On Time mitgelieferten Beispiele sehr einfach.
RTKernel-Betriebssystemaufrufe
Eine RTKernel Task ist eigentlich nichts anderes als eine C-Funktion, die ohne Aufrufparameter und Rückgabewerte (z.B. void GetChannelsTask(void) ), ansonsten aber genauso wie eine Prozedur/Funktion implementiert ist.
Zum Startzeitpunkt des Programmes MUX.EXE existiert zunächst nur eine Task, nämlich die als main()-Funktion deklarierte C-Funktion des Hauptprogramms. Die main()-Funktion wird durch die RTKernel-Funktion RTKernelInit(...) in eine Task verwandelt. Neben verschiedenen Initialisierungen und Prüfungen legt diese RTKernel-Funktion die Priorität der main()-Task fest.
Die main()-Task erzeugt nun ihrerseits durch den Aufruf der RTKernel-Funktion RTCreateTask(...) "parallel" zur ihr arbeitende Tasks. Jede Task besitzt eine Priorität zwischen 1 und 64 und einen eigenen Stack. Alle in einer Task lokal deklarierten Variablen werden auf dem Stack der Task angelegt.
Die Inter-Task-Kommunikation wird durch Semaphoren und Mailboxen abgewickelt.
Semaphoren erlauben es, Signale zwischen den Tasks auszutauschen. Diese können Tasks aktivieren oder sus-pendieren. In diesem Projekt wurde zum "Übermitteln des Abtasttaktes" eine binäre Semaphore (Erzeugung: RTKCreateSemaphore(Binary,0,....) eingesetzt.
Mit der Hilfe einer Mailbox können Daten zwischen Tasks ausgetauscht werden. Die Anzahl der Daten, die eine Mailbox aufnehmen kann, ist konfigurierbar.
Mailboxen (Erzeugung: RTKCreateMailbox(sizeof(int),1024,"Messwerte") ) sind angepasst, um Daten zwischen Tasks oder zwischen Interrupt-Handlern und Tasks zu puffern. Im Projekt wird eine Mailbox eingesetzt, um die Task zur Messwertaufnahme und die Task zum Abspeichern der Daten im Filesystem zu entkoppeln. Die Mailbox Box puffert hierbei die Messdaten.
Ein Auszug aus dem Source MUX.C zeigt in Listing 2 die Initialisierung des RTKernel-System durch den Benutzer.
/****************************************
File MUX.C
****************************************/
void main(int agc,char** argv)
{
.......
.......
// damit sich RTK mit DISKCACHE SMARTDRV von MicroSoft verträgt
SmartDriveInit();
RTKernelInit(MAIN_PRIO); // main() wird zu einer Task mit Priorität MAIN_PRIO
RTKeybrdInit();
ITimerInit();
if (RTKLPSemas > 0) /* Für Preemptions muss (!) der Bibliotheks- Schutz vorhanden sein */
{
printf("\nLibProtect ein");
RTKPreemptionsON();
RTKDiskIntsON();
}
RTTextIOInit();
// PC-Timer 50 ms Takt umschalten
SetTimerIntVal(1000L*PcTimerClock);
.......
.......
/******************* RTK Task Kommunikation *******************************/
SemaStartSample=RTKCreateSemaphore(Binary,0,"Semaphore S");
Box=RTKCreateMailbox(sizeof(int),1024,"Messwerte");
/******************* RTK Task Initialisierungen *******************************/
RTKFarStacks= True;
ClockHandle=RTKCreateTask(Clock,CLOCK_PRIO,DEFAULT_STACK_SIZE, "Uhranzeige");
DummyTaskHandle=RTKCreateTask(DummyTask,CLOCK_PRIO,DEFAULT_STACK_SIZE,"Dummy");
SampleClockHandle =RTKCreateTask(SampleClockRate,CLOCK_PRIO,DEFAULT_STACK_SIZE,"SampleClock");
GetChannelsHandle =RTKCreateTask(GetChannelsTask,CLOCK_PRIO+5,DEFAULT_STACK_SIZE,"GetChannels");
.......
.......
// Endlosschleife der main()-Task
for(;;)
{ .......
.......
}
Listing 2
RTKernel Initialisierungen
Die Programmstruktur
Der Aufbau, der wie ein "normales" DOS-Programm zu startenden RTKernel-Applikation MUX.EXE ist dem Bild 19 zu entnehmen. Nach dem Aufruf der C-MAIN Funktion erzeugt das Programm alle Tasks der Anwendung. Die dann ebenfalls zu einer Task (main()-Task) gewandelte C-MAIN- Funktion, beinhaltet die Bedienertask, d.h. die Steuerung der SAA-Oberfläche. Alle Task sind programmtechnisch als Endlosschleifen zu implementieren. Nur Betriebssystemaufrufe starten oder beenden diese.

Bild 19
Programmstrukur MUX.EXE
Das Herz des Systems ist die Task SampleClockRate(). Diese arbeitet (mit der gewählten Abtastrate) und signalisiert über die Semaphore SemaStartSample, dass die Abtast-Task GetChannelsTask(), die bisher wartete, weiterlaufen soll. Da dieser Vorgang vom RTKernel-Betriebssystem gesteuert wird, ist die Einwirkung auf die Task mit einem Blitz symbolisiert. Nachdem über den MUX alle A/D-Wandlerwerte eingelesen wurden, wartet GetChannelsTask() wieder an der Semaphore SemaStartSample auf ein neues Abtastsignal.
Die aufgenommenen Messwerte schreibt GetChannelsTask() in eine nach dem Fifo-Prinzip arbeitende Mailbox und entkoppelt so die Messwertaufnahme und das Abspeichern der Messwerte. Das Weiterlaufen der FileIOTask() bzw. ConIOTask() wird wieder durch einen Betriebssystemaufruf gesteuert. Deshalb ist die "Wirkung" der beschriebenen Mailbox auf das Weiterarbeiten der letztgenannten Tasks wieder mit einem Blitz symbolisiert.
Sobald die Mailbox mit einem oder mehreren Messwerten gefüllt ist und die FileIOTask() vom Betriebssystem als Task mit der aktuell höchsten Priorität erkannt wurde, läuft diese weiter und speichert die Messwerte in einem File ab.
Unabhängig, quasi parallel zu den übrigen Tasks, läuft die ClockTask(). Sie hält sich selbst durch einen Betriebssystemaufruf immer wieder an und läuft nach einer gewissen Wartezeit weiter. Dabei wird die aktuelle Uhrzeit ausgegeben. Folgende Aufgaben werden von den einzelnen Tasks erledigt:
|
Task |
Modul-Name |
|
|
main() |
Mux.c |
Bedienertask in Form einer Programmschleife. Durch das Beenden der Bedienertask wird das gesammte Programm verlassen. Zunächst werden alle Tasks der Applikation gestartet, und ausserdem der PC-Timer auf 20 Ticks/Sek gestellt. In der Header Datei MESS.DEF sind die Konstanten zur Timermanipulation abgelegt. Die Zeitbasis bildet der TIMER0, eines 8254-kompatiblen Timer/Counter in den PC-Chipsätzen. |
|
SampleClockRate() |
SmplRate.c |
Die Task ist der "Taktgeber" des Abtastsystems. Mit dem vom Bediener eingestellten Zeitraster wird das zyklische Einlesen der Messwerte, also die Abtastung gesteuert. Der Start zum Einlesen von neuen Messwerten wird durch eine Semaphore an die wartende Abtast-Task GetChannelTask() gegeben. |
|
FileIOTask() |
FIO.c |
Diese Task übernimmt die Wandlerdaten von der GetChannelTask() und schreibt diese in eine Datei deren Namen in der Initialisierungsdatei MUX.INI (z.B. MUXDATA.DAT) abgelegt ist. |
|
ConIOTask() |
ConIO.c |
Mittels des RTKernel-Aufrufs RTKernelDelayUntil() läuft die Task, nachdem diese "schlafen gelegt" wurde weiter. Es ist also eine zyklische Task mit einem festen Zeitraster implementiert. Die Task schreibt alle 20 Timerticks (hier: 20*50ms=1s) die Messwerte auf die Console |
|
GetChannelsTask() |
GetADVal.c |
Diese Task wartet zunächst auf das Startsignal, dass durch Setzen einer Semaphore in der Task SampleClockRate() gegeben wird. Die dann vom MUX gelesenen Messwerte werden über eine Mailbox an die Funktion FileIOTask() weitergegeben. Diese Task beinhaltet die gesamte Kommunikation mit dem MUX. |
|
Clock() |
Clock.c |
Anzeige von Datum und Uhrzeit. Diese Task stellt nur eine primitive visuelle Kontrolle dar, ob die RTKernel Applikation läuft. |
Die Kommunikation mit dem MUX
Das Modul GetADVal.C beinhaltet das Hand-Shake-Protokoll zum MUX. Es ist dies das Gegenstück zu dem im PIC16C84 auf dem MUX programmierten Protokoll.
Alle Zugriffe auf den Druckerport sind mit I/O-Befehlen in C programmiert. Listing 3 zeigt einen Auschnitt aus der GetChannelTask() und dem Handshake Protokoll.
void GetChannelsTask(void)
{ .......
.......
//Endlosschleife der Task
while (True)
{
.......
// Trigger Code für Kanal k an Mux
outp(LDP[Lpt],CK[k]);
// Lese Status
if (MUX_HandShake(5)==FALSE)
{
// Wprintf(W, " Time Out \r");
TimeOut=TRUE;
.......
}
}
int MUX_HandShake(int waitticks)
{
Time Start,Akt;
unsigned char result;
//MUX-Zustand: "ACK=1"
outp(LCP[Lpt],SELMUX0); // /SELMUX =0
Start=RTKGetTime();
result=inp(LSP[Lpt])&0x40;
while (result)
{
result=inp(LSP[Lpt])&0x40;
Akt =RTKGetTime(); // Zwischen-Zeit nehmen
.......
}
.......
}
Listing 3
Modul GetADVal.c
Damit sind alle Komponenten des MUX Projektes erläutert. Alle Programmsources, soweit diese nicht lizenzrechtlichen Bestimmungen unterliegen (z.B. RTK-Bibliotheken), werden der ELRAD Redaktion zur Verfügung gestellt.
Literatur- und Quellennachweis
Bild 1 und Bild 2 wurden mit freundlicher Genehmigung der Firma On Time Informatik
dem RTKernel Manual entnommen.
[1] ELRAD 10/93 S.28ff, 8x12 Bit, A/D-Wandler mit 8 Kanälen und 12 Bit Auflösung
[2] Für dieses Projekt entwickelte Software, mit allen Sources verfügbar
[3] MatLab Produzent The MATH WORKS Inc. Web XXXXXXXXX
[4] On Time Informatik, RTKernel 4.5 Real-Time Multitasking Kernel für C/C++ Benutzerhandbuch
oder WEB http://www.on-time.com
[5] ELRAD 1/97 S.82ff, Portwandler, Zweikanal-A/D Interface mit 12-Bit Umsetzer ADS7804 an der
EPP-Schnittstelle
[6] MICROCHIP, 8-Bit CMOS EEPROM Mikrocontroller PIC16C84 Datasheet
[8] Texas Instruments 1997, Firmenschrift Data Transmission Design Seminar
[9] MICROCHIP, Technical Library 1997 includes free MPLAB™ Software
oder WEB http://www.microchip.com
[10] HI-TEC, WEB http://www.htsoft.com
[11] ELRAD 1/94 S.40ff, PICs und fertig, Bassem Yahya
[12] CT 11/92 S.222ff, Windows-Magie, Systemprogrammierung unter Windows am Beispiel Echtzeit
[13] ELRAD 9/96, S.XXXff, Zeitgemäß, Echtzeit-Zusatz für Windows3.x und Windows95
und
Die Wochenzeitung Markt&Technik 29/1996 S25/26 ,Der Trick zu Echtzeit unter Windows,
Ein vergessenes Signal schafft neue Möglichkeiten
[14] Markt&Technik Verlag 1991, Rainer Haselier und Klaus Fahnenstich, Quick C 2.5 Toolbox