Forum: Mikrocontroller und Digitale Elektronik Problem mit Ansteuerung TWI LCD Textdisplay (HD44780)


von Peter H. (hp-soft)


Angehängte Dateien:

Lesenswert?

Hallo zusammen.
Ich bin aus der BASCOM Ecke über Arduino endlich bei C angekommen. Seit 
2 Jahren versuche ich mich nun an der C-Programmierung. Da ich ungern 
irgendwelche fertigen Programmlösungen verwende, versuche ich selbst an 
der Realisierung.
Jetzt aber mal zu meinem Problem.
Ich habe eine TWI_LCD.lib geschrieben, um ein normales Textdisplay mit 
dem HD44780 Chip anzusteuern. Mein Code funktioniert eigentlich bis 
jetzt ganz gut. Ich kann einen Text und auch Zahlen darstellen.
ABER:
Die Hintergrundbeleuchtung geht nicht an. Irgendwo habe ich in meinem 
Spagetti - Code noch einen Fehler. Ich kann ihn aber leider noch nicht 
finden.
Vielleicht ein Denkfehler oder ein Timing Problem. Am LCD liegt es 
nicht. Ich habe mal meine 4 Bit Ansteuerung damit getestet und alles 
Funktioniert. Meine eigene TWI Lib. funktioniert auch.

Kann mir vielleicht jemand weiterhelfen.
(Ja, mein Code ist nicht schön geschrieben und es gibt auch viele 
Verbesserungsvorschläge und Optimierungen. Auch kenne ich die 
funktionierende Software für TWI LCD hier aus dem Forum. Ich bin für 
selbstgemachtes.)
ich hänge die zugehörige LCD_I2C.h hier an:
/*
 * LCD_I2C.h
 *
 * Created: 06.09.2022 08:45:28
 *  Author: Peter Hell
 */


#ifndef LCD_I2C_H_
#define LCD_I2C_H_

/* LCD Pinbelegung */
#define LCD_PIN_RS        0x01
#define LCD_PIN_RW        0x02
#define LCD_PIN_E        0x04
#define LCD_PIN_D4        0x10
#define LCD_PIN_D5        0x20
#define LCD_PIN_D6        0x40
#define LCD_PIN_D7        0x80

/*LCD Steuerbefehle*/
#define LCD_CLEAR        0x01
#define LCD_HOME        0x02
#define LCD_ON          0x0C
#define LCD_ON_C        0x0E
#define LCD_OFF          0x08
#define LCD_SET_4BIT      0x28
#define LCD_SET_2        0x06
#define LCD_SETDDRAM      0x80

/*Hilfsdefinitionen*/
#define LCD_Befehl        0
#define LCD_Daten        1

//Funktionen*/
void lcd_init();
void lcd_send(uint8_t type, uint8_t lcd_command);
void lcd_write(char * t);
void lcd_ein(void);
void lcd_aus(void);
void toggle_enable(void);
void sekunde(uint8_t i);


#endif /* LCD_I2C_H_ */

: Verschoben durch Moderator
von Hmmm (Gast)


Lesenswert?

Peter H. schrieb:
> Die Hintergrundbeleuchtung geht nicht an.

Damit hat der HD44780 nichts zu tun. Was sagt das Datenblatt des 
LCD-Moduls dazu?

von Peter H. (hp-soft)


Lesenswert?

Hmmm schrieb:
> Damit hat der HD44780 nichts zu tun. Was sagt das Datenblatt des
> LCD-Moduls dazu?

Also, ich habe mir das Datenblatt vom HD44780 (HITACHI) angesehen.
Das stehen die einschlägigen Steuerbefehle für das LCD drin.
Damit hat ja auch die LCD Initialisierung (zumindest teilweise) 
funktioniert. Und das Display zeigt auch meine Texte und Zahlen richtig 
an. Halt eben nur ohne Beleuchtung.
Außerdem funktioniert mein anderer Code mit der direkten 4Bit 
Adressierung über einen AVR Port (ohne I2C) mit den gleichen 
Steuerbefehlen.
Nur wird mir beim umschreiben auf I2C ein Fehler unterlaufen sein, den 
ich aber nicht finden kann.

: Bearbeitet durch User
von Schlaumaier (Gast)


Lesenswert?

Peter H. schrieb:
> Also, ich habe mir das Datenblatt vom HD44780 (HITACHI) angesehen.

Nicht richtig.

https://www.playembedded.org/blog/hd44780-lcdii-and-chibioshal/

Pin 15 + 16.

