Display (HD4478099) zeigt nur Kästchen

Gast #329991
Lesenswert?

Hallo leute!
Ich habe gerade versucht ein LCD Display (das normale HD44780) an
meinen AVR anzuschlißen. Leider bin ich aus dem Tutorial hier nicht
ganz schlau geworden, da es in Assembler geschrieben ist (ich nehm
GCC). Ich hab trotzdem versucht das so gut wie möglich zu übersetzen.
Leider wird auf dem Display nichts angezeigt, ich sehe nur 8 Schwarze
Kästchen. Hier mein code:

Ich habe diese beiden Funktionen, die ich nacheinander aufrufe:


void setModeData( void )
{
  PORTC |= (1<<PC1);
}

void writeByte( void )
{
  //PORTC |= (1<<PC2)|(1<<PC3)|(1<<PC4)|(1<<PC5);

  unsigned char i=0;
  while(i<150) {i++;};


  PORTC |= (1<<PC3)|(1<<PC5);

  PORTC |= (1<<PC0);
  i=0;
  while(i<150) {i++;};
  PORTC &= ~(1<<PC0);

  PORTC &= ~(1<<PC3);
  PORTC &= ~(1<<PC5);

  PORTC |= (1<<PC4);

  PORTC |= (1<<PC0);
  i=0;
  while(i<150) {i++;};
  PORTC &= ~(1<<PC0);
}

Hat jemand eine Idee, warum da kein Zeichen ausgegeben wird?
Danke!
Gast #329993
Lesenswert?

Moin,

das sieht mir ganz nach zuviel Kontrast aus!

Also prüfe ob du die Kontrastspannung angeschlossen hast(Pin 3 am
Display)! Wenn ja drehe am Regler und schau ob sich etwas tut. Bis
hierhin brauchst du noch keine Daten zum Display senden.

Im Normalfall solltest du jetzt die Kästchen abschwächen können, bzw.
sie ganz verschwinden lassen. Beachte, wenn du zu wenig Kontrast gibst,
siehst du keine Zeichen mehr!!!!!

Ich stelle den Kontrast zum Test bei mir immer so ein, dass ich die
Segmente immer noch leicht sehen kann. Wenn alles funktioniert kannst
du dann nach deinem Gutdünken verfahren.

mfg

Asterix-007
Gast #329999
Lesenswert?

Das datenblatt hat immerhin 60 Seiten ;-)
Ich hab versucht die Initialisierung zu implementieren, aber ich
versteh sie ehrlich gesagt nicht so ganz. Das ist irgendwie ziemlich
blöd aufgeschrieben...

Das habe ich bis jetzt (von Seite 46):

void initDisplay( void )
{
  // Belegung am Port C:
  //      E RS DB4 DB5 DB6 DB7 ?  ?
  // 0 b  0 0  0   0   0   0   0  0


  WaitMs(20);  // Warte erstmal 20 ms

  PORTC = 0b00110000;  // Setze DB4 und DB5 auf 1

  WaitMs(10);  // Warte nochmal 10 ms

  PORTC = 0b00110000;  // Nochmal: Setze DB4 und DB5 auf 1

  WaitMs(10);  // Warte diesmal 2 ms

  PORTC = 0b00110000;  // Zum 3. mal: Setze DB4 und DB5 auf 1
}

Warum muss ich denn immer wieder den selben Code senden?
Und dann stehen auf der Seite in den nachfolgenden Codes noch *, ein N,
ein F und sowas.... HÄ???

Danke für eure Hilfe :-)
Gast #330001
Lesenswert?

