Forum: Mikrocontroller und Digitale Elektronik LCD Problem mit blafusel´s Routinen


von Jensi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich möchte gerne mit der Include Datei von Blafusel (im Anhang) ein 16x2 
HD44780 LCD-Display ansteuern.
Das Display ist von Pollin:
http://www.pollin.de/shop/dt/ODc1OTc4OTk-/Bauelemente_Bauteile/Aktive_Bauelemente/Displays/LCD_Modul_TC1602A_08.html


Angeschlossen ist alles so wie es in der Routine drinnen steht.
Aber ich bekomme nur wirre Zeichen (Siehe Bild nächster Post).

Kann mir einer sagen was ich da ändern muss?
Versuche das ganze schon seit Tagen zum laufen zu bekommen.

LG

von Jensi (Gast)


Angehängte Dateien:

Lesenswert?

Wurde mit dem Handy gemacht ;-)

von Klaus W. (mfgkw)


Lesenswert?

Das sieht doch schon viel besser als bei den meisten Leuten, die mit LCD 
scheitern.

Aber nur aus der Headerdatei hast du kein laufendes Programm 
herausbekommen, oder?

von Jensi (Gast)


Angehängte Dateien:

Lesenswert?

Nein natürlich nicht ;-)
Im Anhang ist die LCD-Test Datei von Blafusel.

Mein Display ist 2x16, seins 2x24. Das sollte aber doch kein Problem 
sein oder?

Solang ich in der LCD.c nicht über die 16´te Stelle hinaus komme.

von A.H. (Gast)


Lesenswert?

Mir kommt so auf Anhieb die lcd_ini seltsam vor:
1
  lcd_write(0x38,0);     // B 0010 1000 => 8-Bit-Modus aktivieren
2
  lcd_write(0x2,0);    // B 0000 0010 => mit 8-Bit-Command in 4-Bit-Modus umschalten

1. Es steht im Datenblatt und bei der Pollin Beschreibung nur 
"Industriestandard" aber nicht welcher Controller konkret drin ist. D.h. 
für mich, dass vorsichtshalber die vollständige HD44780 Initialisierung 
notwendig ist. Es fehlt also ein Teil der üblichen 3 Function-Set 
Aufrufe  mit den notwendigen Delays dazwischen.

2. lcd_write schickt zwei Halbbytes hintereinander. Im ersten Teil der 
Intialisierung darf für die Function-Sets NUR das obere Halbbyte 
gesendet werden.

3. das zusätzlich lcd_flash_e schickt das letzte untere Halbbyte 
nochmal zum Controller. Das klappt hier garantiert nicht so wie 
erwartet.

Mir kommt es so vor, als ob der ursprüngliche Code für einen 8-Bit 
Anschluss und für irgendeinen KS-Controller gedacht war. Da mag das so 
funktioniert haben.

Mal so direkt im Forum zusammengetippt: Probier mal
1
void lcd_write_init(uint8_t data)
2
{
3
    PORTC = (data>>4);    // output high nibble only,(!) zzgl. Zustand für RS-Leitung
4
  lcd_flash_e ();    
5
}
6
7
....
8
// in lcd_init
9
 delay(16000);    // 10ms warten bis LCD wirklich bereit (max. Wert lt. Datenblatt)
10
11
  lcd_write_init(0x30);     // init 1
12
  delay(4100);
13
  lcd_write_init(0x30);     // init 2
14
  delay(100);
15
  lcd_write_init(0x30);     // init 3
16
  delay(100);
17
18
  lcd_write_init(0x20,0);    // B 0000 0010 => mit 8-Bit-Command in 4-Bit-Modus umschalten 
19
20
  // das lcd_flash_e muss hier garantiert raus.
21
22
  delay(100);      // sicherheitshalber warten
23
24
  // ab jetzt 4-Bit-Modus
25
....

