Hallo Modellbaufreunde,
"Ey, Alter! Hast ma' 'nen Pin?"
Heute Exkurs Teil 2: Portpins sparen - ein LCD-Display mit I2C-Adapter am Mikrocontroller.
Wer brav seine Hausaufgaben gemacht hat, kennt das Problem. Irgendwann ist kein Portpin mehr frei.
So musste der 16-Kanal-Blinker auf 15 Kanäle zurechtgestutzt werden, um den zweiten Taster anzuschließen.
Ach, nicht probiert?
Im letzten offiziellen Post hatten wir das LCD-Display im "genügsamen" 4-Bit-Modus angeschlossen: 4 statt 8 Datenbits, RS und E, kein R/W -> 6 Pins am Tiny belegt.
Es geht sparsamer.
Frau Antje von Philips hat vor langer Zeit den
"Inter-Integrated Circuit", kurz I2C (sprich: Ei-squärd-Sie oder Ei-Tu-Sie), ersonnen.
Man kennt ihn auch unter der Abkürzung TWI für "Two Wire Interface". Das ist das Angenehme: Nur 2 statt 6 Pins am Mikrocontroller belegt.
I2C ist ein klassisches Master-Slave(s) Bussystem:

Quelle: Bascom-Hilfe
Was sehen wir? Die Spannungsversorgung (Vcc; gemeinsamer GND ist sinnvoll), die Taktleitung (SCL) und die Datenleitung (SDA).
SCL und SDA werden je mit einem Pullup-Widerstand (Rp) mit Vcc verbunden;
gebräuchlicher Wert 3,6 kOhm; laut Bascom-Hilfe geht auch 1 kOhm (Einkaufslisten-kompatibel

).
In den meisten Fällen gibt es einen Super-heftig-Oberboss (Master; unser Mikrocontroller) und seine Untertanen (Slaves, unser I2C-LDC-Adapter und ggf. weitere I2C-Slaves).
Der Ton ist rau:
Super-heftig-Oberboss: "Hey, Untertan aus Hütte Nr. XX! Ich habe Arbeit für Dich!"
Nur der Untertan aus Hütte Nr. XX fühlt sich angesprochen, seine Nachbarn sind froh, nichts tun zu müssen.
Untertan aus Hütte Nr. XX: "Ja, Super-heftig-Oberboss?"
Super-heftig-Oberboss: "Fege den Hof, aber zack, zack!"
Super-heftig-Oberboss:"Gut so."
Oder aber:
Super-heftig-Oberboss: "Hey, Untertan aus Hütte Nr. XX! Was hast Du heute gearbeitet?"
Super-heftig-Oberboss: "Was nun?"
Untertan aus Hütte Nr. XX: "Äääh, ich habe 10245 Holzstücke gestapelt!"
Super-heftig-Oberboss: "Gut so."
Die "Übersetzung": Der Mikrocontroller schickt ein Start-Signal, gefolgt von einer I2C-Slave-Adresse (7 Bit) und einem R/W Bit auf den Bus.
So erfährt der I2C-Slave mit der passenden Adresse, ob Daten empfangen oder gesendet werden sollen und je nach Schreib- oder Lesebefehl antwortet der Slave oder der Master mit "ACK".
Das letzte Byte beim Lesen wird vom Master mit einem "NACK" bestätigt: Ende der Übertragung; wird durch das Stop-Signal beendet.
Soweit zur Theorie. In der Praxis nimmt uns Bascom viel Arbeit ab.
Uff!
Nun zu unserem I2C-LCD-Adapter:
Das ist der rot umrandete Bereich auf der Rückseite vom Display.
Er basiert auf dem PCF8574(A)-I2C Treiber, der die seriellen I2C-Daten in für unser LCD-Display verständliche Parallelsignale "übersetzt" und wohnt gewöhnlich in Hütte Nr. 78 oder 126
Er wird auf die Rückseite des LCDs gesteckt oder gelötet.
Kurzer Steckbrief:
- PCF8574(A)-Treiber
- Pins für SDA, SCL, Vcc und GND
- Unterstützt Industriestandard-LCDs mit ST7066 oder HD44780 Chip (praktisch alle 1602 und 2004-LCDs mit 14 (ohne Backlight) oder 16 Anschlusspins)
- Kontrasteinstellung mit Potentiometer
- Backlight mittels Jumper oder (zumeist) Mikrocontroller schaltbar
- I2C-Adresse mit 3 Lötbrücken (A0, A1, A2) änderbar
Gerade bei der Angabe der Adresse machen die Chinamänner oft Fehler!
Die Adresse wird wie folgt korrekt ermittelt:

