Für das Projekt sollte ein myAVR™-Board mit mySmartUSB™-Aufsatz von myAVR verwendet werden, da es bereits vorhanden war. Weiterhin kam ein Punktmatrix-LCD mit 8 Zeilen je 24 Zeichen (Controller M50530) zum Einsatz, unter dem 4 Taster zur Bedienung vorgesehen wurden. Mit dem finalen Gerät habe ich (wie üblich) wieder mal nichts zu tun, deshalb gibt es bei mir wieder mal nur den Testaufbau. Da mein Laptop den USB-Treiber für mySmartUSB™ nicht mag (liegt vermutlich daran, dass der Lappi nur USB1.1 hat), musste ich auf den USB-Aufsatz verzichten, worauf ich mir eine kleine Adapterplatine (Lochraster) gebaut habe, die mir Anschlüsse für ISP und RX/TX zur Verfügung stellt. Somit konnte ich meinen Eigenbau-ISP-Programmer und ein aktives RS232-Adapter (mit MAX232) zum Programmieren bzw. zur Kommunikation mit dem PC einsetzen. Beim Sportverein funktioniert es aber über USB.
Nebenstehendes Bild zeigt den Versuchsaufbau. Oben rechts ist ein Blei-Gel-Akku 12V/1,2Ah zur Stromversorgung. Oben Mitte ist das myAVR™-Board mit aufgestecktem Adapter für ISP und RX/TX. Links daneben ist der RS232-Adapter zu sehen. Diese kleine Platine enthält neben der SUB-D-9-Buchse einen IC MAX232 und die erforderlichen Kondensatoren und ist durch Akku-Schrumpfschlauch geschützt.
In der Erweiterungsbuchsenleiste steckt ein (geflextes) Adapter, an welches das LCD und die 4 Bedientaster angeschlossen sind. Am linken Ende sieht man ein Trimmpoti (10k), das zum Einstellen der Kontrastspannung des LCDs dient. Diese soll etwa 8..12V betragen, weshalb mit einer "fliegenden Leitung" die 12V vom Plus-Anschluss des Brückengleichrichters (zusätzlich angelöteter Pfostensteckerstift) angezapft wurde. Zwischen myAVR™-Board und LCD ist ein Lochraster-Streifen mit 5 Tastern zu sehen. Diese dienen zur Simulation der 4 Lichtschranken (potentialfreie Relaiskontakte) und des Kontaktes in der Startpistole. Sie sind nur mittels Schaltdraht an den Buchsenleisten des Boards angeschlossen. Im finalen Gerät soll da noch eine Schutzbeschaltung die Eingänge vor gefährlichen Störspannungen schützen. Die Holzklötzchen unter dem Platinenstreifen sollen einen stabilen Stand gewährleisten und Kurzschluss mit dem LCD/Tasten-Adapter verhindern. Wie bereits gesagt, das ist der Testaufbau, mit dem finalen Gerät habe ich nichts zu tun. |
Der Mega8 wird mit einem baudratentauglichen Quarz mit 3,6864MHz betrieben. Dies sichert eine stabile UART-Kommunikation für die Übertragung der Daten zum PC. UART und LCD nutzen gemeinsame Print-Routinen und auch einen gemeinsamen Ausgabe-Treiber. Der Ausgabetreiber arbeitet im Timer-Interrupt mit 800Hz und sendet Zeichen aus einem Ringbuffer von 256 Bytes Größe an LCD oder UART. Wegen der Platzierung der Zeichenausgabe im Interrupt wurde diese Zeichenausgabe auch ins Hauptprogramm übernommen und nicht, wie eigentlich üblich, in der Include-Datei belassen. Einige vereinbarte Steuerzeichen bestimmen, wohin die darauf folgenden Zeichen gesendet werden. So schaltet jeder Locate-Befehl (Kennung '0' gefolgt von Position im DD-RAM des LCDs) die Ausgabe auf LCD, das Steuerzeichen '1' schaltet die Ausgabe auf UART. Zur Steuerung der Ausgabe dient das Flag 'v24aktiv' im Register 'flags'. Diese kombinierte Zeichenausgabe bietet die Möglichkeit, die Routinen für die formatierte Ausgabe gemeinsam für LCD und UART zu nutzen. Die restlichen LCD-Routinen sind in einer eigenen Include-Datei zusammengefasst und werden teils von den Routinen der formatierten Ausgabe, teils vom Hauptprogramm aufgerufen.
Gliederung des Programms:
Wie fast jedes ASM-Programm beginnt es nach den Vereinbarungen von Konstanten (auch Include-Datei für Portdefinitionen 'm8def.inc'), SRAM-Variablen und Register-Variablen mit der Interrupt-Sprunhtabelle. Es wird nur der Reset-Vektor und der Timer1-CompareA-Interrupt verwendet. Danach werden die Include-Dateien für LCD und formatierte Ausgabe eingebunden. Dann folgt die Reset-Routine, in der alle Variablen und benutzte Hardware-Komponenten initialisiert werden. Da beim Programmstart das Menü aufgerufen werden muss, um das Display mit Dialog-Text zu füllen, wurden die Menü-Routinen noch vor der Hauptschleife angeordnet. Auch die Routine 'tastaus' zum Löschen der Tastenflags und zur Ausgabe der Menü-Dialogtexte wurde noch vor der Mainloop platziert und wird von den Menüpunkt-Routinen statt der Mainloop angesprungen, wodurch sich der Programmcode der Menüpunkte vereinfacht.
In der Mainloop werden dann die Tastenflags und Lichtschrankenflags abgefragt und in deren Abhängigkeit zum Menü bzw. Stoppuhr verzweigt. Dann wird noch bei aktivem Stopuhrbetrieb die laufende Zeit an das LCD ausgegeben. Dann folgt die Menü-Sprungtabelle (indizierter Routinenaufruf) und die Routinen für die einzelnen Menüpunkte.
Die ISR des Timers setzt erstmal den Zeitpunkt ihres nächsten Interrupts (in 1,25ms). Dann wird das nächste Zeichen aus dem Ringbuffer an LCD oder UART ausgegeben, falls der Buffer noch Zeichen enthält. Dabei werden auch Steuerzeichen (LCD-Ausgabe-Position, Umschaltung auf UART) erkannt und ausgeführt. Nun sorgt ein Vorteiler alle 10ms oder 50ms (je nach eingestellter Auflösung gemäß Flag 'fine' in 'flags') dafür, dass bei aktiver Stopuhr die Zeit hochgezählt wird. Dann werden alle 10ms (nur bei 'scharfer' Anlage) die Lichtschrankeneingänge (incl. Startpistolenkontakt) entprellt. Anschließend ist (auch alle 10ms) die Entprellung der Taster an der Reihe. Beide Entprellroutinen entsprechen dem Algorithmus nach Peter Dannegger ('PeDa') und sind etwas modifiziert. Die Entprellvariablen werden im SRAM gehalten und die Lichtschrankenentprellung wurde um eine 'Wiederholsperre' erweitert. Bei laufender Stopuhr wird von der ISR noch in zyklischen Abständen das Flag 'gibaus' in 'flags' gesetzt, welches die LCD-Ausgabe der laufenden Zeit synchronisiert.
Der Programmcode endet mit den Textbausteinen für Menü und UART.
Im Normalfall wird mit einer Auflösung von 10ms gearbeitet. Das misst zwar auf die Hundertstelsekunde, reicht aber nur bis 10 Minuten und 52 Sekunden. Um auch längere Zeiten messen zu können, wurde eine zweite Auflösung von 50ms eingeführt. Diese ist zwar etwas ungenauer, reicht aber bis 54 Minuten und 24 Sekunden. Dies erforderte auch zwei getrennte Anzeigeroutinen für die Zeit, die vom Flag 'fine' im Register 'flags' ausgewählt werden.
Im SRAM wurde der Bereich $060..$0ff für normale Variablen genutzt. Der Bereich $100..$1ff dient als Ringbuffer für das LCD, der Bereich $200..$2ff dient als Indextabelle für die Rangliste. Der Bereich ab $300 aufwärts ist noch unbenutzt, am oberen Ende liegt aber der nach unten wachsende Stack.