Eigentlich hatte ich gehofft das nicht tun zu müssen. Die Lib ist mir
nämlich etwas zu komplex (OK, dafür auch flexibel) ;-)
Aber ich will mit dem Display ja garnicht viel machen: Nur einmal
initialisieren, und dann von Zeit zu Zeit mal nen String ausgeben...
Ich hatte irgendwie gehofft das wäre leicht machbar :-(
Das kann doch nicht so schwer sein!?!?!
Gast #330006
Lesenswert?

OK, nachdem ich jetzt ales fleißig gelsen habe, habe ich folgende Init
Funktion gebastelt:

PORTC = 0b00110000;
WaitMs(10);
  PORTC = 0b00110000;
WaitMs(10);
  PORTC = 0b00110000;
WaitMs(10);
  PORTC = 0b00010000;
WaitMs(10);
  PORTC = 0b00010000;
WaitMs(10);
  PORTC = 0b00000000;
WaitMs(10);
  PORTC = 0b00000000;
WaitMs(10);
  PORTC = 0b00000100;
WaitMs(10);
  PORTC = 0b00000000;
WaitMs(10);
  PORTC = 0b00100000;
WaitMs(10);
  PORTC = 0b00111000;
WaitMs(10);
Gast #330007
Lesenswert?

OK, nachdem ich nun alles fleißig gelsen habe bin ich zu folgender Init
Funktion gelangt:

WaitMs(20);
  PORTC = 0b00110000;
WaitMs(10);
  PORTC = 0b00110000;
WaitMs(10);
  PORTC = 0b00110000;
WaitMs(10);
  PORTC = 0b00010000;
WaitMs(10);
  PORTC = 0b00010000;
WaitMs(10);
  PORTC = 0b00000000;
WaitMs(10);
  PORTC = 0b00000000;
WaitMs(10);
  PORTC = 0b00000100;
WaitMs(10);
  PORTC = 0b00000000;
WaitMs(10);
  PORTC = 0b00100000;
WaitMs(10);
  PORTC = 0b00111000;
WaitMs(10);

Es tut sich aber leider garnichts :-(

Hier nochmal die Pinbelegung:

// Pin connections:
//  - PC0 - Grün    = E
//  - PC1 - Gelb    = RS
//  - PC2 - Orange    = DB4
//  - PC3 - Rot      = DB5
//  - PC4 - Braun    = DB6
//  - PC5 - Schwarz    = DB7

Oder:

  // Belegung am Port C:
  //      E RS DB4 DB5 DB6 DB7 ?  ?
  // 0 b  0 0  0   0   0   0   0  0
Gast #330011
Lesenswert?

Das musste schon umdrehen, sonst klappt gar nix. Außerdem setzt Du das
Enable nie, so dass überhaupt nix übertragen werden kann. Vielleicht
solltest Du Dir tatsächlich mal ein paar Abschnitte im Datenblatt
ansehen. Und natürlich Grundlagen Zahlendarstellung (Hex und Binär)...
Gast #330012
Lesenswert?

Zur Info: PC0 ist das niedrigstwertige (oder nierderwertigste...???) Bit
in PORTC. Das steht in der Binärdarstellung ganz rechts. Ist genau wie
im Dezimalsystem (da stehen die niederwertigen Stellen auch rechts),
nur dass hier die Basis 2 ist.

Dezimal: z.B.
...1000er, 100er, 10er, 1er

Binär:
...128er, 64er, 32er, 16er, 8er, 4er, 2er, 1er
(0b  0     0     0     0     0    0    0    0)

Solange Du das nicht verstanden hast, brauchst Du mit µC-Programmierung
gar nicht erst anzufangen. Bitte beschäftige Dich zunächst mit den
Grundlagen. Aber lass Dich nicht entmutigen. Es ist noch kein Meister
vom Himmel gefallen. Alles Schritt für Schritt...

Gruß

Johnny
#330016
Lesenswert?

> OK, nachdem ich nun alles fleißig gelsen habe bin ich zu
> folgender Init Funktion gelangt:
>
> WaitMs(20);
>   PORTC = 0b00110000;
> WaitMs(10);
>   PORTC = 0b00110000

WaitMs() wartet nur, richtig?

Also, dann wird das so nichts. Einfach nur am PortC irgendwelche
Daten anlegen ist zuwenig. Dadurch wird nichts uebertragen.
Du musst schon an den anderen Pins (Enable, Write) am LCD
auch noch wackeln.

Studier doch mal den Source Code von Peter Fleury, auch wenn
sie dir jetzt komplex erscheint, was sie in Wirklichkeit
nicht ist). Geh in Gedanken die Init-Sequenz dort durch
und schau nach was er anders macht. Du kannst dadurch nur lernen.
Es hilft auch das ganze mal im AVR-Studio im Debugger durchzusteppen
und die Port-Ausgänge zu beobachten. Auch da sieht mann sehr schön
welche Pins in welcher Reihenfolge auf 1 bzw. 0 gehen müssen.
Zumindest in der Init-Sequenz.
Gast #330018
Lesenswert?

Karl Heinz hat aber im Prinzip recht: Wenn Michael erst mal die
Zahlensysteme verstanden hat und sich noch ein paar weitere Grundlagen
angeeignet hat, dann sollte er sich vielleicht wirklich mal fertigen
Code ansehen und versuchen, den zu verstehen. Die fehlenden Grundlagen
sind sicher auch der Hauptgrund für seine Aussage, dass ihm die Lib von
Peter Fleury zu komplex ist. Klar, wenn ich grad dabei bin, zu lernen,
dass 1 + 1 = 2 ist, dann ist ein Dreisatz für mich auch komplex...
Gast #330019
Lesenswert?

>1 + 1 = 2
Das ist aber eher ein Problem der Definition des Zeichensatzes / der
Syntax (oder war es die Semantik?)...
1 + 1 könnte auch 10 oder 1 sein...
Grundlagen haben noch niemandem geschadet...
Gast #330023
Lesenswert?

@Stefan: nicht unbedingt...
in der "deutschen" Digitaltechnik wird das "Oder" auch als "v"
(vom lateinischen vel = oder) dargestellt. Das "Und" als ^, wobei es
sich bei beiden Symbolen um richtige (kleine) Dreiecke handelt. Man
kann es sich auch so merken: "Oder" ist ist oben offen und "Und"
unten...
"+" und "*" kommen aus dem angloamerikanischen Sprachgebrauch,
wobei das "+" noch einen Kreis drumherum haben müsste...
Gast #330025
Lesenswert?

<digital ist ein Plus ein ODER !!!! ALso 1+1=1 !!
Nicht ganz, weil es ist Sprachenabhängig. Wenn ich es matematisch
betrachte ist die Addition gemeint. Betrache ich es aus der Richtung
Schaltalgebra stimmt das.
Verrückte Welt!
MFG Uwe
Gast #330026
Lesenswert?

@Stephan: Wenn du das "+" als Verknüpfungsoperator gemeint hast, gebe
ich mich geschlagen. Wenn ich aber eine Addition ausführen möchte
verlasse ich mich doch lieber auf das XOR wo 1+1 0 ergibt(plus den
natürlich fälligen Übertrag).

Gruß Chris
Gast #330028
Lesenswert?

Sch**** da hab ich ja was losgetreten... Sollte doch nur ein Beispiel
aus dem wahren Leben sein... und da lernt man zuerst mal normalerweise
Dezimalsystem... Bei mir wars jedenfalls so. Fest steht, dass der
Ausdruck 1+1=2 in jedem gebräuchlichen Zahlensystem, in dessen
Zahlzeichenvorrat es eine 2 gibt, korrekt ist. Das kann man jetzt
wahrscheinlich auch noch tausendmal drehen und wenden...
Gast #330029
Lesenswert?

OK, vielen Dank erstmal für euren Input :-) Ich habe mich mittlwerweile
ein wenig schlau gemacht, was die Binärzahlen angeht. Mein größtes
Problem war wohl, dass ich dachte die Bits an den AVR-Ports wären 0 bis
7 aufsteigend. Aber wenn ich das jetzt richtig verstanden habe siehts so
aus:

