;Programm zum ermitteln der Geschwindigkeit in Km/h
;durch Zeitmessung zwischen 2 Kontakten/Lichtschranken
;
;Ausschliesslich zur privaten, nichtkommerziellen Verwendung
;Copyright Klaus Leidinger 
;(bis auf die verwendeten Mathematikroutinen)  
;
;Homepage: http://www.mikrocontroller-projekte.de
;Fehlermeldungen bitte an klaus@mikrocontroller-projekte.de
;
;Verwendete Hardware:
;Eigenes Board mit 89C2051 Prozessor
;Testsystem 80535 Board mit Paulmon2 als 89c2051 Simulator
;
;Die Zeitroutinen sind für 24Mhz Taktfrequenz ausgelegt
;
;Verwendete Software:
;Compiler RAD51 http://www.systronix.com
;Mathematikroutinen der Loughborough University
;http://www.8052.com/ Rubrik Code Library 
;
;Funktion: Gemessen wird die Zeit zwischen dem Auslösen der Interrupts
; /INT0 und /INT1 wobei die Auslösereihenfolge keine Rolle spielt.
; Die Speicherstellen "MesswegH und MesswegL" enthalten die Länge der Messtrecke
; in mm*36
; Die Zählergeschwindigkeit entspricht 100yS. 
; 
; Wird die maximale 
; Messzeit (6,5535 S) überschritten, erfolgt eine Fehlermeldung.
; Angezeigt werden können Geschwindigkeiten bis 254 km/h.     
;                                         
; Nach erfolgter Messung wird das Gerät für ca. 1 S gesperrt, was durch die LED
; angezeigt wird. Dies dient dem sicheren Ablesen des Messwertes.
; Ist die aktuell gemessene Geschwindigkeit die Maximalgeschwindigkeit
; seit dem einschalten des Gerätes, wird ein Piepton ausgegeben.
;
;Erstellt: Oktober 2001, Klaus Leidinger
;
;Letzte Änderung:  
; 05.10.01 Version 1.0, erster upload

;------------------------------------------------------------------------------

    incl "MOD51.H"  ;default definitionen

; Hier den gemessenen Abstand zwischen den Signalgebern in mm eintragen
Messweg		equ 500 ;Messweg in mm      

DISPwait	equ 02FH;experimenteller Wert für die Mindestleuchtdauer der 7Segmente
T0reload	equ 200	;Abhänig vom Quarz. Wert für 100µS Interruptroutine
                    ;bei Quarz 24 Mhz: 200*0,5µS=100µS
                    ;Die Taktfrequenz im 8051 wird intern durch 12 geteilt.  
T1reload	equ 200	;Verzögerung nach Messung um Anzeige sicher abzulesen
					;und ev. Störungen des 2. auslösenden Interrupts
					;entgegenzuwirken. Wert für 100µS Interruptroutine  
DispDelayVal equ 39 ;Verzögerungswert für Interruptroutine Timer1 ergibt 1S
                                                                 
Soundlength equ 010H;Länge des Pieptones, je nach Geschmack einstellen
Soundfreq   equ 080H;Frequenz des Pieptones, experimenteller Wert je nach
				    ;verwendetem Piepser
                
	org 050H		;interne RAM Adressen
hunderter   ds  1   ;Speicherstelle für wert der hunderter Anzeige
zehner      ds  1   ;Speicherstelle für wert der zehner Anzeige
einer       ds  1   ;Speicherstelle für wert der einer Anzeige

HighscoreH	ds	1	;Speicherstelle für Highscore Hunderterstelle
HighscoreZ	ds	1	;Speicherstelle für Highscore Zehnerstelle
HighscoreE	ds	1	;Speicherstelle für Highscore Einerstelle

divisorH	ds	1   ;Speicherstelle zur Datenrettung
divisorL	ds	1  

MessMulH	ds 1	;Speicherstelle für Ergebnis Messweg*36; High Byte
MessMulL	ds 1	;Speicherstelle für Ergebnis Messweg*36, Low Byte