Das lässt sich zwar in weniger Taktzyklen erledigen, aber ich habe das 
Gefühl, dass im Moment Klarheit mehr gefragt ist :-)

von Klaus W. (mfgkw)


Lesenswert?

Vielleicht macht es auch Sinn, mit etwas zu starten, das besser 
dokumentiert und wartbar ist.
Dafür ist dein lcd_tools.h vielleicht die falsche Wahl.

Die meisten kommen wohl damit halbwegs zurecht:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung

von Jensi (Gast)


Lesenswert?

A.H. schrieb:
> lcd_write_init(0x20,0);    // B 0000 0010 => mit 8-Bit-Command in 4-Bit-Modus 
umschalten

Dabei bekomm ich einen Fehler: Zu viele Argumente! Habe das ",0" mal 
rausgelöscht.

Code ist jetzt:
/* LCD Include-Datei
 *
 * Das LCD ist folgendermaßen angeschlossen:
 * PC4     = RS
 * PC5     = Enable
 * PC0-PC3 = D4-D7
 * R/W ist n.c.
 *
 * 03/2005 Florian Schäffer, http://www.blafusel.de
 *
 */

#include <avr/io.h>
#include <avr/delay.h>

#define delay(us)  _delay_loop_2 (((F_CPU/4000)*us)/1000)    // wartet 
µs


void lcd_write_init(uint8_t data)
{
    PORTC = (data>>4);    // output high nibble only,(!) zzgl. Zustand 
für RS-Leitung
  lcd_flash_e ();
}

// Enable-Leitung toggeln
void lcd_flash_e ()
{
  PORTC = PORTC | ( 1<<DDC5 ) ;    // Enable = HIGH
  delay(1);              // kurz warten, damit Flanke entsteht
  PORTC = PORTC & ~( 1<<DDC5 ) ;    // Enable = LOW
  delay(64);              // Warten, bis der durch Enable angelegte 
Befehl hoffentlich verarbeitet wurde
}

// Kommando oder Zeichen an Display senden: rs=0 => Kommando, rs=1 => 
Zeichen
void lcd_write (uint8_t data, uint8_t rs)
{
  uint8_t dataBits ;

    if (rs)            // write data (RS=1, RW=0)
       dataBits=0x10;    // RS liegt an Pin 4 = B 0001 0000 = H 10
    else             // write instruction (RS=0, RW=0)
       dataBits=0;

    PORTC = dataBits |(data>>4);    // output high nibble first, zzgl. 
Zustand für RS-Leitung
  lcd_flash_e ();
    PORTC = dataBits | (data&0x0F);  // output low nibble, zzgl. 
RS-Leitung
  lcd_flash_e ();
  delay(2000);
}

// Display loeschen
void lcd_cls ()
{
  lcd_write(0x02,0);     // B 0000 0010 => Display loeschen
  delay(2000);      // dauert eine Weile, Wert ausprobiert
  lcd_write(0x01,0);     // B 0000 0001 => Cursor Home
  delay(2000);      // dauert eine Weile, Wert ausprobiert
}

// Zeichenausgabe
void lcd_writechar (uint8_t zeichen)
{
  lcd_write (zeichen, 1);
}

// gibt eine Zeichenkette auf dem LCD aus
void lcd_writetext ( char *text)
{
  uint8_t i = 0;
  while (text[i]!=0)
  {
    lcd_writechar(text[i]);
    i++;
  }
}

// gibt eine int-Zahl auf dem Display aus. Zweiter Parameter = Anzahl 
der Stellen (führende Leerzeichen),
// space=0 => führende Nullen, 1 => führende Leerzeichen
void lcd_writezahl (int32_t zahl, uint8_t pos, uint8_t spacer)
{
   int32_t output;
   char sign = '0';

  pos--;       // Korrektur des Parameters für Benutzerfreundlichkeit

  if (spacer) sign=' ';

  // negatives Vorzeichen oder Leerzeichen
  if (zahl < 0)
  {
  lcd_writechar ('-');
  zahl *= -1;    // positive Zahl
  }

  output = zahl;

  // Hunderttausender-Dezimalstelle oder Leerzeichen (Ausblenden 
fuehrender Nullen)
  if (zahl >= 100000) lcd_writechar (0x30 + output/100000); else if (pos 
>= 5) lcd_writechar (sign);
  output = output % 100000;

  // Zehntausender-Dezimalstelle oder Leerzeichen (Ausblenden fuehrender 
