Elektronik-Projekt: Analog/Digitale Wanduhr (Version 2)


zurück zu Elektronik, Homepage

Fertige Wanduhr (im Betrieb)

4. Softwarebeschreibung

Die Aufgabe der PIC-Software besteht bei der Wanduhr hauptsächlich aus der DCF- Dekodierung. Diese wiederum besteht aus mehreren Teilaufgaben:

Die zweite wichtige Aufgabe der PIC-Software ist die Anzeige der Uhrzeit. Für die Anzeige dient das gleichnamige Unterprogramm (ANZEIGE). Dieses Unterprogramm wird ebenfalls zyklisch alle 4ms aufgerufen. Dazu wird die gleiche 4-ms-Zeitbasis wie für die DCF-Dekodierung verwendet. Der Grund für diese Zeitbasis ist, dass das Unterprogramm ANZEIGE abwechselnd die Minute und die Sekunde ausgibt. (zur Erinnerung: Die Minute und die Sekunde werden ja auf einem gemeinsamen "Leuchtdioden-Kreis" angezeigt). Man spricht hier also von einer einfachen Multiplexansteuerung. Für den Betrachter entsteht so der Eindruck, dass gleichzeitig die Sekunde und die Minute leuchten. Dazu eignet sich die 4-ms-Zeitbasis, und diese ist ja ohnehin schon vorhanden.
Für die Stundenanzeige stehen 12 eigene Leuchtdioden, welche über den Port A angesteuert werden, zur Verfügung. Daher ist hier keine Multiplexansteuerung notwendig.

nach oben

4.1. Das DCF-Dekodierverfahren

Der PIC-I/O-Eingang, an dem das DCF-Empfangsmodul (mit einer Anpasschaltung) angeschlossen ist (hier bei der Wanduhr der Portpin RA0), wird zyklisch (ca. alle 4 ms) vom Unterprogramm DCFROUTINE abgefragt. Als Zeitbasis für den 4-ms-Takt dient der Timer-0-Interrupt. Der Aufruf des Unterprogramms DCFROUTINE erfolgt hier aber nicht von der ISR (Interrupt-Service-Routine), sondern vom Hauptprogramm. Die ISR setzt nur alle 4 ms ein Flag zur Kennzeichnung, dass das Hauptprogramm das Unterprogramm DCFROUTINE aufrufen soll.

Die Aufgabe des Unterprogramms DCFROUTINE besteht darin, aus dem vom DCF- Empfangsmodul empfangenen Datenstrom die Informationen LOW, HIGH und den Minutenwechsel (also das Ausbleiben der 59. Sekunde) gemäß dem im Abschnitt 2. Grundlegendes zu DCF gewonnen Erkenntnisse zu dekodieren. Für diese Informationen befinden sich im DCF-Statusregister (DCFSTATUS) entsprechende Flags. (Siehe Abschnitt 4.2. Benötigte Register, Konstanten, Portdefinition, Makros und Tabellen.)
Weiters beinhaltet das Register DCFSTATUS noch den Zustand des DCF-Eingangs 4ms vor dem Aufruf des Unterprogramms DCFROUTINE. Mit Hilfe des aktuellen Zustands und des Zustands vor 4 ms kann nun erkannt werden, ob sich der Pegel am DCF-Eingang geändert hat.

Das Hauptprogramm prüft nun ständig die Flags DCFNEUESEK (wird zusätzlich zu DCFLOW bzw. DCFHIGH gesetzt, wenn eine gültige Sekunde empfangen wurde) und DCFNEUEMIN, und ruft die zugehörigen Unterprogramme DCFUPSEKUNDE bzw. DCFUPMINUTE auf. Die Aufgabe des Unterprogramms DCFUPSEKUNDE ist es, die empfangenen Low- und High-Pegel in den Register DCFTELEGRAMM1 bis DCFTELEGRAMM8 zwischenzuspeichern.
Die Aufgabe des Unterprogramms DCFUPMINUTE ist dagegen etwas umfangreicher: Zunächst die Zeit und das Datum aus den in den Registern DCFTELEGRAMM1 bis DCFTELEGRAMM8 zwischengespeicherten Werten entsprechend der Tabelle im Abschnitt 2. Grundlegendes zu DCF die Zeit- und Datumswerte zusammensetzen. Anschließend die soeben gewonnen Zeit- und Datumsinformationen mit den Zeit- und Datumsinformationen der vorhergehenden Minute vergleichen. Die Zeit- und Datumswerte der soeben empfangenen Minute sind nur dann gültig, wenn sich die Minute um maximal 1 von der vorhergehenden Minute unterscheidet, während sich die restlichen Zeit- und Datumsinformationen mit denen der vorhergehenden Minute nicht unterscheiden. Dies ist nur eine einfache Überprüfung, die aber manche richtigen Telegramme als falsch auswertet. (Siehe Abschnit 4.5.4. Unterprogramm DCFUPMINUTE)