Messung		ds 1	;inhalt=0 wenn keine Messung läuft, 1 während Messung
Sounddauer  ds 1    ;Länge des Pieptones, default geladen mit #Soundlength
Soundcnt1   ds 1    ;Frequenz des Tones, default geladen mit #Soundfreq
Soundcnt2   ds 1    ;Frequenz des Tones, default geladen mit #Soundfreq

;die Angegebenen Pins gelten für Platine Version 1.0    
H_Sig       bit P3_0 ;Aktivierung hunderter Segment (Seg2)
Z_Sig       bit P3_7 ;Aktivierung zehner Segment (Seg1)
E_Sig       bit P3_5 ;Aktivierung einer Segment (Seg0)
LEDPort		equ P1	 ;Port mit angeschlossenen 7 Segemnt Anzeigen
Wait_Sig    bit P3_1 ;LED "Wait" während Signalsperre (low active)
Summer      bit P3_4 ;Summer für "Highscore" (low active)
    
; Start des Programmcodes

        org 0000H      ;Programmstart
        ljmp STARTPROG
        org 0003H      ;Interrupt 0
        ljmp INT0_int   ;Sprungziel fuer Interrupt 0
        org 000BH      ;Interrupt Timer0
        ljmp Timer0_int ;Sprungziel für Timer0 Interrupt
        org 0013H
        ljmp INT1_int   ;Sprungziel für Interrupt 1
        org 001BH      ;Interrupt Timer1
        ljmp Timer1_int

  ;      org 0033H      ;Ende der Interrupttabelle
  ;Zum indendifizieren der Software bei gebranntem Chip
   db "Geschwindigkeitsmesser Version 1.0  vom 05.10.2001 Klaus Leidinger"
   db " Internet Download"


STARTPROG               ;Start des eigentlichen Programms
        mov  SP,#070H   ;Stack setzen
		setb Wait_Sig	;LED aus
		setb Summer     ;Summer aus
        setb H_Sig		;Alle Anzeigen ausschalten
        setb Z_Sig
        setb E_Sig
        ;umrechnen des Messweges
 		mov R3,#(Messweg/256)   	;High Byte
 		mov R2,#(Messweg and 0FFH);Low Byte         
        mov R0,#36		;Messweg in mm *36
        lcall MUL816    ;Ergebnis kommt nach R1,R0              
 		mov MessMulH,R1 ;Abspeichern für spätere Berechnung
 		mov MessMulL,R0
		mov hunderter,#0	;"0" initialisieren der Anzeige
		mov zehner,#010H	;"0."
		mov einer,#0		;"0"
		mov HighscoreH,#0	;Highscore löschen
		mov HighscoreZ,#010H;Highscore löschen
		mov HighscoreE,#0	;Highscore löschen
		mov Messung,#0		;Flag zurücksetzen
        mov R3,#0			;löschen Zählregister
        mov R2,#0		

        mov  TMOD,#00100010B  ;Timer 0 Gate aus, Mode 2 (8Bit reload)
          					  ;Timer 1 Gate aus, Mode 2 (8Bit reload)
		mov TH0,#256-T0reload ;Reloadwert für T0
		mov TL0,TH0			  ;preload
        clr  PT0              ;Timer0 Prio low
        clr  TR0              ;Timer0 stop
        clr  ET0              ;Timer0 Interrupt abschalten
		mov TH1,#256-T1reload ;Reloadwert für T1
		mov TL1,TH1			  ;preload
        clr  PT1              ;Timer0 Prio low
        clr  TR1              ;Timer0 stop
        clr  ET1              ;Timer1 Interrupt abschalten
        setb IT0              ;Interrupt fallende Flanke an /INT0
        setb IT1              ;Interrupt fallende Flanke an /INT1
        setb EX0              ;erlaube externen Interrupt 0
        setb EX1              ;erlaube externen Interrupt 1

		clr IE0			;INT0 Interrupt Speicher Bit reset
		clr IE1			;INT1 Interrupt Speicher Bit reset

        setb EA         ;Freigabe aller Interrupts
	    	    
		mov DPTR,#LED7HEXvalTAB        ;DPTR laden mit 7 Segment Tabelle
