Aus irgendeinem unerfindlichen Grund lässt sich mein LCD(2x20) nicht am
ATmega8 initialisieren. Ich benutze eine 8-Bitübertragung da ich genug
Pins übrig habe. Verbauter Controller auf dem LCD ist ein KS0066 von
Conrad. Im Anhang das Datenblatt, auf Seite 27 steht der Initvorgang.
Das Script ist selbst geschrieben, aber das Script im AVR-GCC Tutorial
wurde als grobe Vorlage benutzt.
Ich möchte auch auf den Thread verweisen wo die Initalisierung relativ
gut erklärt ist. Nur mit der Umsetzung geht das nicht richtig.
--> Beitrag "LCD (Ks0066) initialisieren"
Pinbelegung:
µC - LCD
PD0 - PD7 Pin 7 - Pin 14
PB6 RS
PB7 E
Mein bisheriger Code (sicher nicht perfekt):
Mit ist klar dass noch alles fehlt zum Text anzeigen, ich will jetzt nur
mal die Init schaffen.
S_ Steht für Steuer; Also Steuerport, usw.
@holger Lol, war wohl ein kleiner Fehler ;) Und das Init funktioniert
jetzt schon relativ gut. Erst die schwarze Reihe oben, dann werden beide
Schwarz und dann geht er wieder auf eine schwarze.
@Andreas Das ist/war nur solange damit auch sicher alles mit den Zeiten
geht und nichts zu kurz ist. Hätte das später sowieso mal verkürzt, aber
wenn es bei so großen Werten nicht mehr geht, habe ich es jetzt auf 100
runter gesetzt. Funktioniert genauso.
Es will einfach nicht fertig werden.
Wie vorhin gesagt passiert folgendes:
- LCD ein, 1 schwarze Zeile
- Init beginnt, 2. Zeile wird auch schwarz
- 2. Zeile wird wieder leer und 1. bleibt schwarz
- nichts mehr, ob jetzt das LCD zum leeren nicht geht, oder beim
sonstigen Init ein Problem hat weiß ich nicht
Im Anhang ein direkter Screen vom Initvorgang im Datenblatt
Zum leeren-->
1
voidlcd_leeren(void){
2
lcd_befehl(0x01);// 01 da nur der erste Pin (PD0) geschaltet wird
Das hier sind die defines die man braucht um den code zu verstehen:
1
///@brief Defines for "gluing" The Portname and the approprite Register Name together
2
//@{
3
#define GLUE(a, b) a##b
4
#define PORTG(x) GLUE(PORT, x)
5
#define DDRG(x) GLUE(DDR, x)
6
//@}
7
8
/**@name Setup specific defines
9
@warning These defines are setup specific and therefore they need to be adjusted!
10
*/
11
//@{
12
/// @brief The Charakters per Line
13
#define DISP_CHARS 16
14
/// @brief The number display lines
15
/// @todo hat keine auswirkung: init muss angepasst werden
16
#define DISP_LINES 2
17
/// @brief The display port register to be used
18
#define DISP_PORT D
19
// @brief The port register of the controllines to be used
20
#define DISP_CTRL_PORT B
21
/// @brief Pin Number of E on DISP_CTRL_PORT
22
#define DISP_CTRL_E 0
23
/// @brief Pin Number of RW on DISP_CTRL_PORT
24
#define DISP_CTRL_RW 1
25
/// @brief Pin Number of RS on DISP_CTRL_PORT
26
#define DISP_CTRL_RS 2
27
//@}
28
29
30
//gluing the portnames together
31
#define DISP_PORT_OUT PORTG(DISP_PORT)
32
#define DISP_PORT_DDR DDRG(DISP_PORT)
33
#define DISP_CTRL_OUT PORTG(DISP_CTRL_PORT)
34
#define DISP_CTRL_DDR DDRG(DISP_CTRL_PORT)
35
36
/**@name Options
37
These are options for the display init
38
*/
39
//@{
40
///@brief Option: Should there be a cursor?
41
#define DISP_OPT_CURSOR 0
42
///@brief Option: Should the cursor blink?
43
#define DISP_OPT_CURSOR_BLK 0
44
//@}
Wenn du willst kannst du dir meine lib mal hier runterladen:
svn://fobg.de/ks0066u_lib. Grundlegend funktioniert alles - nur nicht
besonders komfortabel :) (brauchst einen subversion client)
@Simon Thx, zum lernen nutze ich es gerne. Aber ich will es trotzdem
schaffen dass meine Initialisierung richtig funktioniert.
Aktueller Code im Anhang. Wie ich mit ein paar Debug-LEDs jetzt sehe,
wird Init niemals fertig. Leider weiß ich nicht ob der µC hängen bleibt
oder eine Funktion so Probleme macht.
Ich weiß jetzt dass er nur den 1. Befehl sendet und danach nichts mehr
macht.
Der restliche Code steht im vorherigen Post, falls benötigt. Überlastet
ihn das senden oder was könnte es sein?
1
voidlcd_init(void){
2
3
_delay_us(200);
4
lcd_befehl(0x38);// wird gesendet; danach nichts mehr
mein tipp wäre, dass _delay_ms(1000) in lcd_befehl() probleme macht.
aus der delay.h:
The maximal possible delay is 262.14 ms / F_CPU in MHz.
When the user request delay which exceed the maximum possible one,
_delay_ms() provides a decreased resolution functionality. In this
mode _delay_ms() will work with a resolution of 1/10 ms, providing
delays up to 6.5535 seconds (independent from CPU frequency). The
user will not be informed about decreased resolution.
setz doch deine leds mal innerhalb der lcd_befehl() funktion.
_delay_ms(1000) habe ich seit dem Hinweis von Andreas erst verkürzt und
dann ganz entfernt. Das E_Pin wird normal geschalten und auch lcd_befehl
läuft bis zum Ende durch. Beides durch eine LED Funktion getestet. Aber
sobald er wieder ins lcd_init() zurück soll, und den nächsten Befehl
ausführen, passiert nichts mehr. Da dürfte auch der Grund sein warum
sich das LCD nicht fertig initialisieren lässt. Könnte es vielleicht ein
Speicherproblem sein: überschriebener Speicher? Oder ein Problem beim
beenden der Unterfunktion?
Verkürze auch mal die anderen Wartezeiten ehr in Richtung dem was im
Datenblatt angegeben ist. Du wartest ja schon seeehhrrr lange im
vergleich dazu.
EDIT: Sorry haste ja schon annährend gemacht - hab ich übersehen.
Simon S. wrote:
> Verkürze auch mal die anderen Wartezeiten ehr in Richtung dem was im> Datenblatt angegeben ist. Du wartest ja schon seeehhrrr lange im> vergleich dazu.
Es gibt keine zu langen Wartezeiten...nur zu kurze verursachen Fehler!
Michael H* wrote:
> Niels Hüsken wrote:>> Es gibt keine zu langen Wartezeiten...nur zu kurze verursachen Fehler!> das is einfach falsch
Nein, ist es nicht...
(mal sehen, wohin uns diese Argumentationsebene bringt)
Hi!
Ich kann das mit dem Timeout bestätigen, hatte mal ein 16 Zeichen aus
2x8 Zeichen, da wollten die 2.8 Zeichen nicht anspringen bis ich gemerkt
habe das meine 1.Inittime zu hoch war. Auf Datenblattwert gestellt und
alles war gut. War aber irgendein komischer Kontroller drauf, HD44780
kompatibel, aber scheinbar doch nicht so ganz.
Viel Erfolg, Uwe
Also: Wenn es nur falsche Zeiten wäre, müsste er aber doch die
restlichen Befehle trotzdem ausführen, oder? Ob das LCD die annimmt oder
nicht, ist dabei ja egal. Aber beim LED Test blinken die nur 1x(also 1x
wurde lcd_ein() und 1x wurde lcd_befehl() ausgeführt) und das wars.
Ich habe es jetzt mal mit fast genau den Angaben im Datenblatt gemacht,
nur winzige Abweichungen, brachte keine Besserung.
Testweise wurde das ganze jetzt an einen ATmega32 angeschloßen, aber
nicht mit viel mehr Erfolg. Wenn Init anfängt, wird kurz die 2. Zeile
auch schwarz(1. Initbefehl wird also erfolgreich gesendet) und danach
wieder leer. Die 1. bleibt dauerhaft schwarz. Aber mit den anderen
Zeiten passiert das ganze jetzt schneller.
Mal kleines Info Update: Habe es jetzt mit folgendem noch versucht:
- verschiedene Zeiten
- zu schaltende Pins einzeln angeben --> PORTD |= (1<<PD2);
- sämtlichen benötigten Code in die main () geschrieben
Außer einem kurzen aufleuchten der 2. Zeile passiert wie immer noch
nichts.
void led (unsigned char wert) {
PORTC|= _BV(wert);
_delay_ms (100);
PORTC|= _BV(wert);
}
einschalten, warten, uuuund: einschalten ^^
ich hab das ganze grad am simulator und da zappelt der PIN_E recht brav.
nach ner zeit bleibt er dann aus.
void led (unsigned char led) {
PORTC |= _BV(led);
_delay_ms (100);
PORTC &= ~_BV(led);
}
Ich habe es jetzt korrigiert, dass die LED direkt wieder aus geht.
Leider blinkt sie trotzdem nur 1x. Versucht habe ich jetzt auch schon
die Variablen für jede Funktion anders zu benennen und am Ende der
Funktion mit "" und 0 zu leeren, brachte aber auch nichts :-(
hmm, also bei mir im simulator läuft dein prog recht schön durch.
hast du überall brav stützkodensatoren? vielleicht zieht dein lcd beim
einschalten n bisschen strom, dein regler is 5m weg und schon verreckt
der atmel. hat er nen kondensator am reset?
Die Sachen sind auf einem Steckbrett aufgebaut, alles nur ein paar
Zentimeter von einander entfernt. Der Resetpin ist gar nicht beschalten.
Kondensatoren sind da eigentlich eher weniger verbaut, liegt wohl daran
dass es bisher auch so funktioniert hat. Ich weiß nicht immer sehr gut
;) Was müsste ich da noch alles einbauen?
also erst mal einen pullup an den reset. 10k oder so. einen 100nF gegen
masse dazu. 100n auch zwischen V_cc und gnd nah am atmel. auch beim
AV_cc.
und was nie schaden kann, is ein dicker elko um die 10µF zwischen V_cc
und gnd.
edit: was mir auch grad noch in den sinn kommt: probier die schaltung
doch mal ohne isp. wenn er abgesteckt is, einfach kurz den reset-pin auf
masse ziehn.
im anhang siehst du, was dein atmel tut.
gelb: reset
blau: pc4
rot: pc5
grün: pb7
und auf den datenleitungen zappelts auch recht brav
nF habe ich leider nicht. Dauert noch bis Ende des Monats dass ich mir
welche holen kann. Gehen auch welche im µF Bereich? Da hätte ich bis 1
µF zur Verfügung. Bisher hat sich an dem Problem noch nichts geändert.
Ich glaube ich lass es für heute und mach dann später weiter.
Aber mal ein großes THX für die Hilfe bisher.
ja, 1µF tut auch. für den reset bestimmt zu viel, aber mein simulator
sagt, dass er damit keine probleme hat. ich gönn mir noch ne halbe,
hoffentlich hilft die ^^
Ich habe jetzt mal einen Schaltplan vom derzeitigen Aufbau erstellt. Im
Bild ist Vss gerade auf GND. Versuche es aber immer genauso mit einem
Poti.
Ist nicht alles perfekt gezeichnet, da es mit einer Art Paint Programm
gemacht wurde.
Nicht immer nur alle Downloaden! Auch mal einer antworten.
Update: Habe mal wieder auch den Poti in den Kontrast eingebaut. Jetzt
wird das LCD kurz geleert, und danach erscheint wieder der obere
schwarze Balken. LED blinkt wie bisher nur 1x.
Update: Etwas ziemlich komisches. Der µC hat ahnscheinend massive
Probleme mit den _delay Funktionen. Jetzt habe ich mal eine eigene
benutzt und schon blinkt die LED so oft wie sie soll. Das LCD ist zwar
immer noch nicht initialisiert, das dürfte jetzt aber nur noch ein
Timing Problem sein. Aber was das mit den _delay auf sich hat ist sehr
komisch.
Code:
1
voiddelay_ms(unsignedshortms)
2
/* delay for a minimum of <ms> */
3
/* with a 1Mhz clock, the resolution is 1 ms */
4
{
5
// Note: this function is faulty, see avrm8ledtest-0.2.tar.gz for
Natürlich. Wird immer im Makefile geändert. Dass ich alles umstellen
muss ist mir schon klar. Aber warum _delay... Probleme macht verstehe
ich nicht so ganz.
also dass ein interner takt dermaßen unsauber ist, dass deswegen die
init nicht klappt, kann ich mir eig nicht vorstellen.
aber probier doch mal folgendes:
1
voidwarten(unsignedintbla){
2
for(unsignedintwart;wart<bla;wart++)_delay_ms(1);
3
}
1
while(1){
2
PORTLED^=PINLED;
3
warten(1000);
4
}
schau doch einfach mal, ob deine led mit 0,5Hz blinkt.
Die LED bringt sehr regelmäßig, was sie aber auch bei früheren
Testprogrammen immer tat. Also der Takt dürfte in Ordnung sein.
Der Kontrast ist an einen Poti angeschloßen und auf relativ gut lesbar
eingestellt. Also ca. halb zwischen weg und voll.
tjo, dann rat ich mal weiter: mal die timing zeiten verdoppelt?
oder vielleicht in einer schleife um ein x-faches erhöhen. das aktuelle
x per led oder so ausgeben. was dümmeres fällt mir auch nimmer ein.
schon gar ned zu so ner zeit.
Mir fällt langsam auch keine Möglichkeit mehr ein. Einmal funktioniert
es wieder nur mit _delay..., dann wieder nur mit delay..., ein anderes
mal nur mit beiden gemischt im Code. Entweder es blinkt dann wie gewollt
4x oder mal wieder nur 1x.
Irgendwie hat der µC ziemliche Eigenheiten. Vielleicht ist er nicht gut
drauf, oder launisch?
Naja egal. Immerhin weiß ich jetzt grob dass es an den Zeitfunktionen
liegt. Da habe ich ja dann noch viel Zeit um die richtige Einstellung zu
finden.
Nochmal ein großes THX an alle die mir hier geholfen haben.
Ich bin übrigengs immernoch der Meinung, daß keine zu langen Wartezeiten
bei der Ansteuerung des Kontrollers gibt. Die Referenz, die für einen
Timeout genannt worden ist, betraf einen völlig anderen, einen
grafischen LCD- Kontroller. Diesen Timeout gibt es bei HD44780 und
kompatibelen nicht!
Ich schlage daher vor, du bastelst dir erstmal eine Funktion zusammen,
die es dir ermöglicht, die Signale Schritt für Schritt per Tastendruck
an das LCD zu senden, die du dann mit einem Multimeter direkt am Display
nachmessen kannst. Damit solltest du jeden zweifel aus den Weg räumen
können.
klar, gut möglich. aber die kategorische aussage, dass es keine zu
langen timings gäbe, war ned richtig.
ich glaube zur not könnte man manche displays auch per taster und übung
initialisiern =)
bisher hab ich aber die hd44780 immer schnell genug anders zum laufen
gebracht ^^
Michael H* wrote:
> bisher hab ich aber die hd44780 immer schnell genug anders zum laufen> gebracht ^^
Bei der Ansteuerung meines ersten 44780 Displays (muss ca. anfang 90'er
gewesen sein) hatte ich nichtmal ein Datenblatt mit ner Pinbelegung. Mit
reinem Trial and Error hab ich ca. nach einer Woche erste sinnvolle
Ergebnisse. Vorteil war der ansteuernde C64, der in Basic programmiert
garnicht zu schnell sein konnte :)
Ich nochmal: Soweit ich jetzt rausgefunden habe, darf _delay_us nur ein
paar mal im Code vorkommen, oder eventuell pro Durchgang? Naja das ist
aber eher egal. Mehr ist das Problem dass er das Init noch nicht richtig
annimmt.
Alle 4 Befehle werden gesendet, und nach dem 4. (0x06) erscheint wieder
nur der schwarze Balken oben.
Vom 1. bis zum 4. Befehl ist das LCD leer. Ich wüsste jetzt nicht wo da
ein Fehler im Init vorhanden ist?
Im Anhang nochmal der Screen vom Init im Datenblatt.
LCD genervter wrote:
> Ich nochmal: Soweit ich jetzt rausgefunden habe, darf _delay_us nur ein> paar mal im Code vorkommen, oder eventuell pro Durchgang? Naja das ist
hö? wo steht sowas?
> Alle 4 Befehle werden gesendet, und nach dem 4. (0x06) erscheint wieder> nur der schwarze Balken oben.
hast du mal versucht, jetzt daten aufs lcd zu schreiben?
> Vom 1. bis zum 4. Befehl ist das LCD leer. Ich wüsste jetzt nicht wo da> ein Fehler im Init vorhanden ist?> Im Anhang nochmal der Screen vom Init im Datenblatt.>>
1
>lcd_befehl(0x38);// 111000
2
// 0x38? dispay off?
3
4
>_delay_us(50);
5
>lcd_befehl(0x0E);// 1110
6
// aso, und hier wieder an. mal ohne ausschalten probiert?
7
8
>_delay_us(50);
9
>lcd_leeren();// 0x01
10
>_delay_ms(5);
11
>lcd_befehl(0x06);// 110
12
>
hast du schon mal nur den µc resettet, wenn das LCD schon "warm" ist,
also seit längerem mit spannung versorgt wird?
> S_PORT &= ~(1<<PIN_RS) | (1<<PIN_E); // RS auf 0
bist du dir dabei eig sicher?
setz doch zum schluss deinen R/W und E pin testweise auf high.
ich hab grad ein dbl gefunden, bei dem zur init noch n bisschen mehr
gehört. war von samsung. nen hersteller kannst du woh ned identifiziern?
Was mir gerade noch einfällt zum Thema delay.h: Damit die korrekt
arbeitet, muss die Compileroptimierung -Os eingeschaltet sein...hast du
daran gedacht?
>hö? wo steht sowas?
Das steht nirgendwo. Nur wenn ich mehr davon schreibe, passiert das
Problem was ich oben immer hatte. Er führt nur den 1. Befehl aus, danach
nichts mehr.
Daten schreiben habe ich versucht, aber es wird nichts angezeigt. Weder
in die 2. Zeile wechseln, noch LCD leeren oder irgendwas anzeigen
funktioniert.
> // aso, und hier wieder an. mal ohne ausschalten probiert?
Also E direkt auf High lassen, oder wie ist das gemeint?
Soweit ich gefunden habe ist der KS0066 von Samsung. Zumindest nach dem
bisher gefundenen Datenblatt und den Infos darin. Das ganze Bauteil ist
von "Anag Vision". Conrad-Nr: 183350. Leider ist das Datenblatt von der
Artikelbeschreibung sehr sparsam. Im Datenblatt von Samsung selbst steht
noch ein etwas komischer Init Prozess. Aber außer einem zusätzlichen 1.
Befehl ist er mit dem anderen Init gleich, nur in reiner Textform(Seite
24). Der extra Befehl sagt ungefährt: "Write 20H to all DDRAM".
>> S_PORT &= ~(1<<PIN_RS) | (1<<PIN_E); // RS auf 0>bist du dir dabei eig sicher?
Falsch? Laut Datenblatt müssen die auf Low, also 0 sein.
PIN_E ja nur zum Senden des Befehls auf High.
@mui Ja die Optimierung ist auf Os eingestellt.
>>> S_PORT &= ~(1<<PIN_RS) | (1<<PIN_E); // RS auf 0>> bist du dir dabei eig sicher?> Falsch? Laut Datenblatt müssen die auf Low, also 0 sein.> PIN_E ja nur zum Senden des Befehls auf High.
dann fehlt da entweder eine klammer oder eine zweite invertierung.
Ich habe das jetzt geändert, aber kein Unterschied. Habe auch noch viele
verschiedene Möglichkeiten probiert(direkte Angaben ohne Variablen,
usw.), aber nichts.
Habe jetzt nicht alles gelesen, aber hatte mal so ein blödes Teil wo ich
erst nach weiss nicht wie lang suchen und probieren herausfand, dass man
das LSB zuerst senden muss. War auch irgend ein KS...
Gruss reflection
reflection wrote:
> Habe jetzt nicht alles gelesen, aber hatte mal so ein blödes Teil wo ich> erst nach weiss nicht wie lang suchen und probieren herausfand, dass man> das LSB zuerst senden muss. War auch irgend ein KS...>> Gruss reflection
Das ist doch aber nur im 4-bit Betrieb wichtig.
Hallo,
ich bekomme auch mein LCD nicht zum laufen. Es ist ein L2432 von Seiko,
laut Datenblatt mit KS0066-Controller.
Die Delay-Zeiten sollten nach dem Datenblatt eigentlich hinhauen, die
anderen Funktionen habe ich vom HD44780 übernommen.
Ich habe auch schon andere Zeiten und andere Initialisierungsschritte
versucht - hat alles nichts geholfen.
Weiß jemand ob ich die anderen Funktionen noch abändern muss?
Kann mir jemand sagen wo mein Fehler liegt, ich such und probier jetzt
schon mehrere Tage und finde nix.
Danke schonmal.
Micha
Niels Hüsken wrote:
> ist sicher, daß der Kontroller generell läuft?
Also die erste Zeile ist schwarz, wie beim HD44780 vorm initialisieren.
Bei dem jetzigen Quelltext flackert diese schwarze Zeile regelmäßig,
(wahrscheinlich so wie der ATmega Daten sendet), allerdings sind keine
Zeichen zu erkennen und auch die zweite Zeile kommt nicht. Ich hab
mehrere Displays und es ist bei allen so, von daher denke ich nicht,
dass das Display kaputt ist.
Hallo,
also ich würde mich beim Init sklavisch an das Datenblatt halten, wenn
da ein Delay steht, dann benutze genau das genannte.
Die ersten Befehle sind sehr sensibel, weil der KS0066 wohl darüber eine
eigene Initialisiserung fährt. Daher sollte man die einhalten.
Das Init des KS0066 weicht von anderen Kontrollern ab.
Ach ja, selbst delay_us(1) ist kein Problem, es gibt keine Magie beim
delay.
Gruss,
Michael
@Holger: lcd_init() ist nicht in der Endlosschleife, sondern wird am
Anfang von main() einmal aufgerufen (s.u.)
@Michael: Werd's mal probieren, hab die Delay-Zeiten bisschen
großzügiger bemessen, hat beim HD44780 auch immer geklappt.
Mein Hauptprogramm:
1
#include<avr/io.h>
2
#include"lcd-routines.h"
3
#include<util/delay.h>
4
5
6
#define sbi(port, bit) (port) |= (1 << (bit))
7
#define cbi(port, bit) (port) &= ~(1 << (bit))
8
9
intmain(void)
10
{
11
lcd_init();
12
lcd_clear();
13
14
while(1)
15
{
16
17
lcd_string("Test: ");
18
set_cursor(3,2);
19
lcd_string("Hello World");
20
_delay_ms(100);
21
22
}
23
return0;
24
}
meine Headerdatei lcd-routines.h:
1
voidlcd_data(unsignedchartemp1);
2
voidlcd_command(unsignedchartemp1);
3
voidlcd_enable(void);
4
voidlcd_init(void);
5
voidlcd_home(void);
6
voidlcd_clear(void);
7
voidset_cursor(uint8_tx,uint8_ty);
8
9
// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!
10
#ifndef F_CPU
11
#define F_CPU 1000000
12
#endif
13
// LCD Befehle
14
15
#define CLEAR_DISPLAY 0x01
16
#define CURSOR_HOME 0x02
17
18
// Pinbelegung für das LCD, an verwendete Pins anpassen