Parallel zur Dekodierung des DCF-Eingangs erzeugt das Unterprogramm INNEREUHR eine reine Softwareuhr. Für diesen Zweck ist eine genaue 1-Sekunden-Zeitbasis notwendig. Diese Zeitbasis wird von der schon erwähnten Timer-0-ISR (Interrupt Service Routine) zusätzlich zur 4ms-Zeitbasis erzeugt. Auch für diese Zeitbasis wird in der ISR ein entsprechendes Flag gesetzt, und das Hauptprogramm ruft das Unterprogramm INNEREUHR auf, wenn dieses Flag gesetzt ist. Diese zusätzliche Softwareuhr mag auf dem ersten Blick unnötig erscheinen. Es hat sich aber gezeigt, dass ein DCF-Empfang oft auch über eine längere Zeit nicht möglich ist. In diesem Fall würde die Uhr "stehen". Diese Zeit wird mit einer zusätzlichen Softwareuhr so überbrückt, dass der Betrachter der Uhr davon nichts bemerkt.

nach oben

4.2. Benötigte Register, Konstanten, Portdefinition, Makros und Tabellen

Register:
Für die Wanduhr sind neben einigen internen Register (SFR, Spezielle Funktions- Register) noch eine ganze Menge eigener Register notwendig, wobei der Großteil für die DCF-Dekodierung notwendig sind:

Konstanten:
Die Konstante KONSTISR1SEK gibt die Anzahl der notwendigen ISR-Aufrufe für die 1- Sekunden Zeitbasis an.
Hier wird die ISR alle 4ms aufgerufen, daher ergibt sich für diese Konstanten der Wert 250 (250 x 4ms = 1000ms = 1 Sekunde)

Bei einem LOW dauert die Absenkung des Trägers zwischen 80ms und 120ms, für ein High dauert die Absenkung des Trägers zwischen 160ms und 240ms (siehe auch Abschnitt 2. Grundlegendes zu DCF). Die Konstanten DCFLOWMIN, DCFLOWMAX, DCFHIGHMIN und DCFHIGHMAX dienen zur Ermittlung eines LOW oder eines HIGH.
Das Unterprogramm DCFROUTINE wird alle 4ms aufgerufen, daher ergeben sich für die Konstanten folgende Werte:

Portdefinition:
Im allgemeinen wird bei jeder Anwendung der Eingangspin für die DCF-Dekodierung an einem anderen Portpin verwendet. Damit dies in der Software nur an einer Stelle berücksichtigt werden muss befindet sich in der Software eine Portdefinition für den DCF-Eingang. Diese besteht aus den folgenden 3 Parametern:

Achtung: Wird für DCFINPORT der Port A verwendet, so muss für DCFINTRIS das zum Port A zugehörige TRIS-Register definiert werden. Bei der hier beschriebenen Wanduhr ergeben sich aufgrund der Hardwarebeschaltung folgende Definitionen

DCFINPORT       equ         PORTA
DCFINTRIS       equ         TRISA
DCFIN           equ         0

Makros:

;Umschalten zu Registerbank 0
bank0           MACRO
                bcf         STAT,RP0
                ENDM

;Umschalten zu Registerbank 1
bank1           MACRO
                bsf         STAT,RP0
                ENDM

Tabellen:
Die bei der Wanduhr verwendeten Tabellen dienen zur Anzeige der Uhrzeit:

nach oben

4.3. Hauptprogramm

Aufgaben des Hauptprogramms:
Zuerst wird der Mikrocontroller initialisiert. Diese Tätigkeit wird von einem Unterprogramm (INIT) ausgeführt. Danach wird der Timer0-Interrupt und der globale Interrupt freigegeben. Dafür ist das Register INTCON zuständig. Je nach benötigten Interrupts werden die entsprechenden Freigabebits (im Englischen: Enable) gesetzt. Wird ein Interrupt verwendet so muss zusätzlich zum verwendeten Interrupt auch die globale Interruptfreigabe GIE (General Interrupt Enable) gesetzt werden. Er ist sozusagen der Hauptschalter, der Interrupts ermöglicht. Das INTCON-Register kann einfach mit den Befehlen movlw b‘10100000‘ und movwf INTCON beschrieben werden. Der Timer0-Interrupt ist jetzt eingeschaltet. Er sorgt hier bei der Wanduhr für eine 4-ms-Zeitbasis und für eine1-Sekunden-Zeitbasis.