endloop	;Falls keine Interrups auftreten, wird nur das Display bedient
          mov A,hunderter              ;Wert der Hunderter Speicherstelle
          movc A,@A+DPTR               ;A= DPTR+hunderter
          setb E_Sig                   ;Segment für Einer abschalten
          mov LEDPort,A                ;A auf den 7 Segment Port legen
          clr H_Sig                    ;und das hunderter Segment einschalten
          acall LED7SegDisploop        ;ein bischen warten...
          mov A,zehner                 ;und das gleiche für die anderen 7Segmentanzeigen
          movc A,@A+DPTR
          setb H_Sig
          mov LEDPort,A
          clr Z_Sig
          acall LED7SegDisploop
          mov A,einer
          movc A,@A+DPTR
          setb Z_Sig
          mov LEDPort,A
          clr E_Sig
          acall LED7SegDisploop
          ajmp endloop              ;Und das wars schon mit dem Hauptprogramm


LED7SegDisploop mov R6,#DISPwait	;sorgt für eine mindest Leuchtdauer der Segmente
          djnz R6,$                 ;R6 wird zwar bei den Matheroutinen 
          ret                       ;benutzt, was sich aber hier nicht
          							;bemerkbar macht
        
                          
                            
INT0_int				;Messung Beginn oder Ende 
        clr EX0			;Interrupt 0 Abschalten
		push ACC        
		mov A,Messung    
		cjne A,#0,Ergebnis  ;Wenn "Messung" != 0 dann auswerten
        ajmp MessungStart   ;Gemeinsamer Programmteil beider Interruptroutinen

INT1_int                ;Messung Beginn oder Ende
        clr EX1			;Interrupt 1 Abschalten
		push ACC        ;Achtung! es gibt mehrere Ausgänge aus der Routine
		mov A,Messung
		cjne A,#0,Ergebnis	;Wenn "Messung" != 0 dann auswerten
MessungStart            ;gleicher Programmteil für /INT0 und /INT1
        mov R3,#0 		;initialisieren Zählregister für Timer0 Interrupts
        mov R2,#0		
		setb TR0		;Zähler starten
        setb ET0        ;Timer0 Interrupt einschalten
	    mov Messung,#1	;Flag für Messung setzen
        mov hunderter,#02EH	;"-"
        mov zehner,#02EH	;"-"
        mov einer,#02EH		;"-"
        pop ACC 
		reti			;Für /INT0 und /INT1

Ergebnis				;Berechnung der Geschwindigkeit	
        clr TR0			;Timer anhalten
        clr ET0         ;Timer0 Interrupt ausschalten
		mov divisorH,R3	;sichern der Messwerte der Zeitmessung
		mov divisorL,R2      
 		mov R1,MessMulH
 		mov R0,MessMulL    
 		push DPL        ;der DPTR wird bei den Matheroutinen benutzt
 		push DPH
        acall UDIV16    ;Messweg(mm)*36/Zählerstand(*100µS)  
        pop DPH         ;und wieder zurücksichern
        pop DPL
		mov A,R0
        ;prüfen auf minimaltempo
        jz toslow                                  
        cjne A,#0FFH,SpeedOK  
        ajmp tofast           ;Messung ergab mehr als 254 Km/h
SpeedOK        
		acall b2bcd
		mov A,hunderter
        jnz Highscoretest    ;END_Ergebnis falls kein Highscoretest gewünscht
        mov hunderter,zehner ;Falls Geschwindigkeit <100Km/h, die zehntel
        mov A,einer          ;anzeigen
        add A,#010H		     ;einschalten dezimalpunkt
        mov zehner,A         ;Alle Stellen rücken eins nach links
        mov R0,#10		     ;Rest*10
 		push DPL             ;DPTR wieder retten wg. Matheroutinen
 		push DPH
        lcall MUL816         ;Ergebnis kommt bereits nach R1,R0              
        mov R3,divisorH      ;Die Messwerte holen
        mov R2,divisorL
        acall UDIV16         ;(Rest*10)/Messwert
        pop DPH              ;und wieder zurücksichern
        pop DPL
        mov einer,R0
		ajmp Highscoretest
		;jmp END_Ergebnis	 ;wer keinen test auf Highscore machen möchte...
