![]() |
MikrocomputertechnikProf. Jürgen Plate |
data equ $2000 ; data area (e-ram)
stak equ $7FFF ; stack area (e-ram)
prog equ $8000 ; programm area (e-eerom)
rvec equ $FFFE ; reset vector
porta equ $1000 ; port a data
portb equ $1004 ; port b data
portc equ $1003 ; port c data reg.
ddrc equ $1007 ; port c data dir. reg.
portd equ $1008 ; port d data reg.
ddrd equ $1009 ; port d data dir. reg.
porte equ $100A ; port e data
pioc equ $1002 ; parallel i/o control
portcl equ $1005 ; port c data latch
tmsk equ $1024 ; timer mask
tflg equ $1025 ; timer flag
pacr equ $1026 ; pulse accu control
baud equ $102B ; SCI-baudrate
sccr1 equ $102C ; SCI-control1
sccr2 equ $102D ; SCI-control2
scsr equ $102E ; SCI-status
scdr equ $102F ; SCI-data
***************************
* data area *
***************************
org data
***************************
* program area *
***************************
org prog
main lds #stak ; load stackpointer
***************************
* Nachspann: Vektoren *
***************************
org reset
fdb main
end
* Parameter: A Länge (Anzahl Bytes), X Quelle, Y Ziel
move pshb
mov1 ldab 0,x ; hole Quellbyte
stab 0,y ; speichern im Zielbereich
inx ; Adressen erhöhen
iny
deca ; runterzählen bis 0
bne mov1
pulb
rts
LDAA $2000 ; 1. Zahl holen
CMPA $2001 ; 2. Zahl größer?
BHS WEITER ; 1. Zahl ist größer
LDAA $2001 ; 2. Zahl laden
WEITER STAA $2002 ; Abspeichern
LDAB $2001 ; Operanden holen
LDX #TABELLE ; X-Register auf Tabellenanfang
ABX ; X und B addieren
LDAA 0,X ; B-ten Eintrag aus Tabelle holen
STAA $2002 ; und abspeichern
TABELLE DC.B 0,1,4,9,16,25,36,49,64,81,100
DC.B 121,144,169,196,225
ORG DTA
Summe DS.B 2 ; Summe, 16-Bit-Wert
Anzahl DS.B 1 ; Anzahl Werte, 8-Bit-Wert
Daten DS.B 255 ; Datenfeld
ORG PROG
.
.
.
CHECKSUM CLRA ; Summe in A und B, Register
CLRB ; zuerst mal löschen
LDX #Daten ; Adresse erster Summand (Feldanfang)
CSUM ADDB ,X ; Feldelement addieren
ADCA #0 ; Übertrag im MSB aufaddieren
INX ; X inkrementieren
DEC Anzahl ; Elementezähler vermindern
BNE CSUM ; Wiederholen, solange Zähler > 0 ist
STD Summe ; Checksumme speichern
RTS
org data
eins dc.b 04,82,40 ; 1. Summand
zwei dc.b 02,37,98 ; 2. Summand
drei dc.b $00,$00,$00 ; Ergebnis
org prog
.
.
.
ldaa eins+2
adda zwei+2
staa drei+2
ldaa eins+1
adca zwei+1
staa drei+1
ldaa eins+0
adca zwei+0
staa drei+0
.
.
.
ORG DTA
Zahl1 DC.B $12,$34,$56,$78 ; Speicherung Nibble-weise, daher
Zahl2 DC.B $21,$43,$65,$87 ; Hexadezimal-Zahlen
ORG PROG
.
.
LDAB #4 ; Zahlen sind 4 Byte lang = 8 Stellen
LDX #Zahl1+3 ; 1. Operand, LSB
LDY #Zahl2+3 ; 2. Operand, LSB
CLRA ; Akku A (und Carry-Flag) löschen
BCDADD LDAA 0,X ; zwei Ziffern des 1.Operanden holen
ADCA 0,Y ; zwei Ziffern des 2.Operanden addieren
DAA ; Dezimalkorrektur für BCD
STAA 0,X ; Ergebnis abspeichern
DEY
DEX
DECB
BNE BCDADD ; solange, bis alle Stellen bearbeitet
ANZAHL EQU 20 ; z.B. 20 Feldelemente
FELD DS.B 20 ; Platz für 20 Werte
COUNT DS.B 1 ; 1 Byte Zähler
.
.
.
CLRB ; Zähler für neg. Elemente löschen
LDX #FELD ; X auf Feldanfang
LDAA ANZAHL
STAA COUNT ; Zähler setzen
LOOP LDAA 0,X ; nächstes Feldelement
BPL WEITER ; wenn positiv weiter
INCB ; negative Elemente zählen
WEITER INX
DEC COUNT
BNE LOOP ; bis alle Elemente getestet sind
STAB COUNT ; Ergebnis in COUNT speichern
.
.
.
clr portb ; Portb auf 0 setzen
ldab #%1010 ; Register B setzen
ldaa #%11110000 ; Port C Richtungsregister setzen:
staa ddrc ; Bits 0-3 Eingabe, 4-7 Ausgabe
loop ldaa portc ; Port C lesen
anda #$0F ; untere 4 Bits ausmaskieren
staa portb ; auf Port B ausgeben
stab portc ; Register B ausgeben
eorb #%11110000 ; und Bits 4-7 invertieren
bsr delay ; 0,5 s warten (siehe unten)
jmp loop ; endlosschleife
.
.
.
prog equ $8000
data equ $2000
stack equ $7FFF
pioc equ $1002 ; parallel i/o control
portb equ $1004 ; port b data
portc equ $1005 ; port c data latch
portcl equ $1005 ; port c data latch
tmsk equ $1024 ; timer mask
tflg equ $1025 ; timer flag
pacr equ $1026 ; pulse accu control
baud equ $102B ; SCI-baudrate
sccr1 equ $102C ; SCI-control1
sccr2 equ $102D ; SCI-control2
scsr equ $102E ; SCI-status
scdr equ $102F ; SCI-data
reset equ $fffe
org data
key ds.b 1
org prog
main lds #stack ; load stackpointer
clr key
ldaa #%01010000 ; pa7 freigabe pos. flanke
staa pacr
clra
loop bsr taste
ldaa key
staa portb
bra loop
taste psha
ldaa tflg ; taste gedrueckt?
anda #$10
beq tend ; nix gewesen
ldaa #$10
staa tflg ; Anforderung loeschen
com key ; Ereignis melden
tend pula
rts
org reset
fdb main
end
data equ $2000 ; data area (e-ram)
stak equ $7FFF ; stack area (e-ram)
prog equ $8000 ; programm area (e-eerom)
rvec equ $FFFE ; reset vector
pioc equ $1002 ; parallel i/o control
portb equ $1004 ; port b data
portcl equ $1005 ; port c data latch
portc equ $1003 ; port c data reg.
ddrc equ $1007 ; portc data dir. reg.
tmsk equ $1024 ; timer mask
tflg equ $1025 ; timer flag
pactl equ $1026 ; pulse accu control
baud equ $102B ; SCI-baudrate
sccr1 equ $102C ; SCI-control1
sccr2 equ $102D ; SCI-control2
scsr equ $102E ; SCI-status
scdr equ $102F ; SCI-data
***************************
* data area *
***************************
org data
flag ds.b 1
shift ds.b 2
***************************
* program area *
***************************
org prog
main lds #stak ; load stackpointer
clr flag
ldaa #%01010000 ; pa7 Eingang, Freigabe, pos. Flanke
staa pactl
ldaa #$FF ; portc als Ausgabe
staa ddrc
clr shift ; Schieberegister mit 1 laden
ldab #1
stab shift+1
loop bsr taste ; Tastenstatus abfragen
ldaa flag ; flag = 0 - links, flag = ff - rechts
bne rechts
links ldd shift ; nach links schieben
lsld
bne raus ; falls 0, neu laden mit 1 im LSB
ldab #1
bra raus ; zur Ausgabe
rechts ldd shift ; rechts schieben
lsrd
bne raus ; falls 0 mit 1 laden im MSB
ldaa #$80
raus std shift ; akt. Wert speichern
staa portb ; und ausgeben (auf zwei 8-Bit-Ports)
stab portc
bsr delay
bra loop
rts
taste psha ; Akku retten
ldaa tflg ; Taste gedrueckt?
anda #$10
beq tend ; nix gewesen
ldaa tflg
oraa #$10
staa tflg ; Anforderung loeschen
com flag ; Ereignis melden
tend pula ; Akku restore
rts
delay ldy #$ffff
dely1 nop
nop
nop
nop
nop
nop
nop
dey
bne dely1
rts
***************************
* vectors *
***************************
org rvec
fdb main ; FFFE reset
end
; Vereinbarungen
prog equ $8000
data equ $2000
stack equ $7FFF
portb equ $1004
portc equ $1003
portcl equ $1005
pioc equ $1002
ddrc equ $1007
reset equ $fffe
.
.
org data ; Datenbereich
tflag ds.b 1
.
.
org prog ; Programmbereich
main lds #stack ; Stackpointer laden
clr portb ; Ports/Variablen init.
ldaa #1 ; tflag = 1
staa tflag
loop bsr count ; Hauptschleife, nur zwei UP-Aufrufe
bsr taste ; Taste abfrage
jmp loop ; auf/ab zaehlen
; Zaehl-Unterprogramm
; tflag wird addiert (tflag kann 1 oder -1 sein)
count adda tflag ; zaehlen
staa portb ; ausgeben
bsr delay ; 0,5 s warten (siehe unten)
rts
; Tasten-Abfrage-UP
; bei jedem Tastendruck wird tflag negiert (+1
-1, -1
+1)
taste psha ; Akku A retten
ldaa pioc ; Taste gedrueckt
bpl njet ; nein
fertig
ldaa portcl ; dummy-read zum Ruecksetzend es Tastenbits in pioc
neg tflag ; tflag negieren
njet pula ; Akku A restaurieren
rts
.
.
.
Alternativlösung mit bedingter Verzweigung
loop bsr delay
tst updn
bne decr
inc count
ldaa count
cmpa #$FF
bne endf
com updn
bra endf
decr dec count
ldaa count
tsta
bne endf
com updn
endf ldaa count
staa portb
jmp loop
data equ $2000 ; data area (e-ram)
stak equ $7FFF ; stack area (e-ram)
prog equ $8000 ; programm area (e-eerom)
rvec equ $FFFE ; reset vector
pioc equ $1002 ; parallel i/o control
portb equ $1004 ; port b data
portcl equ $1005 ; port c data latch
portc equ $1003 ; port c data reg.
ddrc equ $1007 ; portc data dir. reg.
tmsk equ $1024 ; timer mask
tflg equ $1025 ; timer flag
pacr equ $1026 ; pulse accu control
baud equ $102B ; SCI-baudrate
sccr1 equ $102C ; SCI-control1
sccr2 equ $102D ; SCI-control2
scsr equ $102E ; SCI-status
scdr equ $102F ; SCI-data
***************************
* data area *
***************************
org data
flag ds.b 1
***************************
* program area *
***************************
org prog
main lds #stak ; load stackpointer
clra
clr flag
bsr init
schl adda #1 ; BCD hochzaehlen
daa
anda #$0F
bsr taste ; Taste abfragen
psha ; a auf den stack
lsla ; 4 x schieben
lsla
lsla
lsla
staa portc ; ausgeben
pula ; a restore
ldab flag ; Tastendruck bearbeiten
stab portb ; auf Port B ausgeben
bne schl1 ; wenn nicht 0
clra ; Zaehler loeschen
com flag ; flag wieder setzen -> sonst "haengt" es
schl1 bsr delay
bra schl
init ldaa #$02 ; hands=0, raising edge 00000010
staa pioc
ldaa #%11110000
staa ddrc
rts
delay ldy #$ffff
dely1 nop
nop
nop
nop
nop
nop
nop
dey
bne dely1
rts
taste psha
ldaa pioc ; taste gedrueckt (Bit 7)?
bpl tend ; nix gewesen
ldaa portcl ; dummy read --> Reset STAF
com flag ; ereignis melden
tend pula
rts
***************************
* vectors *
***************************
org rvec
fdb main ; FE reset
end
Die Bedienung des Timer-Interrupts wird hier nur angedeutet (da noch nicht behandelt). Der CLOCK-Interrupt wird im Beispiel alle 100 ms ausgelöst = 10 Tics/s.
ZEHNTEL DS.B 1 ; 1/10 Sekunden
SEKUNDEN DS.B 1 ; Sekunden
MINUTEN DS.B 1 ; Minuten
STUNDEN DS.B 1 ; Stunden
.
.
.
CLOCK
* An dieser Stelle muß die
* Timer-Hardware bedient werden
INC ZEHNTEL ; 1/10 Sekunden erhöhen
LDAA #10
CMPA ZEHNTEL ; Sekunde erreicht?
BNE ENDCLOCK ; nein - fertig
CLR ZEHNTEL ; sonst 1/10 Sekunden auf 0 setzen
INC SEKUNDEN ; und Sekunden erhöhen
LDAA #60
CMPA SEKUNDEN ; Minute erreicht?
BNE ENDCLOCK ; nein - fertig
CLR SEKUNDEN ; sonst Sekunden auf 0 setzen
INC MINUTEN ; und Minuten erhöhen
CMPA MINUTEN ; Stunden erreicht?
BNE ENDCLOCK ; nein - fertig
CLR MINUTEN ; sonst Minuten auf 0 setzen
INC STUNDEN ; und Stunden erhöhen
LDAA #24
CMPA STUNDEN ; Tageswechsel?
BNE ENDCLOCK ; nein - fertig
CLR STUNDEN ; sonst Stunden auf 0 setzen
ENDCLOCK RTI ; Rücksprung
Die Dauer der ISR beträgt im schlechtesten Fall weniger als 150 Taktzyklen. Da die ISR nur alle 100 ms ausgelöst wird, ist die zusätzliche Belastung des Systems relativ gering (ca. 0,1%).

