Seite 1 von 1

TM1638-Anzeige-Taster-Modul

Verfasst: So 18. Mär 2018, 10:37
von Heinrichs
Das TM1638-Anzeige-Taster-Modul besitzt 8 Siebensegmentanzeigen, 8 LEDs und 8 Taster. Diese können von einem Mikrocontroller über den Baustein TM1638 angesprochen werden; die Kommunikation erfolgt hier über ein SPI-Protokoll.

Die Betriebsspannung ist 5,0 V. Signale unter 0,3 V gelten als Low, Signale über 0,7 V als High. Damit ist das Modul gut geeignet, um die Ein- und Ausgabemöglichkeiten unserer Attiny-Platine zu erweitern.

Zur Ansteuerung der Siebensegmentanzeigen und LEDs benutzt der TM1638 einen Displayspeicher mit 16 Registern vom Typ Byte: Jedes dieser Register ist einer LED bzw. einer Siebensegmentanzeige zugeordnet (s. Abb. 1). Der Inhalt des Registers legt bei einer LED fest, ob sie leuchtet oder nicht, bei einer Siebensegmentanzeige, welche Segmente aktiviert werden. Das Register mit der Adresse 4 ist z. B. der Siebensegmentanzeige Nr. 3 (von links) zugeordnet.

TM1638_modul_mit_Adressen.jpg
TM1638-Modul mit Adressen
TM1638_modul_mit_Adressen.jpg (114.48 KiB) 22929 mal betrachtet

Soll in dieser Siebensegmentanzeige z. B. die Zahl 1 erscheinen, müssen dort die Segmente b und c aktiviert werden (vgl. Abb. 2). Dazu muss man das entsprechende Bitmuster &B00000110 in das Register mit der Adresse 4 speichern. Weiter unten werden wir genau beschreiben, welche Befehle und Daten der Mikrocontroller dazu an den TM1638-Baustein senden muss.

Siebensegentanzeige.jpg
Siebensegmentanzeige
Siebensegentanzeige.jpg (21.86 KiB) 22928 mal betrachtet

