Hallo Allseits !
Wie schon in meiner ersten Anfrage "Was brauche ich ?" angekündigt, bin
absoluter Neuling auf dem Gebiet der µC und kann auch nicht wirklich
programmieren. Trotzdem werde ich versuchen, mein geplantes Projekt mit
einem ATmega8 zu realisieren.
Gleich eines vorweg: Bitte keine Kommentare wie "Dann musst du halt C
lernen" oder sonstige nicht zielführende Aussagen.
Als erste Etappe habe ich mir das Display vorgenommen. Es handelt sich
dabei um ein W204B-NLW von Electronic Assembly. Der Controller auf dem
Ding ist ein KS0073, angeblich HD44780 kompatibel, was nicht ganz
stimmt. Durch das Lesen etlicher Beiträge hier im Forum habe ich das
Display auch zum Laufen gebracht.
An dieser Stelle besonderen Dank an Bitkracherl, Karl Heinz und
besonders an die Verfasser des AVR-GCC-Tutorial/LCD-Ansteuerung sowie an
zahlreiche Andere, welche zu diesem Thema hier etwas Sinnvolles
beigesteuert haben.
Die Zeilendfinition in der lcd-routines.h in Zeile 52 bis 55 habe ich
aus den Original-Datenblatt von EA für dieses Display mit dem KS0073
entnommen.
Wie gesagt, das Display läuft und es zeigt auch das Richtige an der
richtigen Stelle an. Nur, ich habe keine Ahnung, warum es das tut !!!
Der Grund dafür liegt vermutlich in den Dateien lcd-routines.h (Zeile
131 bis Zeile 139 - ist dort #define LCD_FUNCTION_3LINE bzw. #define
LCD_FUNCTION_4LINE wirklich unnötig ???) sowie in der main.c (Zeile 23
bis Zeile 40 - lcd_setcursor ....)
Irgendwie kann ich die Werte bei lcd_setcursor( 0, 0 ); verändern, OHNE
dass sich dabei nachher die Anzeige verändert, z.b bei der zweiten (!!!
Zeile 33 !!!) und vierten (!!! Zeile 38 !!!) Zeile auf lcd_setcursor( 0,
14 ); oder auch auf lcd_setcursor( 0, 15 ); ohne das sich die Anzeige am
Display ändert, es kommt immer das gleiche Ergebnis:
1
zeile 1: 111 erste zeile 111
2
zeile 2: 222 zweite zeile 222
3
zeile 3: 333 dritte zeile 333
4
zeile 4: 444 vierte zeile 444
Ämdere ich besagte Zeilen allerdings auf lcd_setcursor( 0, 1 ); so kommt
folgendes raus:
1
zeile 1: 444 vierte zeile 444
2
zeile 2:
3
zeile 3: 333 dritte zeile 333
4
zeile 4:
Im Übrigen ist mir aufgefallen, dass wenn ich die Reihenfolge der
Programmzeilen vertausche, sich auch die Anzeige am Display ändert:
1
// Die Ausgabemarke in die 1te Zeile setzen
2
lcd_setcursor(0,0);
3
// Text als String ausgeben
4
lcd_string("111 erste zeile 111");
5
6
// Die Ausgabemarke in die 3te Zeile setzen
7
lcd_setcursor(0,0);
8
// Text als String ausgeben
9
lcd_string("333 dritte zeile 333");
10
11
// Die Ausgabemarke in die 2te Zeile setzen
12
lcd_setcursor(0,0);
13
// Text als String ausgeben
14
lcd_string("222 zweite zeile 222");
15
16
// Die Ausgabemarke in die 4te Zeile setzen
17
lcd_setcursor(0,0);
18
// Text als String ausgeben
19
lcd_string("444 vierte zeile 444");
ergibt
1
zeile 1: 111 erste zeile 111
2
zeile 2: 222 zweite zeile 222
3
zeile 3: 333 dritte zeile 333
4
zeile 4: 444 vierte zeile 444
aber
1
// Die Ausgabemarke in die 1te Zeile setzen
2
lcd_setcursor(0,0);
3
// Text als String ausgeben
4
lcd_string("111 erste zeile 111");
5
6
// Die Ausgabemarke in die 2te Zeile setzen
7
lcd_setcursor(0,0);
8
// Text als String ausgeben
9
lcd_string("222 zweite zeile 222");
10
11
// Die Ausgabemarke in die 3te Zeile setzen
12
lcd_setcursor(0,0);
13
// Text als String ausgeben
14
lcd_string("333 dritte zeile 333");
15
16
// Die Ausgabemarke in die 4te Zeile setzen
17
lcd_setcursor(0,0);
18
// Text als String ausgeben
19
lcd_string("444 vierte zeile 444");
ergibt
1
zeile 1: 111 erste zeile 111
2
zeile 2: 333 dritte zeile 333
3
zeile 3: 222 zweite zeile 222
4
zeile 4: 444 vierte zeile 444
Könnte mir das bitte wer erklären? An welcher Stelle werden die
"Einsprungsaddressen" nun wirklich definiert und wie weit ist das für
lcd_setcursor auch bindend bzw. inwieweit hängen die #define
LCD_FUNCTION_1LINE (bzw ..1-4LINE) mit den lcd_setcursor zusammen?
Bitte so erklären, dass es auch ein Laie wie ich verstehen kann.
Hi
Wie jetzt, vier mal die gleiche Cursorposition und unterschiedliche
Zeilen?
>Könnte mir das bitte wer erklären? An welcher Stelle werden die>"Einsprungsaddressen" nun wirklich definiert und wie weit ist das für>lcd_setcursor auch bindend bzw. inwieweit hängen die #define>LCD_FUNCTION_1LINE (bzw ..1-4LINE) mit den lcd_setcursor zusammen?
Die Anfangsadressen der Zeilen sind in der lcd-routines.h definiert:
#define LCD_DDADR_LINE1 0x00 // Werte aus Datenblatt für
#define LCD_DDADR_LINE2 0x20 // LCD Display 4 x 20 mit
#define LCD_DDADR_LINE3 0x40 // Kontroller KS0073
#define LCD_DDADR_LINE4 0x60
>Gleich eines vorweg: Bitte keine Kommentare wie Gleich eines vorweg: Bitte >keine
Kommentare wie "Dann musst du halt C lernen" oder sonstige nicht >zielführende
Aussagen. oder sonstige nicht zielführende Aussagen.
"Dann musst du halt C lernen" ist aber zielführend (auch wenn ich
notorischer Assemblerprogrammierer bin). Man muss sein Werkzeug
beherrschen. Egal welches. Denn dann sind solche Threads unnötig.
MfG Spess
Jep, viermal die gleiche Cursorposition und unterschiedliche Zeilen,
welche das Richtige anzeigen .... und genau das verstehe ich nicht !
Zu
>Die Anfangsadressen der Zeilen sind in der lcd-routines.h definiert:
diese Werte habe ich lt. Datenblatt für das 4x20 Display eingegeben
Aber bitte lies nochmal meine Frage, ich verstehe das Verhalten des
Displays nicht, dass es bei verschiedenen Angeben bei lcd_setcursor
gleich reagiert.
Hi
>Aber bitte lies nochmal meine Frage, ich verstehe das Verhalten des>Displays nicht, dass es bei verschiedenen Angeben bei lcd_setcursor>gleich reagiert.
Vielleicht programmierst du nur einfach das falsche Hex-File.
MfG Spess
>Vielleicht programmierst du nur einfach das falsche Hex-File.
Nö, diesen Fehler habe ich ganz am Anfang vor einer Woche zweimal
gemacht, seither passe ich darauf auf.
Ich habe nur einige der möglichen Werte für lcd_setcursor angegeben, bei
denen das Display das Richtige anzeigt. Bei anderen Werten werden die
Zeilen erwartungsgemäß verschoben oder durcheinandergewürfelt. Im
Endeffekt soll es ja nicht bei diesen Versuchs-Anzeigen bleiben, sondern
es sollen dann verschiedene Menüpunkte sowie diverse Start- und
Stopzeiten, eine Uhr usw. angezeigt werden. Und deshalb möchte ich schon
genau wissen, was wann warum wo angezeigt wird.
Morgen werde ich nochmals einige Werte versuchen und die Ergebnisse dann
hier posten, vielleicht weiß wer einen Rat oder den Grund, warum dies so
ist.
mfg Kurt
@Kurt W.
Das Verhalten könnte daher kommen, dass das sogenannte RE-Bit nicht
gesetzt wird bei der Initialisierung.
HÄÄÄ was ist das RE-Bit?
Das ist, das Erweiterungs-Bit, laut Datenblatt damit es HD44780
kompatible wird.
Im Datenblatt ist es etwas irreführend beschrieben und habe dann damals
beim Hersteller nachgefragt.
@Kurt W.
Das Initalisierungs Beispiel aus dem Datenblatt muss noch
für den 4-Bit Modus angepasst werden. (siehe Anhang)
Wichtig ist hierbei, dass das RE-Bit wieder zurückgesetzt wird
nachdem "8-Bit Datenlänge, extension Bit RE und 4 Zeilen Modus"
eingestellt wurde.
Kurt W. schrieb:> Jep, viermal die gleiche Cursorposition und unterschiedliche Zeilen,> welche das Richtige anzeigen .... und genau das verstehe ich nicht !
Ich schon.
Schau ich mir die Funktion an
1
voidlcd_setcursor(uint8_tx,uint8_ty)
2
{
3
uint8_tdata;
4
5
switch(y)
6
{
7
case1:// 1. Zeile
8
data=LCD_SET_DDADR+LCD_DDADR_LINE1+x;
9
break;
10
11
case2:// 2. Zeile
12
data=LCD_SET_DDADR+LCD_DDADR_LINE2+x;
13
break;
14
15
case3:// 3. Zeile
16
data=LCD_SET_DDADR+LCD_DDADR_LINE3+x;
17
break;
18
19
case4:// 4. Zeile
20
data=LCD_SET_DDADR+LCD_DDADR_LINE4+x;
21
break;
22
23
default:
24
return;// für den Fall einer falschen Zeile
25
}
26
27
lcd_command(data);
28
}
und vergleiche mit deinem Aufruf
1
lcd_setcursor(0,0);
dann sehe ich, dass der Fall 0 für das 2.te Argument gar nicht behandelt
wird. D.h. dein lcd_setcursor macht effektiv gar nichts. Und dieses 'gar
nichts' ist wörtlich zu nehmen.
Hast du selbst da in der lcd_setcursor Funktion rumgepfuscht? Denn als
C-Programmierer ist man eigentlich daran gewöhnt, dass wir IMMER bei 0
anfangen zu zählen und nicht bei 1. Die oberste Zeile in einem LCD ist
nun mal die Zeile Nummer 0 und nicht die Zeile Nummer 1. So wie du das
zwar an der verwendenden Stelle auch gemacht hast, allerdings in der
Funktion dann anders auswertest.
Und der Rest deiner Ausgaben erklärt sich ganz einfach aus der internen
Organisation des LCD, in der die Zeilen eben physikalisch anders
angeordnet sind, als du das annimmst.
PS:
Muss die Sache mit dem "herumpfuschen" zurück nehmen. Denn im Original
sieht der Code auch so aus (auch wenn mir nicht klar ist, was sich der
Autor dabei gedacht hat, die Zeilen bei 1 beginnen zu lassen).
Aber.
Hast du denn den Kommentar nicht gesehen?
// Setzt den Cursor in Spalte x (0..15) Zeile y (1..4)
3
4
voidlcd_setcursor(uint8_tx,uint8_ty)
da steht eindeutig, wie die Funktion zu benutzen ist. Damit sind
Versuche, als 2.ten Wert 0 oder auch 14 bzw. 15 zu übergeben recht
sinnfrei. Es ist als ob die entsprechenden Aufrufe gar nicht da wären.
@ Klaus
Das dürfte nicht das Problem sein, die Anzeige funktioniert ja.
PS: daher habe ich dies auch nicht überprüft, möglich dass ich das noch
nachholen muss ....
Trotzdem Danke für den Hinweis.
@ Karl Heinz
Vielen Dank für die Info !
Ich habe in der Zwischenzeit etliche Versuche durchgeführt und bin in
der Zwischenzeit auf einiges draufgekommen ....
Aber im Moment sitzt meine Tochter neben mir und will für den L17
probefahren .... ich melde mich später wieder mit Genauerem.
lG Kurt
So, ich habe nun einiges ausprobiert. Nochmals Danke an Karl Heinz, die
Versuche haben Deine Antwort größtenteils bestätigt. Der Vollständigkeit
halber stell ich das ganze Protokoll hier rein:
ursprünglicher Code:
1
LN22 // Die Ausgabemarke in die 1te Zeile setzen
2
LN23 lcd_setcursor( 0, 0 );
3
LN24 // Text als String ausgeben
4
LN25 lcd_string("111 erste zeile 111");
5
LN26
6
LN27 // Die Ausgabemarke in die 3te Zeile setzen
7
LN28 lcd_setcursor( 0, 0 );
8
LN29 // Text als String ausgeben
9
LN30 lcd_string("222 zweite zeile 222");
10
LN31
11
LN32 // Die Ausgabemarke in die 2te Zeile setzen
12
LN33 lcd_setcursor( 0, 0 );
13
LN34 // Text als String ausgeben
14
LN35 lcd_string("333 dritte zeile 333");
15
LN36
16
LN37 // Die Ausgabemarke in die 4te Zeile setzen
17
LN38 lcd_setcursor( 0, 0 );
18
LN39 // Text als String ausgeben
19
LN40 lcd_string("444 vierte zeile 444");
Anzeige am Display:
1
+-12345678901234567890-+
2
3
+----------------------+
4
I 111 erste Zeile 111 I
5
I 222 zweite zeile 222 I
6
I 333 dritte zeile 333 I
7
I 444 vierte zeile 444 I
8
+----------------------+
Versuch 1: LN28, LN33 und LN38 mit // deaktiviert,
also //lcd_setcursor( 0, 0 )
Ergebnis: Gleich wie ursprünglich
(Ich nehme mal an, dass der µC die Werte einfach der Reihe nach
abarbeitet.)
Versuch 2: LN30, LN35 und LN 40 ebenfalls mit // deaktivieren,
aber LN 25 ändern:
LN25 lcd_string("111 erste zeile 111222 zweite zeile 222333 dritte
zeile 333444 vierte zeile 444");
Ergebnis: Gleich wie ursprünglich (Genaugenommen habe ich das erwartet)
Versuch 3: Ursprünglichen Zustand wieder herstellen,
aber diesmal LN23, LN25, LN33 und LN38 deaktivieren
LN28 bleibt vorläufig unverändert:
LN28 lcd_setcursor( 0, 0 );
Ergebnis:
+----------------------+
I 222 zweite zeile 222 I
I 444 vierte zeile 444 I
I 333 dritte zeile 333 I
I I
+----------------------+
Auch das habe ich erwartet, irgendwo hier im Forum habe ich gelesen,
dass ein 4x20 Display vom Kontroller her wie ein 2x40 Display behandelt
und einfach in der mitte geteilt wird, also zuerst Zeile 1 und Zeile 3
abgearbeitet werden und dann erst Zeile 2 und Zeile 4
Ich habe dann verschiedenste Werte(x) in LN28 lcd_setcursor( x, 0 );
eingetragen, das Ergebnis war immer das Gleiche, egal ob dort 0, 9, 10
oder 25 stand.
Schließlich habe ich die Zeile wie folgt geändert:
LN28 lcd_setcursor; //( 0, 0 );
Beim compilieren erhielt ich dann eine Warnung, aber das Ergebnis am
Display änderte sich nicht.
Versuch 4: LN17 bis LN20 sowie LN29 bis LN44 deaktiviert
nach LN45 eine neue Zeile eingefügt:
LN46 lcd_data( 'T' );
Dann diverse Werte in LN27 eingetragen.
Anmerkung:
Die erste Zahl steht für die Spalte (beginnend mit 0)
Die zweite Zahl steht für die Zeile (beginnend mit 1)
lcd_cursor ( 0, 1); ergibt ein T in der ersten Zeile in Spalte 0 ( 1)
lcd_cursor (19, 1); ergibt ein T in der ersten Zeile in Spalte 19 (20)
lcd_cursor (20, 1); ergibt ein T in der dritten Zeile in Spalte 0 ( 1)
lcd_cursor (39, 1); ergibt ein T in der dritten Zeile in Spalte 19 (20)
Nun versuchte ich die 2te Zeile anzusprechen und hätte ein T in der
2ten Zeile in Spalte 0 erwartet, aber es kam folgendes:
lcd_cursor ( 0, 2); ergibt ein T in der dritten Zeile in Spalte 12 (13)
lcd_cursor ( 1, 2); ergibt ein T in der dritten Zeile in Spalte 13 (14)
lcd_cursor ( 0, 4); ergibt ein T in der vierten Zeile in Spalte 12 (13)
lcd_cursor ( 1, 4); ergibt ein T in der vierten Zeile in Spalte 13 (14)
Gleich die nächsten Versuche mit
lcd_cursor ( 0, 3); ergibt ein T in der zweiten Zeile in Spalte 0 ( 1)
lcd_cursor (19, 3); ergibt ein T in der zweiten Zeile in Spalte 19 (20)
lcd_cursor (20, 3); ergibt ein T in der vierten Zeile in Spalte 0 ( 1)
lcd_cursor (39, 3); ergibt ein T in der vierten Zeile in Spalte 19 (20)
Erkenntnis daraus: ich kann also auf diese Weise jede beliebige Position
in dem Display ansprechen, allerdings nur mit den Zeilen 1 und 3.
In der lcd-routines.h habe ich in Zeile 52 bis 55 die Werte angepaßt,
Ich glaube es zwar nicht, aber könnte es sein, das dies etwa falsche
Werte sind? Oder liegt der "Fehler" ganz woanders?
Im Moment weiß ich nicht mehr weiter ....
(Für Trolle: Es ist mir durchaus bewusst, dass der größte Fehler hinter
meiner Tastatur sitzt ...)
@Kurt W.
Ersetz mal die lcd_init mit dieser hier und sag bescheid ob es dann
geht.
Noch ein Hinweis. Am LCD gibt es einen speraten RESET den mal für ein
paar
Sekunden auf GND oder 0V anschliessen. evtl. mehr mals probieren dann
das Programm überspielen. Danach evtl. komplett alles aus ein.
////////////////////////////////////////////////////////////////////////
////////
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void )
{
// verwendete Pins auf Ausgang schalten
uint8_t pins = (0x0F << LCD_DB) | // 4 Datenleitungen
(1<<LCD_RS) | // R/S Leitung
(1<<LCD_EN); // Enable Leitung
LCD_DDR |= pins;
// initial alle Ausgänge auf Null
LCD_PORT &= ~pins;
// warten auf die Bereitschaft des LCD
_delay_ms( LCD_BOOTUP_MS );
// Soft-Reset muss 3mal hintereinander gesendet werden zur
Initialisierung
lcd_out( LCD_SOFT_RESET );
_delay_ms( LCD_SOFT_RESET_MS1 );
lcd_enable();
_delay_ms( LCD_SOFT_RESET_MS2 );
lcd_enable();
_delay_ms( LCD_SOFT_RESET_MS3 );
lcd_out(0x20 + 0x04); // Jetzt das
Interface auf 4-Bitmodus Erweiterungsbit RE setzen
lcd_command(0x08 + 0x01 ); // 4 Zeilen
modus einstellen
lcd_command(0x20 ); // Interface in
4-Bitmodus und RE abschalten
lcd_command(0x08 + 0x04); // LCD-Display Ein
lcd_command(0x01); //
LCD-Display Löschen
lcd_command(0x04 + 0x02 ); // Cursor Adresse
Automatisch erhöhen
/*
// 4-bit Modus aktivieren
lcd_out( LCD_SET_FUNCTION |
LCD_FUNCTION_4BIT );
_delay_ms( LCD_SET_4BITMODE_MS );
// 4-bit Modus 2 Zeilen 5x7
lcd_command( LCD_SET_FUNCTION |
LCD_FUNCTION_4BIT |
LCD_FUNCTION_2LINE | // LCD_FUNCTION_2LINE |
LCD_FUNCTION_5X7 ); // LCD_FUNCTION_5X7 );
// Display ein Cursor aus Blinken aus
lcd_command( LCD_SET_DISPLAY |
LCD_DISPLAY_ON |
LCD_CURSOR_OFF |
LCD_BLINKING_OFF);
// Cursor inkrement / kein Scrollen
lcd_command( LCD_SET_ENTRY |
LCD_ENTRY_INCREASE |
LCD_ENTRY_NOSHIFT );
lcd_clear();
*/
}
@ Klaus
Danke für Info. Ich habe das Display mittlerweile auf eine andere Art
zum (hoffentlich richtigem ?) laufen gebracht, trotzdem werde ich den
von Dir geposteten Code ausprobieren, alleine um zu sehen, was sich da
ändert.
Da jetzt jedoch wieder der Alltag beginnt, komme ich praktisch nur
abends dazu.
mfG Kurt
> In der lcd-routines.h habe ich in Zeile 52 bis 55 die Werte angepaßt,> Ich glaube es zwar nicht, aber könnte es sein, das dies etwa falsche> Werte sind?
Höchst wahrscheinlich sind die falsch.
> Oder liegt der "Fehler" ganz woanders?
Du bist sehr wahrscheinlich genau an der richtigen Stelle. Diese 4 Werte
1
#define LCD_DDADR_LINE1 0x00 // Werte aus Datenblatt für
2
#define LCD_DDADR_LINE2 0x20 // LCD Display 4 x 20 mit
3
#define LCD_DDADR_LINE3 0x40 // Kontroller KS0073
4
#define LCD_DDADR_LINE4 0x60
sind der Schlüssel.
Die 0x00 stehen ausser Frage. Das die erste Zeile bei 0 beginnt, ist
nicht sonderlich überraschend.
Aus
1
lcd_cursor (20, 1); ergibt ein T in der dritten Zeile in Spalte 0 ( 1)
folgt, dass die 3. Zeile offenbar an der Adresse 0x14 anfängt. Also
1
#define LCD_DDADR_LINE1 0x00
2
#define LCD_DDADR_LINE2 0x20
3
#define LCD_DDADR_LINE3 0x14
4
#define LCD_DDADR_LINE4 0x60
Aus
1
lcd_cursor ( 0, 4); ergibt ein T in der vierten Zeile in Spalte 12 (13)
folgt dass die 4. Zeile 12 Zeichen vor 0x60 beginnt. Das wäre dann 0x54.
Also
1
#define LCD_DDADR_LINE1 0x00
2
#define LCD_DDADR_LINE2 0x20
3
#define LCD_DDADR_LINE3 0x14
4
#define LCD_DDADR_LINE4 0x54
Aus deinen Beschreibungen lässt sich leider nichts ermitteln, woraus man
auf den Beginn der 2.ten Zeile schliessen könnte. Aus Analogiegründen
würde ich mal mit 0x40 rechnen, denn die 3. Zeile ist 0x14 hinter der
ersten Zeile, die 4. Zeile würde ich dann mal 0x14 hinter der zweiten
Zeile annehmen. 0x54 - 0x14 ergibt 0x40. Ob das stimmt, wird ein Versuch
zeigen müssen.
Mit der Belegung würde ich das daher mal ausprobieren.
1
#define LCD_DDADR_LINE1 0x00
2
#define LCD_DDADR_LINE2 0x40
3
#define LCD_DDADR_LINE3 0x14
4
#define LCD_DDADR_LINE4 0x54
lcd_setcursor mit zulässigen Zeilennummern und jeweils in Spalte 0
positionieren.
So, mal zwischendurch:
@ Klaus:
Ich habe den von Dir geposteten Teil der lcd-routines.c kurzerhand mal
ausgetauscht (die durch das copy-paste entstandenen Fehler habe ich
korrigiert). Beim Testen mit dem ursprünglichem Code (siehe Posting von
06.01.2014 16:38) kam dabei folgendes raus:
+-12345678901234567890-+
+----------------------+
I V e 111222 zweite ze I
I I
I ile 222333 dritte ze I
I I
+----------------------+
Irgendwie ist mir das mittlerweile auch klar, warum dies so ist.
Diese ursprünglich hier geposteten Dateien
[[https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung]]
sind als Vorlage für verschiedenste Möglichkeiten gedacht.
Ich habe mit copy-paste den gesamten Code einfach in die entsprechenden
Dateien hineinkopiert - und da ich wie gesagt bis dato von C oder Cpp
keine Ahnung habe - (mittlerweile weiß ich, das ich nix weiß) habe ich
nur jene Werte angepaßt, auf welche ich hingewiesen wurde - das war zwar
nicht falsch (zumindest nicht ganz falsch), aber bei weitem noch nicht
richtig.
Wie gesagt, der Code ist für mehrere Möglichkeiten gedacht und
sinnvollerweise (?) in mehrere (3) Dateien aufgeteilt. Dadurch kommt es
vor, dass sich gewisse Teile gegenseitig beeinflussen oder aufheben,
gültig ist dann jener Code, der zuletzt vom µC abgearbeitet wurde.
Sollte diese meine Meinung falsch sein, so ersuche ich um Hinweis.
@ Karl Heinz
Ich habe die von Dir angegebenen Werte kurz ausprobiert, funktioniert
leider auch nicht richtig. Wie gesagt, der ursprüngliche Quellcode (Link
siehe oben) ist für ein 16 Zeichen Display ausgelegt und bietet außerdem
mehrere Möglichkeiten, je nachdem, ob ein einzelnes Zeichen oder ein
kompletter String angezeigt werden sollen. Und diese gegenseitigen
Beeinflussungen muß ich noch rausbekommen.
Ganz am Anfang hatte ich Unterstützung von einem Informatik-Student,
welcher mir eben aus diesem angegebenen Quellcode ein Programm
zusammenstellte, welches aber aufgrund von falschen Hardware-Anschlüssen
überhaupt nichts anzeigte. Leider hat dieser Student jetzt nur noch
wenig Zeit, jedoch habe ich nachdem die Hardware richtig angeschlossen
war, sein Programm nochmals hervorgeholt. Nach einigen kleineren
Anpassungen funktioniert dieses tadellos. Im Anhang poste ich das Progi
und sobald ich den Schaltplan ins Reine gezeichnet habe, auch diesen.
Danke für die Unterstützung, ich melde mich sobald die nächsten Troubles
anstehen - also ziemlich bald ....
Kurt W.
LOL.
Ich hab den unten stehenden Code bei mir getstet.
Kommt das gleiche wie bei dir raus.
Aber das ist doch klar und ist mir eben auch aufgefallen.
Da hier beim setzen " lcd_setcursor( 0, 0 ); ", von der
Software das Y = 0 garnicht behandelt wird, wirkt sich das aus wie
der HOME befehl.
Also muss es folglich " lcd_setcursor( 0, 1 ); für die erste Zeile
heissen.
Des weiteren "lcd_setcursor( 0, 5 );", da beginnt die Ausgabe praktisch
wieder bei Zeile 1.
Du hast nur ein 4 Zeilliges Display.
Hier wäre jetzt richtig "lcd_setcursor( 0, 4 );
// Die Ausgabemarke in die 1te Zeile setzen
lcd_setcursor( 0, 0 );
// Text als String ausgeben
lcd_string("111 erste zeile 111");
// Die Ausgabemarke in die 3te Zeile setzen
lcd_setcursor( 0, 0 );
// Text als String ausgeben
lcd_string("333 dritte zeile 333");
// Die Ausgabemarke in die 2te Zeile setzen
lcd_setcursor( 0, 5 );
// Text als String ausgeben
lcd_string("222 zweite zeile 222");
// Die Ausgabemarke in die 4te Zeile setzen
lcd_setcursor( 0, 5 );
// Text als String ausgeben
lcd_string("444 vierte zeile 444");
Korrigierte Version.
// Die Ausgabemarke in die 1te Zeile setzen
lcd_setcursor( 0, 1 );
// Text als String ausgeben
lcd_string("111 erste zeile 111");
// Die Ausgabemarke in die 3te Zeile setzen
lcd_setcursor( 0, 3 );
// Text als String ausgeben
lcd_string("333 dritte zeile 333");
// Die Ausgabemarke in die 2te Zeile setzen
lcd_setcursor( 0, 2 );
// Text als String ausgeben
lcd_string("222 zweite zeile 222");
// Die Ausgabemarke in die 4te Zeile setzen
lcd_setcursor( 0, 4 );
// Text als String ausgeben
lcd_string("444 vierte zeile 444");
Kurt sende mal nur diese zeilen zum Display
lcd_setcursor( 0, 1 );
// Text als String ausgeben
lcd_string("111 erste zeile 111222 zweite zeile 222333 dritte zeile
333444 vierte zeile 444");
Sollte die Ausgabe wie erwartet so sein.
zeile 1: 111 erste zeile 111
zeile 2: 222 zweite zeile 222
zeile 3: 333 dritte zeile 333
zeile 4: 444 vierte zeile 444
Das 4 zeillige Display ist in Wirklichkeit ein Zwei zeilliges.
Das hast du ja schon mit bekommen denke ich.
Hier mal ein Beispiel wie die Offets bei mir aussehen.
#define Zeilen_Offset0 0x00
#define Zeilen_Offset1 0x20 // 20h EADIP204-4 ; 0x14 HD44780
#define Zeilen_Offset2 0x40 // 40h EADIP204-4 ; 0x40 HD44780
#define Zeilen_Offset3 0x60 // 60h EADIP204-4 ; 0x54 HD44780
Klaus schrieb:> Da hier beim setzen " lcd_setcursor( 0, 0 ); ", von der> Software das Y = 0 garnicht behandelt wird, wirkt sich das aus wie> der HOME befehl.
Das ist leider eine Falsch Aussage von mir.
Das heisst: Software das Y = 0 garnicht behandelt wird ist richtig.
Da es nicht behandelt wird auch keine Adresse eingestellt wo die Zeichen
im
Display aus gegeben werden sollen.
Heisst letzt endlich das deine Anweisungen ganz einfach hintereinder
ausgegeben werden.
@ Klaus
> lcd_setcursor( 0, 1 );> // Text als String ausgeben> lcd_string("111 erste zeile 111222 zweite zeile 222333 dritte zeile> 333444 vierte zeile 444");
Jep, kommt genauso raus, wie Du beschrieben hast .... mußte ich nicht
nochmals eingeben, das habe ich schon vorher probiert.
Aber wie gesagt, im Prinzip ist mir diese Problematik (hoffentlich !?)
bereits klar und damit eigentlich keine (???) mehr.
Meine nächste Etappe ist nun der Timer - siehe Anhang in Posting von
07.01.2014 16:34 - Die "Uhr" funktioniert ja vorerst mal.
Damit ich dazu jedoch Fragen stellen und auch zielführende Antworten
bekommen kann, muss ich erstmal den Schaltplan hier reinstellen.
mfG Kurt
ups .... jep .... hab das da nicht durchgetestet und da es derzeit nicht
verwendet wird, ist es mir auch nicht aufgefallen. Ist schon geändert.
Danke für den Hinweis.
Anbei noch der derzeitige Schaltplan, allerdings für das weitere
Vorgehen muss ich diesen um Einiges erweitern. Das Ganze soll wie schon
in
[[Beitrag "Was brauche ich ?"]] erwähnt eine
Pumpensteuerung/Regelung werden und bedarf daher noch mehrerer
Komponenten.
Dazu werde ich aber demnächst einen eigenen Thread aufmachen.
Grins ... da fällt mir auf, dass sich die ganzen Postings hier ja dann
ähnlich wie eine objektorientierte Programmierung verhalten -
Hauptprojekt (noch nicht erstellt) und jede Menge (derzeit nur 2)
Unterprojekte.
( Darf ich das hier im Forum eigentlich so aufziehen ??? )
mfG Kurt
Wenn du keine Frei definierbaren Zeichen brauchst kannst du R/W auf GND
lassen sonst an PD05 so als Vorschlag.
Eventuell, wenn man es dann auch möchte, die Beleuchtung über PWM
ansteuern.
Hi
>Wenn du keine Frei definierbaren Zeichen brauchst kannst du R/W auf GND>lassen sonst an PD05 so als Vorschlag.
Mit frei programmierbaren Zeichen auch.
MfG Spess
Wenn du genau hinsiehst, liegt R/W auf GND.
Aber ich habe vergessen, die Stromversorgung einzuzeichnen.
An Pin 2 des LCD´s liegt natürlich +5VDC an.
Anbei der korr. Schaltplan
spess53 schrieb:> Wenn du keine Frei definierbaren Zeichen brauchst kannst du R/W auf GND>>lassen sonst an PD05 so als Vorschlag.
Sorry! Das hab ich jetzt mit dem Busyabfrage verwechselt.
Tach auch. Ich habe mir mal den Thread hier so durchgelesen, da ich das
selbe Display nun seit Weihnachten habe. Habe auch gründlich das
AVR_GCC-Tutorial studiert. Da habe ich bei mir noch mal nach gesehen.
Auszug aus dem Tutorial und auch so stehen bei mir im Programm:
1
#define LCD_DDADR_LINE1 0x00 //Im Tutorial mit eine 4x16 Display
2
#define LCD_DDADR_LINE2 0x40 //so um 4 Stellen erweitert für 4x20
3
#define LCD_DDADR_LINE3 0x14 //0x10
4
#define LCD_DDADR_LINE4 0x54 //0x50
dazu noch eure Case-Nummer Angabe in der "lcd.c" Datei nach gesehen:
1
voidlcd_setcursor(uint8_tx,uint8_ty){
2
uint8_tdata;
3
4
switch(y){
5
case0:// 1. Zeile
6
data=LCD_SET_DDADR+LCD_DDADR_LINE1+x;
7
break;
8
9
case1:// 2. Zeile
10
data=LCD_SET_DDADR+LCD_DDADR_LINE2+x;
11
break;
12
13
case2:// 3. Zeile
14
data=LCD_SET_DDADR+LCD_DDADR_LINE3+x;
15
break;
16
17
case3:// 4. Zeile
18
data=LCD_SET_DDADR+LCD_DDADR_LINE4+x;
19
break;
20
21
default:
22
return;// für den Fall einer falschen Zeile
23
}
24
25
lcd_command(data);
26
}
und wie man sieht ist die doch bei 0 beginnend.
Zur Probe habe ich meins nun auch noch mal angeschlossen, denn ich hatte
für mich ebenfalls ersteinmal ein Verständnisproblem. Wenn ich nun nach
Logik gehe müsste ja aufgrund der 4 Stellen längeren Zeichenlänge auch
die um 4 Stellen angepasster Hex-Wert passen.
Hab nun ein kleines durchlaufprogramm geschrieben um den Curser-Weg nach
zu prüfen:
1
intmain(void)
2
{
3
lcd_init();
4
5
while(1)
6
{
7
for(i=0;i<8;i++)
8
{
9
if(i==0)
10
{
11
lcd_string("100 K");
12
}
13
elseif(i==1)
14
{
15
lcd_setcursor(0,1);
16
lcd_string("200 K");
17
}
18
elseif(i==2)
19
{
20
lcd_setcursor(0,2);
21
lcd_string("300 K");
22
}
23
elseif(i==3)
24
{
25
lcd_setcursor(0,3);
26
lcd_string("400 K");
27
}
28
elseif(i==4)
29
{
30
lcd_setcursor(15,3);
31
lcd_string("500 K");
32
}
33
elseif(i==5)
34
{
35
lcd_setcursor(16,2);
36
lcd_string("60 K");
37
}
38
elseif(i==6)
39
{
40
lcd_setcursor(17,1);
41
lcd_string("7 K");
42
}
43
elseif(i==7)
44
{
45
lcd_setcursor(19,0);
46
lcd_data('K');
47
}
48
_delay_ms(50);
49
lcd_clear();
50
}
51
}
52
53
return0;
54
}
Funktioniert einwandfrei! Entweder ich habe das hier beschriebene
Problem nicht ganz verstanden oder bei mir klappt das durch ein Zufall
so wie ich es mir zumindestens gedacht habe.
Eine Frage habe ich dazu aber noch, wobei dies eher das
1
_delay_ms(50);
betrifft. Was wird denn dabei eigentlich um 50 Millisekunden verzögert?
Denn der Anzeigetextwechsel findet ungefähr alle 0,8 bis 0,9 Sekunden
statt. Das wäre ja ungefähr das 16-fache von meiner Delay-Einstellung?
Kann mir den bitte hier noch mit erklären, Danke!!!
LG
batty man schrieb:> as wird denn dabei eigentlich um 50 Millisekunden verzögert?> Denn der Anzeigetextwechsel findet ungefähr alle 0,8 bis 0,9 Sekunden> statt. Das wäre ja ungefähr das 16-fache von meiner Delay-Einstellung?> Kann mir den bitte hier noch mit erklären, Danke!!!
Naja! Du würdest nur ein geflimmer sehen oder auch gar nichts.
Die 50ms sind dafür da, das du was siehst bevor das Diaplay gelöscht
wird.
Probiers ganze einfach mal aus.
Wenn ich keine Delay-Zeit nutzen würde, sehe ich wirklich nur
undefiniertes durch Bild huschen.
Mein Verständnisproblem war nun jedoch, das ich gut 0,8 bis 0,9 Sekunden
meinen angezeigten Wert bekomme. Das entspricht nicht 50ms, wie man
unschwer erkennen kann. Dann hab ich mich nochmal mit dem Tutorial
befasst und gelesen das diese "Wartezeit" real durch Störprozesse wie
Interrupts effektiv länger werden können. Problem bei dieser Erklärung
ist jedoch, das ich all das gar nicht habe.
Sind die Dleay-Zeiten von der verwendeten Systemfrequenz abhängig oder
ist das schon in der Header-Datei für Delay-Zeiten schon mit
berücksichtigt? Ich weiß jetzt gerade nicht ab ich 2, 8 oder 16 MHz
verwende.Für mich wäre es nur so, dass 50ms, egal bei welcher
Taktfrequenz, eben 50ms sind.
batty man schrieb:> Sind die Dleay-Zeiten von der verwendeten Systemfrequenz abhängig oder> ist das schon in der Header-Datei für Delay-Zeiten schon mit> berücksichtigt? Ich weiß jetzt gerade nicht ab ich 2, 8 oder 16 MHz> verwende.Für mich wäre es nur so, dass 50ms, egal bei welcher> Taktfrequenz, eben 50ms sind.
Ich hoffe ich sag jetzt nichts falsches, weil ein paar Geier darauf
warten über einen herzufallen.
Ich jetzt nicht weiss welches Programmiertool du verwendest.
Bei Atmel Studio ist so!
Bsp. Externer Quarz 16 Mhz.
Damit 50ms bei dem Systemtakt 50ms werden muss folgendes am Anfang
im Programm stehen:
#define F_CPU 16000000UL // unbedingt vor delay.h
#include <util/delay.h>
Aber das ist noch nicht alles.
Als nächstes ist die Optimerung auf -Os einzustellen.
Dann muss noch zwingend die Fuses des Controllers richtig gesetzt
werden.
Also was auch immer bei #define F_CPU angibtst, sollten die Fuses auch
entsprechend gesetzt werden.
Falls du gar nicht #define F_CPU verwendest wird Standard mäßig
1Mhz verwendet also ohne Quarz.
Die Fuses müssen entsprechend auf den internen Oszilator und 1Mhz
eingestellt sein.
Nabnds,
ach ja ich benutze ein STK600 mit ATmega2560 und LCD EA W204B-NLW.
Also bei mir ist es wie beschrieben genau so aufgebaut, siehe:
1
#include<avr/io.h>
2
#include"lcd.h"
3
#define F_CPU 16000000UL
4
#include<util/delay.h>
5
uint8_ti;
also erst die Taktfrequenz von 16 MHz definiert und anschließend die
Delay-Header-Datei eingebettet.
Da ich mit den Fuses noch keine Berührung hatte, habe ich die
"Voreinstellung" von Atmel drin. Bzw. habe ich schon oft gelesen, dass
man die erst ändern sollte wenn man davon n echten Plan hat, wat man
dort ändert, denn dabei kann auch einiges "versaubeutelt" werden.
Deswegen habe ich mich da auch noch nicht ran getraut.
Was hat das mit der Optimierung immer auf sich und wo find ich die im
Atmel Studio 6.1?
Danke
@batty man
Anbei zwei Bilder!
1. Zeigt das Toolchain an.
Wenn du auf deinen ATmega2560 in der Symboleiste klickst.
Bei Optimization findest versichiedene Einstellungen.
Einfach verschiedene einstellungen ausprobieren.
z.b. eine Led 1 sek an und 1 sek aus.
Mit einer Stoppuhr die Zeiten messen. Am Anfang alles ohne Interrupt
2. Wenn du auf Device Programming klickst
macht sich ein seperates Fenster auf.
Solltest die Default Einstellung haben wie in Bild 3 musst du
den Eintrag wie in Bild 2 auswählen, weil du 16Mhz Quarz angeschlossen
hast.
So, ich habe mal meine Toolchain nach der Optimierung durch gesehen und
meine Default-Werte waren Optimize-O1 und das letzte Kontrollfeld ist
deaktiviert, siehe Anhang. Warin liegen denn die Unterschiede zwischen
O1, O2, O3 und Os bzw. warin bestehen die Vor- bzw. Nachteile die ich
dann in Kauf nehmen muss??? Vielen Dank
-.- Ohhh, ja danke...hehe, das ist ja bloß eine kleine Lektüre für mal
so zwischen Durch :D und dann noch in meiner gängig gesprochenen
Muttersprache, SUUUUPIIII
Nee, mal im Ernst. Das ist wirklich mal ne ganze Menge Lesestoff und fit
bin ich im Englischen nun auch nicht zu 100pro. Mir das mal zu Gemüte zu
ziehen brauch mal eben ein wenig mehr Zeit. Vielen Dank für den Link so
kann ich wenigstens bei Projektleerlauf mal was dazu lernen.
THX
Hey ho allerseits,
ich bin mal neben meinen anderen Baustellen auch noch mit dem TEXT-LCD
am werkeln. Dazu habe ich mal wieder ne kleine Frage.
In der lcd.c und lcd.h ist die lcd_clear() -Funktion ja eingebunden. Die
löscht aber bekanntlich das gesammte 4*20 Display.
Wäre es auch möglich nur eine Zeile löschen zu lassen, während der Rest
weiterhin stehen bleibt???
Wenn ich immer alles lösche und den nicht veränderlichen Text wieder
ausgebe bekomme ich immer so ein nerviges geflacker. Dazu würde ich
gerne die eine Zeile bloß löschen wolllen, da ich dort einen Lauftext
ausgebe. Um das Überschreiben des vorherigen Buchstaben und damit ein
restleuchten habe, ist es ziemlich schwierig zu lesen, sofern der Text
in einer akzeptablen Geschwindigkeit durchläuft. Nun habe ich mir das so
gedacht, dass ich das Nachleuchten durch ein vorheriges Löschen der
Zeile minimiere.
Also mit dem Löschen des Displays und der erneuten Ausgabe kann ich die
Leseeigenschaft verbessern. Blöd dabei ist nur, dass eben der nicht
veränderliche Text nun sichtlicht zuckt/flackert.
Hi
>Wäre es auch möglich nur eine Zeile löschen zu lassen, während der Rest>weiterhin stehen bleibt???
Einfach die Zeile mit Leerzeichen beschreiben.
MfG Spess
ok, danke. Hätt ich jetzt auch so gemacht. Dacht nur eventuell gibts da
auch so eine schöne Funktion wie lcd_clear() nur abgewandelt für eine
Zeile, wobei eben der Rest des Textes auf dem Display unberührt bleibt.
Aber Leerzeichen machens dann wohl einfacher :D
Frohe OSTERN!
Moin,
ich habe auch das LCD-Modul EA W204B-NLW und frage mich welche Schrauben
zum Befestigen des Moduls an eine Frontplatte benötigt werden.
M3 sind zu groß.
Ist es M2,5 oder M2 ?
Vielen Dank für eine Antwort diesbezüglich.
Gruss,
Stephan
Marcel schrieb:> Ist es M2,5 oder M2 ?
Ich habe M2,5 genommen. Schraube gerade ansetzen und dann eben mit
leichtem Druck einschrauben. Ist nur ganz wenig zu klein. Oder eben n
kleinen 2,5 Bohrer und Loch aufweiten.
LG