Oled-Display mit deutschen Sonderzeichen
Verfasst: Do 21. Nov 2019, 11:33
Ein beliebtes (weil recht preiswertes) Display ist das "OLED 128x64 Display SH1106 I2C". Der Name sagt es schon: Es handelt sich um ein OLED-Display mit 128 * 64 Pixeln, welches über I2C gesteuert wird. Die I2C-Adresse ist $78 und kann (durch Umsetzen eines SMD-Widerstandes) auf $7A umgestellt werden. Als Display-Controller wird hier ein SH1106-Baustein verwendet.
Achtung: Eine Reihe von äußerlich gleich aussehenden Displays besitzt den SSD1306; dieser ist fast(!) kompatibel zum SH1106. Einen ausführlichen Beitrag zu diesem Problem findet man hier. Grundsätzliche Bemerkungen zur Funktionsweise dieser beiden Bausteine findet man in meinem Beitrag Mini-Oszi mit OLED SSD1306.
Beide Bausteine besitzen keinen Font; man muss den Font softwaremäßig realisieren. In dem folgenden Programm findet man ihn in Form von Data-Zeilen am Ende des BASCOM-Quellcodes; derartige Byte-Tabellen für Fonts findet man an verschiedenen Stellen im Internet. Leider habe ich dort keine Font-Tabelle gefunden, welche auch die deutschen Sonderzeichen ä, ö, ü, Ä, Ö, Ü und ß besitzt. Deswegen habe ich für diese Zeichen eigene Byte-Muster gebildet und im Programm angefügt. Da die Buchstaben-Matrix (bei der hier verwendeten Kleinschrift) mit 5 x 7 Pixeln (ohne Unterlänge) sehr klein ist, musste ich beim Unterbringen der Punkte einige Kompromisse machen.
Üblicherweise findet man die Codes dieser Sonderzeichen weit jenseits der Grenze von 127; ich habe sie jedoch mit den Codes 128 bis 134 belegt. Auf diese Weise konnte ich überflüssige Data-Zeilen vermeiden. Damit das BASCOM-Programm den üblichen Codes von ä, ö, … die richtigen Data-Zeilen zuweist, wurde für diese Zeichen mit Hilfe einer CASE-Anweisung eine Umcodierung vorgenommen.
Das folgende Programm nimmt eine Zeichenkette mit maximal 128 Zeichen von einem Terminal über die serielle Schnittstelle entgegen und gibt sie auf dem Display aus. Dabei werden Zeilenumbrüche automatisch durchgeführt, ggf. auch mitten im Wort. Das kann dann so wie in der obigen Abbildung aussehen.
Achtung: Eine Reihe von äußerlich gleich aussehenden Displays besitzt den SSD1306; dieser ist fast(!) kompatibel zum SH1106. Einen ausführlichen Beitrag zu diesem Problem findet man hier. Grundsätzliche Bemerkungen zur Funktionsweise dieser beiden Bausteine findet man in meinem Beitrag Mini-Oszi mit OLED SSD1306.
Beide Bausteine besitzen keinen Font; man muss den Font softwaremäßig realisieren. In dem folgenden Programm findet man ihn in Form von Data-Zeilen am Ende des BASCOM-Quellcodes; derartige Byte-Tabellen für Fonts findet man an verschiedenen Stellen im Internet. Leider habe ich dort keine Font-Tabelle gefunden, welche auch die deutschen Sonderzeichen ä, ö, ü, Ä, Ö, Ü und ß besitzt. Deswegen habe ich für diese Zeichen eigene Byte-Muster gebildet und im Programm angefügt. Da die Buchstaben-Matrix (bei der hier verwendeten Kleinschrift) mit 5 x 7 Pixeln (ohne Unterlänge) sehr klein ist, musste ich beim Unterbringen der Punkte einige Kompromisse machen.
Üblicherweise findet man die Codes dieser Sonderzeichen weit jenseits der Grenze von 127; ich habe sie jedoch mit den Codes 128 bis 134 belegt. Auf diese Weise konnte ich überflüssige Data-Zeilen vermeiden. Damit das BASCOM-Programm den üblichen Codes von ä, ö, … die richtigen Data-Zeilen zuweist, wurde für diese Zeichen mit Hilfe einer CASE-Anweisung eine Umcodierung vorgenommen.
Das folgende Programm nimmt eine Zeichenkette mit maximal 128 Zeichen von einem Terminal über die serielle Schnittstelle entgegen und gibt sie auf dem Display aus. Dabei werden Zeilenumbrüche automatisch durchgeführt, ggf. auch mitten im Wort. Das kann dann so wie in der obigen Abbildung aussehen.
Code: Alles auswählen
' Programm für das Nano-Board
' Über die zu zugehörige Konfigurationsdatei werden automatisch Voreinstellungen
' für die Kompilierung übernommen; diese betreffen z. B. die Taktfrequenz, die
' Baudrate, die Anschlüsse von LCD, I2C- und SPI-Modulen.
' Programm nach I. Dobson, Sonal Pinto und Ben Zijlstra & Theo Kleijn
' OLED display 128x64 SSH1106(!) 0.96"
' Text (maximal 16*8 = 128 Zeichen) über COM eingeben
' Anzeige um 180° gedreht
'**********************************************************
$regfile = "m328pdef.dat" 'Dadurch wird auch das Pin Layout bestimmt
$crystal = 16000000
$framesize = 32
$swstack = 32
$hwstack = 64
$baud = 9600
Config Sda = Portc.4
Config Scl = Portc.5
'**********************************************************
'******************* Deklarationen ************************
Declare Sub Zeige_text
Declare Sub Init
Declare Sub Loeschen
Dim Kontrast As Byte
Dim Write_adresse_oled As Byte
Dim Text As String * 128
Dim X As Byte
Dim X1 As Byte
Dim X0 As Byte
Dim Page As Integer
Dim Buchstabe As String * 1
Dim Q As Integer
Dim H As Integer
Dim Temp As Integer
Dim Senden As Byte
Dim Pause As Byte
Dim J As Byte
Dim I As Byte
Dim Anzahlzeichen As Byte
Dim Anzahlzeilen As Byte
Dim Pos As Byte
Dim Zeile As String * 16
Dim Leerzeile As String * 16
Dim Rest As Byte
Dim Rest2 As Byte
'**********************************************************
'****************** Initialisierung ***********************
Ddrb.5 = 1
Config I2cdelay = 1 'I2C-Taktung möglichst rasch
Write_adresse_oled = &H78 'OLED SSD1306
Kontrast = 200 'hoher Kontrast
Pause = 1
'**********************************************************
'******************** Hauptprogramm ***********************
Call Init
Call Loeschen
Leerzeile = " "
Do
Print "Geben Sie eine Text ein (max. 128 Zeichen)! Senden mit CR"
Input Text
Call Loeschen
Anzahlzeichen = Len(text)
Anzahlzeilen = Anzahlzeichen / 16
Rest = Anzahlzeichen Mod 16
For I = 1 To Anzahlzeilen
J = I - 1
Pos = 16 * J
Pos = Pos + 1
Zeile = Mid(text , Pos , 16)
X = 2 'ganz links bei
Page = I
Zeige_text
Next I
If Rest > 0 Then
Anzahlzeilen = Anzahlzeilen + 1
J = Anzahlzeilen - 1
Pos = 16 * J
Pos = Pos + 1
Rest2 = 16 - Rest
Zeile = Mid(text , Pos , Rest) + Mid(leerzeile , 1 , Rest2)
X = 2
Page = Anzahlzeilen
Zeige_text
End If
Loop
'**********************************************************
'******************** Unterprogramme **********************
Sub Init
I2cstart
I2cwbyte Write_adresse_oled
If Err = 0 Then Portb.5 = 1 'LED bei B.5 an, wenn OLED gefunden
I2cstop
Waitms 500
Portb.5 = 0
I2cstart
I2cwbyte Write_adresse_oled
I2cwbyte &H00 'Command Stream(nötig -------------??)
I2cwbyte &HAE 'DISPLAYOFF ------------------------OK
I2cwbyte &HD5 'SETDISPLAYCLOCKDIV ----------------OK
I2cwbyte &H80 'ratio 0x80
I2cwbyte &HA8 'Set MUX
I2cwbyte &H3F '&H1F for 128x32; &H3F for 128x64
I2cwbyte &HD3 'SETDISPLAYOFFSET ------------------OK
I2cwbyte &H00
I2cwbyte &H40 'SETSTARTLINE ----------------------OK
I2cwbyte &H8D 'CHARGEPUMP ------------------------OK
I2cwbyte &H14 'vccstate 14 for chargepump
I2cwbyte &H20 'MEMORYMODE ------------------------OK
I2cwbyte &H00 'horizontal addr mode
I2cwbyte &HA0 'SEGREMAP links-rechts A0/A1 -------OK
I2cwbyte &HC0 'COMSCANDEC (&HC0 vert. gesp.) -----OK
I2cwbyte &HDA 'SETCOMPINS ------------------------OK
I2cwbyte &H12 '&H12 for 64 rows
I2cwbyte &H81 'SETCONTRAST -----------------------OK
I2cwbyte Kontrast 'value 1-->256
I2cwbyte &HD9 'SETPRECHARGE ----------------------OK
I2cwbyte &HF1 'vccstate F1
I2cwbyte &HDB 'SETVCOMDETECT ---------------------OK
I2cwbyte &H30 '&H30 -> 0.83*VCC; bei Arduino &H40 ??
I2cwbyte &HA4 'DISPLAYALLON_RESUME ---------------OK
I2cwbyte &HA6 'NORMALDISPLAY
I2cwbyte &HAF 'Display on ------------------------OK
I2cstop
End Sub
Sub Zeige_text 'schreibt die Zeichenkette "Zeile" (mit genau 16 Zeichen) in die Zeile "Page"
X0 = X Mod 16
X1 = X / 16
X1 = X1 + &H10
I2cstart
I2cwbyte Write_adresse_oled
I2cwbyte &H00 'command stream ------------------??
I2cwbyte X0 'Spalte x Low Nibble
I2cwbyte X1 'Spalte x High Nibble
I2cstop
Page = Page + 175
I2cstart
I2cwbyte Write_adresse_oled
I2cwbyte &H80
I2cwbyte Page 'Bestimmung Page (Y)
I2cstop
I2cstart
I2cwbyte Write_adresse_oled
I2cwbyte &H80
I2cstop
I2cstart
I2cwbyte &H78
I2cwbyte &H40
'Umwandlung von Buchstaben zu Asciiwert zu Columndata der Datenbank
For Q = 1 To 16 'max. 16 Zeichen pro Zeichenkette
Temp = 0
Buchstabe = Mid(zeile , Q , 1)
Temp = Asc(buchstabe)
If Temp > 127 Then
Select Case Temp
Case 228 : Temp = 128 'ä
Case 246 : Temp = 129 'ö
Case 252 : Temp = 130 'ü
Case 196 : Temp = 131 'Ä
Case 214 : Temp = 132 'Ö
Case 220 : Temp = 133 'Ü
Case 223 : Temp = 134 'ß
Case Else : Temp = 32 'SPACE
End Select
End If
Temp = Temp - 32
Temp = Temp * 8
For H = 1 To 8
Senden = Lookup(temp , Asciitab)
I2cwbyte Senden
Incr Temp
Next H
Waitms Pause
Next Q
I2cstop
End Sub
Sub Loeschen 'speziell für SSH1106
For X0 = 0 To 7
X1 = &HB0 + X0
I2cstart
I2cwbyte Write_adresse_oled
I2cwbyte &H80 'Single Command
I2cwbyte X1 'Page (Y) &HB0 = Col0
I2cstop
I2cstart
I2cwbyte Write_adresse_oled
I2cwbyte &H00 'command stream
I2cwbyte &H02 'Select start column 0; offset 2
I2cwbyte &H10
I2cstop
I2cstart
I2cwbyte Write_adresse_oled
I2cwbyte &H40 'Datenstrom für das RAM
For Temp = 0 To 127
I2cwbyte 0
Next Temp
I2cstop
Next X0
End Sub
'**********************************************************
'******************Interruptroutinen***********************
'**********************************************************
Asciitab:
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, 'ASCII-Code 32
Data 0 , 0 , 6 , 95 , 6 , 0 , 0 , 0, 'ASCII-Code 33
Data 0 , 7 , 3 , 0 , 7 , 3 , 0 , 0, '...
Data 0 , 36 , 126 , 36 , 126 , 36 , 0 , 0, '#
Data 0 , 36 , 43 , 106 , 18 , 0 , 0 , 0,
Data 0 , 99 , 19 , 8 , 100 , 99 , 0 , 0,
Data 0 , 54 , 73 , 86 , 32 , 80 , 0 , 0,
Data 0 , 0 , 7 , 3 , 0 , 0 , 0 , 0,
Data 0 , 0 , 62 , 65 , 0 , 0 , 0 , 0, 'ASCII-Code 40
Data 0 , 0 , 65 , 62 , 0 , 0 , 0 , 0,
Data 0 , 8 , 62 , 28 , 62 , 8 , 0 , 0,
Data 0 , 8 , 8 , 62 , 8 , 8 , 0 , 0,
Data 0 , 0 , 224 , 96 , 0 , 0 , 0 , 0,
Data 0 , 8 , 8 , 8 , 8 , 8 , 0 , 0,
Data 0 , 0 , 96 , 96 , 0 , 0 , 0 , 0,
Data 0 , 32 , 16 , 8 , 4 , 2 , 0 , 0,
Data 0 , 62 , 81 , 73 , 69 , 62 , 0 , 0,
Data 0 , 0 , 66 , 127 , 64 , 0 , 0 , 0,
Data 0 , 98 , 81 , 73 , 73 , 70 , 0 , 0, 'ASCII-Code 50
Data 0 , 34 , 73 , 73 , 73 , 54 , 0 , 0,
Data 0 , 24 , 20 , 18 , 127 , 16 , 0 , 0,
Data 0 , 47 , 73 , 73 , 73 , 49 , 0 , 0,
Data 0 , 60 , 74 , 73 , 73 , 48 , 0 , 0,
Data 0 , 1 , 113 , 9 , 5 , 3 , 0 , 0,
Data 0 , 54 , 73 , 73 , 73 , 54 , 0 , 0,
Data 0 , 6 , 73 , 73 , 41 , 30 , 0 , 0,
Data 0 , 0 , 108 , 108 , 0 , 0 , 0 , 0,
Data 0 , 0 , 236 , 108 , 0 , 0 , 0 , 0,
Data 0 , 8 , 20 , 34 , 65 , 0 , 0 , 0, 'ASCII-Code 60
Data 0 , 36 , 36 , 36 , 36 , 36 , 0 , 0,
Data 0 , 0 , 65 , 34 , 20 , 8 , 0 , 0,
Data 0 , 2 , 1 , 89 , 9 , 6 , 0 , 0,
Data 0 , 62 , 65 , 93 , 85 , 30 , 0 , 0,
Data 0 , 126 , 17 , 17 , 17 , 126 , 0 , 0,
Data 0 , 127 , 73 , 73 , 73 , 54 , 0 , 0,
Data 0 , 62 , 65 , 65 , 65 , 34 , 0 , 0,
Data 0 , 127 , 65 , 65 , 65 , 62 , 0 , 0,
Data 0 , 127 , 73 , 73 , 73 , 65 , 0 , 0,
Data 0 , 127 , 9 , 9 , 9 , 1 , 0 , 0, 'ASCII-Code 70
Data 0 , 62 , 65 , 73 , 73 , 122 , 0 , 0,
Data 0 , 127 , 8 , 8 , 8 , 127 , 0 , 0,
Data 0 , 0 , 65 , 127 , 65 , 0 , 0 , 0,
Data 0 , 48 , 64 , 64 , 64 , 63 , 0 , 0,
Data 0 , 127 , 8 , 20 , 34 , 65 , 0 , 0,
Data 0 , 127 , 64 , 64 , 64 , 64 , 0 , 0,
Data 0 , 127 , 2 , 4 , 2 , 127 , 0 , 0,
Data 0 , 127 , 2 , 4 , 8 , 127 , 0 , 0,
Data 0 , 62 , 65 , 65 , 65 , 62 , 0 , 0,
Data 0 , 127 , 9 , 9 , 9 , 6 , 0 , 0, 'ASCII-Code 80
Data 0 , 62 , 65 , 81 , 33 , 94 , 0 , 0,
Data 0 , 127 , 9 , 9 , 25 , 102 , 0 , 0,
Data 0 , 38 , 73 , 73 , 73 , 50 , 0 , 0,
Data 0 , 1 , 1 , 127 , 1 , 1 , 0 , 0,
Data 0 , 63 , 64 , 64 , 64 , 63 , 0 , 0,
Data 0 , 31 , 32 , 64 , 32 , 31 , 0 , 0,
Data 0 , 63 , 64 , 60 , 64 , 63 , 0 , 0,
Data 0 , 99 , 20 , 8 , 20 , 99 , 0 , 0,
Data 0 , 7 , 8 , 112 , 8 , 7 , 0 , 0,
Data 0 , 113 , 73 , 69 , 67 , 0 , 0 , 0, 'ASCII-Code 90
Data 0 , 0 , 127 , 65 , 65 , 0 , 0 , 0,
Data 0 , 2 , 4 , 8 , 16 , 32 , 0 , 0,
Data 0 , 0 , 65 , 65 , 127 , 0 , 0 , 0,
Data 0 , 4 , 2 , 1 , 2 , 4 , 0 , 0,
Data 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128,
Data 0 , 0 , 3 , 7 , 0 , 0 , 0 , 0,
Data 0 , 32 , 84 , 84 , 84 , 120 , 0 , 0,
Data 0 , 127 , 68 , 68 , 68 , 56 , 0 , 0,
Data 0 , 56 , 68 , 68 , 68 , 40 , 0 , 0,
Data 0 , 56 , 68 , 68 , 68 , 127 , 0 , 0, 'ASCII-Code 100
Data 0 , 56 , 84 , 84 , 84 , 8 , 0 , 0,
Data 0 , 8 , 126 , 9 , 9 , 0 , 0 , 0,
Data 0 , 24 , 164 , 164 , 164 , 124 , 0 , 0,
Data 0 , 127 , 4 , 4 , 120 , 0 , 0 , 0,
Data 0 , 0 , 0 , 125 , 64 , 0 , 0 , 0,
Data 0 , 64 , 128 , 132 , 125 , 0 , 0 , 0,
Data 0 , 127 , 16 , 40 , 68 , 0 , 0 , 0,
Data 0 , 0 , 0 , 127 , 64 , 0 , 0 , 0,
Data 0 , 124 , 4 , 24 , 4 , 120 , 0 , 0,
Data 0 , 124 , 4 , 4 , 120 , 0 , 0 , 0, 'ASCII-Code 110
Data 0 , 56 , 68 , 68 , 68 , 56 , 0 , 0,
Data 0 , 252 , 68 , 68 , 68 , 56 , 0 , 0,
Data 0 , 56 , 68 , 68 , 68 , 252 , 0 , 0,
Data 0 , 68 , 120 , 68 , 4 , 8 , 0 , 0,
Data 0 , 8 , 84 , 84 , 84 , 32 , 0 , 0,
Data 0 , 4 , 62 , 68 , 36 , 0 , 0 , 0,
Data 0 , 60 , 64 , 32 , 124 , 0 , 0 , 0,
Data 0 , 28 , 32 , 64 , 32 , 28 , 0 , 0,
Data 0 , 60 , 96 , 48 , 96 , 60 , 0 , 0,
Data 0 , 108 , 16 , 16 , 108 , 0 , 0 , 0, 'ASCII-Code 120
Data 0 , 156 , 160 , 96 , 60 , 0 , 0 , 0,
Data 0 , 100 , 84 , 84 , 76 , 0 , 0 , 0,
Data 0 , 8 , 62 , 65 , 65 , 0 , 0 , 0,
Data 0 , 0 , 0 , 119 , 0 , 0 , 0 , 0,
Data 0 , 0 , 65 , 65 , 62 , 8 , 0 , 0,
Data 0 , 2 , 1 , 2 , 1 , 0 , 0 , 0,
Data 0 , 60 , 38 , 35 , 38 , 60 , 0 , 0, 'ASCII-Code 127
Data 0 , 32 , 85 , 84 , 85 , 120 , 0 , 0, 'ä
Data 0 , 56 , 69 , 68 , 69 , 56 , 0 , 0, 'ö
Data 0 , 60 , 65 , 32 , 125 , 0 , 0 , 0, 'ü
Data 0 , 125 , 18 , 17 , 18 , 125 , 0 , 0, 'Ä
Data 0 , 61 , 66 , 65 , 66 , 61 , 0 , 0, 'Ö
Data 0 , 60 , 65 , 64 , 65 , 60 , 0 , 0, 'Ü
Data 0 , 254 , 9 , 73 , 78 , 48 , 0 , 0 'ß
Data 0 , 126 , 9 , 73 , 73 , 54 , 0 , 0 'ß