Forum: Mikrocontroller und Digitale Elektronik Benötige Hilfe bei Initialisierung LCD mit Pic


von Tobias W. (towa)


Lesenswert?

Hallo,

ich möchte mit dem Code unten ein LCD mit dem Chip 44780 auf 4Bit Modus 
initialisieren. Der Cursor soll nach der Initialisierung auf der 
Startposition blinken, was er jedoch nicht tut. Ich finde einfach nicht 
den Fehler wo es dran liegt. Kann mit bitte jemand helfen??

////////////////////  CODE //////////////////////////
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <pic16f887.h>
4
#include <xc.h>
5
6
#define _XTAL_FREQ 4000000
7
8
// CONFIG1
9
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
10
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
11
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
12
#pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
13
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
14
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
15
#pragma config BOREN = ON       // Brown Out Reset Selection bits (BOR enabled)
16
#pragma config IESO = ON        // Internal External Switchover bit (Internal/External Switchover mode is enabled)
17
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
18
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)
19
20
// CONFIG2
21
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
22
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)
23
24
#define D7 RD3
25
#define D6 RD2
26
#define D5 RD1
27
#define D4 RD0
28
29
#define RS RC4
30
#define EN RC6
31
32
#define datenport PORTD
33
#define RS RC4
34
#define EN RC6
35
36
int Durchlauf = 0;
37
38
void STROBE(void)
39
{
40
    EN = 1;
41
    __delay_us(2);
42
    EN = 0;
43
}
44
45
void main(void)
46
{
47
    __delay_ms(20);
48
    TRISC = 0;
49
    TRISD = 0b00000000;
50
    EN = 0;
51
    RS = 0;
52
    datenport = 0;
53
54
    while(1)
55
    {
56
        while(Durchlauf == 0)
57
        {
58
             
59
        RS = 0;                     // Steuerbefehl
60
        __delay_us(50);             // Wartezeit
61
        datenport = 0b00110000;     // Interface auf 8 Bit setzen
62
        STROBE();                   // Datenport einlesen
63
64
        __delay_ms(5);              // Wartezeit
65
66
        RS = 0;                     // Steuerbefehl
67
        __delay_us(50);             // Wartezeit
68
        datenport = 0b00110000;     // Interface auf 8 Bit setzen
69
        STROBE();                   // Datenport einlesen
70
71
        __delay_us(150);              // Wartezeit
72
73
        RS  = 0;                     // Steuerbefehl
74
        __delay_us(50);              // Wartezeit
75
        datenport = 0b00110000;     // Interface auf 8 Bit setzen
76
        STROBE();                   // Datenport einlesen
77
78
        RS  = 0;                     // Steuerbefehl
79
        __delay_us(50);              // Wartezeit
80
        datenport = 0b00100000;     // Interface auf 4 Bit setzen
81
        STROBE();                   // Datenport einlesen
82
83
        RS  = 0;                     // Steuerbefehl
84
        __delay_us(50);              // Wartezeit
85
        datenport = 0b00100000;     // 1. 2-Zeilen und 5x8 Punktmatrix
86
        STROBE();                   // Datenport einlesen
87
88
        RS  = 0;                     // Steuerbefehl
89
        __delay_us(50);              // Wartezeit
90
        datenport = 0b10000000;     // 2. 2-Zeilen und 5x8 Punktmatrix
91
        STROBE();                   // Datenport einlesen
92
93
        RS  = 0;                     // Steuerbefehl
94
        __delay_us(50);              // Wartezeit
95
        datenport = 0b00000000;     // 1. Display ausschalten
96
        STROBE();                   // Datenport einlesen
97
98
        RS  = 0;                     // Steuerbefehl
99
        __delay_us(50);              // Wartezeit
100
        datenport = 0b10000000;     // 2. Display ausschalten
101
        STROBE();                   // Datenport einlesen
102
103
        RS  = 0;                     // Steuerbefehl
104
        __delay_us(50);              // Wartezeit
105
        datenport = 0b00000000;     // 1. Textpuffer löschen
106
        STROBE();                   // Datenport einlesen
107
108
        RS  = 0;                     // Steuerbefehl
109
        __delay_us(50);              // Wartezeit
110
        datenport = 0b00010000;     // 2. Textpuffer löschen
111
        STROBE();                   // Datenport einlesen
112
113
        RS  = 0;                     // Steuerbefehl
114
        __delay_us(50);              // Wartezeit
115
        datenport = 0b00000000;     // 1.Cursorlaufrichtung rechts, kein Shift
116
        STROBE();                   // Datenport einlesen
117
118
        RS  = 0;                     // Steuerbefehl
119
        __delay_us(50);              // Wartezeit
120
        datenport = 0b01100000;     // 1.Cursorlaufrichtung rechts, kein Shift
121
        STROBE();                   // Datenport einlesen
122
123
        RS  = 0;                     // Steuerbefehl
124
        __delay_us(50);              // Wartezeit
125
        datenport = 0b00000000;     //  1. Cursor auf Startposition
126
        STROBE();                   // Datenport einlesen
127
128
        RS  = 0;                     // Steuerbefehl
129
        __delay_us(50);              // Wartezeit
130
        datenport = 0b00100000;     //  1. Cursor auf Startposition
131
        STROBE();                   // Datenport einlesen
132
133
        RS  = 0;                     // Steuerbefehl
134
        __delay_us(50);              // Wartezeit
135
        datenport = 0b00000000;     // 1.Display einschalten
136
        STROBE();                   // Datenport einlesen
137
138
        RS  = 0;                     // Steuerbefehl
139
        __delay_us(50);              // Wartezeit
140
        datenport = 0b11110000;     // 2.Display einschalten
141
        STROBE();                   // Datenport einlesen
142
143
        Durchlauf = 1;
144
        }
145
    }
146
}
/////////// ENDE ///////////////////


