Die Ansteuerung per Software geschieht in 3 Teilschritten:
-
Zunächst wird der auszugebende Wert in eine
Bitfolge überführt, die auf den Ports ausgegeben werden soll. Diese wird für jedes Segment in einem Datenfeld
zwischengespeichert.
;Speicher vergeben
; hier stehen die auszugebenden Ziffern
Z0 EQU 08h
Z1 EQU 09h
Z2 EQU 0Ah
Z3 EQU 0Bh
; Datenfeld, um die Ausgabewerte aufzunehmen
ZD0 EQU 22h
ZD1 EQU 23h
ZD2 EQU 24h
ZD3 EQU 25h
COUNT EQU 26h ; Zähler für das angezeigte Segment
; Startwerte der benutzten Speicherstellen
mov Z0, #3
mov Z1, #2
mov Z2, #1
mov Z3, #0
; die Datenfelder mit den auszugebenden Bitwerten füllen
mov DPTR,#field
mov R0,#Z0
mov R1,#ZD0
load_again:
mov a,@R0
mov c,ACC.7
clr ACC.7
movc a,@a+DPTR
mov ACC.2,c
cpl ACC.2
mov @R1,a
inc R0
inc R1
cjne R1,#ZD3+1,load_again
ajmp weiter
; Datenfeld, das die Bitmuster für die auszugebenden
; Symbole enthält
field:
db 00010100b ; 0
db 10110111b ; 1
db 00101100b ; 2
db 00100101b ; 3
db 10000111b ; 4
db 01000101b ; 5
db 01000100b ; 6
db 00110111b ; 7
db 00000100b ; 8
db 00000101b ; 9
db 11111111b ; leeres Feld, 10
weiter:
- Dann wird Timer 1 so initialisiert, daß er mit einer Frequenz von 1 kHz
einen Interrupt generiert. Die Frequenz ist so gewählt, daß das Hauptprogramm nicht allzusehr
gestört wird, aber die Anzeige auch nicht flimmert.
; Stackadresse weit weg vom benutzten Bereich setzten
mov sp, #60h
; Timer1 initialisieren, 1ms -> preload 0F82Fh
mov TL1, #02Fh
mov TH1, #0F8h
; Einstellungen zum Einschalten des Timers
mov TMOD,#010h
mov TCON,#040h
mov PCON,#0
; Interrupts einschalten
mov IE, #088h
- Drittens wechselt der Controller bei jedem Interrupt das Segment, holt den
mit dem Segment kongruierenden Binärwert aus dem Datenfeld und gibt diesen aus. Dies geschieht vollständig
transparent für das Hauptprogramm.
; Adresse für die Interruptserviceroutine von Timer1
org 01Bh
; alle veränderten Register retten
push PSW ; die Flags, z.B. Carry
push ACC ; das A-Register
push 0 ; das R0-Register
; Timer wieder laden
mov TL1, #02Fh
mov TH1, #0F8h
; den Wert in ACC laden, der ausgegeben werden soll
; Ausgabewert = Inhalt{ [COUNTER & 3] + Offset(ZD0) }
mov a,COUNT
cpl a
anl a,#00000011b
mov R0,a
mov a,#ZD0
add a,R0
mov R0,a
mov a,@R0
; Die Adresse des Segments ausgeben
mov c,COUNT.0
mov P3.5,c
mov c,COUNT.1
mov P3.7,c
; Die Daten für das Segment ausgeben
mov P1,a
; Zähler weitersetzen
inc COUNT
; Register restaurieren
pop 0
pop ACC
pop PSW
; Interruptserviceroutine beenden
reti
Das vollständige Beispiel findet sich wie immer auf meiner Download-Page.
zurück zum Anfang
|