Sieben-Segment-Anzeige

Hier können Sie ihre eigenen Projekte vorstellen
Antworten
Heinrichs
Beiträge: 185
Registriert: Do 21. Okt 2010, 18:31

Sieben-Segment-Anzeige

Beitrag von Heinrichs » Do 31. Jul 2014, 14:57

Wenn man eine selbstleuchtende Ziffern-Anzeige für die Attiny-Platine sucht (etwa für Temperaturangeben), kann man auf ein Mehrfach-Ziffern-Modul auf der Baisis eines MAX 7219 zurückgreifen. Ein solches Modul lässt sich leicht über SPI ansteuern und ist für ein paar Euro zu erwerben (Abb. 1).

Die LEDs der Matrix werden nicht direkt vom Mikrocontroller angesteuert. Vielmehr geschieht dies über einen speziellen IC, den MAX 7219. Dieser Baustein ist speziell zum Betrieb von Anzeigeeinheiten wie z. B. mehrstellige 7-Segment-Anzeigen oder LED-Dot-Matrix-Elementen konzipiert. Gesteuert wird dieser IC über 2-Byte-Befehle. Diese Bytes werden über SPI übertragen.

sieben_segment_anzeige.jpg
7-Segment-Modul
sieben_segment_anzeige.jpg (7.79 KiB) 28526 mal betrachtet

Der MAX 7219 kann bis zu 8 Siebensegment-Anzeigen steuern; auf unserem Modul sind nur zwei vorhanden. Die linke Siebensegment-Anzeige gilt hier als Digit 0, die rechte als Digit 1.

Folgende Verdrahtung ist erforderlich, damit die weiter unten angegebenen Programmteile funktionieren können: Neben der elektrischen Versorgung muss der Eingang DIN des Moduls mit PB6, der Taktsignaleingang CLK mit PB7 und der Chip-Select-Eingang CS mit PB0 verbunden werden. Der CS-Eingang könnte auch mit anderen Ports verbunden werden; will man auf die im Attiny2313 fest verdrahteten USI-Funktionen zurückgreifen, dann muss die SPI-Kommunikation über PB6 und PB7 laufen.

Eine geeignete SPI-Funktion, die einzelne Bytes an einen Slave sendet, besteht nur aus wenigen Zeilen:

Code: Alles auswählen

Function Spi(s As Byte) As Byte          'Hardware-SPI mit USI
  Ddrb = &B11011111
  Usidr = S
  Usisr = &B01000000                     'USIOIF und Zähler löschen
  Usicr = &B00011010                     'USIWM0, USICS1,USICLK auf 1
  Do
    Usicr.usitc = 1                      'Takten durch Setzen von usitc
  Loop Until Usisr.usioif = 1            '16 mal toggeln
  Spi = Usidr
End Function
Diese Funktion empfängt auch gleichzeitig Daten über PB5; diese Option wird im Folgenden aber nicht genutzt. Ausführlichere Erläuterungen zur SPI-Kommunikation mit dem Attiny2313 findet man unter https://www.forum.g-heinrichs.de/viewto ... ?f=12&t=49.

Wie sehen nun die 2-Byte-Kommandos aus, mit denen das Ziffern-Array-Modul gesteuert wird? Im Wesentlich bestehen sie aus einer Registeradresse und einem Datenbyte. Die Register stehen für verschiedene Funktionen. Diese sind in der folgenden Tabelle zusammengefasst.

Adresse (dezimal) -- Bedeutung
0 ------------------------ No Operation
1 ------------------------ Digit 0 (Spalte 1)
2 ------------------------ Digit 1 (Spalte 2)
3 ------------------------ Digit 2 (Spalte 3)
4 ------------------------ Digit 3 (Spalte 4)
5 ------------------------ Digit 4 (Spalte 5)
6 ------------------------ Digit 5 (Spalte 6)
7 ------------------------ Digit 6 (Spalte 7)
8 ------------------------ Digit 7 (Spalte 8)
9 ------------------------ Decode Mode
10 ----------------------- Intensity
11 ----------------------- Scan Limit
12 ----------------------- Shut Down
15 ----------------------- Display Test