Nullen)
  if (zahl >= 10000) lcd_writechar (0x30 + output/10000); else if (pos 
>= 4) lcd_writechar (sign);
  output = output % 10000;

  // Tausender-Dezimalstelle oder Leerzeichen
  if (zahl >= 1000) lcd_writechar (0x30 + output/1000); else if (pos >= 
3) lcd_writechar (sign);
  output = output % 1000;

  // Hunderter-Dezimalstelle oder Leerzeichen
  if (zahl >= 100) lcd_writechar (0x30 + output/100); else if (pos >= 2) 
lcd_writechar (sign);
  output = output % 100;

  // Zehner-Dezimalstelle oder Leerzeichen
  if (zahl >= 10) lcd_writechar (0x30 + output/10); else if (pos >= 1) 
lcd_writechar (sign);

  // einer Dezimalstelle oder Leerzeichen
  lcd_writechar (0x30 + output % 10);
}

// Zeilenwechsel
void lcd_gotoline (uint8_t zeile)
{
  if (zeile == 1) lcd_write(0x80,0);   // B 1000 0000 => DD-RAM Adress 
Set 1. Zeile/1.Spalte
  if (zeile == 2) lcd_write(0xC0,0);   // B 1100 0000 => DD-RAM Adress 
Set 2. Zeile/1.Spalte (B x100 0000 = H 40)
}

// Cursorpositionieren (Zeile, Spalte)
void lcd_gotopos (uint8_t zeile, uint8_t spalte)
{
  if (zeile == 1) lcd_write(0x80+spalte-1,0);   // DD-RAM Adress 1. 
Zeile + Spalte
  if (zeile == 2) lcd_write(0xC0+spalte-1,0);   // DD-RAM Adress 2. 
Zeile + Spalte
}

// Portrichtung einstellen
void lcd_port_ini ()
{
  DDRC = 0x3F;    // setze Portrichtung (1 = Ausgang): 0011 1111
}

// Display initialisieren. Einmal als erstes aufrufen
void lcd_ini ()
{
  lcd_port_ini();
  PORTC=0x00;      // alle Leitungen LOW

  delay(16000);    // 10ms warten bis LCD wirklich bereit (max. Wert lt. 
Datenblatt)

  lcd_write_init(0x30);     // init 1
  delay(4100);
  lcd_write_init(0x30);     // init 2
  delay(100);
  lcd_write_init(0x30);     // init 3
  delay(100);

  lcd_write_init(0x20);    // B 0000 0010 => mit 8-Bit-Command in 
4-Bit-Modus umschalten



  delay(1000);      // sicherheitshalber warten

  // ab jetzt 4-Bit-Modus
  lcd_write(0x28,0);     // B 0010 1000 => Function Set: 4Bit (kein 
8-Bit Bus), zweizeiliges Display, 5x7 Dots/Zeichen (kein 5x10)
  lcd_write(0x0C,0);     // B 0000 1100 => Display On/Off: Display ein, 
Cursor aus, Blinken aus (0c0C) Cursor an: 0x0E
  lcd_write(0x06,0);     // B 0000 0110 => Entry Mode Set: DD-RAM autom. 
inkr., Cursor bewegen

  lcd_cls();        // Display löschen
}

