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.
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
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
Code: Alles auswählen
befehl = 2
wert = 7
call matrix_command(befehl, wert)
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