Wir wollen z. B. in der rechten Siebensegment-Anzeige eine 7 anzeigen lassen.

Diese Siebensegment-Anzeige wird durch das Digit-1-Register mit der Adresse 2 kontrolliert. Deswegen muss der Wert 7 nun in das Register 2 des MAX-Bausteins übertragen werden. Dazu werden folgende Schritte ausgeführt:

1. MAX-Baustein aktivieren (CS auf Low)
2. Den Wert 2 mit der SPI-Funktion an den MAX-Baustein übertragen (Kommando bzw. Registeradresse für Digit 1 )
3. Den Wert 7 mit der SPI-Funktion an den MAX-Baustein übertragen (Parameterwert)
4. MAX-Baustein deaktivieren (CS auf High)

Diese Schrittfolge fast man sinnvollerweise zu einer Prozedur zusammen:

Code: Alles auswählen

Sub Matrix_command(b As Byte , D As Byte)
  Portb.0 = 0
  Waitus 1
  Dummy = Spi(b)
  Dummy = Spi(d)
  Portb.0 = 1
  Waitus 1
End Sub
Die Ziffer 7 kann damit so in der rechten Stelle zur Anzeige gebracht werden:

Code: Alles auswählen

befehl = 2
wert = 7
call matrix_command(befehl, wert)
Wir verzichten hier übrigens auf eine call-by-value-Referenzierung, weil dies den SRAM-Speicher des Attinys belastet und gegebenfalls zu einem Stapelüberlauf und damit zu merkwürdigen Effekten führen könnte.

Die linke Ziffernanzeige wird natürlich in analoger Weise angesprochen, und zwar mit der Registeradresse 1. Es ist klar: Die einzelnen Ziffern lassen sich immer nur einzeln ansprechen; ihr Inhalt bleibt solange bestehen, bis er geändert wird.

Um das Modul erfolgreich betreiben zu können, muss eine Initialisierung des MAX-Bausteins vorgenommen werden. Man braucht aber nicht alle Befehle des MAX 7219 im Detail kennen. Die folgenden Befehle sind hier wichtig:

1. Shut down

Wenn das Modul eingeschaltet worden ist, befindet es sich zunächst im Shut-Down-Modus. Um das Modul aufzuwecken, muss der Wert 1 in das Shut-Down-Register geschrieben werden.

2. Scan Limit

Über dieses Register stellen wir die Anzahl der benutzten Ziffern ein. In unserem Fall müssen wir den Wert 1 (max. Digit-Kennung) in das Scan-Limit-Register schreiben.

3. Intensity

Mithilfe dieses Registers kann die Helligkeit der LEDs eingestellt werden. Zulässig sind Werte von 0 (minimale Helligkeit) bis 15 (maximale Helligkeit). Die Helligkeit lässt sich nicht für jede LED gesondert einstellen. Vielmehr bezieht sich der Helligkeitswert immer auf alle eingeschalteten LEDs.

4. Decode Mode

Indem wir in dieses Register 9 die Zahl 15=$0F schreiben, sorgen wir dafür, dass der MAX-Baustein automatisch eine (De-)Kodierung vornimmt: Wird nun z. B. die Zahl 7 als Parameter in das Register von Digit 0 geschrieben, dann werden in der linken Anzeige die zugehörigen 3 Segmente (in diesem Fall die beiden rechten und das obere) aktiviert.

Für weitergehende Informationen sei auf das Datenblatt bzw. auf das folgende Beispielprogramm verwiesen. Dieses nimmt über ein Terminal zweistellige Zahlen entgegen und stellt sie mithilfe der 7-Segment-Anzeigen dar:

Code: Alles auswählen

