Schaltung
Zwei Pins des Port D werden mit Leuchtdioden versehen, die über 330-Ohm Widerständen mit Masse verbunden sind. Damit zeigen die LEDs die Ausgangspegel der Pins RD0 und RD1 an. An der Schaltung fällt auf, dass keine Taktquelle zu
sehen ist. Ich benutze den internen 31kHz-Generator des PIC18F66J60. Ein weiterer wichtiger Aspekt bei den 3,3V-PICs ist die
Stromversorgung. Zunächst einmal besitzt ein großer PIC eine
stattliche Anzahl an Vdd- und Vss-Pins, ich habe alle angeschlossen. Die Gesamtschaltung darf mit maximal 3,6V gespeist werden. Die
mindestens nötige Betriebsspannung ist 2,7V, da ansonsten der
Spannungsregler für den Prozessorkern keine ausreichende Spannung
mehr abgibt. |
Programmablauf
Um am Port D ein Wechselblinklicht zu erzeugen muss man:
Mit einem Port LEDs ansteuern
(hier ist eine detaillierte
Beschreibung der I/O-Pins)
Port-Pins sind entweder als Eingänge oder als Ausgänge
nutzbar.
Nach dem Einschalten des PIC (oder einem Reset) sind alle Port-Pins als
Eingänge konfiguriert. Um sie als Ausgänge nutzbar zu machen,
muss man sie zunächst auf die Ausgangsfunktion umschalten.
Dazu
muss man bestimmte Steuerbits setzen bzw. löschen. Jedes
Port-Pin
hat so ein Steuerbit. Ist es auf '1' gesetzt, dann funktioniert das Pin
als Eingang, ist es aber auf '0' gesetzt, so ist es ein Ausgang.
Die 8 Steuerbits für die 8 Pins des PortD befinden sich im
Register
TRISD. Um PortD als Ausgang nutzen zu können, müssen also
alle
8 Bit des TRISD-Registers auf 0 gesetzt werden.
clrf
TRISD
;
PortD
alle output clrf PORTD ; alle LEDs ausschalten |
Um am Port D ein Wechselblinklicht zu erzeugen muss man an diesem Port einen Spannungspegel ausgeben. Jedes Pin kann entrweder 0V oder 3,3V (Vdd) ausgeben. Im obigen Stromlaufplan sieht man, dass die LEDs über einen Widerstand an den Pins des PORTD und mit dem anderen Anschluss mit Masse verbunden sind. Gibt ein Pin 0V aus, dann leuchtet die LED nicht. Gibt das Pin aber 3,3V aus, dann fließt ein Strom durch den Widerstand und die LED nach Masse, wodurch die LED leuchtet. Die von den Pins des PortD ausgegebenen Spannungspegel stellt man ein, indem man die zugehörigen 8 Bits des Registers PORTD setzt (1) oder löscht (0). Eine 1 bewirkt 3,3V am zugehörigen Pin, eine 0 bewirkt 0V.
Im der letzten Zeile des obigen Listings werden mit einem clrf-Befehl
alle
Bits
des PORTD auf 0 gesetzt, anfangs sind also alle LEDs aus.
Will
man die LED am Pin RD0 einschalten, so muss man das Bit0 von PORTD
auf 1 setzen:
; 1. LED einschalten
bsf PORTD,0 ; LED an RD0 einschalten |
Um ein Wechselblinklicht zu erzeugen, verschiebt man diese 1 nun
innerhalb des
Registers PORTD mit Hilfe der Rotierbefehle rlncf
und rrncf abwechselnd hin und
her.
Dadurch wandert die 1 in PORTD ständig zwischen RD0 und RD1 hin
und her, und es leuchten die LEDs D1 und D2 wechselseitig auf:
00000001
00000010
00000001
00000010
...
...
;
Lauflicht Loop call Wait ; Wartezeit rlncf PORTD,f ; laufen zur 2.LED call Wait ; Wartezeit rrncf PORTD,f ; laufen zur 1.LED goto Loop |
Das Verschieben erfolgt in einer Endlosschleife, die durch eine
Warteroutine
(Wait) soweit abgebremst wird, dass ein Durchlauf der Schleife
ca.
2 x 1/4 Sekunde dauert.
Configuration
Wenn man dem Brennprogramm US-Burn keine Config-Einstellungen
vorschreibt,
dann verwendet es die Microchip-Standardeinstellungen, und die sind
nicht
gerade praxistauglich. Deshalb sollte man gleich im HEX-File eine
andere Config einbauen. Das
sieht dann so aus:
;****************************************************************************** ;Configuration bits CONFIG FOSC2 = OFF ; intrc 31 kHz CONFIG WDT = OFF ; watchdog off CONFIG DEBUG = OFF CONFIG XINST = OFF CONFIG CP0 = OFF CONFIG ETHLED = OFF |
Warteschleife
Ich realisiere die Verzögerungen im Programm mit Hilfe
einer 1-Millisekunden-Warteschleife. Das ist also eine Unterprogramm,
das
genau 1 ms lang läuft, und dann zum rufenden Programm
zurückkehrt.
Mit Hilfe einer Schleife rufe ich dieses 1-ms-Warteprogramm vielfach
auf
- für 1/4 Sekunde rufe ich es 250 mal.
Im nachfolgenden Fenster ist eine 1-ms-Routine zu sehen. Sie heißt 'Wai' und ist für einen PIC-Takt von 31 kHz ausgelegt.
Fast alle Befehle eines PIC dauern einen Zyklus lang, wobei ein
Zyklus
4 externen PIC-Takten entspricht. Ein 31-kHz-PIC schafft also 7750
Befehle pro Sekunde, da in einer Sekunde 7750 Zyklen bzw. 31000
externe Takte stattfinden. Ein Zyklus ist hier 129 Mikrosekunde (129
µs)
lang.
Ein Programm, das 1 Millisekunde verzögern soll, muss also
7,75 Zyklen lang sein. Meine Wai-Schleife ist mit 8 Zyklen etwas zu
lang, aber für ein einfaches LED-Blinklicht ist der Fehler
vertretbar.
Wie oft die 1ms-lange Wai-Schleife durchlaufen wird, das hängt
von der Variablen loops ab. Für eine 250ms-Wartezeit springe ich
die Marke Wait an. Hier wird loops mit 250 geladen, und dann zu Wai
weiter gegangen. Dadurch wird Wai genau 250 mal durchlaufen, wodurch
sich 250ms Verzögerung ergibt.
;****************************************************************************** ; Warteschleife 250 ms ; 31 kHZ Takt ; 8 Zyklen pro loop = 1ms Wait movlw D'250' ; 250 ms Pause movwf loops Wai ; Zeitkonstante für 1ms (8 Takte) nop nop nop nop decfsz loops, F ; 250 ms vorbei? goto Wai ; nein, noch nicht retlw 0 ; das Warten hat ein Ende
|
Programmlisting
Das Assembler-Programm ist auch in nachfolgender Tabelle zu sehen. Den überflüssigen Kommentar habe ich grau gefärbt, damit man sich auf den eigentlichen Code konzentrieren kann.;****************************************************************************** ; sprut (zero) Bredendiek 02/2006 ; ; Wechselblinklicht am Port D, RD0 & RD1 ; ; Taktquelle: 31 kHz intern ; ;****************************************************************************** ; ; Pinbelegung ; ---------------------------------- ; PORTD: 0 LED 1 ; 1 LED 2 ; ;****************************************************************************** LIST P=18F66J60 ;der Typ des Prozessors #include <P18F66j60.INC> ;processor-spezifische Variablendefinitionen ;****************************************************************************** ;Configuration bits CONFIG FOSC2 = OFF ; intrc 31 kHz CONFIG WDT = OFF ; watchdog off CONFIG DEBUG = OFF CONFIG XINST = OFF CONFIG CP0 = OFF CONFIG ETHLED = OFF ;****************************************************************************** ;Variable definitions CBLOCK 0x000 loops ENDC ;****************************************************************************** ;Reset vector ; hier beginnt der Prozessor beim Reset ORG 0x0000 goto Main ;go to start of main code ;****************************************************************************** ;Start of main program Main: ; Port D kmnfigurieren ; alle Pins sind output clrf TRISD clrf PORTD ; alle LEDs ausschalten ; 1. LED einschalten bsf PORTD,0 ; LED an RD0 einschalten ; Lauflicht Loop call Wait ; Wartezeit rlncf PORTD,f ; laufen zur 2.LED call Wait ; Wartezeit rrncf PORTD,f ; laufen zur 1.LED goto Loop ;****************************************************************************** ; Warteschleife 250 ms ; 31 kHZ Takt ; 8 Zyklen pro loop = 1ms Wait movlw D'250' ; 250 ms Pause movwf loops Wai ; Zeitkonstante für 1ms (8 Takte) nop nop nop nop decfsz loops, F ; 250 ms vorbei? goto Wai ; nein, noch nicht retlw 0 ; das Warten hat ein Ende ;****************************************************************************** ;End of program END |