Blink: Verschachteltes Wait
Um die Leuchtdioden der Digitalausgänge blinken zu lassen, werden nach einander zwei unterschiedliche Bytes an DOUT gesendet. Zwischen den Ausgaben muss eine Verzögerung stattfinden, damit das menschliche Auge dieses Blinken auch wahrnehmen kann. Im diesem Beispiel wird 01010101b und 1111111b in kurzen Intervallen angezeigt.
Die Verzögerung wird mit einer verschachtelten Zählschleife realisiert. Hierfür werden die beiden Register R7 und R6 mit dem Maximalwert 255 geladen. Die Schleifen benutzen den kurzen Befehl DJNZ (Decrement Jump No Zero). Dieser Zwei-Byte-Befehl subtrahiert jeweils eine 1 im angegebenen Register und fragt anschließend das Ergebnis ab. Enthält das Register 0, wird der kurze Rückwärtssprung zum entsprechenden Label ausgeführt. Die verschachtelte Schleife ist so konfiguriert, dass 255x255 subtrahiert wird. Diese Zeit reicht, um den Programmfluss so zu verzögern, dass das Blinken wahrgenommen werden kann.
0001 0000 DOUT .equ 0E8H ;DOUT
0002 0000
0003 8100 .org 8100H
0004 8100 74 55 start mov a,#85 ;Byte 1
0005 8102 F5 E8 mov DOUT,a ;Ausgabe
0006 8104 7F FF warte mov R7,#255 ;Warten
0007 8106 7E FF l1 mov R6,#255
0008 8108 DE FE l2 djnz R6,l2
0009 810A DF FA djnz R7,l1
0010 810C 74 00 mov a,#0 ;Byte 2
0011 810E F5 E8 mov DOUT,a ;Ausgabe
0012 8110 7F FF warte2 mov R7,#255 ;Warten
0013 8112 7E FF l11 mov R6,#255
0014 8114 DE FE l22 djnz R6,l22
0015 8116 DF FA djnz R7,l11
0016 8118 80 E6 sjmp start ;Zum Anfang
0017 811A .end
tasm: Number of errors = 0
|
Unterprogramme mit CALL
Wiederkehrende Programmteile werden in jeder Programmiersprache als Unterprogramme formuliert. In Assembler wird ein Unterprogramm mit einem CALL aufgerufen. Der Controller legt zunächst die Adresse des nächsten Befehl auf einen internen Stapel (STACK) und springt danach zu der im CALL-Befehl angegebenen Adresse. Das Unterprogramm wird mit einem RET (Return) beendet. Bei diesem Befehl wird die alte Adresse wieder vom Stapel geholt und das Programm wird an dieser Stelle fortgesetzt. In diesem Beispiel wird der LCALL-Befehl benutz, um die Adresse deutlich zu erkennen. Es gibt einen ACALL-Befehl, der ein Byte weniger braucht, aber schwieriger zu berechnen ist. TASM übernimmt dies allerdings. Das Programm ist im Ergebnis gleich dem vorigen Beispiel Blink.
0001 0000 DOUT .equ 0E8H ;DOUT
0002 0000
0003 8100 .org 8100H
0004 8100 74 55 start mov a,#85 ;Byte 1
0005 8102 F5 E8 mov DOUT,a ;Ausgabe
0006 8104 12 81 11 lcall warte ;Warten
0007 8107 74 00 mov a,#0 ;Byte 2
0008 8109 F5 E8 mov DOUT,a ;Ausgabe
0009 810B 12 81 11 lcall warte ;Warten
0010 810E 02 81 00 ljmp start ;Zum Anfang
0011 8111
0012 8111 7F FF warte mov R7,#255 ;Unterprogramm
0013 8113 7E FF l1 mov R6,#255 ;Verzögerung
0014 8115 DE FE l2 djnz R6,l2 ;mit einer
0015 8117 DF FA djnz R7,l1 ;Doppelschleife
0016 8119 22 ret ;RETURN
0017 811A .end
tasm: Number of errors = 0 |
Durch den Einsatz anderer Befehle kann das Programm noch gekürzt werden. Aus 26 Bytes werden nur noch 21, wenn ohne Akku gearbeitet wird. Weitere Einsparungen erfolgen durch den Einsatz von SJMP und ACALL.
0001 0000 DOUT .equ 0E8H ;DOUT
0002 0000
0003 8100 .org 8100H
0004 8100 75 E8 55 start mov DOUT,#85 ;Byte 1
0005 8103 31 0C acall warte ;Warten
0006 8105 75 E8 00 mov DOUT,#0 ;Byte 2
0007 8108 31 0C acall warte ;Warten
0008 810A 80 F4 sjmp start ;Zum Anfang
0009 810C
0010 810C 7F FF warte mov R7,#255 ;Unterprogramm
0011 810E 7E FF l1 mov R6,#255 ;Verzögerung
0012 8110 DE FE l2 djnz R6,l2 ;mit einer
0013 8112 DF FA djnz R7,l1 ;Doppelschleife
0014 8114 22 ret ;RETURN
0015 8115 .end
tasm: Number of errors = 0 |
|