EVENPAR PSHB ; Codewort zwischenspeichern
CLRA ; Zaehler = 0
ZHL LSRB ; naechstes Bit ins Carry holen
ADCA #0 ; Carry zu A ddieren
TSTB ; Restwort = 0?
BNE ZHL ; nein, weiter
PULB ; Codewort holen
ASLB ; links schieben
LSRA ; Parity-Bit ins Carry
RORB ; Parity-Bit ins MSB vom Codewort
RTS
*
* Konvertierung Binär zu ASCII
* Parameter in Akku A
*
BINASC ANDA #0F ; auf Werte zwischen 0 und 15 begrenzen
CMPA #9 ; Wert 0 bis 9 ?
BLS ZIF ; ja, dann direkt umwandeln
ADDA #7 ; "A" - "9" - 1 = $41 - $39 - 1 = 7
ZIF ADDA #$30 ; $30 = "0" (ASCII-Wert)
RTS
*
* Unterprogramm ASCII-Binär-Konvertierung (0 - 9, A - F)
* Parameter in A
*
ASCBIN SUBA #$30 ; $30 = ASCII "0"
BLO FEHL ; Erg. negativ
keine Ziffer
CMPA #9 ; kleiner oder gleich 9?
BLS DONE ; dann fertig
SUBA #7 ; "A" - "F"
10 - 15
CMPA #10 ; kleiner als 10?
BLO FEHL ; dann Fehler
CMPA #15 ; größer 15?
BLS DONE ; nein, fertig
FEHL LDAA #$FF ; Fehlerflag setzen
DONE RTS
hx4a psha ; Akku A auf dem Stack ablegen
bsr hx2a ; Akku B umwandeln (Stelle 3 und 4)
pulb ; Akku A vom Stack holen, in Akku B ablegen
; Nun einfach in hx2a fallen und Akku B
; umwandeln (Stelle 1 und 2)
hx2a pshb ; Akku B aud dem Stack sichern
bsr hx1a ; Bits 0-3 von Akku B umwandeln
pulb ; Original-Akku B wieder holen
lsrb ; viermal schieben (Bits 4-7 --> 0-3)
lsrb
lsrb ; und nun die obere Haelfte umwandeln
lsrb ; indem einfach in hx1a gefallen wird
; Nun wird die eigentliche Arbeit gemacht:
hx1a andb #$0F ; die oberen 4 Bita ausmaskieren
addb #48 ; ASCII-Wert von "0" addieren
cmpb #57 ; groesser als "9"?
bls hx1b ; nein, dann speichern
addb #7 ; sonst die Distanz zwischen "9" und "a" addieren
hx1b stab 0,y ; Im Speicher ablegen, auf den Y zeigt
dey ; Y zeigt jetzt auf die Stelle davor
rts ; und weg
LDX #STRING ; Beginn der Zeichenkette
CHECK LDAA 0,X ; Zeichen lesen
INX ; X erhoehen
CHECK CMPA #$20 ; Leerzeichen?
BEQ CHECK ; Ja, weiter testen
DEX ; nein, Zeiger korrigieren
.
.
.
STRING DC.B ' Zeichenkette mit 4 Leerzeichen am Anfang'
DC.B 0 Abschlußzeichen
; Vergleich zweier Strings, Anfangsadressen in X und Y
; Ergebnis wird in Akku A zurueckgegeben (0: ungleich, FF: gleich)
vergl ldaa 0,X ; Zeichen aus String 1 vergleichen
cmpa 0,Y ; mit Zeichen aus String 2
bne ver0 ; Strings ungleich, fertig
cmpa #0 ; Stringende
beq ver1 ; Strings sind gleich, fertig
inx ; naechstes Zeichen
iny
bra vergl
ver1 ldaa #$ff
rts
ver0 clra
rts
delay pshx ; Register x retten, 4 cycl
ldx #$f211 ; Anfangswert laden, 3 cycl
delay1 nop ; 5 x nop = 10 cycl
nop
nop
nop
nop
dex ; X runterzaehlen, 3 cycl
bne delay1 ; 3 cycl
pulx ; Register restaurieren, 5 cycl
rts ; 5 cycl
delay clra ; Akku D: Akku A = 0, Akku B = Wert
andb #$0F
beq del_end ; Division durch 0 verhindern
ldx #$FF00 ; Wert fuer 1 Hz --> X
xgdx ; Schalter in X, 1-Hz-Wert in D
idiv ; D/X
delay1 nop
nop
nop
nop
nop
nop
nop
dex
bne delay1
del_end rts
org data
sek ds.b 1
zsek ds.b 1
org prog
main lds #stack ; Initialisierung
clr portb
ldaa #%11110000 ; Bits 0-3 als Eingang
staa ddrc
loop ldab portc ; Schalter einlesen
andb #$0F
lslb ; Akku B * 2, weil 16-Bit-Zugriff
; (jeweils 2 Byte)
ldx #tabelle ; Tabellenzugriff: X zeigt aus Tab.-Anfang
abx ; aktuelle Position: B + X
ldd 0,X ; Wert laden
std sek ; Sekunden in sek, 1/10 in zsek
jmp loop
* 0 1 2 3 4 5 6 7
tabelle dc.b 0,0, 2,5, 4,0, 10,0, 15,5, 20,0, 25,3, 31,4,
* 8 9 10 11 12 13 14 15
dc.b 40,0, 51,2, 60,0, 65,8, 72,4, 80,1, 85,7, 95,3
data equ $2000 ; Datenbereich
prog equ $8000 ; Programmbereich
stack equ $7FFF ; Stackbereich
resetv equ $FFFE ; Adresse Reset-Vektor
pcdd equ $1007 ; Adressen Port C
pcdr equ $1003
* Random-Constants:
RndMult equ 181 ; Multiplikationsfaktor
RndAdd equ 359 ; zu addierender Offset
org data
RndSeed ds.b 2 ; 2 Byte Random Seed
RndTmp ds.b 2 ; temporaerer Speicher
org prog
main lds #stack ; Init Stack
ldaa #$FF
staa pcdd ; Port C als output
clr pcdr
bsr RndInit ; Seed = 0
loop bsr Random ; A = random number
staa pcdr ; A -> Port C
bsr Delay ; wait
bra loop
* Initialize the random number generator
RndInit clr RndSeed
clr RndSeed+1
rts
* Return the next 8-bit pseudo random number
* Berechnet SEED = SEED * 181 + 359
* return high byte of the new SEED in A
* Return value: The A register.
Random pshb ; save B
* scratch = seed * RndMult
ldaa #RndMult ; A = #181
ldab RndSeed+1 ; B = low byte of the seed
mul ; D = A x B
std RndTmp ; scratch = D
ldaa #RndMult ; A = #181
ldab RndSeed ; B = high byte of the seed
mul ; D = A x B
* low byte of mult. result is added to the high byte of scratch
addb RndTmp ; B = B + scratch_high
stab RndTmp ; scratch = seed * 181
ldd RndTmp ; D = scratch
addd #RndAdd ; D = D + 359
std RndSeed ; save new seed value
* A holds RndSeed from addition
pulb ; retore B
rts
* Delay wie ueblich ...
Delay LDX #$FFFF
LoopX DEX
BNE LoopX
RTS
org resetv ; Reset-Vektor setzen
dc.w main
prog equ $8000 ; Vereinbarungen
data equ $2000
stack equ $7FFF
portb equ $1004
reset equ $fffe
org prog
main lds #stack
ldx #muster ; X verweist auf das erste Feldelement
loop ldaa 0,x ; erstes Feldelement laden
bne ausg ; wenn nicht 0, ausgeben
ldx #muster ; sonst wieder zum ersten Element
bra loop ; ohne Ausgabe
ausg staa portb ; Bitmuster ausgeben
jsr delay ; 0,5 s warten
inx ; naechstes Element
bra loop
delay pshx ; Delay, siehe oben
ldx #$f422
delay1 nop
nop
nop
nop
nop
dex
bne delay1
pulx
rts
muster dc.b %11110000, %01111000, %00111100, %00011110
dc.b %00001111, %00011110, %00111100, %01111000
dc.b %0
org reset ; Reset-Vektor setzen
fdb main
end