PORTC = 0b76543210;

(Wobei die Zahlen jetzt nur für die Pins stehen, nicht für Bits!). Ist
das korrekt so?


Dann nochmal zum Display: ich habe leichte Probleme mit der
Sprut.de-Tabelle (Hier der Link direkt darauf:
http://www.vankurt.de/images/dispTab.gif)

Zu den ersten drei Befehlen hab ich diesen Init-Code gebastelt:

WaitMs(20);        // Warte erstmal 20 ms
  PORTC = 0b00001101;    // Setze ENABLE, DB4 und DB5 auf 1  (8-Bit 
Modus)
  WaitMs(10);        // Warte 10 ms
  PORTC = 0b00001101;    // Setze ENABLE, DB4 und DB5 auf 1  (8-Bit 
Modus)
  WaitMs(5);        // Warte 5 ms
  PORTC = 0b00001101;    // Setze ENABLE, DB4 und DB5 auf 1  (8-Bit 
Modus)
  WaitMs(5);        // Warte 5 ms
  PORTC = 0b00001001;    // Setze ENABLE, DB4 und DB5 auf 1  (4-Bit 
Modus)

Ist der denn so weit in Ordnung?

Mein Problem ist dann der letze Teil der Tabelle. Sollen das da einfach
10 Befehle sein? Weil zuerst wurden die ja einzelnd tabellenmäßig
getrennt, jetzt stehen sie direkt untereinander....
Und warum sind da Variablen wie N(1) oder F(0) drin? Und was bedeurten
dann die "-" ? Soll man die auf 1 oder 0 setzen? Und wofür stehen die
verschiedenen Hintergrundfarben (gelb, grün, blau)???? Sehr verwirrend
das ganze!! :-(

Ich hoffe ihr helft nochmal :-D
#330032
Lesenswert?

30h,30h,30h,20h,28h,08h,01h,06h,0fh
das sind die werte, so nun mal sehen,

30h   b00001100
20h   b00001000
28h   b0010000 und danach b00001000  erst high dann low

und so weiter, die Signale von RS E und RW kommand dann noch dazu.
Sind jetzt nicht berücksichtigt !!!!
ABER wie ich sagte mache die Belegung anders. Du machst Dir nen Wolf
mit dem Nibbeln der Bytes.

Folgender Vorschlag:
       0b 0  0   0    0   0   0   0   0    Bits binär
             E  RS   RW  DB7 DB6 DB5 DB4   Display
            PC6 PC5  PC4 PC3 PC2 PC1 PC0   Port C

Dann siehst so aus:

30h    0b    x  x  x  0   0   1   1

die X Werte müssen entsprechend gesetzt werden. Je nachdem ob Du
lesen/schreiben willst, Befehle oder Daten sendest.

Ab der 28h wird alles in 2er Paketen geschrieben. Erst High Nibble dann
Low Nibble. Die 28h  wäre dann 0b0000 0010 und 0b0000 1000.
Das Leerzeichen ist nur symbolisch zum besseren Verständnis für Dich.

So mehr kann man jetzt wirklich nicht für Dich tun.

Habe fertig.

stephan
Gast #330033
Lesenswert?

>30h   b00001100
>20h   b00001000

sollte 30h nicht eher b00110000 und 20h b00100000 heissen?
Deine Schreibweise gilt wohl eher als die Bit-Reihenfolge bei der
Übertragung über die serielle Schnittstelle...
Gast #330035
Lesenswert?

Danke erstmal, dass du dir so viel Mühe gibst, Stefan :-)
Leider hab ich's immer noch nicht hinbekommen...
Damit das klar ist:

