7 Segment-Anzeige

Hardware   Software  
Der Einsatz eines LCD-Displays mit seinem eigenem Controller ist einfach zu realisieren und ergibt eine repräsentative Darstellungsmöglichkeit. Doch leider sind LCD-Anzeigen für die meisten Ausgabeaufgaben zu teuer und vom Funktionsumfang her geradezu überqualifiziert. Diese Seite will eine einfach zu realisierende Ansteuerung von mehreren 7 Segment-Anzeigen demonstrieren.

Einleitung

ein Segment 7 Segment-Anzeigen gibt es in verschiedenen Ausführungen, die sich teilweise in ihrer Ansteuerung gravierend unterscheiden. Die gebräuchlichste Ansteuerungsart ist jedoch über eine gemeinsame Anode (+) und für jede LED eine separate Kathode (-). Die Pinbelegung der verschiedenen Anzeigen sind jedoch nicht genormt, so daß mein Beispiel-Layout nicht unverändert übernommen werden kann, ebensowenig wie der Code zur Ansgabe diverser Zahlen und Symbole. Um diese Anpassung zu erleichtern geschieht die Ansteuerung über ein Datenfeld im Flash, in dem sich für jedes Zeichen eine Bitfolge befindet, die dieses Zeichen für das jeweilige Platinenlayout repräsentiert.
zurück zum Anfang

Hardware

Die Ansteuerung selbst geschieht prinzipiell über 2 Verfahren: zum einen kann ein Latch (ein IC mit Flip/Flops) für jedes Segment eingesetzt werden, das vom Controller aus programmiert wird. Der Vorteil dieser Methode ist eine hell leuchtende Anzeige, die nach einmaliger Programmierung durch den Controller keiner weiteren Aufmerksamkeit bedarf, bis sich der angezeigte Wert ändert. Nachteilig ist ein hoher Bauteil- und Schaltungsaufwand. Die zweite Methode benutzt das Time Multiplexing-Verfahren, wobei jedes Sergment nur für einen Sekundenbruchteil mit höchster Intensität aufleuchtet, während alle anderen Segmente dunkel sind. Aufgrund der Trägkeit des Auges geschieht dies vollständig unbemerkt. Der Vorteil dieser Methode ist ein unübertroffen geringer Bauteil- und Layoutaufwand. Zum Nachteil gereicht allerdings, das diese Anzeigemethode den Controller ununterbrochen beansprucht und schlecht skalierbar ist - bei spätestens 8 Anzeigen ist der Helligkeitsverlust nicht mehr hinnehmbar. Den Helligleitsverlust kann man bis zu einer gewissen Grenze durch eine Erhöhung des Stromes, der durch die Anzeige fließt, kompensiert werden. Da aber die Helligkeit der Anzeige nicht konstant mit dem durchfließenden Strom ansteigt und die Anzeigen bei einer Überbeanspruchung durchbrennen, gilt es eine physikalische Grenze nicht zu überschreiten. Bild einer Platine mit 4 7Segment-Anzeigen

Ein Mittelweg ist der Einsatz eines spezialisierten LED-Controllers, der das Time Multiplexing übernimmt und z.B. über denn I2C-Bus angesteuert werden kann (SAA1064 von Philips). Der Einsatz des I2C-Busses wird auf einer anderen Seite noch ausführlich beschrieben werden.
zurück zum Anfang
Schematischer Aufbau einer 7 Segment-Anzeige
In diesem Beispiel wird die Time Multiplexing-Methode verwandt - da der 2051 bis zu 20mA Strom liefern kann, wird nur der Controller, ein Demultiplexer und einige Transistoren benötigt. Grundsätzlich muß der Controller auf den I/O's, an denen die Anzeigen angeschlossen sind, eine Bitfolge liefern, die die Ausgabe für ein Segment bestimmen. Gleichzeitig stellt der Controller über (in diesem Beispiel 2) andere I/O's einen Binärwert, der die aufleuchtende Anzeige spezifiziert, zur Verfügung. Dieser wird durch den Demultiplexer geschickt, welcher dann über einen Transistor die Anode der entsprechenden Anzeige mit Spannung versorgt. Zur Ansteuerung geht im Prinzip jeder Transistor aus der Grabbelkiste, der wenigstens 200 mA aushält.
zurück zum Anfang

Software

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

Seite zurück Startseite Seite vor 
Erik Buchmann
EMail an: Owner@ErikBuchmann.de