Forum: Mikrocontroller und Digitale Elektronik LCD DISPLAY FLACKERT


von Kim (Gast)


Lesenswert?

Hallo,
ich scheitere an einem LCD-Display.
ich benutze den 4-Bit-Modus und habe DB4...DB7 vom LCD-Display mit 
RG6...RG9 am Controller verbunden.

die daten schicke ich dann immer in 4er pack rüber
1
static void lcd_nibble(unsigned char nibble)
2
{
3
    LATGbits.LATG6 = (nibble>>3)&1;
4
    LATGbits.LATG7 = (nibble>>2)&1;
5
    LATGbits.LATG8 = (nibble>>1)&1;
6
    LATGbits.LATG9 = (nibble>>0)&1;
7
    lcd_enable();
8
    delay_ms(2); // Enough time even for slowest command
9
}
10
11
////////////////////////////////////////////////////////////////////////////////
12
// Erzeugt einen Enable-Puls
13
static void lcd_enable( void )
14
{
15
    LCD_EN = 1;
16
    delay_us(LCD_ENABLE_US);  // kurze Pause
17
    LCD_EN = 0;
18
}
19
20
////////////////////////////////////////////////////////////////////////////////
21
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
22
void lcd_init( void )
23
{
24
    LCD_RS = 0;
25
    LCD_RW = 0;
26
    LCD_EN = 0;
27
28
    // LCD Soft Reset
29
    delay_ms(LCD_BOOTUP_MS);
30
    lcd_nibble(LCD_SOFT_RESET);
31
    delay_ms(LCD_SOFT_RESET_MS1);
32
    lcd_nibble(LCD_SOFT_RESET);
33
    delay_ms(LCD_SOFT_RESET_MS2);
34
    lcd_nibble(LCD_SOFT_RESET);
35
    delay_ms(LCD_SOFT_RESET_MS3);
36
    lcd_nibble(0x02);
37
    // Display settings
38
    lcd_cmd(LCD_SET_FUNCTION | LCD_FUNCTION_4BIT | LCD_FUNCTION_2LINE | LCD_FUNCTION_5X7 );
39
    lcd_cmd(LCD_SET_DISPLAY | LCD_DISPLAY_OFF);
40
    lcd_cmd(LCD_DISPLAY_CLEAR);
41
    lcd_cmd(LCD_SET_ENTRY | LCD_ENTRY_INCREASE | LCD_ENTRY_NOSHIFT);
42
    lcd_cmd(LCD_SET_DISPLAY | LCD_DISPLAY_ON | LCD_CURSOR_OFF | LCD_BLINKING_OFF);
43
    lcd_clear();
44
}
45
46
////////////////////////////////////////////////////////////////////////////////
47
// Sendet ein Datenbyte an das LCD
48
void lcd_data( unsigned int data )
49
{
50
    LCD_RS = 1;
51
    lcd_nibble(data >> 4);
52
    lcd_nibble(data & 0x0F);
53
    //LCD_PORT |= (1<<LCD_RS);    // RS auf 1 setzen
54
    delay_us( LCD_WRITEDATA_US );
55
}
56
57
////////////////////////////////////////////////////////////////////////////////
58
// Sendet einen Befehl an das LCD
59
void lcd_cmd( unsigned int data )
60
{
61
    LCD_RS = 0;                 // RS auf 0 setzen
62
    lcd_nibble(data >> 4);
63
    lcd_nibble(data & 0x0F);
64
    delay_us( LCD_COMMAND_US );
65
}
66
67
////////////////////////////////////////////////////////////////////////////////
68
// Sendet den Befehl zur Löschung des Displays
69
void lcd_clear( void )
70
{
71
    lcd_cmd( LCD_DISPLAY_CLEAR );
72
    delay_ms( LCD_DISPLAY_CLEAR_MS );
73
}

hiernach ist das display aber an flackern. Mache ich bei der 
Datenübertragung etwas verkehrt?
Die Variablen (z.B. LCD_DISPLY_CLEAR = 0x01 habe ihc aus dem Datenblatt 
des Displays übernommen)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Kim schrieb:
> hiernach ist das display aber an flackern.
Und WAS genau flackert danach?
WELCHE Daten werden übertragen?
WIE sieht der Rest des Programms aus?

von Axel S. (a-za-z0-9)


Lesenswert?

Kim schrieb:
> hiernach ist das display aber an flackern.

Was ist "hiernach"? Du hast hier einen Sack Funktionen gezeigt, aber 
nicht wie du die aufrufst. Ach ja, der Code wäre in einem Anhang besser 
aufgehoben gewesen.

