Forum: Mikrocontroller und Digitale Elektronik LCD Initialisierung / Character zeigt senkrechte Linien


von Sven W. (ulminpoika)


Angehängte Dateien:

Lesenswert?

Hallo Forum,

ich muss mal wieder zu Kreuze kriechen und euch um Rat zu einem µC 
Problem, genauer zur Ansteuerung eines 2*16 Zeichen LCDs, bitten. Ich 
habe hier ein PICDEM 2 Plus Demo Board mit PIC18F4520 und 4MHz Quarz.

Das Problem besteht darin, dass ich nicht die beabsichtigten Zeichen 
ausgeben kann. Anstatt eines Buchstaben wird ein Symbol aus zwei 
senkrechten Linien dargestellt. Das 5*8 Felder-Symbol hat dann die 
zweite und vierte Spalte dunkel, der Rest hell. Bei manchen Zeichen 
erscheinen auch drei dunkle Linien, die sind dann in der ersten, dritten 
und fünften Spalte.

Ich vermute ein Problem bei der Initialisierung. Muss ich die 
Zeichenauswahl im CGROM konfigurieren? Nach LCD Initialisierung kann den 
Cursor ins gewünschte Feld verschieben, er blinkt auch wie gewünscht 
etc.

Der gesamte Code ist auch angehängt, aber hier das (vermutlich) 
wesentliche, so wird mein LCD initialisiert:
1
void LcdInit(void) {
2
    LcdTris = 0x00;                 // All LCD lines as outputs
3
    Lcd_Vcc = 0;
4
    Lcd_Vcc = 1;
5
6
    __delay_ms(20);
7
    LcdWriteNibble(0x03,1);     // transmit 3 times soft reset
8
    __delay_ms(20);
9
    LcdWriteNibble(0x03,1);
10
    __delay_ms(20);
11
    LcdWriteNibble(0x03,1);
12
    __delay_ms(20);
13
    LcdWriteNibble(0x02,1);
14
15
    LcdWait();
16
    LcdCommand(0x28);           // 4bit interface, 2-line LCD, 5*8 font
17
    LcdWait();
18
    LcdCommand(0x0F);           // Disply ON, Cursor ON, Blinking ON
19
    LcdWait();
20
    LcdCommand(0x06);           // Content fix, cursor posiion incremented
21
    LcdWait();
22
    LcdCommand(0x02);           // Cursor in Start Position
23
    LcdWait();
24
    LcdClear();
25
}
26
27
void LcdCommand(unsigned char cmd) {
28
unsigned char tmp;
29
    tmp = cmd & 0xF0;               // get upper nibble of command byte
30
    tmp = tmp >> 4;                 // shift upper nibble into interface nibble
31
    LcdWriteNibble(tmp,1);          // send low nibble into cmd register
32
    tmp = cmd & 0x0F;               // get lower nibble of command byte
33
    LcdWriteNibble(tmp,1);          // switch on LCD Interface
34
}
35
36
void LcdWriteNibble(unsigned char Msg, unsigned char CmdSelect) {
37
unsigned char tmp;
38
    Lcd_RW = 0;                     // This is a WRITE operation
39
    if (CmdSelect) {                // 1 if Cmd
40
        Lcd_RS = 0;                 // Clear for writing in command register
41
    } else {
42
        Lcd_RS = 1;                 // 0 if Data
43
    }
44
    Lcd_E = 1;
45
46
    tmp = LcdLat;                   // get LATD status
47
    tmp &= 0xF0;                    // clear message lines for new message
48
    LcdLat = tmp | (Msg & 0x0F);    // Reload LATD with updated message
49
    Nop();
50
    Nop();
51
52
    Lcd_E = 0;
53
}
54
55
void LcdWait(void) {
56
unsigned char status;
57
    Lcd_RS = 0;                     // Sending into command register
58
    Lcd_RW = 1;                     // Sending a READ operation
59
    do {
60
        status = LcdReadByte();     // Read LCD state
61
    } while (status & 0x80);        // bit 7 is 1 while busy
62
}
63
64
unsigned char LcdReadByte(void) {
65
unsigned char tmp, res;
66
    LcdTris |= 0x0F;                // make D3:0 inputs
67
    Lcd_E = 1;                      // Enable LCD interface
68
    Nop();
69
    Nop();
70
    tmp = PORTD;                    // first read for first nibble
71
    Lcd_E = 0;                      // Disable LCD interface
72
    res = tmp << 4;                 // shift input to high nibble and save
73
    Lcd_E = 1;                      // Enable LCD interfae
74
    Nop();
75
    Nop();
76
    tmp = PORTD;                    // second read for second nibble
77
    Lcd_E = 0;                      // Disable LCD interface
78
    tmp &= 0x0F;                    // clear upper nibble
79
    res |= tmp;                     // move lower nibble to return result
80
    LcdTris &= 0xF0;                // make D3:0 outputs
81
    return(res);
82
}

