PIC-Lernbeispiel: WALK


zurück , Lernbeispiele , PIC-Prozessoren , Elektronik , Homepage


Folgendes kleine Programm stammt von David Taid, und ist ein kleines hin- und herlaufendes Lauflicht für 4 Leuchtdioden an den Pins RB0 bis RB3. Es gehört zum Download des alten DOS-Parallelportbrenners von David Taid, und soll deshalb mal etwas genauer erklärt werden,

; WALK.ASM
;
; To use this program connect four LEDs from each of RB0-RB3 to ground
; via four 470 ohm resistors.  The LEDs are illuminated one at time in
; a to-and-fro pattern.
;
; The illumination rate is more or less independent of the PIC clock
; frequency and configuration although this program assumes an RC
; oscillator.  The program includes the __CONFIG, __IDLOCS and DE
; directives (mostly just to show how they can be used).  The program
; can be used unchanged on any 16X8X device.

        LIST            P=16C84
        ERRORLEVEL      -302    ;SUPPRESS BANK SELECTION MESSAGES
        __CONFIG        3FF7H   ;RC OSC, WATCHDOG
        __IDLOCS        1234
;
TRISB   EQU     86H
OPTREG  EQU     81H
STATUS  EQU     3
CARRY   EQU     0
RP0     EQU     5
MSB     EQU     3               ;BIT POSITION OF LEFTMOST LED
;
        CLRF    PORTB           ;ALL LEDS OFF
        BSF     STATUS,RP0      ;SELECT REGISTER BANK 1
        CLRF    TRISB           ;SET PORTB TO ALL OUTPUTS
        MOVLW   0AH
        MOVWF   OPTREG          ;ASSIGN PRESCALER (1:4) TO WDT
        BCF     STATUS,RP0      ;SELECT REGISTER BANK 0
        INCF    PORTB,F         ;TURN ON RIGHTMOST LED
        BCF     STATUS,CARRY    ;CLEAR CARRY
LEFT    SLEEP                   ;WAIT FOR WDT TIMEOUT
        RLF     PORTB,F         ;TURN ON LED TO LEFT
        BTFSS   PORTB,MSB       ;REACHED LEFTMOST?
        GOTO    LEFT            ;LOOP IF NOT
RIGHT   SLEEP                   ;WAIT FOR WDT TIMEOUT
        RRF     PORTB,F         ;TURN ON LED TO RIGHT
        BTFSS   PORTB,0         ;REACHED RIGHTMOST?
        GOTO    RIGHT           ;LOOP IF NOT
        GOTO    LEFT            ;START NEW CYCLE
;
        ORG     2100H
;
        DE      "Copyright (C) 1996 David Tait"
        END

Eine Analyse des Programms wird helfen, die Assemblerprogrammierung besser zu verstehen:

Das Programm beginnt mit einer Reihe Zeilen, die mit einem Semikolon beginnen. Das ist ein Kommentar, den der Programmschreiber der Übersichtlichkeit halber eingefügt hat. Dem Assembler ist das egal, da er alles was auf einer Zeile hinter einem Semikolon steht ignoriert. Das sind sozusagen Notizzettel des Programmierers.


        LIST            P=16C84
Dieser Befehl legt für den Assembler den Prozessortyp fest. Indiesem Fall den PIC16C64 den Vorläufer des 16F84.

        ERRORLEVEL      -302    ;SUPPRESS BANK SELECTION MESSAGES
Der Assembler meldet beim Übersetzen Fehler und gibt Warnungen. Hier werden bestimmte Warnungen abgeschaltet. Das ist nicht unbedingt nötig, sondern verkürzt nur die Liste der Warnmeldungen.

        __CONFIG        3FF7H   ;RC OSC, WATCHDOG
In die HEX-Datei wird der Assembler spezielle Infos einfügen, die bestimmte Eigenschaften des PICs festlegen. Hier wird der Oszillatortyp (RC-Oszillator) festgelegt, und der Watchdog-Timer aktiviert. Dieser Timer weckt den PIC in bestimmten noch festzulegenden Zeitabständen aus dem Schlafmodus.
Diese PIC-Eigenschaften können normalerweise vom Brennprogramm nachträglich verändert werden (z.B. ein anderer Oszillatortyp), dieses Programm braucht aber den Watchdog.

        __IDLOCS        1234



TRISB   EQU     86H
OPTREG  EQU     81H
STATUS  EQU     3
CARRY   EQU     0
RP0     EQU     5
MSB     EQU     3               ;BIT POSITION OF LEFTMOST LED

Dieser Teil des Programms enthält keinen Code, der im Prozessor irgentetwas bewirkt. Nein, es ist nur eine Hilfe für den Assembler, die folgenden Zeilen richtig zu verstehen. Dem Assembler werden die Begriffe TRISB, OPTREG, STATUS, CARRY, RP0 und MSB erklärt. Diese Begriffe sind nichts anderes als feste Zahlenwerte, also Konstanten. Hinter STATUS verbirgt sich z.B. die Zahl 3, hinter TRISB der hexadezimale Wert 86H, also dezimal 134.

Mit Hilfe des EQU-Befehls werden die Konstanten dem Assember erklärt, und von nun an kann man STATUS schreiben, wenn man 3 meint.

Standardbezeichnungen, die  man immer wieder braucht, sind in einer Datei P16F84.INC abgelegt. Diese Datei wird mit einer Befehlsszeile
        #include    <P16f84.INC>
in das Programm eingebunden. Diese Variante wird man in den meisten Programmen sehen. Leider nicht hier.


        CLRF    PORTB           ;ALL LEDS OFF
Das Register PORTB wird auf "0" gesetzt. Da Port B noch auf Eingang gestellt ist, hat das noch keine Auswirkungen.

        BSF     STATUS,RP0      ;SELECT REGISTER BANK 1
Die Register des PIC befinden sich in parallelen Bänken (16F84: zwei Bänke, 16F876: vier Bänke). Mit dem Bit RP0 des Registers STATUS (das es in allen Bänken gibt) wird auf die zweite Bank umgeschaltet.

        CLRF    TRISB           ;SET PORTB TO ALL OUTPUTS
Das Register TRISB befindet sich in dieser zweiten Bank und wird nun auf "0" gesetzt. Damit sind alle Pins des Ports B auf Ausgang umgestellt.

        MOVLW   0AH
Das Arbeitsregister W wird mit dem hexadezimalen Wert 0AH (dezimal 10) geladen.

        MOVWF   OPTREG          ;ASSIGN PRESCALER (1:4) TO WDT
Der Inhalt von W (0AH) wird in das Register OPTREG geschrieben. Damit wird der interne Takt des PIC über einen 4:1-Vorteiler auf den Watchdogtimer geschaltet. Dieser erweckt nun alle 256x4-Takte den PIC.
Einen Befehl, um den Wert ohne den Umweg über W in das Register zu schreiben gibt es nicht.

        BCF     STATUS,RP0      ;SELECT REGISTER BANK 0
Es wird zurück zur ersten Bank geschaltet.


        INCF    PORTB,F         ;TURN ON RIGHTMOST LED
Der Wert in PORTB (0) wird um eins erhöht (also auf 1) und wieder nach PORTB geschrieben. Würde anstelle des F ein W stehen, würde die "1" nicht nach PORTB sondern nach W geschrieben werden.

        BCF     STATUS,CARRY    ;CLEAR CARRY
Das CARRY-Flag das im Register STATUS liegt wird gelöscht (0).



Es folgt ein laufen des Lichtes nach "links" von RB0 nach RB3:

LEFT    SLEEP                   ;WAIT FOR WDT TIMEOUT
Der Prozessor wird in den Schlafmodus gelegt und stoppt.

        RLF     PORTB,F         ;TURN ON LED TO LEFT
Die Bits innerhalb des PORTB werden nach links verschoben.

        BTFSS   PORTB,MSB       ;REACHED LEFTMOST?
Ist die "1" schon am Pin RB3 (MSB) angekommen? Wenn ja, dann überspringe den folgenden Befehl.

        GOTO    LEFT            ;LOOP IF NOT
Ansonsten springe hoch zur Marke LEFT.



Und nun ein zurücklaufen des Lichtes nach "rechts" von RB3 nach RB0:

RIGHT   SLEEP                   ;WAIT FOR WDT TIMEOUT
        RRF     PORTB,F         ;TURN ON LED TO RIGHT
        BTFSS   PORTB,0         ;REACHED RIGHTMOST?
        GOTO    RIGHT           ;LOOP IF NOT
        GOTO    LEFT            ;START NEW CYCLE



        ORG     2100H
        DE      "Copyright (C) 1996 David Tait"

Der ORG Befehl weist den Assembler an, dass der nun folgende Programmteil im PIC ab der im ORG-Befehl stehenden Adresse stehen soll.
Normalerweise beginnt ein Programm ab der Adresse 0000H. Ein Interrupt beginnt aber immer an der Adresse 0004H. Deshalb steht im Programm vor einer Interruptroutine immer "ORG 0004H" oder die Kurzform "ORG 4".

Unser Beispiel weist den Assembler an, auf der Adresse 2100H weiterzumachen, das liegt aber weit außerhalb des PIC-Programmspeichers. Mit den Adressen ab 2100H kann man im Assembler aber die EEPROM-Datenzellen adressieren.

Der nun folgende DE-Befehl ist kein richtiger Programmcode, stattdessen bedeutet DE, dass der hinter DE stehende Text in den PIC geschrieben werden soll.
Hier wird also der Text "Copyright (C) 1996 David Tait" in die EEPROM-Datenzellen gebrannt.



        END

Dieser Befehl kennzeichnet für den Assembler das Ende des Programms. Alles was nun noch im Text folgt, wird nicht berücksichtigt.
Wer ein neues Programm aus alten Programmteilen zusammenkopiert, sollte darauf achten, dass dann nicht mitten im Text ein überflüssiges END steht.


zurück , Lernbeispiele , PIC-Prozessoren , Elektronik , Homepage