"30h,30h,30h,20h,28h,08h,01h,06h,0fh
das sind die werte, so nun mal sehen,"

Für welche Pin-belegung sind die denn gedacht? Die aus deinem
Vorschlag?

"Folgender Vorschlag:
       0b 0  0   0    0   0   0   0   0    Bits binär
             E  RS   RW  DB7 DB6 DB5 DB4   Display
            PC6 PC5  PC4 PC3 PC2 PC1 PC0   Port C"

Dann versteh ich nämlich nicht ganz, wie du von 30h (was ja binär
110000) sein müsste auf 0bxxx0011 kommst... oder beziehst du dich da
jetzt auf meine Belegung? (letzteres macht für mich gerade auch keinen
Sinn)
Die Verwirrung ist groß ^^


Danke!!!
Gast #330037
Lesenswert?

Also gut, dann nochmal für Idoten:
Wenn ich deine Pin-Belgung verwende:

"Folgender Vorschlag:
       0b 0  0   0    0   0   0   0   0    Bits binär
             E  RS   RW  DB7 DB6 DB5 DB4   Display
            PC6 PC5  PC4 PC3 PC2 PC1 PC0   Port C"

und dann in kleinen Zeitabständen deine Werte rübersende:
"30h,30h,30h,20h,28h,08h,01h,06h,0fh", dann ist das Display
vernünftig initialisiert?

Bitte entschuldige meine Schwerfälligkeit - das ist eigentlich nicht
meine Art. Aber in diesem Fall stehe ich so derbe auf der Leitung, das
gibt's garnicht ;-)
Ich denke wenn das Ding erstmal läuft macht's auch mehr Spass damit
rum zu experimentieren. Aber so lange man garichts sieht ist das alles
eher frustrierend...

1000 Dank für deine Geduld. Du bist ein echter Held für mich :-D
#330038
Lesenswert?

so siehts aus, allerdings hast Du dann erstmal nur den Kursor zu sehen.

Also 1. Eable setzen, RW,RS, Wert Ausgeben, Enable low

Wie gesagt, ab 20h mußt Du dann zerlegen in Low und High nibble.
4 Bit Modus.
Beim Lesen vom Display auch in 2 Schritten.
Ich habe bei mir RW fest auf MAsse, da ich nicht lesen will und nutze
eine feste Zeit von 5-6ms. Das reicht immer und ist immer noch schnell
genug. 2x16 schaffe ich damit ca. 4 Aktualisierung/Minute.
Gast #330039
Lesenswert?

So, da bin ich wieder :-D
Ich hab mir in der Zwischenzeit jede menge Zeug angelesen, da das alles
einfach nicht funktionieren wollte. Nun war der Meinung, die
Initialisierung endlich hinzubekommen.

Dann habe ich mit diesem Simulator herumgespielt:
http://www.geocities.com/dinceraydin/djlcdsim/djlcdsim.html
und bin zu folgender Befehlsreihenfolge gekommen, die wenigstens einen
blinkenden Cursor erzeugen sollte:


Erst 3 mal DB5 und DB4 an  -> Init 8 bit Modus

Dann nur DB5 an  -> Jetzt in 4 Bit wechseln

Dann alle aus -> Upper Nibble
Dann alle an  -> Lower Nibble -> Jetzt müsste Display AN, Cursor AN und
Blinken AN sein


Der Code dazu sieht so aus:
Belegung:
  //    PC7    PC6    PC5    PC4    PC3    PC2    PC1    PC0
  //  0b  0    0    0    0    0    0    0    0
  //    None  E    RS    None  D7    D6    D5    D4

Dann:

void enable( void )
{
  PORTC |= (1<<PC6);
}

void disable( void )
{
  PORTC &= ~(1<<PC6);
}



void initDisplay( void )
{

  //    PC7    PC6    PC5    PC4    PC3    PC2    PC1    PC0
  //  0b  0    0    0    0    0    0    0    0
  //    None  E    RS    None  D7    D6    D5    D4

WaitMs(30);

  disable();
  PORTC = 0b00000011;
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000011;
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000011;
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000010;
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000000;
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00001111;
  enable();

WaitMs(30);

}