Ich würde mich über Hilfe sehr freuen,

Danke Tobias

: Bearbeitet durch User
von John (Gast)


Lesenswert?

Hallo Tobias,

Tobias Wagner schrieb:
> ein LCD mit dem Chip 44780

Welches?

Hast Du nochmals geprüft ob alles richtig angeschlossen ist?
Sind die Signale am Ausgang des Controllers vorhanden und kommen diese 
auch am LCD an? (Nachgemessen?)
Wie ist der Kontrast eingestellt?
Warum hast Du nach jedem "RS=0" ein Delay von 50µs?

Gruß
John

von Chris B. (dekatz)


Lesenswert?

im 4-Bit-Mode 8-Bit-Daten/Commandos auf den Port schreiben geht nicht 
besonders gut!

von John (Gast)


Lesenswert?

Chris B. schrieb:
> im 4-Bit-Mode 8-Bit-Daten/Commandos auf den Port schreiben geht nicht
> besonders gut!

Deshalb sendet er ja auch zwei 4-bit Werte (ausser den ersten vier 
Befehlen).
Zu erkennen an:
  1. ...
  2. ... (und ja: zwei mal Tippfehler)
Nur die oberen 4-bit sind mit dem LCD verbunden.

von Tobias W. (towa)


Lesenswert?

@ John: Ja alles richtig angeschlossen. Ich nutze die Datenleitungen 
D4,D5,D6,D7 des Displays und habe die an den PortD Pin 4,5,6,7 
angeschlossen.


Nur habe ich jetzt gelesen das ich aufgrund der 4 Bit Einstellung, das 
Datenbyte in 2 Nibble aufgeteilt senden muss. Da stand was mit um 4 
Stellen nach rechts verschieben, das verstehe ich nicht. Kann mir das 
jemand erklären? Und nicht einfach schreiben

"im 4-Bit-Mode 8-Bit-Daten/Commandos auf den Port schreiben geht nicht
besonders gut!"

Das bringt mich nämlich nicht weiter weil es mir zwar das Problem nennt 
aber nicht erklärt wie es stattdessen sein muss.

Gruß,
Tobi

von Chris B. (dekatz)


Lesenswert?

John schrieb:
> Chris B. schrieb:
>> im 4-Bit-Mode 8-Bit-Daten/Commandos auf den Port schreiben geht nicht
>> besonders gut!
>
> Deshalb sendet er ja auch zwei 4-bit Werte (ausser den ersten vier
> Befehlen).
> Zu erkennen an:
>   1. ...
>   2. ... (und ja: zwei mal Tippfehler)
> Nur die oberen 4-bit sind mit dem LCD verbunden.

OK, das habe ich komplett übersehen (weil ich mit DER Methode einfach 
nicht gerechnet habe) ;-)

von John (Gast)


Lesenswert?

Chris B. schrieb:
> OK, das habe ich komplett übersehen (weil ich mit DER Methode einfach
> nicht gerechnet habe) ;-)

Hab mich auch erst gewundert, warum er alles doppelt sendet. Dann erst 
hab ich gesehen, dass sich die oberen vier Bit bei 1. und 2. 
unterscheiden.