> Mache ich bei der Datenübertragung etwas verkehrt?

Kann keiner sagen, weil ja keiner weiß was du machst.

Ich rate mal wild drauf los: du hast eine Endlosschleife, in der du 
immer wieder das Display löschst und neu beschreibst. Dann wird es 
natürlich flackern.

von Kim (Gast)


Angehängte Dateien:

Lesenswert?

Eigentlich dürfte es nur einmal durchlaufen werden.
aufrufen tu ich die initialisierung nur einmal in der main-funktion vor 
der Endlosschleife
1
int main (void)
2
{
3
    pin_init();
4
    lcd_init();
5
    while (1) {}
6
}
in pin_init() setze ich nur die benötigten pins als ausgang und auf low.
die ganze lcd datei habe ich mal in anhang gepackt.

von Kim (Gast)


Angehängte Dateien:

Lesenswert?

jetzt die c auch nich in txt

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Kim schrieb:
> nur einmal in der main-funktion vor der Endlosschleife
Könnte es sein, dass der Watchdog des unbekannten Mikrocontrollers da 
laufend einen Reset macht?

von Stefan F. (Gast)


Lesenswert?

Dann prüfe doch mal, ob nach der Initialisierung noch eine Kommunikation 
zum Display stattfindet. Dazu genügt notfalls eine LED an der 
Enable-Leitung.

von Kim (Gast)


Lesenswert?

Der Watchdog ist eigentlich ausgestellt.
1
_FOSC(CSW_FSCM_OFF & ECIO_PLL8); 
2
_FWDT(WDT_OFF);                 
3
_FBORPOR(MCLR_EN & PWRT_OFF);
4
_FGS(CODE_PROT_OFF);

Nach der Initialilsierung ist Enabled wieder auf low gesetzt. diesen 
setze ich jedesmal beim senden von daten auf das display auf high und 
anschliessend wieder auf low.

der controller ist ein dspic30f6011 von microchip

von Pete K. (pete77)


Lesenswert?

Was ist denn das für ein Display und wie sieht der Hardware-Aufbau aus?

Den includes nach zu urteilen handlet es sich wohl um einen PIC.

Stromversorgung stabil? ca. 250mA?

von Kim (Gast)


Lesenswert?

das ist ein ganz normales 2x16 lcd display mit hd44780
Verbunden habe ich es folgendermassen
Display/dspic30f6011
VSS/GND
VDD/VDD
V0/GND
RS/RB2
RW/GND
E/RB4
DB0...DB3 / nicht verbunden
DB4...DB7/ RB6...RB9
Die Verbindungen sind auch alle vorhanden und spannung bekommt er auch.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Kim schrieb:
> Der Watchdog ist eigentlich ausgestellt.
> ....
> Nach der Initialilsierung ist Enabled wieder auf low gesetzt. diesen
> setze ich jedesmal beim senden von daten auf das display auf high und
> anschliessend wieder auf low.
Das ist im geposteten Quellcode NICHT zu sehen. Da werden keine Daten 
gesendet...

Was soll denn das Gestocher im Trüben?
Wie soll man dir Tipps geben, wenn du unvollständigen Quellcode postest?

von Kim (Gast)


Lesenswert?

Ich habe ja doch die datei im anhang geladen.
zunächst möchte ich nur das display in betrieb nehmen und das display 
löschen. Es soll ja noch ncihts angezeigt werden, da das ja auch nicht 
funktioniert.

von Karl H. (kbuchegg)


Lesenswert?

Kim schrieb:

> zunächst möchte ich nur das display in betrieb nehmen und das display
> löschen.

Alles schön und gut.

Nur: Wenn die Initialisierung durch ist, und irgendwann ist sie durch,
gehen deiner Aussage nach auch keine Kommandos mehr an das LCD. Und von 
alleine flackert ein LCD nicht. Selbst dann nicht, wenn die 
Intialisierung fehl schlägt.

> Es soll ja noch ncihts angezeigt werden, da das ja auch nicht
> funktioniert.

Und was genau flackert dann?
Hintergrundbeleuchtung?

