Hallo,
ich versuche gerade, ein alphanumerisches LCD der Firma Newhaven an
einem ARM Cortex M0+ (SAMD20) in Betrieb zu nehmen. Das LCD wird über
I2C bedient und besitzt einen Controller vom Typ ST7036i. Ich habe schon
viel mit I2C gearbeitet, aber eine derartig verkorkste
I2C-Implementierung ist mit bisher noch nicht untergekommen. Die
Initialiserungsroutine habe ich sinngemäß aus dem Datenblatt übernommen:
1 | void init_LCD()
|
2 | {
|
3 | I2C_Start();
|
4 | I2C_out(Slave);//Slave=0x78
|
5 | I2C_out(Comsend);//Comsend = 0x00
|
6 | I2C_out(0x38);
|
7 | delay(10);
|
8 | I2C_out(0x39);
|
9 | delay(10);
|
10 | I2C_out(0x14);
|
11 | I2C_out(0x78);
|
12 | I2C_out(0x5E);
|
13 | I2C_out(0x6D);
|
14 | I2C_out(0x0C);
|
15 | I2C_out(0x01);
|
16 | I2C_out(0x06);
|
17 | delay(10);
|
18 | I2C_Stop();
|
Für die Kommunikation verwende ich das interne SERCOM-Modul und kein
Bit-banging wie im Datenblatt. Die I2C-Routinen funktionieren mit
anderen Bauteilen wie einem 24C256-EEPROM problemlos, deshalb nehm ich
an, dass sie korrekt sind.
Leider läuft die Kommunkation mit dem LCD nicht durch:
Die Adresse und die ersten beiden Bytes werden korrekt übertragen (der
Slave antwortet mit ACK), beim Kommando 0x39 hängt er sich dann auf
(NAK).
Ich vermute einen Zusammenhang mit dem Befehl "delay(10)", dessen
Bedeutung mir nicht ganz klar ist. Ich denke dass der Slave hier etwas
länger braucht und per Clock-Stretching um etwas mehr Zeit bittet. Ein
solches Clock-stretching kann ich im Oszilloskop aber nicht erkennen.
Als Umgehungslösung
sende ich jetzt jedes Kommando in einem einzelnen Buszyklus, natürlich
jeweils mit dem Kommandobyte 0x00 davor. Damit funktioniert die
Initialsierung, allerdings nur bei 100kHz Taktfrequenz. Bei den nach
Datenblatt erlaubten 400kHz kommt es weiterhin zu gelegentlichen NAKs.
Ein weiteres Problem bringt mich zum Verzweifeln: Wie lese ich das
Busy-Flag aus? Laut Datenblatt muss ich dazu das RS-bit auf 0 und R/W
auf 1 setzen. Sende ich aber das Adressbyte mit gesetztem R/W-bit,
verweigert das Display die Antwort.
Mir ist vor allem aber nicht klar, wie ich das RS-bit dem Display
mitteilen soll. Dazu muss ich doch erst einmal ein Kommandowort
schicken, also R/W auf 0 setzen. Wie mache ich das? Ich habe schon
folgendes Schema in Analogie zum Lesezugriff auf ein 24C256 versucht,
jedoch ebenso ohne Erfolg:
1 | I2C_Start();
|
2 | I2C_out(Slave);//Slave=0x78, R/W = 0
|
3 | I2C_out(Comsend);//Comsend = 0x00
|
4 | I2C_Start(); //repeated start condition
|
5 | I2C_out(Slave+1); //Slave = 0x78, R/W=1
|
6 | byte = I2C_in();
|
7 | I2C_Stop();
|
Die Dokumentation des Displays liefert hier kein Beispiel. Leider
schweigt sich auch das Datenblatt des St7036i über die Leseprozedur aus.
Ich bin inzwischen mit meinem Latein am Ende und vermute einen Fehler im
St7036i-Controller oder in der Dokumentation. Oder habe ich etwas
Grundlegendes übersehen?
Deshalb meine Frage hier im Forum: Kennt sich jemand mit dem Teil aus
und kann mir einen Tipp geben?
Vielen Dank