Nun befindet sich die Software in einer Endlosschleife. Diese Schleife besitzt die Aufgabe ständig die so genannten Botschaftsflags abzufragen. Ist eines dieser Botschaftsflags gesetzt, so muss vom Hauptprogramm eine bestimmte Aufgabe ausgeführt werden. Diese Aufgaben sind in Form von Unterprogrammen vorhanden. Zwei dieser Botschaftsflags werden in der Timer-ISR gesetzt. Und zwar wird alle 4ms ein Flag gesetzt. Das zweite Flag von der ISR wird jede Sekunde gesetzt.

Hier Zusammenfassend die Tätigkeiten in der Endlosschleife, welche durch die Botschaftsflags ausgelöst werden:

nach oben

4.4. ISR (Timer 0)

Eine ISR (Interrupt Service Routine) ist im Prinzip ein Unterprogramm, welches aber im Gegensatz zu normalen Unterprogrammen, "unvorhergesehen" aufgerufen wird. Hier, beim Timer 0-Interrupt jedes Mal, wenn der Timer 0 überläuft, also von 255 auf 0 wechselt. Würde zum Beispiel ein RB-Interrupt verwendet werden, so würde bei jeder Pegeländerung von RB4 bis RB7 ein Interrupt auftreten und die entsprechende ISR wird ausgeführt. Eine ISR sollte daher so kurz wie möglich sein.

Ein weiterer wichtiger Punkt bei einer ISR ist, dass das w-Register (Working- oder Arbeitsregister) und das STATUS-Register in andere Registern zwischengespeichert werden müssen, falls diese in der ISR ihren Registerinhalt verändern. Der Grund dafür ist, dass eine ISR eben unvorhergesehen aufgerufen wird, und die angesprochenen Register unter Umständen zu diesem Zeitpunkten gerade benötigte Werte enthalten. Nach Ausführung der ISR springt diese zwar wieder genau an die Stelle zurück, wo sie war, bevor der Interrupt auftauchte, aber mit einem möglicherweise falschen Wert im w-Register (bzw. STATUS-Register). Das Zwischenspeichern des w-Register bzw. des STATUS-Registers wird häufig auch als PUSH bezeichnet. Das Widerherstellen von w-Register und STATUS-Register nennt man POP.

Woher weiß das Programm, dass ein Interrupt aufgerufen werden muss? Dazu gibt es für jede Interruptquelle ein Kontroll-Flag. Dies wird vom Controller gesetzt wenn dieser Interrupt auftritt. (Vorausgesetzt, dass diese Interruptquelle freigegeben ist). Damit aber die ISR nicht ständig aufgerufen wird, muss dieses Bit in der ISR wieder gelöscht werden.

Nun aber zur wanduhrspezifischen Timer 0-ISR. Diese hat lediglich die Aufgabe eine Zeitbasis für 4ms und eine Zeitbasis für 1 Sekunde zu erzeugen. Eine Zeitbasis für 4ms ist hier besonders einfach zu erzeugen, da ja diese ISR ohnehin schon zu genau diesen Zeitabständen aufgerufen wird. Es ist also nur notwendig ein Flag zu setzen. Dieses Flag trägt hier den Namen FLAG4MSEK und befindet sich im Register FLAGSISRHP. Die Generierung für die 1-Sekunden-Zeitbasis ist dagegen schon etwas "umfangreicher". Damit eine Zeit von einer Sekunde entsteht muss die ISR 250 mal aufgerufen werden (250 x 4ms = 1000ms = 1 Sekunde). Bei jedem ISR-Aufruf muss also ein Zählregister um 1 vermindert werden. Besitzt es danach den Wert 0, so ist eine Sekunde vergangen. Nun wird das Botschaftsflag FLAG1SEK im Register FLAGSISRHP gesetzt, und das Zählregister muss mit dem Wert 250 neu geladen werden. Der Wert 250 wird hier durch die Konstante KONSTISR1SEK ersetzt.