Hast du schon überprüft, ob dein Programm immer wieder neu anläuft? Das 
lässt sich mit einer LED leicht feststellen. Ganz am Anfang in main() 
einen Portpin auf Ausgang konfigurieren, LED einschalten, ein bischen 
warten (halbe Sekunde), LED wieder ausschalten.
legst du Spannung an den µC dann darfst du EINMALIG die LED aufleuchten 
sehen. Blinkt die aber, dann läuft dein Programm immer wieder von vorne 
weg. Warum auch immer.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Kim schrieb:
> Ich habe ja doch die datei im anhang geladen.
Aber nicht diejenige, die für ein solches Verhalten verantwortlich 
sein könnte.
Oder ich sage mal so: wenn der Fehler nicht in der Hardware ist, dann 
ist er in der Software. Und die Hardware ist ja recht einfach...

: Bearbeitet durch Moderator
von Sascha W. (sascha-w)


Lesenswert?

Kim schrieb:
> Eigentlich dürfte es nur einmal durchlaufen werden.
> aufrufen tu ich die initialisierung nur einmal in der main-funktion vor
> der Endlosschleife
>
1
> int main (void)
2
> {
3
>     pin_init();
4
>     lcd_init();
5
>     while (1) {}
6
> }
> in pin_init() setze ich nur die benötigten pins als ausgang und auf low.
> die ganze lcd datei habe ich mal in anhang gepackt.

ob nicht vielleicht dein Compiler die leere while-Schleife wegoptimiert? 
Dann würde das Programm mit dem Verlassen von Main wieder von vorn 
starten.

Sascha

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Sascha Weber schrieb:
> Dann würde das Programm mit dem Verlassen von Main wieder von vorn
> starten.

Die meisten Compiler setzen automatisch nach main() eine Endlosschleife 
ein.

von Karl H. (kbuchegg)


Lesenswert?

Sascha Weber schrieb:

> ob nicht vielleicht dein Compiler die leere while-Schleife wegoptimiert?

Warum sollte er?
Das wäre völlig unzulässig und grob falsch.

Mit so einem Compiler kann man nur eines tun: weit, weit wegwerfen.

Gott sei Dank kennen allerdings die Compilerbauer die Sprache besser und 
wissen, dass man eine Endlosschleife nicht einfach wegoptimieren kann. 
Selbst dann nicht, wenn sie leer ist.

von Harald N. (haraldn)


Lesenswert?

Arbeitest du am Steckbrett? Dann Jumperkabel tauschen. Evtl manchmal 
auch das Steckbrett selbst.

von C. L. (calle)


Lesenswert?

Hallo,

Kim schrieb:
> ich benutze den 4-Bit-Modus und habe DB4...DB7 vom LCD-Display mit
> RG6...RG9 am Controller verbunden.

Wenn Du im 4 Bit Modus bist, muss Du am Display die Eingänge 0...3 auch 
auf Masse legen, sonst kann es an diesen offenen Pins zu Schwebungen 
kommen.

Gruß CL

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Angehängte Dateien:

Lesenswert?

C. L. schrieb:
> muss Du am Display die Eingänge 0...3 auch
> auf Masse legen, sonst kann es an diesen offenen Pins zu Schwebungen
> kommen.

Nein, das ist eine Legende, die nur den Stromverbrauch erhöht. Sowohl 
der HD44780 als auch der KS0066 haben leichte Pullups an den 
Datenleitungen, die bei offenen Anschlüssen für definierte Pegel sorgen. 
Die Innenschaltung eines DB Pins habe ich mal angehangen.

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

C. L. schrieb:
> Wenn Du im 4 Bit Modus bist, muss Du am Display die Eingänge 0...3 auch
> auf Masse legen, sonst kann es an diesen offenen Pins zu Schwebungen
> kommen.
Diese "offenen" Pins haben idR. einen Pullup im Display. Aus Gründen der 
Stromaufnahme ist es deshalb ungünstig, die Pins auf GND zu legen.
http://elm-chan.org/docs/lcd/hd44780_e.html
http://www.lcd-module.de/pdf/doma/4_16.pdf
Wie das bei dem immer noch unbekannten Display hier ist, weiß man 
aber nicht. Auf jeden Fall scheint es mir aber sinnvoller, im 
Zweifelsfall die Pins nicht an GND, sondern an Vcc zu legen...

Kim schrieb:
> das ist ein ganz normales 2x16 lcd display mit hd44780
Statt dieses langen Satzes könnte man einfach hinschreiben, WELCHES 
Display es ist...

EDIT: Pech, Zweiter... ;-)

: Bearbeitet durch Moderator
von C. L. (calle)


Lesenswert?

Hi!

Ahhh, dass war mir neu, habe die Leitungen immer auf GND gelegt, weil 
ich an einem LCD damit definitiv Probleme hatte. Seitdem mache ich es 
immer so.
Wieder was gelernt, thx!