Quelle: Datenblatt
PCF8574 Datasheet.pdf
Links sehen wir den PCF8574, rechts den PCF8574A. Sie unterscheiden sich ausschließlich in Ihren Basisadressen.
Zwischen (S) und (A) sehen wir 8 Bit:
Im Falle des PCF8574 sind das: 0 1 0 0 A2 A1 A0 0 und im Falle des PCF8574A: 0 1 1 1 A2 A1 A0 0
A0 - A2 sind die Lötbrücken. Es gilt negative Logik: Lötbrücke geschlossen = 0; Lötbrücke offen = 1
Das Bit ganz rechts ist das R/W Bit - für die Adressermittlung = 0.
Im Auslieferungszustand sind alle Lötbrücken offen; also I2C-Slave Adresse:
PCF8574 = &B01001110 = &H4E = 78
PCF8574A = &B01111110 = &H7E = 126
Also schön schauen, welcher Chip verbaut wurde oder ausprobieren.
Oder das folgende I2C-Slave Scanprogramm benutzen:
I2C-Scanner.zip
Das ist denkbar einfach: Tiny aufs Steckbrett, LCD im 4 Bit Modus (wie bisher) anschließen, den Adapter (ohne LCD) an Vcc, GND, SCL und SDA; Reset (10 kOhm), SCL und SDA mit 1kOhm Pullup-Widerständen auf Vcc; USBASP-Adapter anschließen, kompilieren, programmieren & Slave-Adresse ablesen:
"Hey, Untertan, isch weiß, wo Deine Hütte wohnt!"
Dann lassen wir ihn mal arbeiten. Das LCD bitte mit dem Adapter verbinden; Schaltung wie oben, natürlich jetzt ohne LCD im 4 Bit Modus.
Ein kleines Testprogramm und eine Neuerung:
Wir benutzen das erste Mal eine Bascom-Library.
Eine Library macht uns durch Unterroutinen in Maschinensprache das Leben leichter.
So ermöglicht uns die
lcd_i2c_v3.zip
unser neu angeschlossenes Display mit den gewohnten Befehlen zu nutzen.
Die Lib bitte entpacken und in das Verzeichnis
<Laufwerk>:\Program Files (x86)\MCS Electronics\BASCOM-AVR\LIB
kopieren.
Hier das Testprogramm:
|
Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
'***************************
'*
'* I2C-LCD Test
'*
'***************************
$regfile = "attiny4313.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$lib "Lcd_i2c_v3.lib" ' Library einbinden
Dim _out_rw As Byte ' s. u.
Dim _out_e2 As Byte ' s. u.
Dim _lcd_e As Byte ' Enable-Modi, s. u.
Config I2cdelay = 1 ' Schnelligkeit des I2C Busses; 1 ist am schnellsten
Config Scl = Portb.7 ' I2C Scl (Pin 19)
Config Sda = Portb.5 ' I2C Sda (Pin 17)
Const Pcf8574_lcd = &H7E ' I2C Slaveadresse des Adapters
Const Pcf_e2_is_output = 1 ' festlegen, dass E2 ein Ausgang ist
Const Pcf_rw_is_output = 1 ' festlegen, dass RW ein Ausgang ist
'*************** festlgen, welcher Pin des LCDs von welchem Pin des PCF8574A angesteuert wird
Const Pcf_d4 = 4
Const Pcf_d5 = 5
Const Pcf_d6 = 6
Const Pcf_d7 = 7
Const Pcf_rs = 0
Const Pcf_rw = 1
Const Pcf_e2 = 3
Const Pcf_e1 = 2
Dim I As Byte
Config Lcd = 16x2
Waitms 100
Display On
Waitms 100
Initlcd
Waitms 100
_lcd_e = 128 ' 64=E2 128=E1 192=E1+E2
_out_rw = 0 ' Ausgang einschalten
_out_e2 = 1 ' Hintergrundbeleuchtung
Do
Cls
Locate 1 , 1
Lcd "Test Zeile 1"
Locate 2 , 1
Lcd "Test Zeile 2"
Wait 5
Cls
Lcd "Countdown"
For I = 10 To 1 Step -1
Locate 2 , 1
Lcd I ; " "
Wait 1
Next I
Cls
Lcd "**** BOOOM! ****!"
Wait 5
Loop
End
|
Was passiert da?
In den Zeilen 17 - 19 sagen wir dem Compiler, dass wir den I2C-Bus flott benutzen wollen und welche die SCL- und SDA- Pins am Tiny sind (siehe auch Pinout-Abbildung in einem früheren Post).
In Zeile 13 binden wir die Library
Lcd_i2c_v3.lib ein.
Diese verlangt die Definition spezieller Variablen mit festgelegten Namen (Zeilen 14 - 16) und
Konstanten mit ebenfalls festgelegten Namen (Zeilen 20 - 22 und 24 - 31).
Die Erklärung entnehmt Ihr bitte den Kommentaren im Programm.
Besonders wichtig ist die Angabe der korrekten Slave-Adresse in Zeile 20. Die Adresse solltet ihr ja jetzt kennen.
Mit den Konstanten
Const Pcf_XX = <Pin>
in den Zeilen 24 - 31 sagt Ihr dem Compiler, an welchem Pin des PCF8574(A) z. B. Datenleitung 4 = Pin 4 angeschlossen ist. Ruhig einmal nachmessen.
E2 (Enable 2) existiert auf Standard-Displays nicht. Statt dessen können die meisten Adapter damit die Hintergrund-Beleuchtung des LCDs schalten.
Daher auch in Zeile 41:
_lcd_e = 128
Wir brauchen nur E1 = E.
Mit
_out_rw = 0
in Zeile 42 machen wir dasselbe wie bei der 4-Bit-Anbindung aus dem letzten Post. R/W liegt auf Masse.
Ansonsten können wir jetzt alle LCD-Befehle wie gewohnt benutzen.
Erwähnenswert ist noch die Zählschleife in Zeile 57 - 61. Mit
Step -1
geben wir die Schrittweite der einzelnen Zählvorgänge und ob addiert oder subtrahiert werden soll, vor.
Hier also jeweils Subtraktion von 1
Viel Spaß!
Hausaufgabe:
- Stellt das Blinker-Programm mit 4 Bit LCD Unterstützung auf das I2C-LCD um.
Schalten Sie auch nächstes Mal wieder ein, wenn sie die M&Ms sagen hören: "Resultate! Dem Manne kann geholfen werden!"
Viele Grüße
Mathias & Micha
Inhaltsverzeichnis aller Projekt-Posts in Post 1