@ Tobias
Was ist es für ein LCD?
Hast Du die Möglichkeit die Signale zu messen (Oszilloskop)?
Wie sieht es mit dem Kontrast aus?

von Stefan (Gast)


Lesenswert?

Warum nimmst du nicht zuerst mal ein
funktionierendes Programm aus dem Netz ?
Dann weist du zumindest das deine Hardware richtig ist.
Und dann kann man sich daran machen, selber ein
Programm zu schreiben. So bist du nicht sicher,
ob es am Programm liegt oder vielleicht ein Fehler
an der Hardware ist.

von holger (Gast)


Lesenswert?

>Ich nutze die Datenleitungen
>D4,D5,D6,D7 des Displays und habe die an den PortD Pin 4,5,6,7
>angeschlossen.

Ahh, ja. Wieso steht das dann in deinem Code.

#define D7 RD3
#define D6 RD2
#define D5 RD1
#define D4 RD0

von Tobias Wagner (towa) (Gast)


Lesenswert?

hallo,

ich habe ein funktionierendes Programm was ich eingespielt habe. Alles 
funktioniert perfekt. Hardware ist also in Ordnung. Jetzt will ich aber 
nicht einfach etwas fertiges nehmen sondern ein eigenes Programm 
schreiben, damit ich das auch richtig verstehe.

@holger:

ich habe den Teil jetzt ausgeklammert aber es funktioniert immer noch 
nicht.


Ich habe jetzt noch nicht richtig verstanden was ich machen muss um das 
Problem zu beheben. Ich habe aber rausgelesen das es was mit den Bits 
die ich sende zu tun hat. Ich teile das Datenbyte in zwei "Nibble" auf 
und sende diese nacheinander an das Display?
Ist mein Ansatz oben denn so grob richtig, bzw. zielt er in die richtige 
Richtung? Ich würde es ganz gerne erst einmal so machen mit dem 1. und 
2. und wenn das dann geht den Code erweitern und das Senden über die 
Bitverschiebung in einer Schleife machen.

Freue mich über Hilfe,

Gruß Tobias

von Peter D. (peda)


Lesenswert?

Hier ein sehr einfacher und vor allem modular aufgebauter LCD-Code.
D.h. er kommt ohne die sonst oft zu sehende Codedoppelung an vielen 
Stellen aus.

Die Pinzugriffe und das Delay können beim PIC eine etwas andere Syntax 
haben. Der Rest sollte portabel sein.

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=102296

: Bearbeitet durch User
von Tobias Wagner (towa) (Gast)


Lesenswert?

hallo,

ich habe den code jetzt abgeändert. Er funktioniert aber immer noch 
nicht. Kann mir jemand helfen und sagen warum nicht.

Der Code soll ein 2x16 LCD mit HD44780 Chip auf 4Bitmodus 
initialisieren:

////////CODE//////////
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <pic16f887.h>
4
#include <xc.h>
5
6
#define _XTAL_FREQ 4000000
7
8
// CONFIG1
9
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
10
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
11
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
12
#pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
13
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
14
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
15
#pragma config BOREN = ON       // Brown Out Reset Selection bits (BOR enabled)
16
#pragma config IESO = ON        // Internal External Switchover bit (Internal/External Switchover mode is enabled)
17
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
18
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)
19
20
// CONFIG2
21
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
22
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)
23
24
#define Datenport PORTD
25
#define RS RC4
26
#define EN RC6
27
28
29
void STROBE(void)
30
{
31
    EN = 1;
32
    __delay_us(2);
33
    EN = 0;
34
}
35
36
void KONFIGDATEN_SENDEN(unsigned char DATENBYTE)
37
{
38
    Datenport = (DATENBYTE >> 4);
39
    __delay_us(2);
40
    STROBE();
41
    Datenport = (DATENBYTE);
42
    __delay_us(2);
43
    STROBE();
44
}
45
46
void InitialisierungLCD()
47
{
48
    __delay_ms(20);
49
    KONFIGDATEN_SENDEN(0x38);    // Interface auf 8 Bit stellen (mit Zeile und Schrift)
50
    __delay_ms(5);
51
    KONFIGDATEN_SENDEN(0x38);    // Interface auf 8 Bit stellen (mit Zeile und Schrift)
52
    __delay_ms(1);
53
    KONFIGDATEN_SENDEN(0x38);    // Interface auf 8 Bit stellen (mit Zeile und Schrift)
54
    KONFIGDATEN_SENDEN(0x28);    // Interface auf 4 Bit, 2 Zeilen und 5x7 Font einstellen
55
    KONFIGDATEN_SENDEN(0x28);    // Interface auf 4 Bit, 2 Zeilen und 5x7 Font einstellen
56
    KONFIGDATEN_SENDEN(0x0c);    // Display EIN, Cursor AUS, Cursor Blinken AUS
57
    KONFIGDATEN_SENDEN(0x01);    // Display löschen
58
    KONFIGDATEN_SENDEN(0x06);    // Displayinhalt FEST, Cursorposition inkrementieren
59
}
60
61
void main(void)
62
{
63
    __delay_ms(20);
64
    TRISC = 0;
65
    TRISD = 0;
66
    void InitialisierungLCD();
67
}
///////  CODE ENDE ////////