ABER IMMERNOCH STREIKT DAS BLÖDE DING UND ZEIGT NUR SCHWARZE
KÄSTCHEN!!! Das kann doch nicht wahr sein!?!?! :-(
#330041
Lesenswert?

WaitMs(30);

  disable();
  PORTC = 0b00000010;
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000000;
  enable();

WaitMs(30);

hier fehlt noch ne Null !!!!!
Du willst doch 0Fh schreiben oder nicht ???

zB.: disable ();
     portc = 0b00000000;
     lalala


  disable();
  PORTC = 0b00001111;
  enable();

WaitMs(30);
Gast #330042
Lesenswert?

Ahh, du hast Recht. Es fehlt tatsächlich eine 0.
Hab also folgendes draus gebastelt:

WaitMs(30);

  disable();
  PORTC = 0b00000011;     // 8Bit
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000011;     // 8Bit
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000011;     // 8Bit
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000010;     // Jetzt 4Bit
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000000;     // ...
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00000000;     // Alles anschalten
  enable();

WaitMs(30);

  disable();
  PORTC = 0b00001111;     // ...
  enable();

WaitMs(30);
Persönliche Seite #330045
Lesenswert?

Soweit ich weiß liest das LCD die Daten vom Port mit fallender Flanke am
Enable-Pin.
D.h. das müsste bei dir so aussehen:

DDRC = 0xFF //alle Pins an Port C als Ausgang

WaitMS(20); //am Anfang reichen 20ms
PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01000011;  //8-Bit
PORTC &= ~(1<<PC6);  //Enable-Pin Low

WaitMS(5);
PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01000011;  //8-Bit
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(160);

PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01000011;  //8-Bit
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(160);

PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01000010;  //4-Bit Modus - MSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(1);
PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01000000;  //4-Bit Modus - LSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(160);

WaitMS(20);
PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01000010;  //4-Bit Modus - MSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(1);
PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01000000;  //4-Bit Modus . LSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(160);

PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01000000;  //Display AN, Cursor AN - MSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(1);
PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01001100;  //Display AN, Cursor AN - LSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(160);

PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01001000;  //DD-RAM Position 0 - MSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(1);
PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01000000;  //DD-RAM Position 0 - LSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(160);

PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01100100;  //Schreibt ein A - MSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(1);
PORTC |= (1 << PC6); //Enable-Pin High
PORTC = 0b01100001;  //Schreibt ein A - LSB
PORTC &= ~(1<<PC6);  //Enable-Pin Low
WaitUS(160);

WaitUS(x) wartet x µs, ich weiß nicht, wie die Funktion bei dir dafür
heißt, ich benutze delay.h von WinAVR (einbinden über #include
<util/delay.h>) dort heißt es "_delay_us(x)".

So funktioniert es bei mir einwandfrei

Zwei Hilfreiche Links sind auch:
http://www.myke.com/lcd.htm
http://www.ulrichradig.de/site/atmel/avr_lcd/pdf/LC.pdf
Gast #330046
Lesenswert?

@ Stephan
Ja, ich denke schon:
- RS ist bei mir an PC5, also in allen meinen Binärcodes = 0. =>
Befehlsmodus
- RW hab ich nicht verwendet, ist an GND gelötet. => Schreibzugriff
- E setze ich ja immer mit enable/disable vor und nach jedem Befehl,
den ich übertragen möchte (siehe Code)

Ist doch richtig so, oder?


@Peter
Bei fallender Flanke also? Nagut, hab meine Funktionen "enable" und
"disable" mal vertauscht (die machen

PORTC |= (1 << PC6); //Enable-Pin High
PORTC &= ~(1<<PC6);  //Enable-Pin Low

genau wie in deinem Code).

Leider bringt das immer noch nichts. Nach wie vor nur 8 schwarze
Kästchen, und die andere Hälfte komplet leer :-(
Gast #330047
Lesenswert?

Kurze Frage an peter: Warum hast du in allen deinen Befehlscodes (z.B.
0b01000011) an der zweiten Stelle nach dem b eine 1?
Ich verwende ja auch diesen Code, bei mir ist's allerdings 0b00000011,
also nur DB4 und DB5 an. Ist da noch was wichtiges an diesem Pin?

Und für alle Ideen, die zur Lösung meines Problems beitragen bin ich
natürlich absolut dankbar!!!
Persönliche Seite #330050
Lesenswert?

Bei mir (1x16 LCD) kann ich auch nur an den ersten 8 Stellen etwas
anzeigen, die hinteren 8 bleiben einfach leer. Ich dachte, dass mein
Display kaputt sei, denn wenn ich den Kontrast erhöhe sehe ich ganz
schwach Kästchen. Ich habe auch mal versucht, ob die hinteren acht
Stellen vom Controller vielleicht als zweite Zeile angesteuert werden,
aber das hat auch nicht funktioniert.
Hat dafür vielleicht jemand eine Lösung?

@Michael
Bist du dir sicher, dass dein Timing stimmt und die Funktion WaitMS(x)
auch x Millisekunden wartet?
Ich weiß von _delay_ms(x), dass die nur y / Mhz Millisekunden warten
kann, wobei y irgendeine Zahl ist, die ich gerade nicht mehr weiß.
Persönliche Seite #330051
Lesenswert?

Ich habe ebengerade noch einmal versucht mein Display im 2-Zeilen Modus
anzusteuern und es hat doch funktioniert. Das liegt wahrscheinlich an
den Adressen der Zeichen (vermutlich: 80..87, C1..C7; ich war von 80
bis 8F ausgegangen).
Als Lösung habe ich meine Routine so umgeschrieben, das sie ab einem
Spaltenindex von 8 automatisch in die 2. Zeile umspringt und man das
Display nun wie ein 1x16 LCD ansteuern kann.
Gast #330054
Lesenswert?

Mittlerweile sieht der Code so aus:


void enable( void )
{
  PORTC |= (1<<PC6);
}

void disable( void )
{
  PORTC &= ~(1<<PC6);
}



void initDisplay( void )
{

  //    PC7    PC6    PC5    PC4    PC3    PC2    PC1    PC0
  //  0b  0    0    0    0    0    0    0    0
  //    None  E    RS    None  D7    D6    D5    D4

WaitMs(30);

  enable();        // Setze E auf 1
  PORTC = 0b01000011;    // Befehl
  disable();        // Jetzt E auf 0 -> fallende Flanke

WaitMs(30);

  enable();
  PORTC = 0b01000011;
  disable();

WaitMs(30);

  enable();
  PORTC = 0b01000011;
  disable();

WaitMs(30);

  enable();
  PORTC = 0b01000010;
  disable();

WaitMs(30);

  enable();
  PORTC = 0b01000000;
  disable();

WaitMs(30);

  enable();
  PORTC = 0b01000000;
  disable();

WaitMs(30);

  enable();
  PORTC = 0b01001111;
  disable();

WaitMs(30);

}


Und ratet was passiert? Genau! Schwarze Kästchen!!!!!!
ICH BEKOMM HIER GLEICH NEN NERVENZUSAMMENBRUCH VERDAMMT!!!!!!  ^^
Das kann doch echt nicht wahr sein.... gibt es sonst noch Tips?

(Mal wieder vielen Dank an alle Mithelfenden!)
Gast #330058
Lesenswert?

1) Also das mit dem Timing ist OK. Meine Funktion wartet eher zu lang
als zu kurz, was ja kein Problem ist, oder?
Ich benutze die auch um eine LED blinken zu lassen (mit 100ms, das
sieht schon ganz OK aus).

2) Das hab ich wohl gemacht.