Ich benutze zwar diese i2c-Adapater aber ich würde mal frech behaupten 
wenn ich (wie eine normale LED) Pin 15 + 16 anschließe geht die 
Beleuchtung an.

Ergo musst du die Beleuchtung als LED Programmieren. ;)

von Peter H. (hp-soft)


Lesenswert?

Hätte ich ja direkt dazuschreiben können.
Ich benutze auch das 16 Pol. i2C Modul mit dem PCF8574.
Zwischenzeitlich habe ich mal die HD44780_PCF8574 aus dem Forum geladen 
und getestet. Die funktioniert richtig.
Also liegt der Fehler in meinem Programm. Aber wo??

von Hmmm (Gast)


Lesenswert?

Peter H. schrieb:
> Ich benutze auch das 16 Pol. i2C Modul mit dem PCF8574.

Das einzige Modul, das es gibt, klar. Link zu Produkt und/oder 
Datenblatt?

Peter H. schrieb:
> Also liegt der Fehler in meinem Programm.

Ich wiederhole es nochmal: Der HD44780 steuert NUR das LCD, der hat mit 
der Hintergrundbeleuchtung NICHTS zu tun.

Wie die angesteuert wird, hängt vom verwendeten Modul ab. Es können 
einfach getrennte Pins sein oder sogar nur ein Widerstand, der auf dem 
Modul noch bestückt werden muss, das findest Du im Datenblatt des Moduls 
(nicht des HD44780).

Dass das Modul überhaupt eine Hintergrundbeleuchtung hat, weisst Du 
aber?

von Schlaumaier (Gast)


Lesenswert?

Hmmm schrieb:
> Peter H. schrieb:
>> Ich benutze auch das 16 Pol. i2C Modul mit dem PCF8574.
>
> Das einzige Modul, das es gibt, klar. Link zu Produkt und/oder
> Datenblatt?

So seiner Verteidigung muss ich sagen das ich auch nur EIN Kenne. Das 
hier :
https://www.christians-shop.de/I2C-IIC-Serielle-Schnittstelle-fuer-LCD-Display-1602-und-2004

Den Rest macht die Libs.

lcd.Blacklight = true ' und schon ist es an.

Ich hatte in meiner Aussage das NACKTE LCD-Modul gedacht. Das wo man wie 
im Link ganze viele Kabel zum Steuergerät (UNO / Nano etc.) schicken 
muss.
Da mir die Pins immer zu wenig sind,  sind Display's (Egal ob LCD o. 
OLED) das erste was an den I2C-Bus bei mir kommt.

Peter H. schrieb:
> Also liegt der Fehler in meinem Programm. Aber wo??

Ich würde folgendes machen.

Suche in der Libs nach BACKLIGHT und schau wie da was gemacht wird. Wenn 
das Modul das selbe ist, ist die Ansteuerung auch die selbe.

Ach und nur so nebenbei. Vergiss nicht auf den Modul die Schraube 
mächtig zu drehen. ALLE Module ich ich gekauft habe, waren so mies 
eingestellt das ich > 2 Umdrehungen gebraucht habe bis ich was gesehen 
habe. Und ich habe 8 Stück aus 3 Quellen :)

von Peter H. (hp-soft)


Lesenswert?

Schlaumaier schrieb:


Habe das Problem gelöst. Danke an Schlaumaier.

von Hmmm (Gast)


Lesenswert?

Peter H. schrieb:
> Habe das Problem gelöst.

Wenn Du wenigstens jetzt mal beantwortest, um welches LCD-Modul es geht 
und wie Du es gelöst hast, könnte das später nochmal anderen Leuten 
weiterhelfen.

von Manfred (Gast)


Lesenswert?

Hmmm schrieb:
>> Also liegt der Fehler in meinem Programm.
> Ich wiederhole es nochmal: Der HD44780 steuert NUR das LCD, der hat mit
> der Hintergrundbeleuchtung NICHTS zu tun.

Der HD44780 nicht, wohl aber der I2C-Konverter PCF8574.
Der muss seine Ausgänge zum Display passend angesteuert bekommen, mal 
ein Beispiel aus Arduino:
1
// Set the pins on the I2C chip used for LCD connections:
2
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
3
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

Am Ende "bl,blpol" dürften die sein, die die Beleuchtung ansteuern.

von Peter Hell (Gast)


Lesenswert?

Hmmm schrieb:
> Wenn Du wenigstens jetzt mal beantwortest, um welches LCD-Modul es geht
> und wie Du es gelöst hast, könnte das später nochmal anderen Leuten
> weiterhelfen.

