Forum: Mikrocontroller und Digitale Elektronik Zweite Zeile LCD Display


von immer_das_gleiche... (Gast)


Lesenswert?

Hallo Leute,
bin seit geraumer Zeit mit dem AVR GCC Tutorial beschäftigt und dabei 
eine Library für mein LCD zu schreiben.
Ich möchte keine fertige nehmen, der Lerneffekt ist beim selber machen 
größer :)

Problem ist nun das ich keine Buchstaben in die zweite Zeile bekomme ... 
sobald ich die Adresse auf 0x40 setze kommt nichts. Ich muss aber dazu 
sagen, dass es ohne Probleme Funktioniert, einen String an eine 
bestimmten Stelle in der 1.Zeile zu schreiben.

Ja habe die Forensuche benutzt und bin auf keine passende Antwort 
gestoßen :(

Ich benutze das myAVR Board LPT mit dem Display Add-on.
http://www.myavr.info/download/produkte/lcd/techb_lcd_de_en.pdf

Hier ist mal ein Ausschnitt aus dem Code:
Hauptprogramm:
1
// Bibliotheken
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdint.h>
5
#include "myavr_lcd.h"
6
7
// Definitionen
8
#ifndef F_CPU
9
#define F_CPU           3686400
10
#endif
11
12
int i=0;
13
14
int main(void) {
15
    // LCD Initialisieren
16
    lcd_initialisieren();
17
18
    // LCD Ausgabe
19
    lcd_set_string(2,1,"blub");
20
21
22
    // Programmende 
23
    return 0;
24
}

Auschnitt aus der Library:
1
// String zur aktuellen Cursor Position senden
2
void lcd_string(const char *string) {
3
    // String zerlegen und schicken
4
    while(*string != '\0')
5
        lcd_data(*string++);
6
}
7
8
// Cursor Position setzen
9
void lcd_set_cursor(uint8_t zeile, uint8_t spalte) {
10
    // 1.Zeile
11
    if(zeile == 1) {
12
        lcd_command(0x80 + (spalte-1));
13
    }
14
    // 2.Zeile
15
    if(zeile >= 2) {
16
        lcd_command(0x80 + 0x40 + (spalte-1));
17
    }
18
} 
19
20
// String zu einer definierten Position schicken
21
void lcd_set_string(uint8_t zeile, uint8_t spalte, const char *string) {
22
    // Cursor Position festlegen
23
    lcd_set_cursor(zeile,spalte);
24
25
    // String zur Position senden
26
    lcd_string(string);
27
}

von tt2t (Gast)


Lesenswert?


von LCD (Gast)


Lesenswert?

Es kann sein das die zweite Zeile garnicht Initialisiert wird.
Dies kann durch zukurze wartezeiten passieren.

von immer_das_gleiche... (Gast)


Lesenswert?

Also dann scheinen meine Unterprogramme ok zu sein.
Habe die Wartezeiten mal erhöht aber der Effekt ändert nichts.

Wartezeiten
1
/////////////////////////////////////////////////////////////////////
2
/*                    LCD PAUSEN ZEITEN (in ms)                    */
3
/////////////////////////////////////////////////////////////////////
4
#define lcd_en_time     6           // Enable Zeit
5
#define lcd_start_time  50          // Hochfahrzeit
6
#define lcd_cmd_time    2           // Befehlszeit
7
#define lcd_data_time   0.5         // Datenzeit
8
9
// Reset Zeiten    
10
#define lcd_reset_a     5      
11
#define lcd_reset_b     0.1
12
#define lcd_reset_c     5

Initialisierung & Befehle
1
/////////////////////////////////////////////////////////////////////
2
/*                          LCD BEFEHLE                            */
3
/////////////////////////////////////////////////////////////////////
4
#define lcd_reset       0b00110000  // Software Reset
5
#define lcd_modus       0b01000000  // 4Bit Modus
6
#define lcd_funktion    0b00101000  // 4Bit Modus, 2Zeile, 5x7Dots
7
#define lcd_entry       0b00000110  // Cursor increase, Display not shifted
8
#define lcd_off         0b00001000  // Display aus
9
#define lcd_on          0b00001100  // Display ein, Cursor aus, Cursor blink aus
10
#define lcd_clear       0b00000001  // Display löschen
11
12
#define lcd_ddram       0x80  // Benötigt um DDRAM Adresse zu setzen
13
#define lcd_ddram_2     0x40  // Adresse der zweiten Zeile
14
15
// LCD Initialiseren
16
void lcd_initialisieren(void) {
17
    // Kurze einschaltpause
18
    _delay_ms(lcd_start_time);
19
20
    // Port einstellen
21
    lcd_port_ddr = 0b11111100;
22
    lcd_port     = 0x00;
23
24
    // LCD Resetten
25
    lcd_port |= lcd_reset;
26
    lcd_enable();
27
    _delay_ms(lcd_reset_a);
28
    
29
    lcd_enable();
30
    _delay_ms(lcd_reset_b);
31
    
32
    lcd_enable();
33
    _delay_ms(lcd_reset_c);
34
35
    // 4Bit Modus aktivieren
36
    lcd_port = lcd_modus;
37
38
    // Display einstellen (2 Zeilen, 5x7 Dots, 4Bit Modus)
39
    lcd_command(lcd_funktion);
40
41
    // Eingabemodus einstellen
42
    lcd_command(lcd_entry);
43
44
    // Display ausschalten
45
    lcd_command(lcd_off);
46
47
    // Display löschen
48
    lcd_command(lcd_clear);
49
50
    // Display einschalten und Cursor einstellen
51
    lcd_command(lcd_on);  
52
}

Werde mal nebenbei bei Sprut schauen

von LCD (Gast)


Lesenswert?

immer_das_gleiche... schrieb:
> lcd_command(lcd_funktion);
>
>     // Eingabemodus einstellen
>     lcd_command(lcd_entry);

Versuch mal zwischen diesen beiden zeilen eine Pause zumachen zb 5ms.

von immer_das_gleiche... (Gast)


Lesenswert?

Passiert leider nichts :(

von immer_das_gleiche... (Gast)


Lesenswert?

also bei sprut bin ich nicht fündig geworden was meine situation ändern 
könnte :(

von LCD (Gast)


Lesenswert?

Wird die zweite Zeile denn dunkel wenn du den Kontrast voll aufdrehst?

von immer_das_gleiche... (Gast)


Lesenswert?

also sollange etwas in der ersten zeile dargestellt wird und ich dann am 
kontrast regler spiele. wird nur die erste zeile dunkel.

sieht wohl so aus als ob da was falsch initialisiert wird... oder irre 
ich mich?

von tonia (Gast)


Lesenswert?

lcd_reset_b ist zu kurz

von tonia (Gast)


Lesenswert?

wenn Du im 4-bit-Modus bist, musst Du immer 2x4 Bit (HI-LO) übertragen, 
damit der Befehl komplett ist. Du übeträgst nur 1x 4 Bit.

Steht alles bei sprut unter "Beispiel für eine Initialisierung mit 4-Bit 
Interface:"

von LCD (Gast)


Lesenswert?

Wenn das LCD richtig Initialisiert ist werden beide Zeilen dunkel wenn 
man mehr Kontrast reingibt. So wie das bei dir ausieht kann es durchaus 
an der Initialisierung liegen zB das die delays zu kurz sind.

von immer_das_gleiche... (Gast)


Lesenswert?

Danke schonmal soweit, habe die Zeiten mal geändert und es hat sich 
soweit auch nichts geändert.

Das einzigste was ich noch vermuten könnte ist das meine lcd_command(); 
funktion nicht ganz richtig ist.
1
// Befehl zum LCD senden
2
void lcd_command(uint8_t command) {
3
    // Obere Bits schicken
4
    lcd_port = (command & 0xF0);
5
    lcd_enable();
6
    
7
    // Untere Bits schicken
8
    lcd_port = (command << 4) & 0xF0;
9
    lcd_enable();
10
11
    // Kurze Pause
12
    _delay_ms(lcd_cmd_time);
13
}

Wobei ich mich frage, wenn das LCD doch nicht richtig initialisiert ist, 
dann sollte es doch gar nichts darstellen oder?

von immer_das_gleiche... (Gast)


Lesenswert?

ich muss aber noch dazu sagen, dass ich den cursor und sowas ändern 
kann. also sollten ja beide nibbel komplett übertragen werden :/

von usuru (Gast)


Lesenswert?

#define lcd_modus       0b01000000  // 4Bit Modus --- Deine Einstellung
---------------------------^

#define lcd_modus       0b00100000  // 4Bit Modus --- gefällt mit eher
----------------------------^

von immer_das_gleiche... (Gast)


Angehängte Dateien:

Lesenswert?

usuru schrieb:
> #define lcd_modus       0b01000000  // 4Bit Modus --- Deine Einstellung
>
> ---------------------------^
>
>
>
> #define lcd_modus       0b00100000  // 4Bit Modus --- gefällt mit eher
>
> ----------------------------^

danke, habe es geändert. leider funzt das auch nicht :(

habe aber nochmal den kompletten code angehangen. die reset zeiten habe 
ich mal an die aus dem LCD Tutorial angepasst.

von usuru (Gast)


Lesenswert?

#define lcd_reset_a     5
#define lcd_reset_b     1
#define lcd_reset_c     1

viele Displays brauchen längere Delays (manche aus kürzere). Mach das 
alles mal mindestens 10 msec lang. LCD-Displays sind keine Ferraris, 
sondern eher Fussgänger ...

Probier mal folgende Muster, damit initialisiere ich immer:

b'00110000'  ; 8-bit-interface
b'00110000'  ; 8-bit-interface
b'00110000'  ; 8-bit-interface
b'00100000'  ; 4-bit-interface
b'00101000'  ; 4-bit  2-zeilig  5x8
b'00000110'  ; cursor increase, display shifted
b'00001100'  ; display on
b'00000001'  ; löschen, cursor home

von immer_das_gleiche... (Gast)


Lesenswert?

mit den 10ms klappt es auch nicht :(
also laut der myavr anleitung sind die pausenzeiten
1. 5ms
2. 100us
3. 5ms
habe die anleitung auch schon 1 zu 1 gemacht aber es ist immer nur die 
1. zeile aktiv.
kaputt ist das display auch nicht, das test programm läuft.

deine reihenfolge ändert auch nichts an dem sachverhalt.
langsam verzweifel ich

von immer_das_gleiche... (Gast)


Lesenswert?

Hat jemand denn jemand einen anderen ansatz für die initialisierung? 
evtl. eine checkliste die ich durchgehen kann?

von su (Gast)


Lesenswert?

immer_das_gleiche... schrieb:
> Problem ist nun das ich keine Buchstaben in die zweite Zeile bekomme ...
>
> sobald ich die Adresse auf 0x40 setze kommt nichts.

ich verwende die Adresse für zweite Zeile 0x20, und erste Zeile 0x00.

lg

von Thomas (Gast)


Lesenswert?

>> Problem ist nun das ich keine Buchstaben in die zweite Zeile bekomme ...
>>
>> sobald ich die Adresse auf 0x40 setze kommt nichts.

> ich verwende die Adresse für zweite Zeile 0x20, und erste Zeile 0x00.

richtige Spur aber flasche Zahl: Die 2. Zeile wird mit 0x28 erreicht was
dez der pos 40 entspricht


Thomas

von spess53 (Gast)


Lesenswert?

Hi

>richtige Spur aber flasche Zahl: Die 2. Zeile wird mit 0x28 erreicht was
>dez der pos 40 entspricht

Aber nicht bei dem o.g. Display (S.10):
http://www.myavr.info/download/produkte/lcd/techb_lcd_de_en.pdf

MfG Spess

von Thomas (Gast)


Lesenswert?

> Aber nicht bei dem o.g. Display (S.10):
> http://www.myavr.info/download/produkte/lcd/techb_...

das scheint mir ein Fehler in diesem Datenblatt zu sein. So einen
Controller habe ich noch nie gesehen.
Die mir bekannten Controller können alle 80 Zeichen verwalten, weshalb
die 2. Zeile bei 40 anfängt. Die 0x40 halte schlicht für falsch.

Thomas

von Rene K. (draconix)


Lesenswert?

Nicht 0x40 sondern 0x28 was int 40 entspricht ;)

von Thomas (Gast)


Lesenswert?

> Nicht 0x40 sondern 0x28 was int 40 entspricht ;)

ich bin ja deiner Meinung und hatte das auch so geschrieben nur im 
zitierten Datenblatt steht eben 40h.

Thomas

von spess53 (Gast)


Lesenswert?

Hi

>Die 0x40 halte schlicht für falsch.

Stimmt aber für fast alle Displays, die ich kenne.

Sieh dir mal S.5 an:

http://www.lcd-module.de/pdf/doma/2_20.pdf

MfG Spess

von immer_das_gleiche (Gast)


Lesenswert?

so da bin ich wieder :D

also bei dem display ist die adresse 0x40.
das problem mit der zweiten zeile habe ich gelöst, in der 
initialisierung musste einfach hinter dem befehl lcd_command(lcd_modus); 
noch eine kurze wartezeit von 5ms ergänzt werden.

nun habe ich aber noch ein anderes problem, um den code übersichtlicher 
zu machen habe ich eine unterfunktion ergänzt
1
void lcd_display_reset(unsigned int time) {
2
    lcd_port = lcd_reset;
3
    lcd_enable();
4
    _delay_ms(time);
5
}
6
7
// LCD Initialiseren
8
void lcd_initialisieren(void) {
9
    // Kurze einschaltpause
10
    _delay_ms(lcd_start_time);
11
    
12
    // Port einstellen
13
    lcd_port_config();
14
15
    // LCD Resetten
16
    lcd_display_reset(lcd_reset_a);
17
    lcd_display_reset(lcd_reset_b);
18
    lcd_display_reset(lcd_reset_c);
19
20
    // 4Bit Modus aktivieren
21
    lcd_command(lcd_modus);
22
    _delay_ms(lcd_modus_time);
23
24
    // Display einstellen (2 Zeilen, 5x7 Dots, 4Bit Modus)
25
    lcd_command(lcd_funktion);
26
27
    // Display ausschalten
28
    lcd_command(lcd_off);
29
30
    // Display löschen
31
    lcd_display_clear();
32
33
    // Eingabemodus einstellen
34
    lcd_command(lcd_entry);
35
36
    // Display einschalten und Cursor einstellen
37
    lcd_command(lcd_on);  
38
}

sollange die funktion lcd_display_reset(); eingebaut ist, ist der code 
bei knapp 50% speichergröße des mega8.
die größe steigt erst von 5% auf 50%, sobald man in das _delay_ms(); die 
variable "time" einfügt.
gibt es dafür einen bestimmen grund?

von Serieller (Gast)


Lesenswert?

Ja. Steht in der FAQ bzw. in der Doku der Delay-Funktionen der avr-libc. 
Man darf nur eine Konstante als Argument übergeben, keine Variablen.

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.