3) OK, da muss ich nochmal gucken... ;-)


Die C-Datei findet sich im Anhang.
Angehängte Dateien:
Persönliche Seite #330059
Lesenswert?

Also wenn ich mein Display einfach nur initialisiere ohne Daten ins
DD-RAM zu schreiben bekomme ich auch nur schwarze Kästchen angezeigt.

Schreibe mal noch folgendes an das Display: (hinter deinem bisherigen
initDisplay)

  enable();
  PORTC = 0b01001000;
  disable();
WaitMS(1);

  enable();
  PORTC = 0b01000000;
  disable();
WaitMS(5);

  enable();
  PORTC = 0b01100100;
  disable();
WaitMS(1);

  enable();
  PORTC = 0b01100001;
  disable();
WaitMS(5);

Und verkürze die Wartezeiten zwischen MSB und LSB mal auf 1ms.
Gast #330060
Lesenswert?

Ich werd's gleich mal testen. Aber eigentlich sagt mein letzter
Befehl:
"Display ein, Cursor ein, Blinken ein"
Beim Simulator funktioniert's auch, da ist dann ein blinkender Cursor
zu sehen.....
Gast #330062
Lesenswert?

Kannst du jetzt mal bitte dein komplettes Programm zippen und anhängen?


Und mach mal zwischen enable und disable n paar takte pause, vielleicht
ist der abstand einfach zu kurz und dein Display bekommts nicht mit.
Immerhin kommen enable und disable fast im darauffolgenden Takt. Soviel
ich weiß muss enable aber auch ne bestimmte mindestzeit auf High stehen.


  enable();
  PORTC = 0b01100100;
  //hier warten
  disable();

Gruß Andreas
Gast #330065
Lesenswert?

@Stefan:
"erst Enable high ; das Display wieß..Ah jetzt kommt was für mich
dann RSund RW ; das Display wieß , Ah... Komando/ Daten,
schreiben/lesen
jetzt die Daten ;
und jetzt Enable auf Low; Display.... OK hab ich !!"

Dieser Textblock ist syntaktisch etwas merkwürdig... ich bin nicht
sicher, ob ich den richtig lesen kann ;-)


@Andreas:
Es ist ein AVR Mega16, mit einem 11 Mhz Quarz...oder was mainst du?
Gast #330066
Lesenswert?

Mal ne Frage zu deinem Code:

void enable( void )
{
  PORTC |= (1<<PC6);
}

