Hallo Forum, habe das Forum abgescannt und viele Vorschläge getestet, aber leider nicht erfolgreich. Nutze Atmel Studio 7.0, die LCD und I2C Haeder- und C-Dateien von Peter Fleury mit einem Atmega 328P mit 16 MHz. Habe bisher ein 2x16 Display genutzt. Alles funktioniert einwandfrei. Habe mir jetzt mehrer 4x20 Displays gekauft. In den Headerdateien die defines auf 4 Zeilen und 20 Spalten und die Zeilenadressen angepasst. Funktioniert bedingt, die Zeilendarstellung bekomme ich nicht hin. Mir ist bekannt, das die Zeile 1 in Zeile 3, respektive Zeile 2 in Zeile 4 fortgesetzt wird. Das funktioniert auch einwandfrei. Ich möchte aber nach einem "lcd_print nextline()" eine neue Zeile nutzen. Nach Zeile 1 klappt es, da die Zeilenadresse für Zeile 2 0x40 wohl übernommen wir. Habe mehrer Vorschläge für die Zeilen wie z.B. 0x00, 0x40, 0x14, 0x54 getestet. lcd_print nextline wird ab Zeile 2 nicht angenommen. Ich habe im Datenblatt des 2004A gesehen, dass als LCD Controller ein ST7066U verbaut ist. Ist u.U dieser Baustein nicht kompatibel mit HD 44870 etc.
Das LCD enthält einfach nur einen großen Buffer in den dies strings (als ASCII) reingschrieben werden. Das nextline macht deine library im hintergrund. Solange wir die nicht kennen ist alles nutzlos....
Heinz W. schrieb: > Ich habe im Datenblatt des 2004A gesehen, dass als LCD Controller ein > ST7066U verbaut ist. Ist u.U dieser Baustein nicht kompatibel mit HD > 44870 etc. Hi, habe 2 x 16 LCDs mit KS0066U-(ST7066) selber getestet. Kein Unterschied. Was vielleicht etwas anders sein kann, sind die Befehlsausführungszeiten und die Pausen zwischen den einzelnen Schritten gerade bei der Initialisierung. Und wenn es ein 40-er sein sollte, der zwei Controller hätte, dann müsstest Du auch 2 Enable Anschlüsse haben. Und entsprechend 2x Enableimpuls senden (jeweils einen auf den jeweiligen Pin.) Ist aber wohl nicht so. Wie sieht deine Befehlsfolge zu "locate" aus? Bei mir: Schnipsel in ASM. Wobei zwei Routinen drin sind. Einmal Befehl auf LCD dann Charakter auf LCD Die kennst Du bestimmt schon, brauche ich hier nicht ausführen. Die Anfangsadressen findest Du doch durch Addition raus. Schau Dir das Dabla für die Funktionsaufrufe einmal daraufhin an. ciao gustav
:
Bearbeitet durch User
Heinz W. schrieb: > Habe mir jetzt > mehrer 4x20 Displays gekauft. In den Headerdateien die defines auf 4 > Zeilen und 20 Spalten und die Zeilenadressen angepasst. Das reicht u.U. nicht. Welche Library ist es denn? Es gibt ja nur ca. hundert verschiedene ... > Funktioniert bedingt, die Zeilendarstellung bekomme ich nicht hin. Großartige Fehlerbeschreibung! > Mir ist bekannt, > das die Zeile 1 in Zeile 3, respektive Zeile 2 in Zeile 4 fortgesetzt > wird. Das funktioniert auch einwandfrei. Ich möchte aber nach einem > "lcd_print nextline()" eine neue Zeile nutzen. Ja, dann machs halt. Der Code für die Behandlung des NEWLINE Zeichens muß die aktuelle Zeile anschauen und basierend darauf die Schreibposition und die (neue) aktuelle Zeile setzen. Für ein 4-Zeilen Display brauchst du also eine Kette aus 4 if() Statements. Irgendwo da hast du einen Fehler drin. Zeig den Code!
Den Antworten zu urteilen habe ich nicht hinreichend klar formuliert. Grundsätzlich ist die Funktion gegeben. Habe diese kurze Routine: i2c_init(); lcd_init(); DDRB = 0xFF; PORTB = (1<<PB1); _delay_ms(100); lcd_command(LCD_DISPLAYON); _delay_ms(1000); lcd_command(LCD_CLEAR); _delay_ms(2); lcd_light(1); lcd_command(LCD_HOME); lcd_print("Zeile 1:XXXXXXXXXXXX"); lcd_nextline(); lcd_print("Zeile 2:yyyyyyyyyyyy"); lcd_nextline(); lcd_print("Zeile 3:ZZZZZZZZZZZZ"); lcd_nextline(); lcd_print("Zeile 4:UUUUUUUUUUUU"); Ergebnis: Display Zeile 1:Zeile 1:XXXXXXXXXXXX Display Zeile 2:Zeile 4:UUUUUUUUUUUU Display Zeile 3: Display Zeile 4:Zeile 3:ZZZZZZZZZZZZ Display Konfiguration in i2clcd.h #define LCD_I2C_DEVICE 0x4E #define LCD_LINES 4 #define LCD_COLS 20 #define LCD_LINE_MODE LCD_4LINE #define LCD_LINE1 0x00 #define LCD_LINE2 0x40 #define LCD_LINE3 0x15 #define LCD_LINE4 0x54 Danke für einen Tipp.
hast du den thread gelesen ? WAS FÜR EINE LIBRARY VERWENDEST DU ? es gibt ja nicht nur eine i2clcd.h auf diesem Planten....
Hat er doch geschrieben, die Peter Fleury library hier aus dem Forum.
Versuche mal #define LCD_LINE1 0x00 #define LCD_LINE2 0x38 #define LCD_LINE3 0x14 #define LCD_LINE4 0x54 oder #define LCD_LINE1 0x00 #define LCD_LINE2 0x38 #define LCD_LINE3 0x28 #define LCD_LINE4 0x48 Das sind Werte die ich früher bei 20x4 Displays verwendet hatte.
Bei mir sehen die Adressen anders aus: Siehe Bild. Ist I2C über USI Krücke. Funktioniert aber. Ob das I2C ist oder sonstwas, (über den PIC Adapter): die Startadressen sind LCD-spezifisch. https://bin-dez-hex-umrechner.de/ Max D. schrieb: > Das LCD enthält einfach nur einen großen Buffer in den die strings (als > ASCII) reingeschrieben werden. Immer alternierend addieren: in Dezimal: 128 192 148 212 Wieso das so ist, liegt am Displaycontroller. Frag mich nicht, der Hersteller hat sich da was gedacht. Vermutung: Es werden für verschiedene "Längen" eben dieselben Controller verwendet. Und da gibt es eben "Lücken", weil nicht alles was adressierbar wäre, auch angezeigt werden kann. Z.B. bei einem 2 x 16 die restlichen 4 Stellen fehlen. Dafür gibt es aber keine "Extrawurst". ciao gustav
:
Bearbeitet durch User
Karl B. schrieb: > Frag mich nicht, der Hersteller hat sich da was gedacht. Das liegt unter anderem daran, das es einen Expanderchip für den alten HD44780 gibt, den HD44100. Der hängt als Unterling am 44780 und füllt die fehlenden Speicheradressen. (Gut, es ist ein wenig komplizierter, aber das Prinzip ist so).
Du hast doch fast alle notwendigen Werte schon gefunden... Heinz W. schrieb: > Ergebnis: > > Display Zeile 1:Zeile 1:XXXXXXXXXXXX > Display Zeile 2:Zeile 4:UUUUUUUUUUUU > Display Zeile 3: > Display Zeile 4:Zeile 3:ZZZZZZZZZZZZ > > Display Konfiguration in i2clcd.h > > #define LCD_I2C_DEVICE 0x4E > #define LCD_LINES 4 > #define LCD_COLS 20 > #define LCD_LINE_MODE LCD_4LINE > > #define LCD_LINE1 0x00 > #define LCD_LINE2 0x40 > #define LCD_LINE3 0x15 > #define LCD_LINE4 0x54 Zeile 1 erscheint mit richtigem Inhalt an der gewünschten Position. Also ist #define LCD_LINE1 0x00 richtig. In Zeile 2 erscheint der Inhalt für Zeile 4. Also änderst du LCD_LINE4 von 0x54 auf 0x40. In Zeile 4 kommt der Inhalt für Zeile 3. Also wird LCD_LINE3 zu 0x54. Fehlt noch die Zeile 2. 0x15 ist mit Sicherheit falsch. Sinnvoller wäre 0x14 (20 Zeichen Versatz). Macht als Tabelle: #define LCD_LINE1 0x00 #define LCD_LINE2 0x14 #define LCD_LINE3 0x54 #define LCD_LINE4 0x40
Heinz W. schrieb: > lcd_command(LCD_HOME); > lcd_print("Zeile 1:XXXXXXXXXXXX"); > lcd_nextline(); > lcd_print("Zeile 2:yyyyyyyyyyyy"); > lcd_nextline(); > lcd_print("Zeile 3:ZZZZZZZZZZZZ"); > lcd_nextline(); > lcd_print("Zeile 4:UUUUUUUUUUUU"); Das halte ich generell für grenzwertig. Die (uralte) Fleury-Lib die ich hier in einem Projekt verwende, hat ein Konfigurationsflag LCD_WRAP_LINES (defaultmäßig aktiv) und schaltet am Ende einer Zeile automatisch auf die nächste Zeile. Da du oben immer 20 Zeichen ausgibst, wären in diesem Fall die Aufrufe von lcd_nextline() komplett unnötig. Und ganz generell würde ich da eher lcd_gotoxy() verwenden. > Display Konfiguration in i2clcd.h > > #define LCD_LINE1 0x00 > #define LCD_LINE2 0x40 > #define LCD_LINE3 0x15 > #define LCD_LINE4 0x54 Wenn du nicht gerade ein ganz und gar exotisches Display hast, dann müßte das so aussehen: #define LCD_LINE1 0x00 #define LCD_LINE2 0x40 #define LCD_LINE3 0x14 #define LCD_LINE4 0x54 Wenn ich bei einem Display nicht sicher bin, dann fülle ich einfach mal das Display-RAM mit dem ASCII (oder was das Display dafür hält) Zeichensatz. In einer Schleife mit ein paar 100ms Pause nach jedem Zeichen. Da sieht man dann sehr gut, welche Zeile welcher Adresse entspricht.
Max D. schrieb: > Das nextline macht deine library im > hintergrund. > Solange wir die nicht kennen ist alles nutzlos.... Axel S. schrieb: > Das reicht u.U. nicht. Welche Library ist es denn? Es gibt ja nur ca. > hundert verschiedene ... ? Heinz W. schrieb: > die LCD und I2C Haeder- und > C-Dateien von Peter Fleury mit einem Atmega ich zeige sie euch, muss schwer sein ;) http://www.peterfleury.epizy.com/avr-software.html Axel S. schrieb: > Wenn ich bei einem Display nicht sicher bin, dann fülle ich einfach mal > das Display-RAM mit dem ASCII (oder was das Display dafür hält) > Zeichensatz. In einer Schleife mit ein paar 100ms Pause nach jedem > Zeichen. Da sieht man dann sehr gut, welche Zeile welcher Adresse > entspricht. genauso, oder in die LIB schauen und passend machen, sehe da auch keine Probleme. Habe mit der Fleury LIB auch angefangen, sehr gut zu verwenden unter AVR oder Arduino(Atmel AVR) wer keine anderen findet.
Heinz W. schrieb: > Habe mir jetzt > mehrer 4x20 Displays gekauft. Hi, gibt es dazu Datenblätter? http://www.sprut.de/electronic/lcd/ ciao gustav
Schreibe doch einfach alle Buchstaben von A-Z und von a-z ab der DD-RAM-Adresse 0 aufs Display. Dann kannst Du einfach ausrechnen, wo die weiteren Zeilen beginnen. Wenn Du dann noch nichts in einer Zeile siehst, setzte voher den Cursor auf 0x20, 0x30 oder 0x40 und probiere es noch mal. In dem Datenblatt für ein 4x20 display ist die Rede von einem "1-line mode" mit linearen Adressen von 0x00-0x4F (0-79), sowie ein "2-line mode" mit Adressen von 0x00-0x27 Zeile 1 (und vermutlich nahtloser Übergang in Zeile 3) und 0x40-0x67 für Zeile 2 (weiter in 4). https://www.beta-estore.com/download/rk/RK-10290_410.pdf Was bei diesen Speicherorganisationen dann nicht geht ist scrollen des Display-Inhaltes. Edit: nicht CG-RAM sondern DD-RAM Adresse. CG ist der Speicher zum definieren eigener Sonderzeichen.
:
Bearbeitet durch User
Hi, ist der Unterschied von 2004 zu 2004A so groß? Oben sind die Anfangs-Adressen des SainSmart2004 schon einmal angegeben worden. Beitrag "Re: LCD 4x20 2004A auf Zeilen schalten" Könnte man doch einmal ausprobieren, oder? ciao gustav
Hallo Forum -- ich bin schon fast verzweifelt-- habe in der Zwischenzeit alle?? Vorschläge zur 4 Zeilen Darstellung auf dem Display 2004A mit I2C Interface (LCD und I2C Haeder- und C-Dateien von Peter Fleury) ausprobiert. Leider funktioniert es nicht. Habe ein weiteres Display nach dem AVR-GCC-Tutorial/LCD-Ansteuerung vorbereitet und siehe da, alles funktioniert wunschgemäß. Bei der I2C Anbindung und der 4 Zeilen Konfiguration erhalte ich bei folgender Sequenz: lcd_gotolc(1,5); lcd_print("12345"); lcd_gotolc(1,30); lcd_print("ABCD"); lcd_gotolc(2,8); lcd_print("56789"); lcd_gotolc(2,85); lcd_print("EFG"); Das im Bild dargestelle Ergebnis. Die Zeilenadressen habe ich die aus dem Programm s.o. übernommen. Bei erhärtet sich der Eindruck, dass durch i2clcd.c der gewünschte Modus vom Display nicht umgeschaltet wird. Für einen Tipp oder erprobte Routine wäre ich dankbar. MfG Heinz
Bitte probier das folgende Programm aus und zeige uns die Ausgabe: (ich kenne nicht den Namen deiner Funktion, die nur ein Zeichen ausgibt, ich nenne sie mal lcd_lcd_char) char i; lcd_initialisieren(); (heisst bei dir bestimmt anders) lcd_gotolc(1,1); for (i = 0x21; i < 0x72; i++) { lcd_lcd_char(i); } Das sollte dir das gesamte Display voll schreiben.
lcd_gotolc(1,5); lcd_print("12345"); Die nächste Schreibposition ist 10. lcd_gotolc(1,30); In Zeile1 gibt es keine Pos.30! Die Funktion wird nix tun. lcd_print("ABCD"); Hier wird nun ab Pos10 weitergeschrieben. Ändere die 30 auf 18.
Vllt. das hier mal ausprobieren! #define LCD_LINE1 0x00 #define LCD_LINE2 0x20 #define LCD_LINE3 0x40 #define LCD_LINE4 0x60 Sind zwar Adressen für einen KS0073 aber mal probieren. Schau bitte auch mal ins Datenblatt ob ein sog. Erweiterungs Bit RE, für Sonderfunktionen (Function Set)setzen musst zum Umschalten in den 4 Bit Modus.
Ich hatte vor kurzem auch ein Problem mit der LCD-Library von Peter Fleury bei 16 MHz. Ich vermute ein Timing-Problem mit der internen delay-Funktion. Ich meine, etwas in der Library von 4 Mhz gelesen zu haben. Eventuell liegt hier die Herausforderung!?
Das meine ich: [c] /*********************************************************************** ** delay for a minimum of <us> microseconds with a 4Mhz crystal, the resolution is 1 us ************************************************************************ */ static void delay(uint16_t us) { while ( us ) us--; } [-c] Bei 16 MHz sind das dann keine 1µs Wartezeit.
Das meinte ich:
1 | /*************************************************************************
|
2 | delay for a minimum of <us> microseconds
|
3 | with a 4Mhz crystal, the resolution is 1 us
|
4 | *************************************************************************/
|
5 | static void delay(uint16_t us) |
6 | {
|
7 | while ( us ) us--; |
8 | }
|
Bei 16 MHz ist das dann keine 1µs Wartezeit.
Als "Kopiervorlage":
1 | #define F_CPU 16000000UL (falls nicht im Projekt eingetragen)
|
2 | |
3 | #define LCD_LINES 4
|
4 | #define LCD_DISP_LENGTH 20
|
5 | #define LCD_LINE_LENGTH 0x40
|
6 | #define LCD_START_LINE1 0x00
|
7 | #define LCD_START_LINE2 0x40
|
8 | #define LCD_START_LINE3 0x14
|
9 | #define LCD_START_LINE4 0x54
|
10 | #define LCD_WRAP_LINES 0
|
Hugo H. schrieb: > #define F_CPU 16000000UL (falls nicht im Projekt eingetragen) Das hilft aber nicht der internen delay-Funktion. Die wird nicht von dieser Einstellung korrigiert. In meinem Projekt reagierte das Display bei Clear, Home und GotoXY seltsam.
BlaBla schrieb: > Das meinte ich: > /*********************************************************************** ** > delay for a minimum of <us> microseconds > with a 4Mhz crystal, the resolution is 1 us > ************************************************************************ */ > static void delay(uint16_t us) > { > while ( us ) us--; > } > > Bei 16 MHz ist das dann keine 1µs Wartezeit. Und die Funktion wird auch noch im AS7 (-O1) weg optimiert.
1 | /*************************************************************************
|
2 | delay for a minimum of <us> microseconds
|
3 | with a 4Mhz crystal, the resolution is 1 us
|
4 | *************************************************************************/
|
5 | __attribute__((optimize(0))) |
6 | static void delay(uint16_t us) |
7 | {
|
8 | while ( us ) us--; |
9 | }
|
Damit bleibt sie auch bei der Optimierung (-O1) im Code erhalten.
1 | /*************************************************************************
|
2 | delay for a minimum of <us> microseconds
|
3 | with a 16Mhz crystal, the resolution is 1 us
|
4 | *************************************************************************/
|
5 | __attribute__((optimize(0))) |
6 | static void delay(uint16_t us) |
7 | {
|
8 | while ( us ) us--; |
9 | while ( us ) us--; |
10 | while ( us ) us--; |
11 | while ( us ) us--; |
12 | }
|
BlaBla schrieb: > static void delay(uint16_t us) > { > while ( us ) us--; > while ( us ) us--; > while ( us ) us--; > while ( us ) us--; > } Möchtest du das bitte noch einmal überlegen? Hinweis: Welchen Wert hat us nach dem ersten while?
:
Bearbeitet durch User
Georg G. schrieb: > Möchtest du das bitte noch einmal überlegen? Oh ja.... stimmt. Krasser Fehler. Aber ist sinngemäß gemeint.
Hallo und guten Tag, habe mein Problem gelöst. Das Display 2004A funktioniert mit dem I2C Modul jetzt einwandfrei. Ich denke der Compiler hat mir die Sorgen bereitet. Habe die Optimierung in AS 7.0 auf "Optimize for size (-Os) gestellt. Konnte allerdings noch nicht ermitteln was wegoptmiert wurde. Betreibe den Atmega 328P nach wie vor mit 16 MHz und die I2C Schnittselle mit 1 kHz. Meine Zeilenadessen sind 0x00, 0x40, 0x14 und 0x54. Ich bedanke mich für alle Beiträge zur Lösung meiner Problematik. Da ich schon etwas älter bin (Jahrgang 1943) und keine externe Hilfe habe, muss ich mir Unterstützung in den Foren suchen. Ist wieder einmal sehr gut gelungen. Danke!! MfG Heinz
Dann geht es eventuell so:
1 | /*************************************************************************
|
2 | delay for a minimum of <us> microseconds
|
3 | with a 16Mhz crystal, the resolution is 1 us
|
4 | *************************************************************************/
|
5 | |
6 | __attribute__((optimize(0))) |
7 | static void delay(uint16_t us) |
8 | {
|
9 | while ( (uint32_t) us << 2 ) us--; |
10 | |
11 | }
|
Ob jetzt noch die 1 µs stimmen?!? War jetzt mal quick & dirty. Heinz W. schrieb: > habe mein Problem gelöst. Den Optimierer auszuschalten ist trotzdem blöd. Der wird von <util/delay.h> benötigt. Ich wollte jetzt auch nicht zuviel in Peters Lib ändern. Aber schön das es läuft.
BlaBla schrieb: > while ( (uint32_t) us << 2 ) us--; Wie oft glaubst du, wird das Leftshift ausgefuehrt? Argl - Kresse halten und so ... leo
1 | /*************************************************************************
|
2 | delay for a minimum of <us> microseconds
|
3 | with a 16Mhz crystal, the resolution is 1 us
|
4 | *************************************************************************/
|
5 | __attribute__((optimize(0))) |
6 | static void delay(uint16_t us) |
7 | {
|
8 | uint32_t us1 = us << 2; |
9 | while (us1) us1--; |
10 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.