Die ISR wird, wie schon mehrmals erwähnt, alle 4ms aufgerufen Diese 4ms ergeben sich folgendermaßen: TMR0 wird mit dem Wert 0 geladen – es dauert also 256 Taktzyklen bis das Register wieder den Wert 0 besitzt, der Vorteiler besitzt den Wert 16 (vgl. Unterprogramm INIT, Abschnitt. 4.5.1). Der Taktzyklus ergibt sich aus dem verwendeten Quarz (X1). Dieser ist bei der PIC-Familie wie folgt definiert:

Formel

Daraus ergibt sich folgender Zusmmenhang:

Formel

Also ein ISR-Aufruf alle 4000µs, was gleichbedeutend mit 4ms ist.

Eine ISR muss mit dem Befehl retfie beendet werden. Beim Aufruf der ISR wird automatisch das Bit GIE gelöscht, damit während der Ausführung der ISR kein weiterer Inerrupt ausgelöst werden kann, was bei mehreren freigegebenen Interruptquellen durchaus möglich sein kann. Mit dem Befehl retfie wird zunächst an die Stelle im Programm zurückgesprungen, wo sich die Programmabarbeitung befand bevor die ISR aufgerufen wurde, und die verwendeten Interrupts werden wieder freigegeben (hier bei der Wanduhr der Timer0-Interrupt)

nach oben

4.5. Unterprogramme

Die insgesamt sieben Unterprogramme lassen sich folgendermaßen einteilen:

nach oben

4.5.1. Unterprogramm INIT

Dieses Unterprogramm dient zur Initialisierung des Mikrocontrollers. Der Portpin an dem der DCF-Empfänger angeschlossen ist muss als Eingang definiert werden, während die Portpins zur Anzeige der Stunde, Minute und Sekunde als Ausgang definiert werden.
In der Initialisierungsroutine muss für den erste Aufruf des Unterprogramms DCFROUTINE der aktuelle Zustand dieses Portpins gelesen, und im Register DCFSTATUS kopiert werden.

Da das Unterprogramm DCFROUTINE zyklisch (alle 4ms) aufgerufen wird, ist eine entsprechende Zeitbasis notwendig. Diese wird mit Hilfe eines Timer-Interrups erzeugt. Für die Definition der Zeitbasis ist hier das mikrocontrollerinterne Funktions-Register OPTREG (in der Registerbank 1) zuständig. Damit bei einer PIC-Taktfrequenz von 4,096MHz eine Zeitbasis von 4ms erzeugt wird, muss das Register OPTREG mit dem binären Wert b‘00000011‘ geladen werden. Das Zählregister für dies Zeitbasis (Funktions-Register TMR0, in Registerseite 0) muss gelöscht werden.

Weiters müssen einige Register vorbelegt (gelöscht) werden.

nach oben

4.5.2. Unterprogramm DCFROUTINE

Das Unterprogramm DCFROUTINE ist für die DCF-Dekodierung die wichtigste Komponente.

Diese Routine wird ca. alle 4 ms aufgerufen