Das LCD-Modul ist wie in der Überschrift geschrieben ein Textdisplay
genau gesagt ein QAPASS.  Es ist 16 polig. Hersteller kenne ich nicht. 
Irgendein Chinese.
Die Problemlösung war einfach nur 0x08 an den I2C Controller schicken

von Holger L. (max5v)


Lesenswert?

Peter Hell schrieb:
> QAPASS

Geil :-)

QA = quality assurance = Qualitätssicherung
PASS = Prüfung im Sinne von pass through also durchlaufen, bestanden

Nur so, ich mußte ein wenig schmunzeln.

von Wilhelm S. (wilhelmdk4tj)


Lesenswert?

Hallo zusammen.

Peter H. schrieb:
> Ich bin aus der BASCOM Ecke über Arduino endlich bei C angekommen.

Was bildest du dir darauf ein?
Andere haben gleich mit C angefangen, und wieder andere hassen Arduino, 
erst recht C und kommen mit BASCOM bestens zurecht.

73
Wilhelm

von Peter Hell (Gast)


Lesenswert?

Wilhelm S. schrieb:
> Was bildest du dir darauf ein?
> Andere haben gleich mit C angefangen, und wieder andere hassen Arduino,
> erst recht C und kommen mit BASCOM bestens zurecht.

Bist Du mit dem falschenFuß aufgestanden oder einfach nur auf kravall 
gebürstet???

von Karl B. (gustav)


Lesenswert?

Hi,
was mir dazu einfällt:
der Portadapter kann verschiedene Adressen haben.
Und 7 Bit. Auf 8 Bit dann ergänzen.

"...Thus, one covers slave addresses’ range from $27 to $20, and when 
using the unit PCF8574A from $3F to $38..."
Aber das war ja nicht die Frage

Beleuchtung kann "softwaremäßig" ein- und ausgeschaltet werden.
Dazu aber dann Bits im String "verkapseln".
Muss man sowieso, da Enable, Read/write etc. nicht als Extra-Pins 
herausgeführt werden.
"...The string for backlight on should read: 0b00001000 or $08..."
stand oben ja schon...
Doppelt gemoppelt hält besser ;-)

ciao
gustav

: Bearbeitet durch User
von my2ct (Gast)


Lesenswert?

Karl B. schrieb:
> Hi,
> was mir dazu einfällt:
> der Portadapter kann verschiedene Adressen haben.
> Und 7 Bit. Auf 8 Bit dann ergänzen.

I2C kennt lt. I2C-Spezifikation nur 7-Bit Adressen (wenn man von der 
eher exotischen 11-Bit Variante absieht).

Oder hast du bei dir an der Haustür auch zwei verschiedene Nummern - je 
nach Bewegungsrichtung - dran stehen?

von Karl B. (gustav)


Lesenswert?

my2ct schrieb:
> Oder hast du bei dir an der Haustür auch zwei verschiedene Nummern - je
> nach Bewegungsrichtung - dran stehen?

Hi,
wenn man es vom 8-Bit Standpunkt aus sieht, natürlich.
Das WR-Bit wird einfach dazugerechnet.

ciao
gustav

von Wolfgang (Gast)


Lesenswert?

Karl B. schrieb:
> Das WR-Bit wird einfach dazugerechnet.

Das gehört aber nicht zur Adresse, sondern bestimmt die Richtung.

Beispiele für die Byte-Aufteilung bei I2C stehen doch nun wirklich in 
fast jedem Datenblatt von I2C-Komponenten.

von Wolfgang (Gast)


Angehängte Dateien:

Lesenswert?

Hier noch das Bild dazu aus den I2C Specs (UM10204 von NXP)
Adresse: 1-7 (1,2,3,4,5,6,7)

von W.S. (Gast)


Lesenswert?

Holger L. schrieb:
> Peter Hell schrieb:
>> QAPASS
>
> Geil :-)

Ist wie im Witz zu Kanzler Kohl aud Afrikareise: In einem Nationalpark 
sahen er und Hannelore eine Menge verschiedener Tiere und Hannelore 
fragte, was das eine oder andere Tier denn sei. Und der gute Helmut 
antwortete immer "Das ist ein Dangoro". Irgendwann wurde Hannelore 
stutzig und fragte ihn, woher er denn das weiß. Antwort von Helmut: "Am 
Eingang stand ein Schild, worauf zu lesen war 'ALL AMIMALS ARE 
DANGOROS'"...