' Datei für Attiny-Platine von E. Eube, G. Heinrichs und U. Ihlefeldt
' SPI-Master
' Achtung: DIN auf PB6, Clock auf PB7, CS auf PB0
'
'----------------------------------------------------------------------------

$regfile = "attiny2313.dat"                                 'Attiny2313
$crystal = 4000000                                          '4 MHz
$baud = 9600

$hwstack = 40
$framesize = 30
$swstack = 20


'**********************************************************
'******************* Deklarationen ************************

Declare Function Spi(s As Byte) As Byte
Declare Sub Matrix_command(b As Byte , D As Byte)
Declare Sub Matrix_init
Declare Sub Zahl_anzeigen(z As Byte)
Dim Bef As Byte
Dim Dat As Byte
Dim Dummy As Byte
Dim Zahl As Byte
Dim Z1 As Byte
Dim Z0 As Byte

'****************** Initialisierung ***********************

Ddrb = &B11111111                                           'Port B als Ausgangsport
Ddrd = &B01110000                                           'D4, D5, D6 als Ausgang; Rest als Eingang
Portd = &B10001111                                          'Eingänge auf high legen


'**********************************************************
'******************** Hauptprogramm ***********************

Call Matrix_init

Do
  Inputbin Zahl
  Call Zahl_anzeigen(zahl)
Loop

End


'**********************************************************
'******************* Unterprogramme ***********************

Function Spi(s As Byte) As Byte
  Ddrb = &B11011111
  Usidr = S
  Usisr = &B01000000                                        'USIOIF und Zähler löschen
  Usicr = &B00011010                                        'USIWM0, USICS1,USICLK auf 1
  'Waitms 1
  Do
    Usicr.usitc = 1                                         'Takten durch Setzen von usitc
    'Waitms 1                                                'später weg!
  Loop Until Usisr.usioif = 1                               '16 mal toggeln
  Spi = Usidr
End Function


Sub Matrix_command(b As Byte , D As Byte)
  Portb.0 = 0
  Waitus 1
  Dummy = Spi(b)
  Dummy = Spi(d)
  Portb.0 = 1
  Waitus 1
End Sub

Sub Matrix_init
  'shut down aus : normal operation
  Bef = &H0C
  Dat = 1
  Call Matrix_command(bef , Dat)
  ' alle Stellen anzeigen
  Bef = &H0B
  Dat = 1
  Call Matrix_command(bef , Dat)
  'Helligkeit
  Bef = &H0A
  Dat = 15                                                  ' Helligkeit 15/16
  Call Matrix_command(bef , Dat)
  'Decode mode
  Bef = &H09
  Dat = &H0F                                                'Bit 0-3 dekodieren                                                  ' Helligkeit 15/16
  Call Matrix_command(bef , Dat)
  'Nullsetzen
  Dat = 0
  Bef = 1
  Call Matrix_command(bef , Dat)
  Bef = 2
  Call Matrix_command(bef , Dat)
End Sub

Sub Zahl_anzeigen(z As Byte)
  If Z < 100 Then
    Z0 = Z Mod 10                                           'Einer
    Z1 = Z / 10                                             'Zehner
    Bef = 1                                                 'linke Stelle, Zehner
    Call Matrix_command(bef , Z1)
    Bef = 2                                                 'rechte Stelle, Einer
    Call Matrix_command(bef , Z0)
  Else
    Dat = 128                                               'Punkt als Fehlerindikator
    Bef = 2
    Call Matrix_command(bef , Dat)
  End If
End Sub
Das 7-Segment-Modul kann ggf. den Upload-Vorgang stören. Es empfiehlt sich deswegen, vor dem Upload die Verbindung zu Vcc zu unterbrechen und nach dem Upload die Attiny-Platine auszuschalten, die Verbindung zu Vcc wieder herzustellen und zuletzt die Attiny-Platine wieder einzuschalten.

Antworten