Aufgabe und Vorgehensweise:
Die Aufgabe des Unterprogramms DCFROUTINE besteht darin aus den Abtastungen herauszufinden, ob ein Low, ein High oder ein Minutenwechsel gesendet wurde. Dazu wird bei jedem Aufruf des Unterprogramms DCFROUTINE entweder das Zählregister DCFPULS oder das Zählregister DCFPAUSE um 1 erhöht (inkrementiert), wenn sich der Pegel vom DCF-Eingang zum vorhergehenden Aufruf dieses Unterprogramms nicht verändert hat. Ist der DCF-Eingang Low (also logisch 0), so wird das Zählregister DCFPULS um 1 erhöht, ist der DCF-Eingang High (also logisch 1), so wird das Zählregister DCFPAUSE um 1 erhöht. Beide Zählregister können maximal den Wert 255 aufnehmen, was einer Zeit von 1020 ms (oder 1,02 Sekunden) entspricht (=255 * 4ms).
Unterscheidet sich der aktuelle Pegel des DCF-Eingangs mit dem Pegel vom vorhergehenden Aufruf, so spricht man von einer Flanke, wobei hier zwischen einer fallenden und einer steigenden Flanke unterschieden werden muss. Bei einer fallenden Flanke (der aktuelle Pegel des DCF-Eingangs ist logisch 0, während der Pegel beim vorhergehenden Aufruf noch logisch 1 war), erfolgt zunächst eine Auswertung des Zählregisters DCFPULS. Beinhaltet dieses Zählregister einen Wert zwischen den Konstanten DCFLOWMIN und DCFLOWMAX, so wurde ein LOW des DCF-Telegramms ermittelt. Im DCF-Statusregister (DCFSTATUS) werden daher die Flags DCFLOW und DCFNEUESEK gesetzt. Das Flag DCFNEUESEK dient als Zeichen einer neu empfangenen und gültigen Sekunde. Anschließend wird das Zählregister DCFPULS gelöscht. Beinhaltet das Zählregister DCFPULS einen Wert zwischen den Konstanten DCFHIGHMIN und DCFHIGHMAX, so wurde ein HIGH des DCF-Telegramms ermittelt. Im DCF-Statusregister (DCFSTATUS) werden daher die Flags DCFHIGH und DCFNEUESEK gesetzt. Das Flag DCFNEUESEK dient auch hier als Zeichen einer neu empfangenen und gültigen Sekunde, und auch das Zählregister DCFPULS wird anschließend gelöscht. Beinhaltet das Zählregister DCFPULS einen Wert der weder zwischen den Konstanten DCFLOWMIN und DCFLOWMAX noch zwischen den Konstanten DCFHIGHMIN und DCFHIGHMAX liegt, so handelt es sich um einen Übertragungsfehler. In diesem Fall wird das Fehlerflag (DCFFEHLER) im DCF-Statusregister (DCFSTATUS) gesetzt und auch das Zählregister DCFPULS wird anschließend gelöscht. Das Flag DCFNEUESEK wird hier aber nicht gesetzt, da es sich in diesem Fall um keine gültige Sekunde handelt. Das Fehlerflag wird erst bei der Erkennung einer neuen Minute wieder gelöscht. Achtung: Solange das Fehlerflag gesetzt ist erfolgt keine Auswertung des Zählregisters DCFPULS. Dieses Zählregister wird aber dennoch bei jeder fallenden Flanke zurückgesetzt.
Bei einer steigenden Flanke (der aktuelle Pegel des DCF-Eingangs ist logisch 1, während der Pegel beim vorhergehenden Aufruf noch logisch 1 war) wird das Zählregister DCFPAUSE gelöscht.
Entsprechend dem im 2. Grundlegendes zu DCF beschriebenen Protokoll erfolgt in der 59. Sekunde keine Absenkung des Trägers. Da es also in der 59. Sekunde keine fallende Flanke gibt, gibt es auch keine steigende Flanke. Das Zählregister DCFPAUSE "läuft über", da es nur einen Zählbereich von 0 bis 255 besitzt. Dieser Überlauf wird hier ausgenützt. Zur Bestimmung einer neuen Minute bzw. zur Bestimmung des Telegrammbeginns. Ist das Fehlerflag gesetzt, so wird es nun gelöscht. War es nicht gesetzt, so wird das Flag DCFNEUEMIN im DCF-Statusregister (DCFSTATUS) gesetzt.

Das im Abschnitt 7. Download downloadbare Flussdiagramm soll das soeben beschriebene und umfangreiche Unterprogramm verdeutlichen. In den grau hinterlegten Bereichen erfolgt das Setzen oder Rücksetzen der zur weiteren Verwendung notwendigen Übergabeflags im DCF-Statusregister (DCFSTATUS). Die Unterprogramme DCFUPSEKUNDE und DCFUPMINUTE greifen auf diese Flags zu.

Anmerkung:
Die temporären Register TEMP1 und TEMP2 werden hier nur als Hilfsregister benötigt. Sie können daher auch in anderen Unterprogrammen verwendet werden.

nach oben

4.5.3. Unterprogramm DCFUPSEKUNDE

Aufgaben:

Vorgehensweise:
Ist das Flag DCFLOW (im Register DCFSTATUS) gesetzt das Carryflag (im SFR STAT) löschen, ist aber das Flag DCFHIGH (ebenfalls im Register DCFSTATUS) gesetzt das Carryflag setzten. Dieses Carryflag nun dem Telegramm hinzufügen. Dieser Vorgang erfolgt mit einem so genannten Schiebebefehl. Dabei werden alle Bits des Registers DCFTELEGRAMM1 auf die nächst höhere Position verschoben. (Bit 6 wandert ins Bit 7, Bit 5 wandert ins Bit 6 usw. Bit 0 wandert ins Bit 1). Der Inhalt vom Carryflag wandert ins Bit 0. Der Inhalt von Bit 7 wird ins Carryflag geschoben. Bei den Registern DCFTELEGRAMM2 bis DCFTELEGRAMM6 erfolgt der selbe Vorgang. (Der Inhalt von Bit 7 des Registers DCFTELEGRAMM1 wird ins Carry geschoben, und das Carry aber weiter in das Bit 0 des Registers DCFTELEGRAMM2)