von Jensi (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Vielleicht macht es auch Sinn, mit etwas zu starten, das besser
> dokumentiert und wartbar ist.
> Dafür ist dein lcd_tools.h vielleicht die falsche Wahl.

Möchte gerne die Routine verwenden, da ich gerne auf der Basis von 
Blafusel meine ersten gehversuche mit OBD machen möchte.

von Jensi (Gast)


Lesenswert?

Hier geht es um das IO-Board
http://www.blafusel.de/misc/atmega8_io.html

Dort steht in der Hardwareauflistung:
Anschluß für ein LCD (beachte die Einführung zum C-Control LCD-Modul!)

Wenn man da drauf klickt kommt man zu:
http://www.blafusel.de/misc/ccontrol2.html#1

Und dort steht:
Das LCD ist ein Standard Dot-Matrix LC-Display (und bitte nicht "LCD 
Display"!) mit HD44780/KS0070B/KS0076B kompatiblen Controller von 
Electronic Assembly mit 2x24 Zeichen in weißer Schrift bei blauer 
Hintergrundbeleuchtung (EA W242B-NLW). Prinzipiell sind auch andere LCDs 
möglich.

von A.H. (Gast)


Lesenswert?

Die Frage ist jetzt: Hat's etwas gebracht? Oder wie verhält sich das 
Display jetzt?

PS: Im Code steht: "R/W ist n.c." Ich hoffe doch, dass du das auf Ground 
gelegt hast?

von Jensi (Gast)


Lesenswert?

> Die Frage ist jetzt: Hat's etwas gebracht? Oder wie verhält sich das
> Display jetzt?
Sorry hatte ganz vergessen dazu was zu schreiben :-D
Nein hat leider garnix gebracht. Genau so wie vorher :-(


> PS: Im Code steht: "R/W ist n.c." Ich hoffe doch, dass du das auf Ground
> gelegt hast?
Ja habe ich... R/W und D0 bis D3.

von A.H. (Gast)


Lesenswert?

Dann fallen mir nur folgende Punkte ein:

 - Passt die F_CPU Einstellung zum tatsächlichen Takt? Daraus leiten 
sich ja die Delays ab.
 - Gibt es durch zu hohes F_CPU irgendwelche Überläufe innerhalb von 
_delay_loop_2 ?
 - Den "delay(64)" in "lcd_flash_e" löschen, der ist überflüssig.

Wenn das nichts hilft, prüf nochmal die Schaltung nach.
Insbesondere: Ist die Versorgungsspannung ausreichend (5V) und stabil?

Denn wenn ich mir das Bild ansehe: Da sind etliche Buchstaben im einen 
Pixel zuweit nach rechts gerutscht. Das kann eigentlich nicht durch 
Software zustandekommen.

Wenn das immer noch nichts bringt: Gehe zurück auf Start und mach das 
schon erwähnte Tutorial.

von Jensi (Gast)


Lesenswert?

A.H. schrieb:
> - Passt die F_CPU Einstellung zum tatsächlichen Takt? Daraus leiten
> sich ja die Delays ab.
Ja die passt.

>  - Gibt es durch zu hohes F_CPU irgendwelche Überläufe innerhalb von
> _delay_loop_2 ?
Nachdem ich die Fuses auf 1 mhz und im Makefile 1MHZ eingetragen habe 
geht es.....

Ich brauche aber die 8MHZ für die OBD anwendung oder?

von Jensi (Gast)


Lesenswert?

Nach Strom weg, Strom drauf ist wieder alles beim alten....

Nix geht mer -.-

Ich verzweilfel langsam -.-

von Oliver J. (skriptkiddy)


Lesenswert?

Beim googlen hab ich herausgefunden, das dort wahrscheinlich ein 
SPLC780D verbaut ist. In wie weit der sich vom Standard unterscheidet 
kann ich nicht sagen. Einfach mal schauen, wie man das Teil richtig 
initialisiert.


Beitrag "Bibliothek fuer SPLC780D"
http://www.oppod.com/pdf/TC1602A_Manual.pdf


Gruß Skriptkiddy

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