Hallo! Ich verwende ein Displaytech 162B im 4-Bit Betrieb) und verstehe die Initialisierungsroutine nicht ganz. Wenn ich das Datenbit DB4 in den ersten 3 Schritten auf 1 stelle, funktioniert die Anzeige nicht. Ist das Bit jeweils auf 0, ist alles OK! Sollte nach der Anleitung im Datenblatt nicht 3 Mal eine 1 für DB4 geschrieben werden? Der 4-Bit Modus wird ja erst im 4. Schritt (set function - interface auf 4 bit setzen) eingestellt. Oder habe ich hier etwas falsch verstanden? Anbei meine Init-Tabelle und das Datenblatt.
Die 1 bedeutet 8-Bit-Mode, die 0 4-Bit-Mode. Da man sich nie sicher sein kann, in welchem Zustand sich das Dislay befindet (z.B. nach Reset am μC): Startzustand: 8-Bit 4-Bit 1.Nibble 2.Nibble Nibble 1. 0011 8-Bit-Mode 8-Bit-Mode abh.von 1.Nibble, dont care 2. 0011 8-Bit-Mode 1line,5x7 8-Bit-Mode 3. 0011 8-Bit-Mode 8-Bit-Mode 1line,5x7 Ab hier haben wir definitiv 8-Bit-Mode (ein E-Pulse->ein Kommando) 4. 0010 4-Bit-Mode 4-Bit-Mode 4-Bit-Mode Ab hier haben wir definitiv 4-Bit-Mode, müssen also 2 Nibbles je Kommando ausgeben 5. 0010 4-Bit-Mode 6. NFxx N:lines; F:font Damit hat man EINEN zuverlässigen Weg aus jedem Anfangszustand. Nach Power-On am Display funktionieren auch andere. Erst bei Reset am μC sieht man, ob's immer geht.
Also ich mach das eigentlich auch so :-( Aber das Display schreibt nur komische Zeichen... hier mein Code zur Initialisierung:
1 | /****** Initialisierung des LCD Controllers *****/
|
2 | void lcd_init() |
3 | {
|
4 | /* Port auf Ausgang schalten */
|
5 | LCDDDR = 0xFF; |
6 | LCDPORT = 0x00; |
7 | _delay_ms(40); // Warten bis LCD bereit ... |
8 | |
9 | /* Init 1 */
|
10 | sbi(LCDPORT, LCD_PIN_D5); // D5 = 1 |
11 | sbi(LCDPORT, LCD_PIN_D4); // D4 = 1 |
12 | _delay_ms(40); |
13 | |
14 | /* Init 2*/
|
15 | sbi(LCDPORT, LCD_PIN_D5); // D5 = 1 |
16 | sbi(LCDPORT, LCD_PIN_D4); // D4 = 1 |
17 | _delay_ms(5); |
18 | |
19 | /* Init 3*/
|
20 | sbi(LCDPORT, LCD_PIN_D5); // D5 = 1 |
21 | sbi(LCDPORT, LCD_PIN_D4); // D4 = 1 |
22 | |
23 | /* 4-Bit Modus starten ... */
|
24 | sbi(PORTD, LCD_PIN_E); // Set ENABLE from L to H |
25 | cbi(PORTD, LCD_PIN_E); |
26 | _delay_ms(5); |
27 | |
28 | /* 2 Zeilen, 4-Bit Modus, Matrix 5x7 */
|
29 | lcd_send(BEFEHL, LCD_SET_1); // Register SET FUNCTION = 0010 1000 |
30 | |
31 | lcd_send(BEFEHL, LCD_OFF); // Set LCD OFF |
32 | lcd_send(BEFEHL, LCD_CLEAR); // Clear LCD |
33 | |
34 | lcd_send(BEFEHL, LCD_SET_2); // Entry Mode = Cursor increase, Display-Shift OFF |
35 | lcd_send(BEFEHL, LCD_ON); // Set LCD ON |
36 | }
|
m. g. schrieb: > sbi(LCDPORT, LCD_PIN_D5); // D5 = 1 > sbi(LCDPORT, LCD_PIN_D4); // D4 = 1 > _delay_ms(40); Ich glaube, du solltest die Daten auch abschicken.
Ralf G. schrieb: > Ich glaube, du solltest die Daten auch abschicken. Huiii! Natürlich ;-) Ich hab´s jetzt mal so gelöst: Die Lösung mit den beiden Bits D5 und D4 in 2 Zeilen für die oberen 4 Bits zu setzen gefällt mir aber nicht wirklich gut. Hat hier jemand eine bessere Lösung?
1 | /****** Initialisierung des LCD Controllers *****/
|
2 | void lcd_init() |
3 | {
|
4 | /* Port auf Ausgang schalten */
|
5 | LCDDDR = 0xFF; |
6 | LCDPORT = 0x00; |
7 | _delay_ms(40); // Warten bis LCD bereit ... |
8 | |
9 | /* LCD Soft-Reset 1*/
|
10 | LCDPORT = (1 << LCD_PIN_D5); |
11 | LCDPORT |= (1 << LCD_PIN_D4); |
12 | set_enable(); // Daten/Kommando übernehmen |
13 | LCDPORT = 0x00; |
14 | set_enable(); // Daten/Kommando übernehmen |
15 | _delay_ms(40); |
16 | |
17 | /* LCD Soft-Reset 2*/
|
18 | LCDPORT = (1 << LCD_PIN_D5); |
19 | LCDPORT |= (1 << LCD_PIN_D4); |
20 | set_enable(); // Daten/Kommando übernehmen |
21 | LCDPORT = 0x00; |
22 | set_enable(); // Daten/Kommando übernehmen |
23 | _delay_ms(5); |
24 | |
25 | /* LCD Soft-Reset 3*/
|
26 | LCDPORT = (1 << LCD_PIN_D5); |
27 | LCDPORT |= (1 << LCD_PIN_D4); |
28 | set_enable(); // Daten/Kommando übernehmen |
29 | LCDPORT = 0x00; |
30 | set_enable(); // Daten/Kommando übernehmen |
31 | _delay_ms(1); |
32 | |
33 | /* 2 Zeilen, 4-Bit Modus */
|
34 | lcd_send(BEFEHL, LCD_SET_1); // Register SET FUNCTION = 0010 1000 |
35 | lcd_send(BEFEHL, LCD_OFF); // Set LCD OFF |
36 | lcd_send(BEFEHL, LCD_CLEAR); // Clear LCD |
37 | lcd_send(BEFEHL, LCD_SET_2); // Set ENTRY MODE = 0000 0110 |
38 | lcd_send(BEFEHL, LCD_ON); // Set LCD ON |
39 | }
|
m. g. schrieb: > Hat hier jemand eine bessere Lösung? LCDPORT &= ~(alle bits die du neu setzen willst) ^ not! LCDPORT |= (genau das was du alles reinschreiben willst) >> set_enable(); eine sehr ungeeignete Benamung, denn was man setzt ist erst einmal gesetzt. Das was deine Routine macht ist aber offensichtlich einen Zyklus ausführen.
Mitlesa schrieb: >>> set_enable(); > > eine sehr ungeeignete Benamung, denn was man setzt ist > erst einmal gesetzt. Das was deine Routine macht ist aber > offensichtlich einen Zyklus ausführen. Ja, da hast du recht! Ich hab meinen Code nun wie folgt geändert:
1 | /****** Initialisierung des LCD Controllers *****/
|
2 | void lcd_init() |
3 | {
|
4 | /* Port auf Ausgang schalten */
|
5 | LCDDDR = 0xFF; |
6 | LCDPORT = 0x00; |
7 | _delay_ms(40); // Warten bis LCD bereit ... |
8 | |
9 | /* LCD Soft-Reset 1*/
|
10 | LCDPORT = (1 << LCD_PIN_D5)|(1 << LCD_PIN_D4); // Oberes Nibble = 0011 |
11 | toggle_enable(); // Daten/Kommando übernehmen |
12 | LCDPORT = 0x00; // Unteres Nibble = 0000 |
13 | toggle_enable(); // Daten/Kommando übernehmen |
14 | _delay_ms(40); |
15 | |
16 | /* LCD Soft-Reset 2*/
|
17 | LCDPORT = (1 << LCD_PIN_D5)|(1 << LCD_PIN_D4); // Oberes Nibble = 0011 |
18 | toggle_enable(); // Daten/Kommando übernehmen |
19 | LCDPORT = 0x00; // Unteres Nibble = 0000 |
20 | toggle_enable(); // Daten/Kommando übernehmen |
21 | _delay_ms(5); |
22 | |
23 | /* LCD Soft-Reset 3*/
|
24 | LCDPORT = (1 << LCD_PIN_D5)|(1 << LCD_PIN_D4); // Oberes Nibble = 0011 |
25 | toggle_enable(); // Daten/Kommando übernehmen |
26 | LCDPORT = 0x00; // Unteres Nibble = 0000 |
27 | toggle_enable(); // Daten/Kommando übernehmen |
28 | _delay_ms(1); |
29 | |
30 | /* LCD auf 2 Zeilen, 4-Bit Modus, 5x7 Matrix einstellen */
|
31 | lcd_send(BEFEHL, LCD_SET_1); // Register SET FUNCTION = 0010 1000 |
32 | lcd_send(BEFEHL, LCD_OFF); // Set LCD OFF |
33 | lcd_send(BEFEHL, LCD_CLEAR); // Clear LCD |
34 | lcd_send(BEFEHL, LCD_SET_2); // Set ENTRY MODE = 0000 0110 |
35 | lcd_send(BEFEHL, LCD_ON); // Set LCD ON |
36 | }
|
Du schreibst immer noch den ganzen Port obwohl du nur 4 Bit brauchst und willst. Könnte ja sein dass due die anderen Bits für was anderes brauchst. Das LCD braucht beim Init nur die 4 Bit da es ja noch nicht weiss ob es 4 oder 8 bit machen soll, daher ist der zweite Zyklus, das untere Nibble, nicht erforderlich.
Vor allem betreibst du die Schnittstelle immer im 4-Bit-Modus (Ausgabe des 2.Nibbles). Diese 3x "8-Bit-Mode" am Anfang sollen das LCD aber definiert in den 8-Bit-Modus bringen. Erst dann weiß man, daß das nun folgende "4-Bit" richtig interpretiert wird.
1 | /****** Initialisierung des LCD Controllers *****/
|
2 | void lcd_init() |
3 | {
|
4 | /* Port auf Ausgang schalten */
|
5 | LCDDDR = 0xFF; |
6 | LCDPORT = 0x00; |
7 | _delay_ms(40); // Warten bis LCD bereit ... |
8 | |
9 | #define LCD_8BITMODE ((1 << LCD_PIN_D5)|(1 << LCD_PIN_D4))
|
10 | |
11 | /* LCD Soft-Reset 1*/
|
12 | LCDPORT = LCD_8BITMODE; // geht davon aus, daß nichts anderes als LCD an dem Port hängt |
13 | toggle_enable(); // Kommando übernehmen |
14 | _delay_ms(40); |
15 | |
16 | /* LCD Soft-Reset 2*/
|
17 | toggle_enable(); // Kommando übernehmen |
18 | _delay_ms(5); |
19 | |
20 | /* LCD Soft-Reset 3*/
|
21 | toggle_enable(); // Kommando übernehmen |
22 | _delay_ms(1); |
23 | |
24 | // ab jetzt haben wir sicher 8-Bit Mode,
|
25 | // d.h. nächste Kommando wird sicher als ein solches verstanden
|
26 | |
27 | /* LCD auf 2 Zeilen, 4-Bit Modus, 5x7 Matrix einstellen */
|
28 | lcd_send(BEFEHL, LCD_SET_1); // Register SET FUNCTION = 0010 1000 |
29 | lcd_send(BEFEHL, LCD_OFF); // Set LCD OFF |
30 | lcd_send(BEFEHL, LCD_CLEAR); // Clear LCD |
31 | lcd_send(BEFEHL, LCD_SET_2); // Set ENTRY MODE = 0000 0110 |
32 | lcd_send(BEFEHL, LCD_ON); // Set LCD ON |
33 | }
|
Falls es dir aber nicht darum geht das zu verstehen, warum nimmst du nicht einfach den Code aus dem Tutorial?
Carl D. schrieb: > Falls es dir aber nicht darum geht das zu verstehen, warum nimmst du > nicht einfach den Code aus dem Tutorial? Danke für die Hilfe! Mir geht es vor allem darum, den Code und die Initialisierung zu verstehen!
m. g. schrieb: > Danke für die Hilfe! Dann noch eine zum Schluss: Was heisst LCD? Was heisst LCD Display? Was ist ein weisser Schimmel?
Stimmt, ich hätte jedwede Hilfe aus formalen Gründen ablehnen sollen. (es gibt neben dem weißen Schimmel auch noch den Schwarzen, nicht zu vergessen den Adligen: von Amtswegen)
:
Bearbeitet durch User
Ok, soweit habe ich das jetzt verstanden! Wenn ich jetzt aber am PORTD den Pin 3 für Enable und Pin 2 für RS verwenden möchte, dann muss ich die Bits D5 und D4 mit dem Makro sbi(Port,Pin) setzen. Richtig?
1 | #define LCDPORT PORTD
|
2 | #define LCDDDR DDRD
|
3 | #define LCD_PIN_RS 2
|
4 | #define LCD_PIN_E 3
|
5 | #define LCD_PIN_D4 4
|
6 | #define LCD_PIN_D5 5
|
7 | #define LCD_PIN_D6 6
|
8 | #define LCD_PIN_D7 7
|
9 | #define LCD_SETDDRAM 0x80 // Set Display RAM Address
|
10 | ...
|
11 | ...
|
12 | ...
|
13 | /****** Initialisierung des LCD Controllers *****/
|
14 | void lcd_init() |
15 | {
|
16 | /* Port auf Ausgang schalten */
|
17 | LCDDDR = 0xFF; |
18 | LCDPORT = 0x00; |
19 | _delay_ms(40); // Warten bis LCD bereit ... |
20 | |
21 | /* LCD Soft-Reset 1*/
|
22 | sbi(LCDPORT, LCD_PIN_D5); // LCD D5 = 1 |
23 | sbi(LCDPORT, LCD_PIN_D4); // LCD D4 = 1 |
24 | toggle_enable(); // Kommando übernehmen |
25 | _delay_ms(40); |
26 | |
27 | /* LCD Soft-Reset 2*/
|
28 | toggle_enable(); // Kommando übernehmen |
29 | _delay_ms(5); |
30 | |
31 | /* LCD Soft-Reset 3*/
|
32 | toggle_enable(); // Kommando übernehmen |
33 | _delay_ms(1); |
34 | |
35 | // Ab hier ist sicher der 8-Bit Mode eingestellt!
|
36 | // Somit wird das folgende Kommando auch richtig verstanden!
|
37 | |
38 | /* LCD auf 2 Zeilen, 4-Bit Modus, 5x7 Matrix einstellen */
|
39 | lcd_send(BEFEHL, LCD_SET_4Bit); // Register SET FUNCTION = 0010 1000 |
40 | lcd_send(BEFEHL, LCD_OFF); // Set LCD OFF |
41 | lcd_send(BEFEHL, LCD_CLEAR); // Clear LCD |
42 | lcd_send(BEFEHL, LCD_SET_2); // Set ENTRY MODE = 0000 0110 |
43 | lcd_send(BEFEHL, LCD_ON); // Set LCD ON |
44 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.