Anmerkung:
Die Flags DCFLOW und DCFHIGH können nie gleichzeitig gesetzt sein. Es ist nur möglich, dass entweder nur DCFLOW oder nur DCFHIGH gesetzt ist, aber nie beide gleichzeitig.

nach oben

4.5.4. Unterprogramm DCFUPMINUTE

Aufgaben:

Anmerkung:
Das temporäre Register TEMP1 wird hier nur als Hilfsregister benötigt, und kann daher auch in anderen Unterprogrammen verwendet werden.

nach oben

4.5.5. Unterprogramm INNEREUHR

Aufgaben:
Für den Fall dass kein gültiges DCF-Telegramm empfangen werden kann sorgt dieses Unterprogramm dafür, dass die Uhrzeit trotzdem jede Sekunde aktualisiert wird. Ist für eine längere Zeit kein korrekter DCF-Empfang möglich, so würden die Minuten, Stunden, Tage usw. stehen bleiben, da ja im Unterprogramm DCFUPMINUTE nur gültige DCF-Telegramme übernommen werden. Dieses Unterprogramm wird also parallel zu den Unterprogrammen für die DCF- Dekodierung aufgerufen.

Vorgehensweise:
Die Sekunden (Register UHRSEKUNDE) um 1 erhöhen. Beinhalte dieses Register nun den Wert 60, so beginnt eine neue Minute. Daher die Sekunden löschen und die Minuten (Register UHRMINUTE) um 1 erhöhen. Beinhaltet dieses Register nun den Wert 60, so beginnt eine neue Stunde. Daher die Minuten löschen und die Stunden (Register UHRSTUNDE) um 1 erhöhen. Beinhaltet dieses Register nun den Wert 24, so beginnt ein neuer Tag. Daher die Stunden löschen. Ist das Mitzählen des Datums notwendig, so muss nun ein Register für den Tag (z.B. DATUMTAG) um 1 erhöht werden und dieses Überprüft werden, wobei diese Prüfung nun nicht mehr so einfach ist, da ja jeder Monat unterschiedlich viele Tage besitzt. Erschwerend kommt auch noch hinzu, dass auch die Schaltjahre miteinbezogen werden müssen!

Achtung:
Dieses Unterprogramm muss daher jede Sekunde aufgerufen werden.

nach oben

4.5.6. Unterprogramm ANZEIGE

Dieses Unterprogramm wird vom Hauptprogramm alle 4ms aufgerufen.

Aufgabe:
Wenn die mitlaufende Uhr mit der DCF-Uhr synchronisiert ist (Flag DCFSYNC im Register DCFSTATUS gesetzt) die Uhrzeit wie folgt ausgeben. Andenfalls dieses Unterprogramm vorzeitig beenden: Die Stunde am Port A und abwechselnd Minute und Sekunde am Port B ausgeben. Abwechselnd bedeutet hier, dass beim Aufruf dieses Unterprogramms entweder die Minuten am Port B ausgegeben werden oder die Sekunden. Diese Methode entspricht einer einfachen Multiplex-Ansteuerung. Die Unterscheidung, ob die Minuten oder die Sekunden ausgegeben werden hängt vom Bit 0 des Registers FLAGS ab. Dieses Bit wird bei jedem Aufruf invertiert (getoggelt). Besitzt es danach den Wert 1, so werden die Minuten angezeigt. Beim nächsten Aufruf dieses Unterprogramms (in ca. 4ms) werden dann die Sekunden angezeigt, da dieses Bit ja wieder invertiert wurde und daher den Wert 0 besitzt. Mit Hilfe der beiden Tabellen TABSTUNDEN und TABMINUTENSEKUNDEN erfolgt eine Anpassung an die Hardware (Umwandlung von 24 Stunden auf 12 Stunden, LED- Matrix am Port B).

nach oben

4.5.7. Unterprogramm BCDBIN2

Aufgabe:
Die im w-Register stehende 2-stellige-BCD-Zahl nach Binär umwandeln. Das Ergebnis befindet sich wieder im w-Register.

Vorgehensweise:

Anmerkung:
Das temporäre Register TEMP1 wird hier nur zum Zwischenspeichern benötigt, und kann daher auch in anderen Unterprogrammen verwendet werden.

nach oben


zurück zu Elektronik, Homepage

Autor: Buchgeher Stefan
Erstellt: 17. Februar 2004
Letzte Änderung: 10. Oktober 2004