toslow						 ;Messung hat weniger als 1Km/h ergeben
        mov hunderter,#5	 ;Text "SLo" laden    
        mov zehner,#026H
        mov einer,#028H
        ajmp END_Ergebnis
tofast						 ;Messung hat mehr als 254 Km/h ergeben
        mov hunderter,#0FH	 ;Text "FAS" , für engl. fast laden    
        mov zehner,#0AH
        mov einer,#5
END_Ergebnis
        mov Messung,#0		 ;löschen des Flag
		clr Wait_Sig		 ;LED "Wait" ansteuern
        mov R3,#DispDelayVal ;setzten Zählregister für Timer1 Interrupts (1S)
        mov R2,#0		
		setb IT1			
		setb TR1			 ;Zähler für Ablesezeit starten
        setb ET1    	     ;Timer1 Interrupt einschalten
		pop ACC				 ;wurde bei Start der Interruptroutinen gesichert
        reti

;Highscore test Vergleicht den aktuellen Geschwindigkeitswert mit Highscore
Highscoretest
        mov A,HighscoreZ     ;Prüfen ob Dezimalstelle
        clr C
        subb A,#010H		 ;prüfe ob Zehnerstelle=Kommastelle
        jc Highscore_hunderter ;bei CY=1, keine Kommastelle km/H >99.9
		mov A,zehner         ;prüfe ob aktuelle Geschwindigkeit >99.9
		clr C
		subb A,#010H
		jc NewHighscore      ;Bei CY=1 ist die akt. Geschwindigkeit >99.9, also Highscore
		ajmp Highscore_comp  ;falls < 100, vergleiche alle Stellen      

Highscore_hunderter          ;Highscore ist > 99.9, prüfe ob akt. Geschw. ebenfalls
		mov A,zehner
		clr C
		subb A,#010H
		jc Highscore_comp    ;bei CY=1 ist akt. Geschw. >99.9, also vergleichen
		ajmp NoHighscore     ;falls nicht, sind wir jetzt langsamer
		
Highscore_comp               ;hier werden alle Dezimalstellen verglichen
	    mov A,hunderter
	    clr C
	    subb A,HighscoreH
	    jc NoHighscore       ;bei CY=1 war highscore grösser
        jnz NewHighscore     ;bei != Zero war der akt. Wert grösser
	    mov A,zehner         ;nächste Dezimalstelle vergleichen
	    clr C
	    subb A,HighscoreZ
	    jc NoHighscore
        jnz NewHighscore
	    mov A,einer          ;und die letzte Stelle
	    clr C
	    subb A,HighscoreE
	    jc NoHighscore
	    jz NoHighscore
NewHighscore
        mov HighscoreH,hunderter   ;neuen highscore abspeichern
        mov HighscoreZ,zehner
        mov HighscoreE,einer
        setb H_Sig                 ;Display abschalten
        setb Z_Sig
        setb E_Sig
        acall piep	               ;Feier!
NoHighscore
        ajmp END_Ergebnis          ;und wieder weiter im Programm
;Ende Highscoretest


Timer1_int  ;Interrupt erfolgt alle 100yS. Zum sicheren Ablesen des Messwertes
        djnz R2,T1_int_end   ;R2 ist #0
        djnz R3,T1_int_end   ;R3 wurde mit DispDelayVal geladen
        clr TR1	  			 ;Timer1 anhalten
        clr ET1         	 ;Timer1 Interrupt ausschalten
		clr IE0				 ;Interrupt Speicher Bit reset
		clr IE1				 ;Interrupt Speicher Bit reset
        setb EX0        	 ;Interrupts wieder einschalten
        setb EX1
		setb Wait_Sig		 ;LED "Wait" wieder ausschalten    
T1_int_end
		reti
		