prog equ $8000
data equ $2000
stack equ $7FFF
portb equ $1004
reset equ $fffe
org data
count ds.b 1
org prog
main lds #stack
clr count ; Speicher loeschen
loop ldab count ; Schleifenbeginn, count mod 16 hochzaehlen
incb
andb #$0F
stab count
bsr umco ; Count in Akku B wird umcodiert, Ergebnis in Akku B
stab portb ; und ausgeben
jsr delay ; 0,5 s warten
bra loop
; Umcodierung binaer --> 7-Segment, eingabe und Ausgabe in Akku B
umco ldx #umcotab ; Tabellenadresse laden
andb #$0F ; fuer B nur Werte 0 - F zulassen
abx ; X = X + B
ldab 0,x ; 7-Sement-Wert holen, Adressierung durch X-Register
rts
delay pshx ; Delay, siehe oben
ldx #$f422
delay1 nop
nop
nop
nop
nop
dex
bne delay1
pulx
rts
; Siebensegment-Tabelle (Segmentanordnung: -abcdefg)
; Die Ziffern "0" bis "9" sind decodiert, fuer "A" bis "F"
; wird nur ein "-" angezeigt --> noch zu ergaenzen
umcotab dc.b %01111110, %00110000, %01101101, %01111001
dc.b %00110011, %01011011, %01011111, %01110000
dc.b %01111111, %01111011, %00000001, %00000001
dc.b %00000001, %00000001, %00000001, %00000001
org reset
fdb main
end
gets stx pufanf
gets0 bsr recv
cmpb #cr
beq gets1
cmpb #bs
beq gets2
cmpb #' ' ; Zeichen < ' ' ignorieren
blo gets0
bsr send
stab 0,x
inx
bra gets0
gets1 clrb ; Newline - Eingabeende
stab 0,x ; Nullbeit als Abschluss
bsr crlf ; cr + lf ausgeben
rts
gets2 cpx pufanf ; Backspace
beq gets0 ; nur bis Pufferanfanng zurück
dex
ldab #bs ; BS , Leer, BS ausgeben
bsr send
ldab #' '
bsr send
ldab #bs
bsr send
bra gets0
; cr+lf ausgeben
crlf ldab #cr
bsr send
ldab #lf
bsr send
rts
data equ $2000 ; data area (e-ram)
stak equ $7FFF ; stack area (e-ram)
prog equ $8000 ; programm area (e-eerom)
rvec equ $FFFE ; reset vector
baud equ $102B ; SCI-baudrate
sccr1 equ $102C ; SCI-control1
sccr2 equ $102D ; SCI-control2
scsr equ $102E ; SCI-status
scdr equ $102F ; SCI-data
cr equ $0D
lf equ $0A
bs equ $08
***************************
* data area *
***************************
org data
pflag ds.b 1
***************************
* program area *
***************************
org prog
main lds #stak ; load stackpointer
jsr init
loop bsr prop
jsr delay
bra loop
; Serieller "Propeller"
prop pshx
pshb
ldx #pchar
ldab pflag
abx
ldab 0,x
bsr send
ldab #bs
bsr send
ldab pflag
incb
andb #%00000011
stab pflag
pulb
pulx
rts
pchar dc.b '|/-\\'
; seriell byte senden
; Parameter: Zeichen in Akku B
send psha
send1 ldaa scsr
anda #%10000000 ; $80 (bpl)
beq send1
stab scdr
pula
rts
; seriell init
init clr SCCR1
ldaa #$0C
staa SCCR2
ldaa #$30
staa BAUD
clr pflag
rts
; Warteschleife
delay ldx #30000
dely nop
nop
dex
bne dely
rts
***************************
* vectors *
***************************
org rvec
fdb main ; FE reset
end
; Vereinbarungen
prog equ $8000
data equ $2000
stack equ $7FFF
portb equ $1004
portc equ $1003
portcl equ $1005
pioc equ $1002
ddrc equ $1007
scdr equ $102f
scsr equ $102e
sccr1 equ $102c
sccr2 equ $102d
baud equ $102b
reset equ $fffe
; ASCII-Zeichen
cr equ 13
lf equ 10
org prog
main lds #stack ; Initialisierungen
bsr sini
loop ldx #cmd ; Prompt ausgeben
bsr ssend
bsr recv ; Befehl (1 Zeichen) einlesen
cmpa #'a' ; ist es 'a'?
bne next1 ; nein, weiter
bsr doit ; Kommando 'a' verarbeiten
bra loop
next1 cmpa #'b' ; ist es 'b'?
bne next2 ; nein, weiter
bsr doit ; Kommando 'b' verarbeiten
bra loop
next2 cmpa #'c' ; ist es 'c'?
bne next3 ; nein, weiter
bsr doit ; Kommando 'c' verarbeiten
bra loop
next3 ldx #oops ; falsche Eingabe: "Oops" ausgeben
bsr ssend
bra loop
; Kommandobearbeitungsroutine, hier als Dummy
doit psha ; Kommandobearbeitung, erst Akku A retten
ldx #k1 ; Text "Eingabe war" ausgeben
bsr ssend
pula ; Akku A wiederherstellen
suba #$20 ; Kleinbuchstaben in Grossbuchstaben wandeln
bsr send ; ausgeben
bsr crlf ; "neue Zeile" ausgeben
rts
; Carriage Return und Line Feed ausgeben
crlf ldaa #cr
bsr send
ldaa #lf
bsr send
rts
; String ausgeben (ohne cr/lf am Ende), Stringadresse (erstes Zeichen)
; muss in Register X uebergeben werden (siehe Kapitel 5)
ssend ldaa 0,x
beq sfin
bsr send
inx
bra ssend
sfin rts
; serielle Schnittstelle initialisieren (siehe Kapitel 5)
sini clr sccr1
ldaa #$0C
staa sccr2
ldaa #$30
staa baud
rts
; Zeichen seriell ausgeben (siehe Kapitel 5)
send ldab scsr
bpl send
staa scdr
rts
; Zeichen seriell empfangen (siehe Kapitel 5)
recv ldab scsr
andb #$20
beq recv
ldaa scdr
rts
; String-Konstanten (Strings werden durch ein 0-Byte abgeschlossen)
cmd dc.b 'Kommando: '
dc.b 0
oops dc.b 'Oops!'
dc.b cr,lf,0
k1 dc.b 'Eingabe war '
dc.b 0
org reset ; Reset-Vektor setzen
fdb main
end
prog equ $8000
data equ $2000
stack equ $7FFF
portb equ $1004
portc equ $1003
ddrc equ $1007
reset equ $fffe
tvec equ $FFDE ; interrupt vector of timer
tmsk equ $1024 ; timer mask
tflg equ $1025 ; timer flag
pacr equ $1026 ; pulse accu control
org data
count ds.b 1
cflg ds.b 1
org prog
main lds #stack ; init variables
clr portb
clr count
clr cflg
ldab #$40 ; enable PA7 interrupt
stab pacr ; enable pulse accu
ldab #$80
stab tmsk
cli ; enable interrupts
loop ldaa cflg ; get clock flag
cmpa #20 ; trigger point?
bne loop ; no, wait
clr cflg ; yes, clear clock flag
inc count ; count up
ldaa count
staa portb ; display counter
bra loop
; interrupt service routine
tirq ldaa #$80
staa tflg ; clear interrupt
inc cflg ; count interrupts
rti
org tvec ; set interrupt vector
fdb tirq ; DE timer overflow
org reset ; set reset vector
fdb main
end
data equ $2000 ; data area (e-ram)
stak equ $7FFF ; stack area (e-ram)
prog equ $8000 ; programm area (e-eerom)
pvec equ $FFDA ; vector pa7
tvec equ $FFDE ; vector timer
svec equ $FFF2 ; sirq vector
rvec equ $FFFE ; reset vector
pioc equ $1002 ; parallel i/o control
pbdr equ $1004 ; port b data
portcl equ $1005 ; port c data latch
tmsk equ $1024 ; timer mask
tflg equ $1025 ; timer flag
pacr equ $1026 ; pulse accu control
***************************
* data area *
***************************
org data
flag ds.b 1 ; irq flag
***************************
* program area *
***************************
org prog
main lds #stak ; load stackpointer
bsr init ; data init
cli ; enable irq
loop ldaa flag
staa pbdr ; display
bra loop ; close main loop
***************************
* subroutines *
***************************
init clr flag
ldab #$40 ; enable STRA interrupt
stab pioc
rts
***************************
* interrupt handler *
***************************
sirq ldaa pioc ; stra isr
ldaa portcl ; clear interrupt
com flag
rti
***************************
* vectors *
***************************
org svec
fdb sirq ; STRA
org rvec
fdb main ; FE reset
end
data equ $2000 ; data area (e-ram)
stak equ $7FFF ; stack area (e-ram)
prog equ $8000 ; programm area (e-eerom)
pvec equ $FFDA ; vector pa7
tvec equ $FFDE ; vector timer
svec equ $FFF2 ; sirq vector
rvec equ $FFFE ; reset vector
pioc equ $1002 ; parallel i/o control
pbdr equ $1004 ; port b data
pcdl equ $1005 ; port c data latch
tmsk equ $1024 ; timer mask
tflg equ $1025 ; timer flag
pacr equ $1026 ; pulse accu control
baud equ $102B ; SCI-baudrate
sccr1 equ $102C ; SCI-control1
sccr2 equ $102D ; SCI-control2
scsr equ $102E ; SCI-status
scdr equ $102F ; SCI-data
***************************
* data area *
***************************
org data
flag ds.b 1 ; irq flag
***************************
* program area *
***************************
org prog
main lds #stak ; load stackpointer
bsr init ; data init
cli ; enable irq
loop ldaa flag
staa pbdr ; display
bra loop ; close main loop
***************************
* subroutines *
***************************
init clr flag
ldab #$40 ; enable STRA interrupt
stab pioc
ldab #$40 ; enable PA7 interrupt
stab pacr
ldab #$10
stab tmsk
rts
***************************
* interrupt handler *
***************************
sirq ldaa pioc ; stra isr
ldaa pcdl ; clear interrupt
ldaa flag
eora #$0F ; toggle lower nibble
staa flag
rti
pirq ldaa #$10 ; pa7 isr
staa tflg ; clear interrupt
ldaa flag
eora #$F0 ; toggle upper nibble
staa flag
rti
***************************
* vectors *
***************************
org pvec
fdb pirq ; PA7 interrupt
org svec
fdb sirq ; STRA
org rvec
fdb main ; FE reset
end
data equ $2000 ; data area (e-ram)
stak equ $7FFF ; stack area (e-ram)
prog equ $8000 ; programm area (e-eerom)
pvec equ $FFDA ; vector pa7
tvec equ $FFDE ; vector timer
svec equ $FFF2 ; sirq vector
rvec equ $FFFE ; reset vector
pioc equ $1002 ; parallel i/o control
pbdr equ $1004 ; port b data
pcdl equ $1005 ; port c data latch
tmsk equ $1024 ; timer mask
tflg equ $1025 ; timer flag
pacr equ $1026 ; pulse accu control
***************************
* data area *
***************************
org data
coun ds.b 1 ; counter
cflg ds.b 1 ; clock flag
updn ds.b 1 ; direction flag
stop ds.b 1 ; stop flag
***************************
* program area *
***************************
org prog
main lds #stak ; load stackpointer
bsr init ; data init
cli ; enable irq
loop ldaa cflg ; get clock flag
cmpa #20 ; trigger point?
bne loop ; no, wait
clr cflg ; yes, clear clock flag
tst stop ; stop active?
bne loop ; yes, wait
bsr count ; update counter
bra loop ; close main loop
***************************
* subroutines *
***************************
count ldaa coun ; load counter
adda updn ; inc/dec counter
staa coun ; save counter
staa pbdr ; display counter
rts
init clr coun ; counter default
clr cflg ; no clock seen
clr stop
ldaa #1
staa updn ; default count up
ldab #$40 ; enable STRA interrupt
stab pioc
ldab #$40 ; enable PA7 interrupt
stab pacr ; enable pulse accu
ldab #$90 ; $80 (Timer) + $10 (PA7)
stab tmsk
rts
***************************
* interrupt handler *
***************************
tirq ldaa #$80 ; timer isr
staa tflg ; clear interrupt
inc cflg ; count interrupts
rti
sirq ldaa pioc ; stra isr
ldaa pcdl ; clear interrupt
neg updn ; toggle direction
rti
pirq ldaa #$10 ; pa7 isr
staa tflg ; clear interrupt
com stop ; toggle stop flag
rti
***************************
* vectors *
***************************
org pvec
fdb pirq ; PA7
org tvec
fdb tirq ; timer overflow
org svec
fdb sirq ; STRA
org rvec
fdb main ; FE reset
end
Kochrezeptartig kann man dabei folgenden Aufbau vornehmen:
Im Hauptprogramm wird festgestellt, welcher Zustand aktuell eingenommen wird und dann das zugehörige "Aktions"-Unterprogramm aufgerufen. Im Unterprogramm erfolgen dann nicht nur die Ein- und Ausgaben, sondern es wird abhängig vom aktuellen Zustand und den äußeren Bedingungen (Eingabe von Port C) der Folgezustand eingestellt.
data equ $2000 ; data area (e-ram)
stak equ $7FFF ; stack area (e-ram)
prog equ $8000 ; programm area (e-eerom)
rvec equ $FFFE ; reset vector
pioc equ $1002 ; parallel i/o control
portb equ $1004 ; port b data
portcl equ $1005 ; port c data latch
portc equ $1003 ; port c data reg.
ddrc equ $1007 ; portc data dir. reg.
* Zustaende
oben equ 0
abwaerts equ 1
aufwaerts equ 2
unten equ 3
* Ausgaenge Motor an Port B
Mup equ %00000001 ; Motor RL
Mdown equ %00000010 ; Motor LL
* Taster an Port C
Tup equ %00000001 ; Taste "auf"
Tdown equ %00000010 ; Taste "ab"
Eup equ %00000100 ; Endstellung "oben"
Edown equ %00001000 ; Endstellung "unten"
***************************
* data area *
***************************
org data
state ds.b 1
***************************
* program area *
***************************
org prog
main lds #stak ; init stack
clr ddrc ; Port C Eingang
ldaa portc
anda #Eup ; Tor offen oder zu?
beq m2 ; nicht offen
ldaa #oben
bra m3
m2 ldaa #unten ; nicht offen = zu
m3 staa state
; mainloop = statemachine
loop jsr display ; Anzeige zum Testen
jsr delay
ldaa state ; aktueller Status
cmpa #oben ; Tor offen?
bne abw ; nein, weiter
bsr DoTop ; Aktion und Statuswechsel ausfuehren
bra loop
abw cmpa #abwaerts ; Tor schliesst?
bne aufw ; nein, weiter
bsr DoDown ; Aktion und Statuswechsel ausfuehren
bra loop
aufw cmpa #aufwaerts ; Tor oeffnet?
bne tzu ; nein, weiter
bsr DoUp ; Aktion und Statuswechsel ausfuehren
bra loop
tzu cmpa #unten ; Tor geschlossen?
bne loop ; nein, zu loop (keine Fehlerbehandlung)
bsr DoBottom ; Aktion und Statuswechsel ausfuehren
bra loop
* Aktion und Statuswechsel fuer "oben"
DoTop
ldaa portc ; Schliessen gewuenscht?
anda #Tdown
beq Tope ; nein
ldaa #Mdown ; sonst Motor auf LL
staa portb
ldaa #abwaerts ; Statuswechsel
staa state
Tope rts
* Aktion und Statuswechsel fuer "unten"
DoBottom
ldaa portc ; Oeffnen gewuenscht?
anda #Tup
beq Bote ; nein
ldaa #Mup ; sonst Motor auf RL
staa portb
ldaa #aufwaerts ; Statuswechsel
staa state
Bote rts
* Aktion und Statuswechsel fuer "abwaerts"
DoDown
ldaa portc ; Oeffnen gewuenscht?
anda #Tup
beq Dow1 ; nein
ldaa #Mup ; sonst Motor auf RL
staa portb
ldaa #aufwaerts ; Statuswechsel
staa state
rts
Dow1 ldaa portc ; Endstellung erreicht?
anda #Edown
beq Dow2 ; nein
clr portb ; Motor stopp
ldaa #unten ; Statuswechsel
staa state
Dow2 rts
* Aktion und Statuswechsel fuer "aufwaerts"
DoUp
ldaa portc ; Schliessen gewuenscht?
anda #Tdown
beq Up1 ; nein
ldaa #Mdown ; sonst Motor auf LL
staa portb
ldaa #abwaerts ; Statuswechsel
staa state
rts
Up1 ldaa portc ; Endstellung erreicht?
anda #Eup
beq Up2 ; nein
clr portb ; Motor stopp
ldaa #oben ; Statuswechsel
staa state
Up2 rts
* Zur Kontrolle den Status in den oberen 4 Bits von
* Port B ausgeben
display
ldaa portb
anda #$0F ; alten Wert ausblenden
staa portb ; jetzt nur die Mototbits gesetzt
ldaa state ; state shiften
lsla
lsla
lsla
lsla
oraa portb ; state dazu-odern
staa portb
rts
* Warteschleife, zentraler takt
delay pshx
ldx #$ffff
dely1 nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
dex
bne dely1
pulx
rts
* Reset-Vektor
org rvec
fdb main ; dc.w
end
Zum vorhergehenden Abschnitt |
Zum Inhaltsverzeichnis |
Zum nächsten Abschnitt |