Die Aufgabe der Software für den PIC-Mikrocontroller besteht beim elektronischen Adventkalender hauptsächlich in der Erzeugung sehr vieler Flackerlichter (40 mal für jede Leuchtdiode, die den Baum bilden, 12 mal für jede Leuchtdiode, die den Stern symbolisieren und 24 für die Flammen der Kerzen. Diese Kerzen sind der eigentliche Adventkalender, da mit jedem Tag eine Kerze mehr leuchtet. Macht in Summe 76 Flackerlichter. Anmerkung: Die roten Leuchtdioden, die das Wachs der Kerze symbolisieren flackern natürlich nicht. Diese leuchten dauerhaft, wenn diese Kerze aktiv ist.). Diese 76 Flackerlichter und die 24 Leuchtdioden für das Wachs jeder Kerze sind in den Variablen (Register) Flackerlichter0 bis Flackerlichter12 abgelegt (Abbildung 3.1).
Die zweite wichtige Aufgabe der Software ist die Ausgabe der Variablen Flackerlichter0 bis Flackerlichter12 durch die Schieberegister IC2 bis IC14 (vgl. Abschnitt Abschnitt 2 (Schaltungsbeschreibung) .
|
Wichtig:
Die Zuordnung der Bits in den Variablen Flackerlichter0 bis Flackerlichter12 für die Leuchtdioden muss der Beschaltung der Schieberegister gemäß der Schaltung in Abbildung 2.2 entsprechen. Daher ist in Abbildung 3.1 zu jeder Variablen auch das zugehörige Schieberegister angegeben, und zur besseren Übersicht sind die Bits, die den Leuchtdioden entsprechen in deren Farben dargestellt (gelb: Flamme bzw. Stern, rot: Wachs und grün: Baum). |
Die dritte wichtige Aufgabe der Software ist das Erkennen ob die Taste (S1) gedrückt wurde. Diese Aufgabe muss regelmäßig durchgeführt werden und erfolgt mit dem Unterprogramm TastenRoutine (siehe Abschnitt 3.4.2. Unterprogramm zur Tastenabfrage). Zur Erinnerung: Der Taster S1 aktiviert den Adventkalender, in dem die erste Kerze aktiviert wird. Zusätzlich flackern auch die grünen Leuchtdioden, die den Baum symbolisieren. Mit jedem weiteren Tastendruck leuchtet zusätzlich eine weitere Kerze. Siehe Abschnitt 2 (Schaltungsbeschreibung).
Manche Unterprogramme müssen zyklisch (also regelmäßig) aufgerufen werden. Dazu sind mehrere Zeitbasen notwendig. Diese werden mit Hilfe des Timer-Interrupts erzeugt. Siehe Abschnitt 3.2. Hauptprogramm und Abschnitt 3.3. Interrupt-Service-Routine (ISR, Timer 0).
Die in der Schaltung vorgesehenen Jumper (JP1 bis JP3) sind für zukünftige Optionen und Erweiterungen vorgesehen. In dieser Version werden diese nicht benötigt.
Zur besseren Übersicht ist der Quellcode in mehrere Dateien aufgeteilt:
Als Programmiersprache wurde hier C, und als Compiler die freie Demoversion des CC5X-Compilers von B. Knudsen DatamikroC von [B Knudsen Data 2007] verwendet.
|
Achtung:
Bei diesem Projekt wurde die freie (kostenlose) Demoversion des CC5X-Kompilers verwendet, da dieser einen sehr kompakten Assemblercode erzeugt. Der größte Nachteil an dieser Demoversion ist aber, dass der Compiler nur 1k große Programme kompilieren kann. Wenn man den gesamten Quellcode allerdings in mehrere C-Dateien aufteilt, kann man diese Einschränkung umgehen. Abschnitt 6 (Umgehen der 1k-Grenze des CC5X-Compilers) zeigt wie man dabei vorgeht. Ein weiterer Nachteil an der Demoversion ist die Anzahl der Übergabeparameter an ein Unterprogramm. Aus diesem Grund sind bei diesem Projekt sehr viele externe Variablen notwendig. Meine Erkenntnisse zur freien Demoversion des CC5X-Compiler habe ich auf einer anderen Seite auf meiner Webseite [Buchgeher 2006] zusammengefasst. |
Externe Register:
Die Variablen Flackerlichter0 bis Flackerlichter12
(Zeilen 26 bis 38) müssen als externe Register deklariert werden.
Weiters ein Register Namens TagesZaehler (Zeile 40). Dieses Register
beinhaltet den aktuellen Tag.
Der Grund warum diese Variablen als externe Register deklariert werden müssen ist, weil diese Register von mehreren C-Dateien verwendet werden. Hier auch von den Dateien FLACKERLICHT_BAUM.C, FLACKERLICHT_KERZEN.C und FLACKERLICHT_STERN.C.
|
Wichtig:
Diese externen Variablen müssen in der Datei PROJEKT.H mit dem Schlüsselwort extern deklariert werden. |
Globale Register:
Für die Erzeugung der Zeitbasen (hier für 409.6µs, 10ms und 1 Tag) sind die folgenden globalen Register
notwendig:
Für die Tastenabfrage und für das automatische Weiterzählen sind die folgenden globalen Register notwendig:
Weitere globale Register werden auch für die Erzeugung der Flackerlichter benötigt (siehe 3.4.4. Konstanten, globale Variablen, Tabellen und Unterprogramme zur Erzeugung der Flackerlichter).
Portdefinitionen:
Im Allgemeinen werden bei jeder Anwendung die Ein- und Ausgangspins der diversen Hardwarekomponenten (hier
Jumper, Taster und die Schieberegister) 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.
Portdefinition für die Schieberegister:
Für die Kommunikation mit den Schieberegistern sind drei Portleitungen des Mikrocontrollers notwendig. Diese
müssen gemäß der Schaltung nach Abbildung 2.1 definiert werden (Zeilen 291 bis 293 in der Datei PROJEKT.H).
Portdefinition für die Jumper:
Die Jumper (JP1 bis JP3) werden zwar hier noch nicht verwendet, eine Portdefinition ist aber schon in der
Datei PROJEKT.H vorgesehen (Zeilen 296 bis 298).
Portdefinition für den Taster:
Für den Taster ist keine Portdefinitionen notwendig, siehe
Unterprogramm TastenRoutine (Abeschnitt 3.4.2.)
Konstanten:
Beim elektronischen Adventkalender werden einige Konstanten zur Erzeugung der Zeitbasen und zur Erzeugung der Flackerlichter benötigt.
Konstanten für die Zeitbasen:
Für die Kommunikation mit den Schieberegistern sind drei Portleitungen des Mikrocontrollers notwendig. Diese
müssen gemäß der Schaltung nach Abbildung 2.1 definiert werden (Zeilen 291 bis 293 in der Datei PROJEKT.H).
Die Konstante KONSTZEITBASIS1SEK beinhaltet den Wert 102, da die 1-Sekunden-Zeitbasis mit Hilfe der 10-ms-Zeitbasis (genauer: 9.83 ms) erzeugt wird. Analoges gilt für die Konstanten KONSTZEITBASIS1MIN, KONSTZEITBASIS1STD und KONSTZEITBASIS1TAG: Die Zeitbasis für eine Minute wird mit Hilfe der 1-Sekunden-Zeitbasis erzeugt, daher beinhaltet die Konstante KONSTZEITBASIS1MIN den Wert 60. Die Zeitbasis für eine Stunde wird mit Hilfe der 1-Minuten-Zeitbasis erzeugt, daher beinhaltet die Konstante KONSTZEITBASIS1STD den Wert 60, und die Zeitbasis für einen Tag wird mit Hilfe der 1-Stunden-Zeitbasis erzeugt, daher beinhaltet die Konstante KONSTZEITBASIS1TAG den Wert 24. Siehe auch Abschnitt 3.3. (Interrupt-Service-Routine, ISR, Timer 0)
Konstanten für die Flackerlichter:
Die Konstanten, die für die Erzeugung der Flackerlichter benötigt werden, werden im Abschnitt 3.4.4. (Konstanten, globale Variablen, Tabellen und Unterprogramme zur Erzeugung der Flackerlichter)
behandelt.
Zuerst müssen der Mikrocontroller und die (globalen) Register für die Erzeugung der Flackerlichter initialisiert werden. Diese Aufgaben werden von den Unterprogrammen Init (Zeile 576), Init_Flackerlicht_Baum (Flackerlichter für den Baum, Zeile 577), Init_Flackerlicht_Kerzen (Flackerlichter für die Kerzen, Zeile 578) ausgeführt. Die Flackerlichter für den Stern werden mit dem Unterprogramm Init_Flackerlicht_Stern (Zeile 579) initialisiert.
Nun befindet sich das Hauptprogramm 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.
Hier die Tätigkeiten in der Endlosschleife, welche durch die Botschaftsflags ausgelöst werden:
|
Achtung:
Die Botschaftsflags müssen nach der Ausführung der Aufgaben wieder gelöscht werden, da diese Aufgaben sonst ununterbrochen wiederholt werden! |
Listing 3.5 zeigt das Hauptprogramm (Auszug aus Adventkalender.c).
Eine Interrupt-Service-Routine (kurz: ISR) 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 so kurz wie möglich sein.
Ein wichtiger Punkt bei einer ISR ist, dass das w-Register (Working- oder Arbeitsregister) und das STATUS-Register in andere Register
zwischengespeichert werden müssen, falls diese Register in der ISR ihre Registerinhalte verändern. Der Grund dafür ist, dass eine ISR eben
unvorhergesehen aufgerufen wird, und die angesprochenen Register unter Umständen zu diesen 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 Wiederherstellen von w-Register und STATUS-Register nennt man POP.
Beim CC5X-Compiler erfolgt das Zwischenspeichern der genannten Register mit der Anweisung int_save_registers
(Zeile 159) und das zurückschreiben mit der Anweisung int_restore_registers (Zeile 199).
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 wurde). Damit aber die ISR nicht ständig aufgerufen wird, muss dieses Bit in der ISR wieder gelöscht werden.
Ein wichtiger Punkt beim CC5X-Compiler ist, dass dem Compiler mitgeteilt werden muss, dass die Interrupt-Routine im Arbeitsspeicher des Mikrocontrollers ab Adresse 0004h beginnen muss. Dies erfolgt mit einer so genannten pragma-Anweisung (Zeile 155).
Nun aber zur projektspezifischen Timer 0-ISR. Diese hat lediglich die Aufgabe eine Zeitbasis für 409.6µs und eine zweite für ca. 10ms zu erzeugen. Damit eine Zeit von 10ms entsteht muss die ISR 24-mal aufgerufen werden (24 x 409.6µs = 9.83ms). Bei jedem ISR-Aufruf muss daher ein Zählregister (hier: ZaehlerZeitbasis10ms) um 1 vermindert werden. Besitzt es danach den Wert 0, so ist eine Zeit von ca. 10ms vergangen. Nun wird das Botschaftsflag FlagZeitbasis10ms im Register FlagISRHP gesetzt, und das Zählregister muss mit dem Wert 24 neu geladen werden. Der Wert 24 wird hier durch die Konstante KONSTZEITBASIS10MS ersetzt. Das selbe Prinzip wird auch für die Erzeugung der 24-Stunden-Zeitbasis verwendet, wobei mit Zwischenschritten auch Zeitbasen für eine Sekunde, eine Minute und eine Stunde erzeugt werden, die aber bei diesem Projekt nicht benötigt werden.
Anmerkung:
Die 409.6µs-Zeitbasis wird für die Erzeugung der Flackerlichter benötigt, die 10-ms-Zeitbasis für das
regelmäßige Abfragen des Tasters und die 1-Tages-Zeitbasis für das automatische Weiterzählen der Tage.
Die Zeit von 409.6µs ergibt sich, weil als Taktquelle ein 20-MHz-Quarz (X1) verwendet wird, und weil der Vorteiler (VT) mit dem Wert 1:8 (TMR0 Rate, Zeile 231 im Unterprogramm Init) geladen wird. Für diese Zeit gilt:
Listing 3.6 zeigt die kurze Interrupt-Service-Routine (Auszug aus Adventkalender.c).
Die insgesamt 11 Unterprogramme lassen sich wie folgt einteilen:
Das Unterprogramm Init dient zur Initialisierung des Mikrocontroller und muss daher am Beginn des Hauptprogramms aufgerufen werden.
Da die Interrupt-Service-Routine (ISR) zyklisch (alle 409.6µs) aufgerufen wird, ist eine entsprechende Zeitbasis notwendig. Diese wird mit Hilfe eines Timer-Interrupts erzeugt. Für die Definition der Zeitbasis ist hier das mikrocontrollerinterne Funktions-Register OPTION zuständig. Damit bei einer PIC-Taktfrequenz von 20MHz eine Zeitbasis von 409.6µs erzeugt wird, muss das Register OPTION mit dem binären Wert bxxxx0010 geladen werden (Zeile 231). Das Zählregister für diese Zeitbasis (Funktions-Register TMR0) muss gelöscht werden (Zeile 229).
Die beiden Ports (beim PIC16F87 die Ports A und B) müssen gemäß der Beschaltung nach Abbildung 2.1 entweder als Eingang oder als Ausgang definiert werden (Zeilen 260 und 271).
|
Achtung:
Der PIC16F87 verfügt über analoge Komparatoren. Diese werden bei diesem Projekt nicht verwendet und müssen daher deaktiviert werden (Zeilen 283 und 284). |
Alle Leuchtdioden deaktivieren. Daher die externen Register zur Erzeugung der Flackerlichter löschen, und mit dem Unterprogramm SR_74xx595_SendData ausgeben (Zeilen 288 bis 301).
Die globalen Zählregister für die Zeitbasen müssen initialisiert werden (Zeilen 305 bis 313).
Zum Schluss werden der Timer0-Interrupt und der globale Interrupt freigegeben (Zeile 231) [1]. Für das Freigeben der Interrupts ist hier das Register INTCON zuständig. Je nach benötigten Interrupts müssen die Freigabebits (im Englischen: Enable) gesetzt werden. (Hier das Freigabebit T0IE (Bit 5) für den Timer 0.) Zusätzlich muss auch die globale Interruptfreigabe GIE (General Interrupt Enable, Bit 7) gesetzt werden. Er ist sozusagen der Hauptschalter, der Interrupts ermöglicht. Der Timer-0-Interrupt ist nun eingeschaltet und sorgt hier für eine 409.6-µs-Zeitbasis.
Listing 3.7 zeigt das Unterprogramm zur Initialisierung des PIC16F87 (Auszug aus der Datei Adventkalender.c).
Das Unterprogramm TastenRoutine hat die Aufgabe regelmäßig zu prüfen, ob die Taste S1 gedrückt wurde (Zeilen 403 bis 407). Wurde die Taste gedrückt (Zeile 409) das Zählregister TagesZaehler erhöhen (Zeile 411) und die Zählregister für die Erzeugung der 1-Stunden-Zeitbasen neu initialisieren (Zeilen 417 bis 422). Weiters die automatische Tageszählung freigeben (TagesZaehlerEnable, Zeile 424). Dieses Unterprogramm wird daher zyklisch (ca. alle 10ms) vom Hauptprogramm aufgerufen.
Vorgehensweise:
Anmerkungen:
Listing 3.8 zeigt das Unterprogramm zur Tastenabfrage (Auszug aus Adventalender.c).
Das Unterprogramm Naechster_Tag hat die Aufgabe die automatische Tageszählung zu erhöhen, falls das Register TagesZaehlerEnable gesetzt ist, und der Tageszähler noch kleiner als 24 ist. Dieses Unterprogramm wird zyklisch (ca. alle 24 Stunden) vom Hauptprogramm aufgerufen.
Anmerkungen:
Besitzt das Zählregister TagesZaehler den Wert 24, so wird dieser Zähler
nicht mehr erhöht. D.h. Der Baum, alle Kerzen und der Stern "blinken" weiter. Das "Löschen"
ist nur mit dem Taster oder mit dem Ein/Ausschalter möglich!
Listing 3.9 zeigt dieses Unterprogramm (Auszug aus Adventalender.c).
Das Prinzip zur Erzeugung von Flackerlicht ist im Abschnitt 1 (Grundlegendes zur Erzeugung von Flackerlicht) sehr ausführlich erklärt. Hier erfolgen nun die Besonderheiten bei diesem Projekt.
Ein wichtiger Punkt bei der Erzeugung mehrerer Flackerlichter ist, dass der Eindruck entsteht, dass die Leuchtdioden unabhängig voneinander flackern. Bei diesem Projekt werden die Flackerlichter mit einer Tabelle erzeugt. Damit der Eindruck entsteht, dass die Leuchtdioden uabhängig voneinander flackern, besitzt jede Leuchtdioden eigene Variablen, und die Zählvariablen, die die Positionen in der Tabelle angeben, startet an einer anderen Position in der Tabelle. Dadurch erscheint der Eindruck, dass die Leuchtdioden unabhängig voneinander flackern. In Wirklichkeit ist der Flackerzyklus für jede Leuchtdiode gleich, sie sind nur zeitlich verschoben.
Anmerkung zum Quellcode:
Wenn man den Quellcode genau betrachtet, dann fällt auf, dass hier auf Schleifen verzichtet wurde. Mit
Schleifen wäre der Quellcode deutlich kürzer und würde viel weniger Programmspeicher benötigen. Warum wurden
hier keine Schleifen verwendet? Gegen die Verwendung von Schleifen spricht, dass diese sehr viel Overhead
produzieren, und bei sovielen Flackerlichtern wie hier (insgesamt 76, wenn alle 24 Kerzen, der Baum und der
Stern flackern) die Ausführungsgeschwindigkeit zu gering ist, sodass kein "flackern" mehr entsteht,
nur mehr ein sehr langsames "hell-und-dunkler-werden" der Leuchtdioden.
Um die 1k-Grenze der freien Version des CC5X-Compilers nicht zu sprengen, wurde die Erzeugung der gesamten
Flackerlichter in drei C-Quelldateien aufgeteilt (in Baum, Kerzen und Stern).
Konstanten:
Gemäß Abschnitt 1 (Grundlegendes zur Erzeugung von Flackerlicht)
sind für die Erzeugung der Flackerlichter die beiden Konstanten KONST_PWM_OBERGRENZE
(Zeile 156, beinhaltet den Wert 32) und KONST_GLEICHHEIT (Zeile 157, beinhaltet
den Wert 5) notwendig.
Die Konstanten KONST_TABSTART_TAGxx (Zeilen 160 bis 235) geben für jede Leuchtdiode den Startwert in der Tabelle TabFlackerlicht an. So entsteht, wie schon vorher erwähnt, der Eindruck dass alle Leuchtdioden unabhängig voneinander flackern.
Bei einem "normalen" Adventkalender ist es üblich, dass die Türchen des Adventkalenders
"durcheinander" angeordnet sind. So auch bei dieser elektronischen Variante. Die Türchen sind hier
die Kerzen. Ab welchen Tag welche Kerze aktiv sein soll bestimmen die Konstanten KONST_TAGA
bis KONST_TAGZ (Zeilen 238 bis 263), wobei KONST_TAGA
dem Baum entspricht, KONST_TAGB bis KONST_TAGY
den Kerzen und KONST_TAGZ dem Stern. Hier mein Vorschlag: am ersten Tag leuchtet
zustätzlich zur ersten Kerze (Tag L) auch der Baum (Tag A), und am 24ten Tag zusätzlich zur letzten Kerze (Tag D) auch der
Stern (Tag Z). Mit Hilfe der Konstanten KONST_TAGA bis KONST_TAGZ
kann diese Zuordnung eigenen Bedürfnissen angepasst werden.
Die Abbildung 3.2 zeigt die Zuordnung der Kerzen und an welchem Tag welche Leuchtdioden aktiv werden.
Alle Konstanten sind in der Header-Datei PROJEKT.H definiert (Listing 3.10):
Globale Variablen:
Damit die vielen Leuchtdioden unabhängig voneinander flackern sind für jede Leuchtdiode zwei globale
Variablen notwendig (TabZaehlerTagXX und PWM_LED_TagXX).
Tabelle:
Wie im Abschnitt 1 (Grundlegendes zur Erzeugung von Flackerlicht)
beschrieben erfolgt beim elektronischen Adventkalender die Erzeugung der Flackerlichter mit Hilfe einer Tabelle.
Diese Tabelle soll hier wegen der Vollständigkeit nochmal erwähnt werden. Listing 3.11 zeigt (nochmal) die Tabelle
TabFlackerlicht.
Unterprogramme:
Für die Erzeugung der vielen Flackerlichter sind sechs Unterprogramme notwendig.
Unterprogramm Init_Flackerlicht_Baum:
Dieses Unterprogramm hat nur die Aufgabe die Zählregister für die Leuchtdioden die den Baum symbolisieren
mit den Anfangspositionen zu initialisieren und zwei Register für die Puls-Weiten-Modulation (für den Baum).
Listing 3.12 zeigt dieses Unterprogramm.
Anmerkung:
Dieses Unterprogramm wird im Hauptprogramm nach dem Initialisieren des Mikrocontrollers aufgerufen (Siehe
Hauptprogramm, Listing 3.5, Zeile 577).
Unterprogramm Flackerlicht_Baum:
Dieses Unterprogramm erzeugt das Flackern (Puls-Weiten-Modulation, PWM) für die Leuchtdioden, die den Baum
symbolisieren.
Es entspricht vom Prinzip her dem Listing aus Abschnitt 1 (Grundlegendes zur Erzeugung von Flackerlicht).
Die wesentlichen Unterschiede gegenüber Abschnitt 1 sind:
|
Wichtig:
Dieses Unterprogramm muss im Hauptprogramm regelmäßig (zyklisch) aufgerufen werden (Siehe Hauptprogramm, Listing 3.5, Zeile 585). |
Listing 3.13 zeigt die Realisierung von diesem etwas längerem Unterprogramm.
Unterprogramm Init_Flackerlicht_Kerzen:
Dieses Unterprogramm hat nur die Aufgabe die Zählregister für die Leuchtdioden die die Kerzen symbolisieren
mit den Anfangspositionen zu initialisieren und zwei Register für die Puls-Weiten-Modulation (für die Kerzen).
Listing 3.14 zeigt dieses Unterprogramm.
Anmerkung:
Dieses Unterprogramm wird im Hauptprogramm nach dem Initialisieren des Mikrocontrollers aufgerufen (Siehe
Hauptprogramm, Listing 3.5, Zeile 578).
Unterprogramm Flackerlicht_Kerzen:
Dieses Unterprogramm erzeugt das Flackern (Puls-Weiten-Modulation, PWM) für die Leuchtdioden, die die Kerzen
symbolisieren.
Es entspricht vom Prinzip her dem Listing aus Abschnitt 1 (Grundlegendes zur Erzeugung von Flackerlicht).
Die wesentlichen Unterschiede gegenüber Abschnitt 1 sind:
|
Wichtig:
Dieses Unterprogramm muss im Hauptprogramm regelmäßig (zyklisch) aufgerufen werden (Siehe Hauptprogramm, Listing 3.5, Zeile 586). |
Listing 3.15 zeigt die Realisierung von diesem etwas längerem Unterprogramm.
Unterprogramm Init_Flackerlicht_Stern:
Dieses Unterprogramm hat nur die Aufgabe die Zählregister für die Leuchtdioden die den Stern symbolisieren
mit den Anfangspositionen zu initialisieren und zwei Register für die Puls-Weiten-Modulation (für den Stern).
Listing 3.16 zeigt dieses Unterprogramm.
Anmerkung:
Dieses Unterprogramm wird im Hauptprogramm nach dem Initialisieren des Mikrocontrollers aufgerufen (Siehe
Hauptprogramm, Listing 3.5, Zeile 579).
Unterprogramm Flackerlicht_Stern:
Dieses Unterprogramm erzeugt das Flackern (Puls-Weiten-Modulation, PWM) für die Leuchtdioden, die den Stern
symbolisieren.
Es entspricht vom Prinzip her dem Listing aus Abschnitt 1 (Grundlegendes zur Erzeugung von Flackerlicht).
Die wesentlichen Unterschiede gegenüber Abschnitt 1 sind:
|
Wichtig:
Dieses Unterprogramm muss im Hauptprogramm regelmäßig (zyklisch) aufgerufen werden (Siehe Hauptprogramm, Listing 3.5, Zeile 587). |
Listing 3.17 zeigt die Realisierung von diesem etwas längerem Unterprogramm.
Die Ansteuerung der Leuchtdioden erfolgt bei diesem Projekt mit Hilfe von Schieberegistern. Die softwaretechnische Ansteuerung der Schieberegister erfolgt mit Hilfe von zwei Unterprogrammen.
Protokoll zur Kommunikation mit den Schieberegistern:
Die Abbildung 3.3 zeigt das sehr einfache Protokoll zur Kommunikation mit den Schieberegistern vom Typ 74xx595, und die Reihenfolge, in
welcher die Register in die Schieberegister geschoben werden müssen, damit die "richtigen" Leuchtdioden angesteuert werden.
Beim Übertragen der einzelnen Bits muss die Steuerleitung Port_Enable low sein. Erst nachdem alle Bits gesendet wurden muss ein kurzer High-Impuls (Ladeimpuls) erfolgen. Erst bei diesem Ladeimpuls übernehmen die Schieberegister die Daten.
|
Wichtig:
Das 8-Bit-Datenregister welches für das Schieberegister, dass vom Mikrocontroller am "weitesten entfernt" ist, zuständig ist (hier IC14), muss als erstes gesendet werden. Hier muss daher das Register Flackerlichter12 (für IC14) als erstes gesendet werden. |
Portdefinitionen:
Für die Kommunikation mit den Schieberegistern sind drei Portleitungen des Mikrocontrollers notwendig. Diese werden in der Datei
PROJEKT.H gemäß der Schaltung nach Abbildung 2.1 definiert.
Listing 3.18 zeigt die Portdefinitionen für die Kommunikation mit den Schieberegistern.
Unterprogramme:
Die Kommunikation mit den Schieberegistern erfolgt mit den beiden Unterprogrammen SR_74xx595_SendData und
SR_74xx595_SendByte.
Unterprogramm SR_74xx595_SendData:
Dieses Unterprogramm erzeugt dass Protokoll gemäß Abbildung 3.3. Zunächst muss die Steuerleitung
Port_Enable gelöscht werden, dann nacheinander die Datenbits (in den Registern
FlackerlichterXX) mit dem Unterprogramm SR_74xx595_SendByte
in die Schieberegister schieben. Nach dem letzten Datenbit einen Ladeimpuls für die Übernahme in die Schieberegister
erzeugen.
Listing 3.19 zeigt die Realisierung dieses Unterprogramms.
Hilfs-Unterprogramm SR_74xx595_SendByte:
Dieses Hilfs-Unterprogramm gibt mit Hilfe einer Schleife das MSB (Bit 7) am Datenausgang aus, erzeugt einen Takt und schiebt alle Bits
um eine Stelle weiter.
Listing 3.20 zeigt die Realisierung dieses Unterprogramms.
Ein praktischer Vorteil des CC5X-Compiler gegenüber anderen Compilern ist, dass die Konfigurationsbits für den Mikrocontroller (hier für den PIC16F87) direkt im Quellcode gesetzt werden können.
Listing 3.21 zeigt die notwendigen Einstellungen für den PIC16F87 für dieses Projekt.
1 Der PIC16F87 besitzt 12 Interruptquellen. Bei diesem Projekt wird aber nur der Timer-0-Interrupt benötigt.