Hallo, Ich weis, das Thema wurde schon x mal besprochen. Hab auch gestern und heut den ganzen Tag gesucht und probiert. Aber es funktioniert einfach nicht Hab mir im Betreff stehendes Display bei Reichelt gekauft und möchte es mit einem Atmega 8515 betreiben. Anschlußplan siehe Anhang. Mein Problem ist: Ich bekomme keinen Buchstaben angezeigt. Ich denke Initsalliesiert ist es richtig. Die zwei Balken sind immer hin weg. Was mach ich falsch? Danke für die Hilfe. Jürgen
> Anschlußplan siehe Anhang. sehe ich nicht. >Ich denke Initsalliesiert ist es richtig. sehe ich auch nicht. hilfe ich bin blind!
Komisch, ich hatte doch alles zusammen gepackt. Nächster versuch.
>//Display initsialieseiern >DISPLAY_COMANDO(0b00111000); //Aus Datenblatt >DISPLAY_COMANDO(0b00001111); >DISPLAY_COMANDO(0b00000001); >DISPLAY_COMANDO(0b00000110); erst nach der initalisierung kann man das busy flag abfragen. während der initalisierung es muss anderweitig gewartet werden. auch muss vorher erst mal 20 ms gewartet werden bevor initalisiert wird. http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD#Initialisierung_des_Displays
Einen schönnen guten Abend. Ich komme nicht weiter. :-( Habe mir das Datenblatt genauer angeschaut (http://www.lcd-module.de/pdf/doma/blueline-w.pdf) Und das Zeitdiagram analysiert(schreibt man glaub ich anderst. Aber egal:-) ). Jetzt habe ich folgenden Code geschrieben um das Display zu initialisieren:
1 | warte(500); //Warten bis Display hochgefahren ist |
2 | RS_L; |
3 | RW_L; |
4 | EN_S; |
5 | DISPLAY_PORT = 0b00111000; //Aus Datenblatt |
6 | asm("nop"); //Ein Zyklus Pause. Bei einem Takt von 4Mhz |
7 | asm("nop"); //250ns. x2 500ns |
8 | EN_L; |
9 | RS_S; |
10 | RW_S; |
11 | warte(1); |
12 | |
13 | RS_L; |
14 | RW_L; |
15 | EN_S; |
16 | DISPLAY_PORT = 0b00001111; //Aus Datenblatt |
17 | asm("nop"); |
18 | asm("nop"); |
19 | EN_L; |
20 | RS_S; |
21 | RW_S; |
22 | warte(1); |
23 | |
24 | RS_L; |
25 | RW_L; |
26 | EN_S; |
27 | DISPLAY_PORT = 0b00000001; //Aus Datenblatt |
28 | asm("nop"); |
29 | asm("nop"); |
30 | EN_L; |
31 | RS_S; |
32 | RW_S; |
33 | warte(1); |
Wenn ich es richtig verstanden habe müsste jetzt der Cursor blinken und der rest ist leer.? Die Balken gehen zwar weg, aber der Cursor blinkt nicht. Was mach ich falsch?
Hallöchen.. Kleine Anregung zur LC-Display Ansteuerung in 4Bit-Mode ohne Busy-Abfrage. Schau dir mal die Funktion lcd_init() genauer an. Das Komplette Projekt mit Schaltplan kann man sich hier anschaun: http://www.cczwei-forum.de/cc2/thread.php?postid=23657#post23657
1 | //----------------------------------------------------------------------
|
2 | // Titel : "2-Draht LC-Display" für den ATmega88/168
|
3 | //----------------------------------------------------------------------
|
4 | // Funktion : Ansteuerung für 2-Draht-LC-Display
|
5 | // : (kompatiebel zum CC2-Interface)
|
6 | // Schaltung : "PC-Lüftersteuerung"
|
7 | //----------------------------------------------------------------------
|
8 | // Prozessor : ATmega88/168
|
9 | // Takt : 16.0000 MHz
|
10 | // Sprache : C
|
11 | // C-Compiler : WinAVR - 20080610 (programmiert in AVR-Studio)
|
12 | // : (http://sourceforge.net/projects/winavr/)
|
13 | // Datum : 10.10.2008
|
14 | // Version : 1.0 R.Degen
|
15 | //----------------------------------------------------------------------
|
16 | #define DF_CPU 16000000 // Taktfrequenz ATmega
|
17 | #include <avr\io.h> // AVR Register und Konstantendefinitionen |
18 | #include <util\delay.h> // Bibliothek mit Warteroutinen |
19 | //----------------------------------------------------------------------
|
20 | |
21 | // Pinbelegung für das LCD, an verwendete Pins anpassen
|
22 | |
23 | #define lcd_port PORTC // Port für LCD
|
24 | #define lcd_ddr DDRC // Port-Richtung
|
25 | #define lcd_clk PC0 // Clk-Leitung an Schieberegister 74HCT164
|
26 | #define lcd_data PC1 // Data-Leitung an Schieberegister u. Enable-Signal LCD
|
27 | |
28 | //-----------------------------------------------
|
29 | // Funktions-Routinen
|
30 | //-----------------------------------------------
|
31 | |
32 | // Clk-Impuls für Schieberegister erzeugen
|
33 | void lcd_clk_impuls() |
34 | {
|
35 | _delay_us(5); // 5µsec warten |
36 | lcd_port |= (1<<lcd_clk); // Clk-Pin auf 1 |
37 | _delay_us(10); // 10µsec warten |
38 | lcd_port &= ~(1<<lcd_clk); // Clk-Pin auf 0 |
39 | _delay_us(5); // 5µsec warten |
40 | }
|
41 | |
42 | // Ausgänge des Schieberegisters auf 0 setzen
|
43 | void lcd_clr_schieberegister() |
44 | {
|
45 | lcd_port &= ~(1<<lcd_data); // Data-Leitung am Eingang des Schieberegisters auf 0 |
46 | uint8_t i; // Bit-Zähler (8Bit Integer ohne Vorzeichen) |
47 | for (i=0;i<7;i++) // Zählerschleife |
48 | {
|
49 | lcd_clk_impuls(); // 7x Clk-Impulse am Schieberegister erzeugen |
50 | } // Zählerschleife beenden? |
51 | }
|
52 | |
53 | // Enabled-Impuls am LC-Display erzeugen und danach Schieberegister löschen
|
54 | void lcd_enabled_impuls() |
55 | {
|
56 | _delay_us(5); // 5µsec warten |
57 | lcd_port |= (1<<lcd_data); // Data-Leitung auf 1 |
58 | _delay_us(10); // 10µsec warten |
59 | lcd_clr_schieberegister(); // Schieberegister löschen |
60 | _delay_us(5); |
61 | }
|
62 | |
63 | // sende Hi-Nibble an LC-Display (LCD-init.Mode)
|
64 | void lcd_send_hi_nibble(uint8_t nibble) |
65 | {
|
66 | lcd_port |= (1<<lcd_data); // Lcd-Enabled-Bit auf 1 |
67 | lcd_clk_impuls(); // Bit ins Schieberegister übertragen |
68 | lcd_port &=~ (1<<lcd_data); // Lcd-RS-Bit auf 0 |
69 | lcd_clk_impuls(); // Bit ins Schieberegister übertragen |
70 | uint8_t i; // Bit-Zähler (8Bit Integer ohne Vorzeichen) |
71 | for (i=0;i<4;i++) // Zählerschleife (4 mal) |
72 | {
|
73 | if (nibble & 0x80) // Bit7 in nibble prüfen (Bits in nibble mit 0b10000000 maskieren) |
74 | {
|
75 | lcd_port |= (1<<lcd_data); // wenn Bit7=1 dann Data-Leitung auf 1 |
76 | }
|
77 | else
|
78 | {
|
79 | lcd_port &=~(1<<lcd_data); // wenn Bit7=0 dann Data-Leitung auf 0 |
80 | }
|
81 | lcd_clk_impuls(); // Bit ins Schieberegister übertragen |
82 | nibble = nibble<<1; // Bits in nibble 1x nach links routieren |
83 | } // Zählerschleife beenden? |
84 | lcd_port &= ~ (1<<lcd_data); // erstes Bit im Schieberegister auf 0 setzen (unbenutzt) |
85 | lcd_clk_impuls(); // Bit ins Schieberegister übertragen |
86 | lcd_enabled_impuls(); // Lcd-Enabled Impuls erzeugen |
87 | }
|
88 | |
89 | // sende ein Byte ans LC-Display
|
90 | // wenn cmd=0 ein LCD-Kommandobyte senden / wenn cmd=1 ein LCD-Datenbyte senden)
|
91 | // in data befindet das Kommando- oder Datenbyte
|
92 | void lcd_send_data(uint8_t cmd, uint8_t data) |
93 | {
|
94 | uint8_t i1; // Zähler (8Bit Integer ohne Vorzeichen) |
95 | for (i1=0;i1<2;i1++) // 1.Zählerschleife (2 mal) um high- und low-nibble zu senden |
96 | {
|
97 | lcd_port |= (1<<lcd_data); // Lcd-Enabled-Bit auf 1 |
98 | lcd_clk_impuls(); // Bit ins Schieberegister übertragen |
99 | if (cmd==0) // LCD-Kommandobyte ? |
100 | {
|
101 | lcd_port &=~(1<<lcd_data); // Lcd-RS-Bit auf 0 |
102 | }
|
103 | else
|
104 | {
|
105 | lcd_port |= (1<<lcd_data); // Lcd-RS-Bit auf 1 |
106 | }
|
107 | lcd_clk_impuls(); // Bit ins Schieberegister übertragen |
108 | uint8_t i2; // Bit-Zähler (8Bit Integer ohne Vorzeichen) |
109 | for (i2=0;i2<4;i2++) // 2.Zählerschleife (4 mal) für ein nibble |
110 | {
|
111 | if (data & 0x80) // Bit7 in data prüfen (Bits in data mit 0b10000000 maskieren) |
112 | {
|
113 | lcd_port |= (1<<lcd_data);// wenn Bit7=1 dann Data-Leitung auf 1 |
114 | }
|
115 | else
|
116 | {
|
117 | lcd_port &=~(1<<lcd_data);// wenn Bit7=0 dann Data-Leitung auf 0 |
118 | }
|
119 | lcd_clk_impuls(); // Bit ins Schieberegister übertragen |
120 | data = data<<1; // Bits in Data 1x nach links routieren |
121 | } // 2.Zählerschleife beenden? |
122 | lcd_port &= ~ (1<<lcd_data); // erstes Bit im Schieberegister auf 0 setzen (unbenutzt) |
123 | lcd_clk_impuls(); // Bit ins Schieberegister übertragen |
124 | lcd_enabled_impuls(); // Lcd-Enabled Impuls erzeugen |
125 | } // 1.Zählerschleife beenden ? |
126 | _delay_ms(5); // warte bis LCD bereit für nächsten Datenempfang |
127 | }
|
128 | |
129 | // Init. LC-Display:4-Bit Interface,5x7 Dots,2 Rows,Cursor on,Line-Cursor on,Display on
|
130 | void lcd_init() |
131 | {
|
132 | _delay_ms(100); // 100ms warten bis LC-Display bereitnach Power on |
133 | lcd_clr_schieberegister(); // Schieberegister löschen |
134 | _delay_us(10); // 10us warten |
135 | // ab hier: LCD-Resetsequenz
|
136 | lcd_send_hi_nibble(0b00110000);// sende 1.Hi-Nibble an LC-Display |
137 | _delay_ms(5); // 5ms warten bis LC-Display bereit |
138 | lcd_send_hi_nibble(0b00110000);// sende 2.Hi-Nibble an LC-Display |
139 | _delay_ms(5); // 5ms warten bis LC-Display bereit |
140 | lcd_send_hi_nibble(0b00110000);// sende 3.Hi-Nibble an LC-Display |
141 | _delay_ms(5); // 5ms warten bis LC-Display bereit |
142 | // LCD in 4Bit-Mode schalten
|
143 | lcd_send_hi_nibble(0b00100000);// sende Hi-Nibble an LC-Display |
144 | _delay_ms(5); // 5ms warten bis LC-Display bereit |
145 | // ab hier ist LCD im 4-Bit Modus
|
146 | // (Parameterliste: 1.Byte = cmd, 2.Byte = Data)
|
147 | lcd_send_data(0,0b00101000); // LCD-Command 2 Zeilen, 5x8 Dots |
148 | lcd_send_data(0,0b00001000); // LCD-Comand Display aus |
149 | lcd_send_data(0,0b00000001); // LCD-Comand Display löschen |
150 | lcd_send_data(0,0b00000110); // LCD-Comand Display Entrymode |
151 | lcd_send_data(0,0b00001111); // LCD-Comand Display ein |
152 | }
|
153 | |
154 | //-----------------------------------------------------------------
|
155 | // Hauptprogramm
|
156 | //-----------------------------------------------------------------
|
157 | |
158 | int main (void) |
159 | {
|
160 | lcd_ddr |= (1<<lcd_clk); // Portleitung CLK (Clk-Schieberegister) auf Ausgang konfigurieren |
161 | lcd_ddr |= (1<<lcd_data); // Portleitung DATA (Data-Schieberegister) auf Ausgang konfigurieren |
162 | lcd_port &=~(1<<lcd_clk); // CLK auf 0 setzen |
163 | lcd_port &=~(1<<lcd_data); // DATA auf 0 setzen |
164 | lcd_init(); // init. LC-Display |
165 | lcd_send_data(1,'H'); // Text senden |
166 | lcd_send_data(1,'a'); |
167 | lcd_send_data(1,'l'); |
168 | lcd_send_data(1,'l'); |
169 | lcd_send_data(1,'o'); |
170 | lcd_send_data(1,' '); |
171 | lcd_send_data(1,'C'); |
172 | lcd_send_data(1,'o'); |
173 | lcd_send_data(1,'m'); |
174 | lcd_send_data(1,'p'); |
175 | lcd_send_data(1,'u'); |
176 | lcd_send_data(1,'t'); |
177 | lcd_send_data(1,'e'); |
178 | lcd_send_data(1,'r'); |
179 | lcd_send_data(1,'C'); |
180 | lcd_send_data(1,'l'); |
181 | lcd_send_data(1,'u'); |
182 | lcd_send_data(1,'b'); |
183 | lcd_send_data(1,' '); |
184 | lcd_send_data(1,'2'); |
185 | }
|
Gruß Rolf
Dein „warte(1)“ kehrt sofort zurück. Warum? Schau' Dir einfach den Code mal an. Der kleinste Wert, bei dem gewartet wird, ist 2. Und da bekommst Du nicht 2ms, sondern irgendetwas Zufälliges zwischen 0 und 2 ms. Die Idee, Zeitschleifen über einen Timer zu machen, ist grundsätzlich gut, aber dann sollte die Timerauflösung deutlich über der benötigten Zeit liegen und nicht darunter. Function warte() hat eine weitere Macke: das Beschreiben der Variable „timer“ (eine 2-Byte-Variable) ist nicht dagegen gesichert, dass nach dem Schreiben des ersten Bytes ein Interrupt kommt. Auch ist es überflüssig, R/W und RS auf einen Ruhezustand jedesmal zurückzusetzen. Das fordert keiner, tut allerdings auch niemand weh. Weiter habe ich nicht geschaut. Warum nimmst Du zum Start nicht eine der vielen Implementationen, die es im Netz gibt?
Guten Morgen und ein herzliches Dankeschön für die ausführlichen Antworten. Hc Zimmerer schrieb: > Dein „warte(1)“ kehrt sofort zurück. Warum? Schau' Dir einfach den > Code mal an. Der kleinste Wert, bei dem gewartet wird, ist 2. Und da > bekommst Du nicht 2ms, sondern irgendetwas Zufälliges zwischen 0 und 2 > ms. Du hast recht, ich kann ja nicht 1 durch 2 teilen. (Ich schon, aber µC nicht ;-)) Werde ich noch mal überarbeiten müßen. Hc Zimmerer schrieb: > aber dann sollte die Timerauflösung deutlich über der > benötigten Zeit liegen und nicht darunter. Denn Satzteil verstehe ich nicht. Wenn ich die Auflösung kleiner mach kann ich doch eine Variable hochzählen lassen bis zu der Zeit wo ichs brauch. Wenn ich die Auflösung größßer mach muss ich ja wieder was abziehen. Wie geht das? Hc Zimmerer schrieb: > Function warte() hat eine weitere Macke: das Beschreiben der Variable > „timer“ (eine 2-Byte-Variable) ist nicht dagegen gesichert, dass nach > dem Schreiben des ersten Bytes ein Interrupt kommt. Hab ich verstanden. Werd ich in der nächsten Version ändern. Hc Zimmerer schrieb: > Auch ist es überflüssig, R/W und RS auf einen Ruhezustand jedesmal > zurückzusetzen. Das fordert keiner, tut allerdings auch niemand weh. Schau dir bitte den Anhang noch mal an. Habe dort die Stellen markirt warum ich es gemacht habe. So hab ichs halt verstanden. Hc Zimmerer schrieb: > Warum nimmst Du zum Start nicht eine > der vielen Implementationen, die es im Netz gibt? Aus einem einfachen Grund: Kopieren kann jeder. Ich möchte aber einen Lerneffekt erreichen und versuche das zu verstehen was ich schreib. Wir haben in der Schule eine lcd.c und eine lcd.h bekommen und die einzelnen Befehle dazu. Punkt das wars. Es hat funktioniert aber keiner hat verstanden wie. Der Lehrer war ein Profie was C angeht und hat auch demmensprechend seine Programme geschrieben. Jetzt will ichs aber verstehen und schreibe somit selber. Rolf Degen schrieb: > Poti für den Kontrast mal verstellen. Das verstehle ich bei jedem neuen versuch. Noch malls Danke. Ihr habt mir viel weitergeholfen. Werde weiter probieren.
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.