Für Tipps wäre ich sehr dankbar.

Gruß Tobias

: Bearbeitet durch User
von John (Gast)


Lesenswert?

Zum dritten Mal die Frage:
Hast Du mal nachgemessen ob dein Controller überhaupt etwas ausgibt?

Und: Wo konfigurierst Du die entsprechenden Pins von Port C und D als 
Ausgang?

von Peter D. (peda)


Lesenswert?

Tobias Wagner (towa) schrieb:
> Für Tipps wäre ich sehr dankbar.

Du hast Dir meinen Link nichtmal angesehen, stimmts.

von Tobias Wagner (Gast)


Lesenswert?

hy,

doch den habe ich mir angesehen, den kannte ich aber schon. die seite 
hat mir halt auch nicht weiter geholfen.

die ports konfiguriere ich oben in main mit den Befehlen:


TRISC = 0;
TRISD = 0;


Gruß,Tobias

von Karl H. (kbuchegg)


Lesenswert?

Tobias Wagner (towa) schrieb:
> hallo,
>
> ich habe ein funktionierendes Programm was ich eingespielt habe. Alles
> funktioniert perfekt.

Wenn du ein funktionierendes Programm hast, dann STUDIERE es!

Ja, das geht. Man kann sich bei anderen ansehen, wie die die Dinge 
machen. Und: man lernt dabei sogar noch was.

von Uwe (de0508)


Lesenswert?

Hallo Peter,

es ist wirklich traurig; dein Code läuft und bildet exakt die 4Bit 
Initialisierung aus dem Datenblatt ab.

Wenn der TO es nicht schafft die Unterschiede der Funktionen Nibble und 
Byte zu verstehen, dann wird sein Code nicht funktionieren.

Nebenbei steht das alles 1 zu 1 im Datenblatt.
Warum ist das für so viele angehende Coder so schwierig ein HD44780 
Datenblatt zu lesen?

Peter Dannegger schrieb:
> Du hast Dir meinen Link nichtmal angesehen, stimmts.

Tipp:

http://www.sprut.de/electronic/lcd/

von Karl H. (kbuchegg)


Lesenswert?

Tip:

Du kannst am Anfang der InitialisierungLCD noch nicht KONFIGDATEN_SENDEN 
benutzen (btw. bescheuerter Name für diese Funktion).
KONFIGDATEN_SENDEN ist darauf ausgelegt, dass das LCD bereits im 4 Bit 
Modus ist, daher ja auch die 2 Ausgaben. Am Anfang ist das LCD aber noch 
nicht im 4 Bit Modus!

Studiere das funktionierende Programm!
Studieren bedeutet nicht, dass man es draufspielt und sich daran 
erfreut, dass es funktioniert, sondern dass man den Code durchgeht und 
sich bei jeder Anweisung fragt: was wird hier bezweckt, warum steht das 
da?

: Bearbeitet durch User
von Chris B. (dekatz)


Lesenswert?

CursorHome, ClearDisplay brauchen 1,6ms.
Alle anderen Steuerbefehle bis zu 40µs.
Also hier mal ein paar Zeiten einfügen!

von Tobias Wagner (Gast)


Lesenswert?

Hallo,

ja das funktionierende Programm habe ich "studiert" und wie ich dachte 
verstanden. Um zu sehen ob ich es wirklich verstanden habe habe ich 
angefangen ein eigenes zu schreiben, was aber bis jetzt noch nicht 
läuft. Das mit den Zeite füge ich ein und das mit Konfigdaten_Senden 
überarbeite ich.

Vielen Dank schonmal,
Gruß Tobi

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.