W.S.

von Karl B. (gustav)


Lesenswert?

OK. Man könnte sich auf die Formulierung einigen:
Slaveadresse plus RW-Bit.
Ich muss 8 Bit haben.
Einfach 7 Bit eingeben, nimmt der µP nicht.
Nur das ist für mich interessant, was ich beim Programmieren eingeben 
muss.
Alles andere ist einfach nur Korinthenk...und trägt zur Verwirrung bei.


lcdinit:
;LCD-Port:    D0-D3=n.c.; D4-D7=Daten;
;
;      ; P7 | P6 | P5 | P4 | P3 | P2 | P1 | P0
;      ; D7 | D6 | D5 | D4 | LED| ENA| R|W| RS
;      ;=======================================
rcall wait3        ; LCD POSR abwarten
rcall twistart
ldi temp, 0x70      ; Slave Startadresse + RW-Bit
rcall twiout      ; PCF8574->0x40; PCF8574A->0x70
rcall lcd_achtbitinit  ; LCD-Init: acht Bit
rcall lcd_acht_vier    ; LCD-Init: acht zu vier Bit
rcall lcd_vier_zwei_z  ; LCD-Init: vier Bit, 2 Zeilen
rcall lcd_on_off    ; LCD-Init: Displaypuffer aus
rcall lcd_clear      ; LCD-Init: Anzeige loeschen
rcall lcd_entrymode    ; LCD-Init: Entry Mode Set
ret
;
lcd_achtbitinit:
ldi temp, 0b00001000  ; LED-Hintergrundlicht ein
rcall twiout

...

ciao
gustav

von Wilhelm S. (wilhelmdk4tj)


Lesenswert?

Hallo zusammen.

Peter Hell schrieb:
> Bist Du mit dem falschenFuß aufgestanden oder einfach nur auf kravall
> gebürstet???

Nein, weder noch! Der TO erweckte nur den Eindruck als hätte er sich nun 
mit C die 'ultimativste' aller Programmiersprachen angeeignet. Dem 
wollte ich widersprechen.
In diesem (keinem) Forum will ich über DIE! Programmiersprache 
diskutieren.

73
Wilhelm

von W.S. (Gast)


Lesenswert?

Peter H. schrieb:
> /* LCD Pinbelegung */
> #define LCD_PIN_RS        0x01
> ...

So etwas gehört eigentlich nicht in eine Header-Datei, denn es betrifft 
nur die innere Funktionalität des Displaytreibers - oder eben nur die 
innere Funktionalität des I2C-Treibers, der dann vom Displaytreiber 
benutzt wird.

Denke mal daran, daß du besser nur das in die .h Datei schreibst, was 
von den aufrufenden Programmteilen auch wirklich benötigt wird. Sonst 
gibt es sehr leicht und schnell Spaghetticode, weil man gar zu leicht 
meint, mit sowas dann in den höheren Schichten der Firmware 
herumfuchteln zu müssen. Ich habe hier schon grauenvolle Quellen 
gesehen, wo sogar in main() noch an irgendwelchem Zeug herumfuchtelt, 
das in die zugehörigen Treiber gehört.

Also: wenn du dein LCD per I2C benutzen willst, dann schreibe dir 
zunächst einen Lowlevel-I2C-Treiber und teste ihn gründlich. Dieser 
Treiber wäre dann für alle Geräte da, die am I2C hängen. Nicht nur für 
das Display. Dazu braucht er nur wenige Funktionen für die allgemeine 
Anwendung bekanntzugeben, entsprechend kurz ist dann die .h Datei.

void I2C_Init(void);
bool OpenSlave(byte Adresse, bool RW);
bool WriteSlave(byte Datenbyte);
byte ReadSlave(bool ObMitAck);
void CloseSlave(void);

Mehr braucht es für die aufrufenden Programmteile nicht.
So, damit braucht der Displaytreiber sich um die allerunterste Schicht 
nicht mehr selbst zu kümmern.
Ähnlich geht es, wenn man ein Display byteweise ansteuert. Dann kommt 
die allerunterste Schicht (Verwalten von A0, RW, C, Datenbyte) in einen 
separaten Treiber, der dann ähnlich gestaltete Funktionen bietet, so daß 
sich der eigentliche Displaytreiber nicht um das physische Signalspiel 
kümmern muß.
Mit so einer Herangehensweise zerteilt man ein Gesamtproblem in kleinere 
überschaubare Stücke, so daß man es insgesamt besser lösen kann.

W.S.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.