LCD Problem mit blafusel´s Routinen

Gast #2286705
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
Angehängte Dateien:
Gast #2286782
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 :-)
Gast #2286881
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
}
Gast #2286911
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.
Gast #2286948
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.
Gast #2287081
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.
Gast #2287101
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?

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