PORTC |= (1<<PC6); ??? macht man das so bei einem AVR? Bitschubsen für
das setzen eines einzelnen PortPins.
Ich kenn das halt vom MSP430 anders oder versteh ich die drei Zeilen
nicht?
Steuer mein Display allerdings auch nur im 8bit-Modus an.
Gast #330068
Lesenswert?

@Marcel: Ja das macht man so. Was er da macht ist normale Bitmaskierung.
Geschoben wird (ein halbwegs intelligenter Copiler vorausgesetzt) an der
Stelle gar nicht: Das ganze kann schon zur compile-zeit als Konstante
berechnet werden (in diesem fall 00100000).

@Michael: Genau das meinte ich - 11 Mhz Quarz bedeutet 1 Takt braucht
ca 90ns (1/11000000 = 9,0909... x 10e-8). Schau mal wieviele ns das
enable signal high sein muss (Datenblatt)

Und poste endlich mal deinen kompletten Code, damit wir sehen was du
machst!

Gruß Andreas
Persönliche Seite #330069
Lesenswert?

@Stephan:
""
erst Enable high ; das Display wieß..Ah jetzt kommt was für mich
dann RSund RW ; das Display wieß , Ah... Komando/ Daten,
schreiben/lesen
jetzt die Daten ;
und jetzt Enable auf Low; Display.... OK hab ich !!
""

Das ist übrigens Quark.

Wichtig ist: Zur Zeit, wo Enable von High auf Low wechselt, müssen
einfach nur die Datenleitungen und die RS+RW Leitungen valide Daten
aufweisen. Mehr nicht. Nix mit "Ah jetzt weiß das Display"..
Persönliche Seite #330070
Lesenswert?

PS: Hier mal einen Ausschnitt aus meiner eigenen Lib, die übrigens mit
einem EA DOG-M (16*2) super läuft.
1
void lcd_cmd8(unsigned char cmd)
2
{
3
  
4
  LCD_PORT = (cmd & 0xF0) >> 4;
5
  
6
  LCD_PORT &= ~(1<<LCD_RS);
7

8
  LCD_PORT |= (1<<LCD_E);
9
  nop();
10
  nop();
11
  nop();
12
  nop();
13
  nop();
14
  nop();
15
  LCD_PORT &= ~(1<<LCD_E);
16
  
17
  nop();
18
  nop();
19
  nop();
20
  nop();
21
  nop();
22
  nop();
23

24
  LCD_PORT = (cmd & 0x0F);  
25

26
  LCD_PORT |= (1<<LCD_E);
27
  nop();
28
  nop();
29
  nop();
30
  nop();
31
  nop();
32
  nop();
33
  LCD_PORT &= ~(1<<LCD_E);
34

35
  _delay_us(30);
36
}
#330071
Lesenswert?

@Simon,

für gewöhnlich aktiviert man Bausteine bevor man sie mit Daten
füttert.
Und das passiert mit Enable.
Ich habe lediglich versucht es für Michael verständlich auszudrücken,
( bildlich gesprochen ) sozusagen. Er scheint ja nicht mal die
Vorschläge von ganz oben porbiert zu haben, sonst hätte er ja nicht
knapp 80 Einträge im Tread. Und das erst beim INIT. .......
#330074
Lesenswert?

@Simon,

Zitat: "Das Display überwacht den Pegel von ENABLE. Ändert sich dieser
Pegel von Low nach High, dann fragt es die Leitungen RS und R/W ab
etc.pp :"

nachzulesen bei Sprut und im Datenblatt !!!
Es heist Enable und nicht /Enable

ergo..... es ist High aktiv.....

aber warscheinlich auch nur Quark !!!!

Meine Display gehen jedenfalls sehr gut !!
Und du solltest auch Hausaufgaben machen so wie Michael.
Gast #330075
Lesenswert?

"Er scheint ja nicht mal die Vorschläge von ganz oben porbiert zu
haben"
glaub mir, ich HABE SO ZIEMLICH ALLES probiert. Ich kann mir auch nicht
erklären woran's hapert.... aber ich werde da mal zusätzliche delays
einbauen, so wie ihr das vorgeschlagen habt.
Gast #330078
Lesenswert?