Timer0_int  ;Zeitmessung. Interrupt erfolgt alle 100yS
        inc R2               ;R2 wurde bei Start der Messung auf 0 gesetzt
        cjne R2,#0,T0_int_end
        inc R3               ;R3 wurde bei Start der Messung auf 0 gesetzt
        cjne R3,#0,T0_int_end
        ;Messung Überlauf
        mov hunderter,#0EH	;Text "Err" laden    
        mov zehner,#02AH
        mov einer,#02AH
        mov Messung,#0
        clr TR0			;Timer anhalten
        clr ET0         ;Timer0 Interrupt ausschalten
		clr IE0			;Interrupt Speicher Bit reset
		clr IE1			;Interrupt Speicher Bit reset
        setb EX0        ;Interrupts wieder einschalten
        setb EX1
T0_int_end
		reti


b2bcd	;wandelt ACC in dezimal (Speicherstellen hunderter, zehner, einer)
		push	b		; Register B sichern
		mov	b,#100		
		div	ab			; dividieren durch 100  
		mov	hunderter,A	; Hunderter abspeichern
		mov A,B         ; Rest in Akku
		mov	b,#10		; und jetzt die 10er
		div	ab			; dividieren durch 10
		mov zehner,A	; ...und wieder abspeichern           
		mov einer,B		; der Rest sind die einer
		pop	b			; und den Stack wieder einrichten
        ret

piep            
          mov Sounddauer,#Soundlength
          mov Soundcnt1,#Soundfreq
          mov Soundcnt2,#Soundfreq
Sstart    mov Sounddauer,#Soundlength
Ssig1     mov Soundcnt1,#Soundfreq
Ssig2     mov Soundcnt2,#Soundfreq
          djnz Soundcnt2,$
          cpl Summer              ;Pin INT1 umschalten
          djnz Soundcnt1,Ssig2
          djnz Sounddauer,Ssig1
          ret


;Die Mathematikroutinen sind entnommen aus dem File "math.lib"
;Downloadpfad: http://www.8052.com/ Rubrik Code Library

;*****************************************************************
;*                                                               *
;*                Some Useful Maths Subroutines                  *
;*             for the 8x51 Microcontroller series               *
;*                   Loughborough University                     *
;*        Department of Electronic & Electrical Engineering      *
;*                       Vsn 3.0 WGM 2000                        *
;*                                                               *
;*****************************************************************

; All parameters in Register bank 0, (r0 to r7)
; Bits 21H and 22H reserved

;=================================================================
; subroutine Cr0
; 8-Bit 2's Complement -> magnitude / Sign Bit Conversion
;
; input:     r0 = signed byte
;
; output:    r0 = magnitude
;            Bit 21H = sign (21H is set if r0 is a negative number)
;
; alters:    acc
;=================================================================

Cr0:           mov     a, r0           ; read X into accumulator
               jb      acc.7, Cr0a     ; X is negative if bit 7 is 1
               clr     21H             ; clear sign bit if 'positive'
               ret                     ; done

Cr0a:          cpl     a               ; X negative, find abs value
               inc     a               ; XA = complement(XT)+1
               mov     r0, a           ; save magnitude
               setb    21H             ; set sign bit if 'negative'
               ret

;====================================================================
; subroutine Cr2r3
; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion
;
; input:    r3, r2 = signed word
;
; output:   r3, r2 = magnitude
;           Bit 22H = sign (22H is set if negative number)
;
; alters:   acc, C
;====================================================================

Cr2r3:         mov     a, r3           ; read high into accumulator
               jb      acc.7, c1a      ; negative if bit 7 is 1
               clr     22H             ; clear sign bit if 'positive'
               ret                     ; done

c1a:           setb    22H             ; set sign flag
               mov     a, r2           ; number is negative
               cpl     a               ; complement
               add     a, #1           ; and add +1
               mov     r2, a 
               mov     a, r3           ; get next byte
               cpl     a               ; complement
               addc    a, #0
               mov     r3, a
               ret

;====================================================================
; subroutine Mr0r3
; 32-Bit magnitude / Sign Bit -> 2's Complement Conversion
;
; input:    r3, r2, r1, r0 = magnitude
;           Bits 21H & 22H = sign bits of operands X and Y
;           (set if negative)
;
; output:   r3, r2, r1, r0 = signed word
;
; alters:   acc, C
;====================================================================

Mr0r3:         jb      21H, Mr0r3b     ; test X sign
               jb      22H, Mr0r3a     ; test Y sign
               ret

Mr0r3b:        jnb     22H, Mr0r3a
               ret

Mr0r3a:        mov     a, r0           ; negate number
               cpl     a               ; complement
               add     a, #1           ; and add +1
               mov     r0, a 
               mov     a, r1           ; get next byte
               cpl     a               ; complement
               addc    a, #0
               mov     r1, a
               mov     a, r2           ; get next byte
               cpl     a               ; complement
               addc    a, #0
               mov     r2, a
               mov     a, r3           ; get next byte
               cpl     a               ; complement
               addc    a, #0
               mov     r3, a
               ret                     ; done

 
;====================================================================
; subroutine MUL816
; 8-Bit x 16-Bit to 32-Bit Product signed Multiply
; 2's Complement format
;
; input:    r0 = multiplicand X
;           r3, r2 = multiplier Y
;
; output:   r3, r2, r1, r0 = product P = X x Y (r3 = sign extension)
;
; calls:    Cr0, Cr2r3, Mr0r3
;
; alters:   acc, C, Bits 21H & 22H
;====================================================================

MUL816:        push    b
               anl     PSW, #0E7H      ; Register Bank 0
               acall   Cr0             ; 2's comp -> Mag/Sign
               acall   Cr2r3           ; 2's comp -> Mag/Sign
               mov     a, r0           ; load X low byte into acc
               mov     b, r2           ; load Y low byte into B
               mul     ab              ; multiply
               push    acc             ; stack result low byte
               push    b               ; stack result high byte
               mov     a, r0           ; load X into acc again
               mov     b, r3           ; load Y high byte into B
               mul     ab              ; multiply
               pop     00H             ; recall X*YL high byte
               add     a, r0           ; add X*YL high and X*YH low
               mov     r1, a           ; save result
               clr     a               ; clear accumulator
               addc    a, b            ; a = b + carry flag
               mov     r2, a           ; save result
               pop     00H             ; get low result
               mov     r3, #0
               acall   Mr0r3           ; Mag/Sign -> 2's Comp
               pop     b
               ret

;====================================================================
; subroutine UDIV16
; 16-Bit / 16-Bit to 16-Bit Quotient & Remainder Unsigned Divide
;
; input:    r1, r0 = Dividend X
;           r3, r2 = Divisor Y
;
; output:   r1, r0 = quotient Q of division Q = X / Y
;           r3, r2 = remainder 
;
; alters:   acc, B, dpl, dph, r4, r5, r6, r7, flags
;====================================================================

UDIV16:        mov     r7, #0          ; clear partial remainder
               mov     r6, #0
               mov     B, #16          ; set loop count

div_loop:      clr     C               ; clear carry flag
               mov     a, r0           ; shift the highest bit of
               rlc     a               ; the dividend into...
               mov     r0, a
               mov     a, r1
               rlc     a
               mov     r1, a
               mov     a, r6           ; ... the lowest bit of the
               rlc     a               ; partial remainder
               mov     r6, a
               mov     a, r7
               rlc     a
               mov     r7, a
               mov     a, r6           ; trial subtract divisor
               clr     C               ; from partial remainder
               subb    a, r2
               mov     dpl, a
               mov     a, r7
               subb    a, r3
               mov     dph, a
               cpl     C               ; complement external borrow
               jnc     div_1           ; update partial remainder if
                                       ; borrow
               mov     r7, dph         ; update partial remainder
               mov     r6, dpl
div_1:         mov     a, r4           ; shift result bit into partial
               rlc     a               ; quotient
               mov     r4, a
               mov     a, r5
               rlc     a
               mov     r5, a
               djnz    B, div_loop
               mov     a, r5           ; put quotient in r0, and r1
               mov     r1, a
               mov     a, r4
               mov     r0, a
               mov     a, r7           ; get remainder, saved before the
               mov     r3, a           ; last subtraction
               mov     a, r6
               mov     r2, a
               ret



;  org ( $ + 0FFH) and 0FF00H    ;Startet mit der Tabelle auf einer geraden
                                ;Segmentadresse (z.B. 0F00H)
                                ;dies dient nur der übersicht

LED7HEXvalTAB ;Die Werte sind abhängig vom Anschluss der 7 Segmentanzeige 
			  ;für die Platine Version 1.0 gelten folgende Werte
          ;P1_0=g       a
          ;P1_1=c      -----
          ;P1_2=d    f|     |b
          ;P1_3=a     |  g  |
          ;P1_4=f      -----
          ;P1_5=b    e|     |c
          ;P1_6=e     |  d  |
          ;P1_7=dp     ----- . dp
          ;dpebfadcg
          ;------------------------------------------
         db 10000001B    ; 7 segment Steuerung für 0
         db 11011101B    ; 7 segment Steuerung für 1
         db 10010010B    ; 7 segment Steuerung für 2
         db 11010000B    ; 7 segment Steuerung für 3
         db 11001100B    ; 7 segment Steuerung für 4
         db 11100000B    ; 7 segment Steuerung für 5
         db 10100000B    ; 7 segment Steuerung für 6
         db 11010101B    ; 7 segment Steuerung für 7
         db 10000000B    ; 7 segment Steuerung für 8
         db 11000000B    ; 7 segment Steuerung für 9
         db 10000100B    ; 7 segment Steuerung für A
         db 10100100B    ; 7 segment Steuerung für b
         db 10100011B    ; 7 segment Steuerung für C
         db 10011000B    ; 7 segment Steuerung für d
         db 10100010B    ; 7 segment Steuerung für E
         db 10100110B    ; 7 segment Steuerung für F
; Adresse 10H für Anzeige mit Dezimalpunkt
         db 00000001B    ; 7 segment Steuerung für 0.
         db 01011101B    ; 7 segment Steuerung für 1.
         db 00010010B    ; 7 segment Steuerung für 2.
         db 01010000B    ; 7 segment Steuerung für 3.
         db 01001100B    ; 7 segment Steuerung für 4.
         db 01100000B    ; 7 segment Steuerung für 5.
         db 00100000B    ; 7 segment Steuerung für 6.
         db 01010101B    ; 7 segment Steuerung für 7.
         db 00000000B    ; 7 segment Steuerung für 8.
         db 01000000B    ; 7 segment Steuerung für 9.
         db 00000100B    ; 7 segment Steuerung für A.
         db 00100100B    ; 7 segment Steuerung für b.
         db 00100011B    ; 7 segment Steuerung für C.
         db 00011000B    ; 7 segment Steuerung für d.
         db 00100010B    ; 7 segment Steuerung für E.
         db 00100110B    ; 7 segment Steuerung für F.
;Adresse 20H für Sonderzeichen
          ;dpebfadcg
         db 11111111B    ; 7 segment Steuerung für " "= 020H (Blank)
         db 10111010B    ; 7 segment Steuerung für c  = 021H
         db 10001100B    ; 7 segment Steuerung für H  = 022H
         db 10101100B    ; 7 segment Steuerung für h  = 023H
         db 11111111B    ; 7 segment Steuerung für i  = 024H
         db 11011001B    ; 7 segment Steuerung für J  = 025H
         db 10101011B    ; 7 segment Steuerung für L  = 026H
         db 10101110B    ; 7 segment Steuerung für n  = 027H 
         db 10111000B    ; 7 segment Steuerung für o  = 028H
         db 10000110B    ; 7 segment Steuerung für P  = 029H
         db 10111110B    ; 7 segment Steuerung für r  = 02AH
         db 10001001B    ; 7 segment Steuerung für U  = 02BH
         db 10111001B    ; 7 segment Steuerung für u  = 02CH
         db 11111110B    ; 7 segment Steuerung für -  = 02DH
         db 11111011B    ; 7 segment Steuerung für _  = 02EH
         db 01111111B    ; 7 segment Steuerung für .  = 02FH
          
;Ende des Programmes