Und auf diese Art möchte ich ein Zeichen ausgeben:
1
 void LcdPutChar(unsigned char value) {
2
unsigned char tmp;
3
    tmp = value & 0xF0;             // get upper nibble of character
4
    tmp >> 4;                       // shift upper nibble into data lines
5
    LcdWriteNibble(tmp,0);
6
    tmp = value & 0x0F;             // get lower nibble of character
7
    LcdWriteNibble(tmp,0);
8
    LcdWait();
9
}
10
11
void LcdWriteNibble(unsigned char Msg, unsigned char CmdSelect) {
12
unsigned char tmp;
13
    Lcd_RW = 0;                     // This is a WRITE operation
14
    if (CmdSelect) {                // 1 if Cmd
15
        Lcd_RS = 0;                 // Clear for writing in command register
16
    } else {
17
        Lcd_RS = 1;                 // 0 if Data
18
    }
19
    Lcd_E = 1;
20
21
    tmp = LcdLat;                   // get LATD status
22
    tmp &= 0xF0;                    // clear message lines for new message
23
    LcdLat = tmp | (Msg & 0x0F);    // Reload LATD with updated message
24
    Nop();
25
    Nop();
26
27
    Lcd_E = 0;
28
}

Vielleicht sieht jemand von euch einen Fehler? Wenn ihr noch weitere 
Infos braucht, kann ich die gerne anbieten.

Viele Grüße und herzlichen Dank,
Ulminpoika

von Karl H. (kbuchegg)


Lesenswert?

Sven W. schrieb:

> Das Problem besteht darin, dass ich nicht die beabsichtigten Zeichen
> ausgeben kann. Anstatt eines Buchstaben wird ein Symbol aus zwei
> senkrechten Linien dargestellt.


Prüfe mal alle Datenleitungen die zum LCD gehen.
Prüfe, ob du sie eventuell vertauscht hast, oder ob du zwischen 
Datenleitungen einen Kurzschluss hast.


Wenn du den ASCII Code eines Zeichens ausgibst und am LCD wird etwas 
ganz anderes sichtbar, dann ist die naheliegenste Vermutung, dass das 
LCD bitmässig ganz etwas anderes sieht, als das was du auf den Weg 
geschickt hast. Was zb sein kann, wenn es irgendwo Kurzschlüsse gibt.

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


Lesenswert?

War das Display ganz normal vom Händler oder vllt. ein Restposten? Es 
gibt nämlich sehr exotische Zeichensätze. Wenn da ein HD44780 verbaut 
ist, kann man am Suffix erkennen, ob es ein kundenspezifischer Typ ist:
A00 - japanischer Standard
A02 - Europa Standard
BXX - Kundenspezifisch

: Bearbeitet durch User
von Sven W. (ulminpoika)


Lesenswert?

Hallo,

vielen Dank für eure Antworten.

Bei meiner Antwort an euch ist mir der Fehler in der Funktion 
"LcdPutChar" aufgefallen. Da die Steuerkommandos funktionieren, das 
Schreiben aber nicht, musst der Fehler irgendwo in der Schreibroutine 
oder in der Übergabe liegen.

Aus dieser Funktion
1
 void LcdPutChar(unsigned char value) {
2
unsigned char tmp = 0;
3
    tmp = value & 0xF0;             // get upper nibble of character
4
    tmp >> 4;                 // (Korrigiert) shift upper nibble into data lines
5
    NOP();
6
    LcdWriteNibble(tmp,0);
7
    tmp = value & 0x0F;             // get lower nibble of character
8
    LcdWriteNibble(tmp,0);
9
    LcdWait();
10
}

wurde diese:
1
 void LcdPutChar(unsigned char value) {
2
unsigned char tmp = 0;
3
    tmp = value & 0xF0;             // get upper nibble of character
4
    tmp = tmp >> 4;                       // shift upper nibble into data lines
5
    NOP();
6
    LcdWriteNibble(tmp,0);
7
    tmp = value & 0x0F;             // get lower nibble of character
8
    LcdWriteNibble(tmp,0);
9
    LcdWait();
10
}

Ich hatte das Rechts-Schieben in der LcdCommand Funktion korrekt 
programmiert, aber in der LcdPutChar dann den Fehler. Deswegen liefen 
alle Steuerbefehle ordentlich, aber in der Schreibfunktion gings dann 
nicht.

Hat mir wieder mal geholfen, einfach jemandem mein Problem zu schildern. 
Und schon wirds besser.

Vielen Dank und ne scöne Woche noch.

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.