Da der TM1638-Baustein viele unterschiedliche Funktionen besitzt, reicht es nicht aus, ihm die Bitmuster für die Siebensegmentanzeigen zu übertragen. Neben diesen Daten muss man ihm vielmehr auch Steuerbefehle (commands) übermitteln. Sowohl Daten als auch Steuerbefehle werden mit dem SPI-Protokoll übertragen (s. https://www.forum.g-heinrichs.de). Die Taktsignale erhält der TM1638 (Slave) über den Eingang CLK vom Mikrocontroller (Master); die maximale Taktfrequenz ist 1 MHz. Damit der Baustein die einzelnen Bits empfangen kann, muss der STB-Eingang des Bausteins auf Low (Chip Selected) sein. Man beachte, dass der TM1638-Baustein bei der seriellen Übertragung der einzelnen Bits erwartet, dass das LSB (Least Significant Bit) zuerst gesendet wird. Will man die USI-Einheit des Attiny2313 ausnutzen (s. u.), dann muss man PortB.7 (USCK) und PortB.6 (DO) des Attiny mit den Anschlüssen CLK bzw. DIO bei dem MT1638-Modul verbinden.

Es gibt drei verschiedene Steuerbefehle. Allen ist gemeinsam, dass sie durch eine negative Flanke am STB-Eingang eingeleitet werden müssen; das unterscheidet sie gerade von den Datenbytes.

Setting of Data Command (B7 = 0; B6 = 1; Restliche Bits: Parameter)
Setting of Address Command (B7 = 1; B6 = 1; Restliche Bits: Parameter)
Display Control Command (B7 = 1; B6 = 0; Restliche Bits: Parameter)

Man erkennt unschwer, dass die Steuerbefehle jeweils durch die beiden Bits B6 und B7 gekennzeichnet sind.

Wir begnügen uns an dieser Stelle damit, für drei Beispiele die nötigen Befehlssequenzen anzugeben. Wer mehr über die Funktionsweise des TM1638-Moduls erfahren möchte, den verweise ich auf das ausführliche Skript im Anhang.


1. Ziffer “1” in der Siebensegmentanzeige Nr. 3 zur Anzeige bringen (w = write)

STB = 1
STB = 0 //erzeugt negative Flanke
w &B01000100 //Schreibmodus; feste Adresse
STB = 1
STB = 0 //erzeugt negative Flanke
w &B11000110 //Adresszeiger auf &B0110 (6)
w &B00000110 //Datenbyte (Bitmuster entspricht der Ziffer 1)
STB = 1
STB = 0 //erzeugt negative Flanke
w &B10001111 //Display einschalten


2. Display ausschalten

STB = 1
STB = 0 //erzeugt negative Flanke
w &B10000000 //Display ausschalten


3. Alle Displayregister löschen (nach power-up empfohlen)

STB = 1
STB = 0 //erzeugt negative Flanke
w &B01000100 //Schreibmodus; autom. Inkrement
STB = 1
STB = 0 //erzeugt negative Flanke
w &B11000000 //Adresszeiger auf &B0000 (Startadresse 0)
Wiederhole 16 mal:
w &B00000000 //Datenbyte 0 (kein Segment aktivieren)

Am Ende sollte der TM1638-Baustein jeweils durch STB = 1 deaktiviert werden.

Für unserer Attiny-Platine kann zur Übertragung der Befehls- und Datenbytes die folgende Funktion benutzt werden

Code: Alles auswählen

Function Spi(s As Byte) As Byte
  DDRB = &B11011111
  For K = 0 To 7                                            'Umkehrung
    K1 = 7 - K
    S1.k = S.k1
  Next K
  Usidr = S1
  Usisr = &B01000000                                        'USIOIF und Zähler löschen
  Usicr = &B00011010                                        'USIWM0, USICS1,USICLK auf 1
  Waitus 1
  Do
    Usicr.usitc = 1                                         'Takten durch Setzen von usitc
    Waitus 1                                                'später weg!
  Loop Until Usisr.usioif = 1                               '16 mal toggeln
  S1 = Usidr
  For K = 0 To 7                                            'Umkehrung
    K1 = 7 - K
    S1.k = Usidr.k1
  Next K
  Spi = S1
End Function

Hier haben wir nur kurz dargelegt, wie man die Siebensegmentanzeigen ansteuert. Wer mehr über die Funktionsweise des TM1638-Moduls erfahren möchte, insbesondere auch, wie man den Status der Tasten abfragt, der sei auf das Skript im Anhang verwiesen.

Hier gibt es noch ein BASCOM-Programm für unsere Attiny-Platine, welches die Nummer der betätigten Taste in der rechten Siebensegmentanzeige anzeigt.

Code: Alles auswählen

' Datei für Attiny-Platine von E. Eube, G. Heinrichs und U. Ihlefeldt
' SPI-Master
' Achtung: MOSI (DO) über 1K-Widerstand auf PB6, MISO (DI) auf PB5; beim Lesevorgang muss auch ddrb.6 = 0 sein
' CLK auf PB7
' STB auf PB4
' Pinkonfiguration im Manual nicht ganz korrekt!
' In Wirklichkeit hat der Attiny kein echtes MISO/MOSI, sondern nur DI/DO!
'
' Test für TM1638-Modul
' Bei TM1638 muss das LSB zuerst übertragen werden!
' Für Tasterscan muss DIO von TM1638-Modul auch an PB5 angeschlossen sein;
' beim Lesevorgang muss dann PortB.6 durch DDRB.6 hochohmig gemacht werden.
'
' Programm zeigt die Nummer des zuletzt gedrückten Tasters auf der rechten Sieben-Segment-Anzeige an.
'
'----------------------------------------------------------------------------

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

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

Declare Function Spi(s As Byte) As Byte
Declare Sub Loeschen
Declare Sub Display_einschalten
Declare Sub Ziffer_zeigen
Declare Sub Init_muster
Declare Sub Keyscan
Dim Bef1 As Byte
Dim Bef2 As Byte
Dim Bef3 As Byte
Dim Dummy As Byte
Dim Pause As Byte
Dim Wert As Byte
Dim I As Byte
Dim K As Byte
Dim K1 As Byte
Dim S As Byte
Dim S1 As Byte
Dim Pos As Byte
Dim Scan(4) As Byte
Dim Muster(10) As Byte


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

Ddrb = &B11011111                                           'Port B als Ausgangsport; B.5 als Input
Ddrd = &B01110000                                           'D4, D5, D6 als Ausgang; Rest als Eingang
Portd = &B10001111                                          'Eingänge auf high legen
Portb.4 = 1                                                 'STB auf 1
Waitms 10

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

Pause = 2

Call Init_muster
Call Loeschen
Call Display_einschalten
Wert = Muster(1)
Pos = 14
Call Ziffer_zeigen

Do
  Waitms 10
  Call Keyscan
  For I = 1 To 4
    S = Scan(i)
    If S.0 = 1 Then
      K = I + 1
      Wert = Muster(k)
    End If
    If S.4 = 1 Then
      K = I + 5
      Wert = Muster(k)
    End If
    Call Ziffer_zeigen
  Next I
Loop

End

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

Function Spi(s As Byte) As Byte
  For K = 0 To 7                                            'Spiegeln
    K1 = 7 - K
    S1.k = S.k1
  Next K
  Usidr = S1
  Usisr = &B01000000                                        'USIOIF und Zähler löschen
  Usicr = &B00011010                                        'USIWM0, USICS1,USICLK auf 1
  Waitus 1
  Do
    Usicr.usitc = 1                                         'Takten durch Setzen von usitc
    Waitus 1                                                'später weg!
  Loop Until Usisr.usioif = 1                               '16 mal toggeln
  S1 = Usidr
  For K = 0 To 7                                            'Spiegeln
    K1 = 7 - K
    S1.k = Usidr.k1
  Next K
  Spi = S1
End Function

Sub Loeschen
  Portb.4 = 0
  Waitus Pause
  Bef1 = $40
  Dummy = Spi(bef1)                                         'Displayreg, Autoinkr.
  Portb.4 = 1
  Waitus Pause
  Portb.4 = 0
  Waitus Pause
  Bef2 = $c0
  Dummy = Spi(bef2)                                         'Startadresse
  Waitus Pause
  Wert = 0
  For I = 0 To 15
    Dummy = Spi(wert)
    Waitus Pause
  Next I
  Portb.4 = 1
  Waitus Pause
End Sub

Sub Display_einschalten
  Portb.4 = 0
  Waitus Pause
  Bef3 = $8f                                                '$8F = 16/16 an; &B10001011 = 10/16 an (PWM)
  Dummy = Spi(bef3)                                         'Display
  Portb.4 = 1
End Sub

Sub Init_muster
  Muster(1) = &B00111111                                    '0
  Muster(2) = &B00000110                                    '1
  Muster(3) = &B01011011                                    '2
  Muster(4) = &B01001111                                    '3
  Muster(5) = &B01100110                                    '4
  Muster(6) = &B01101101                                    '5
  Muster(7) = &B01111101                                    '6
  Muster(8) = &B00000111                                    '7
  Muster(9) = &B01111111                                    '8
  Muster(10) = &B01101111                                   '9
  ' ggf. weiter Muster...
End Sub

Sub Ziffer_zeigen
  Portb.4 = 0
  Waitus Pause
  Bef1 = $44
  Dummy = Spi(bef1)                                         'Displayreg, Autoinkr.
  Portb.4 = 1
  Waitus Pause
  Portb.4 = 0
  Waitus Pause
  Bef2 = $c0 + Pos
  Dummy = Spi(bef2)
  Waitus Pause
  Dummy = Spi(wert)
  Portb.4 = 1
  Waitus Pause
End Sub

Sub Keyscan
  Portb.4 = 0
  Waitus Pause
  Bef1 = $42                                                'read command
  Dummy = Spi(bef1)
  Waitus Pause
  Ddrb.6 = 0                                                'wichtig, weil sonst DI beim Lesen durch DO beeinflusst wird
  Waitus Pause
  For I = 1 To 4
    Scan(i) = Spi(dummy)
    Waitus Pause
  Next I
  Ddrb.6 = 1
  Portb.4 = 1
  Waitus Pause
End Sub