Ich habe jetzt überall noch kleine Delays (1 ms) eingebaut, wenn ich das
E-Bit ändere. Damit sollte es jetzt also auch keine Probleme mehr
geben...
Leider hat das ganze noch immer keine Wirkung gezeigt :-(

Mit den Fremdbibliotheken ist so eine Sache... die sind quasi garnicht
dokumentiert (keine Tutorials oder Referenz so weit ich sehen kann).
Und da sind krass viele merkwürdige Konstanten drin, die man wohl
irgendwie setzen muss, die ich aber nicht verstehe :-(
Persönliche Seite #330079
Lesenswert?

Versuche einfachmal folgenden Code für die LCD-Ansteuerung zu verwenden,
bei mir funktioniert dieser einwandfrei. Wenn es auch damit nicht geht
liegt das Problem woanders.
1
#include <util/delay.h>
2

3
#define ENABLE_PIN 6
4
#define RS_PIN 5
5

6
void LCDenable(void)
7
{
8
  PORTC |= (1 << ENABLE_PIN);
9
  _delay_loop_1(2);
10
  PORTC &= ~(1 << ENABLE_PIN);
11
}
12

13
void LCDwrite(char Data,char rs)
14
{
15
  DDRC = 0xFF;
16
  if (rs == 0)
17
  {
18
    PORTC &= ~(1 << RS_PIN); //rs == 0 -> Steuerregister
19
  } else {
20
    PORTC |= (1 << RS_PIN); //rs == 1 -> Datenregister
21
  }
22
  PORTC = (PORTC&0xF0) + ((Data&0xF0)>>4); //Write Nibbel MSB
23
  LCDenable();
24
  PORTD = (PORTC&0xF0) + (Data&0x0F); //Write Nibbel LSB
25
  LCDenable();
26
  _delay_us(160);
27
}
28

29
void LCDclear (void)
30
{
31

32
  LCDwrite (1,0); //Clear Display
33
  _delay_ms(5);
34
  LCDwrite (0x80,0);  //Set DD-Ram Adresse = 0
35
}
36

37
void LCDinit(void)
38
{
39
  DDRC = 0xFF;
40
  _delay_ms(20);
41
  LCDwrite(0x30,0);
42
  _delay_ms(5);
43
  LCDwrite(0x30,0);
44
  LCDwrite(0x30,0);
45
  LCDwrite(0x28,0); //LCD in 4bit Modus - 2 Zeilen
46
  _delay_ms(20);
47
  LCDwrite(0x28,0); //LCD in 4bit Modus - 2 Zeilen
48
  LCDwrite(0x06,0); //Cursor wird nach schreiben nach rechts verschoben
49
  LCDwrite(0x0C,0); //Display an, Cursor aus, Blink_Cursor aus
50
  LCDwrite(0x80,0); //Set DD-Ram Adresse = 0 | 1000 0000 | 1=DD-Ram
51
0000000=Adresse
52
}
53

54
int main(void)
55
{
56
  LCDinit();
57
  LCDclear();
58
  LCDwrite(0x54,1);
59
  LCDwrite(0x65,1);
60
  LCDwrite(0x73,1);
61
  LCDwrite(0x74,1);
62
}
Gast #330082
Lesenswert?

Hast du denn die Vorschläge von oben schon probiert:

- PortC überprüfen (JTAG o.ä. deaktiviert?), oder nimm mal einen andern
Port.

- schmeiß deine eigene Wartroutine weg, ich wette es liegt am Timing.
Nimm zum testen mal die busy-wait routine _delay_ms(...)

Gruß Andreas
Gast #330083
Lesenswert?

@Peter:
Erstmal vielen Dank für deinen Code! Leider bringt auch der keine
Veränderung: nach wie vor nur 8 schwarze Kästchen.
Ich denke mal wir haben die gleiche Pinbelegung, ja? (zumindest RS und
E sind schonmal korekt).....
Woran könnte es denn dann liegen?

@Andreas:
Ich hab zwar keine Ahnung wer oder was JTAG ist, aber der Port scheint
OK zu sein. Hab auch mal alles an Port A gehängt (natürlich Software
entsprechend geändert), hat aber auch nicht geholfen.

Die Ports sind aber OK, ich hab LED-blink-Tests damit gemacht, und
jeder Pin ist OK.

Ich habe auch mit nem Multimeter geprüft, ob die Pins vom AVR gut mit
dem Display verlötet sind. Das scheint ebenfalls so zu sein...
Gast #330090
Lesenswert?

Vorschlag zur systematischen Fehlersuche:

1. Verwende bewährte Software (z.B. peter fleury´s lib)
2. Nehme die entsprechenden Einstellungen in der Software vor, meistens
nur im Kopf der Quelltexte nötig
3. Baue Deine Schaltung komplett neu auf, nach den getroffenen
Vorgaben, um zu verhindern, dass Du murks verdrahtet hast
4. Verwende ggf. R/W um die Busy Flag auslesen zu können.
5. Setze ggf. die Taktung Deines MC in der Configuaration herunter, da
zu hohe Datenraten nicht verarbeitet werden
6. Mit Strom auf dem Module regele den Kontrast mit einem Poti an Pin 3
so ein, das die schwarzen Kästen gerade noch zu sehen sind

Dann kannst Du immer noch Deine eigene (Code-) Suppe kochen und die
Performance steigern.
Sollte es immer noch nicht funktionieren versuche ggf. ein anderes
Display.


Viel Glück
Gast #330091
Lesenswert?

Äh ich hoffe deine "LED-Blink-Tests" hast du nicht direkt am Bus
gemacht? Dann könnte es sein, dass die Spannung die an den LEDs abfällt
zu groß ist und die übrige Spannung nicht mehr eindeutig genug ist..

Nochmals die andere Frage: Hast du endlcih deine Warteroutine
weggeworfen??

Gruß Andreas

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren