; 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
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).
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.
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
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.
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.