Wie lang sind denn die Pausen hier wirklich?
 delay_us(LCD_ENABLE_US);  // kurze Pause

Bei der Initphase lange genug gewartet?


CL

von Kim (Gast)


Lesenswert?

Habe viele sachen ausprobiert.
Zunächst 
www.reichelt.de/Background-green/LCD-162C-LED/3/index.html?&ACTION=3&LA= 
2&ARTICLE=31653&GROUPID=3005&artnr=LCD+162C+LED  das ist das Display.
und ich habe jetzt auch erst gemerkt, dass es kein HDD780 sondern 
KS0066U hat.

Das Problem war die Funktion
1
void lcd_string( const char *data )
2
{
3
    while( *data != '\0' )
4
        lcd_data( *data++ );
5
}
immer wenn ihc diese ausgeführt habe, hat sich der controller resettet. 
Aber ihc meine, dass ich diesen Code mit einem anderen Controller 
gemacht habe.

Jetzt ist es so, dass ich nur zwei zeilen mit schwarzen Balken sehe.
Die warte-funktionen habe ich jetzt auch mit
__delay_ms(x), bzw. __delay_us(x) umgesetzt. Die Zeiten habe ich mit dem 
Blinken einer LED verglichen und die passen auch nach gefühl.
LCD_ENABLE_US sind 20us.
beim Initialisieren
warte 20ms
schicke 0x03
warte 5ms
schicke 0x03
warte 1ms
schicke 0x03
warte 1ms
schicke 0x02
schicke die anderen Daten

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Kim schrieb:
> immer wenn ihc diese ausgeführt habe, hat sich der controller resettet.
Amoklaufender Pointer...

> Jetzt ist es so, dass ich nur zwei zeilen mit schwarzen Balken sehe.
Dann dreh mal den Kontrast richtig hin...

> Jetzt ist es so, dass ich nur zwei zeilen mit schwarzen Balken sehe.
Und was erwartest du stattdessen?

> schicke die anderen Daten
Welche denn?

Das, was hier gerade abläuft nennen die Angelsachsen:
to worm something out of somebody...
Auf Deutsch wäre das dann:
jedes Wort aus der Nase ziehen...

von Kim (Gast)


Angehängte Dateien:

Lesenswert?

Habe einmal komplett strom weggenommen. jetzt sehe ich nur noch die 
erste zeile mit scharzen balken.
also der komplette ablauf ist folgender
warte 15ms
schicke 0x03
warte 5ms
schicke 0x03
warte 1ms
schicke 0x03
warte 1ms
schicke 0x02
schicke 0x28 (4 Bit, 2 Linien, 5x7 punkte)
schicke 0x08 (display aus)
schicke 0x01 (display löschen)
schicke 0x06 (Kurserbewegungsrichtung steigend, display ist nicht 
versetzt? (Display is not shifted)

Bei den Display-Einstellungen (letzten 4 Befehle) schicke ich immer 
zuerst die oberen 4 bits und daraufhin die unteren 4 bits (0x28: zuerst 
0x02 dann 0x08)
nach dem senden warte ich 45us.

Dann ist das Display fertig initialisert. Folgend schicke ich
0x0F, damit ich den Cursor an der ersten Stelle blinken sehe.
habe auch alles andere aus meinem code rausgenommen, nur um erst einmal 
das hinzubekommen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Kim schrieb:
> habe auch alles andere aus meinem code rausgenommen
Ähm, mal grundlegend: man schreibt keinen Programmcode in eine 
Header-Datei...

Sehe ich das hier in der "lcd.h" richtig:
1
#include "lcd.h"
Du inkludierst den "ldc.h" in sich selber?

Mwein Tipp: warte mal nach dem Power-Up ganz am Anfang noch ein paar 
hundert ms. Und mach alle Verzögerungszeiten einfach mal geräumig 
lang...

von Pete K. (pete77)


Lesenswert?

Vielleicht mal den Programmer abziehen?

Wir haben immer noch kein Bild vom Hardware-Aufbau...

von Bernd N (Gast)


Lesenswert?

Bis auf das Flackern hat die Initialisierung doch schon einmal 
funktioniert oder ? Dein Anhang hat keine "main".

Wie wäre es wenn du den Code herzeigst den du wirklich verwendest ?

Häng mal den Code hier herein welcher im Flackern endet. Sollte das der 
obige, in Textform angehangene sein, dann wundert mich nichts da ich 
keine Endlosschleife sehe.

Also ganz einfache Übung, zeig den Code der soweit funktioniert und im 
Flackern endet.

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.