Hi, ich versuche grade ein LCD (http://www.pollin.de/shop/downloads/D120060D.PDF) an einem Atmega 644 anzuschließen, der steckt auf so einem ABR-NET-IO Board (http://www.pollin.de/shop/downloads/D810058B.PDF) Die anleitung aus dem http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial passte nicht ganz da auf dem Board andere Ports für die Kommunikation vorgesehen sind, daher habe ich Codes hoffentlich korrekt angepasst. Leider bekomme ich immer noch kein bild, das der LCD an sich geht weis ich da er am LPT Port mit dem Proggi stlcd Funtzt. Könnte mit einer bitte helfen das zum laufen zu bekommen.
wird F_CPU gesetzt? (über define) Was sagt der Compiler beim Neuerstellen?
F_CPU ist gesetzt und stimmt auch, wen ich eine LED im sekunden takt blinken lasse dann ist es auch ziemlich genau ne sekunde. Den Kompiler output is in console.txt im Anhang.
Schaltplan? Gemäß Code oben (hier ein Ausschnitt)
1 | #define LCD_RW PD2
|
2 | #define LCD_RS PD3
|
3 | |
4 | // DB4 bis DB7 des LCD sind mit PD0 bis PD3 des AVR verbunden
|
Hast du eine unzulässige Doppelbelegung von PD2 und PD3 bei Datenleitungen (DB6 und DB7) und Steuerleitungen (RW, RS).
Der Schaltplan ist in meinem ersten post http://www.pollin.de/shop/downloads/D810058B.PDF irgendwo in der Mitte ist ein plan des Boards, und am ende eine Pinbelegung für ein LCD am EXT Stecker. Doppel Belegung sollte nicht sein die LCD Daten pins DB4 bis DB7 sollten auf die pins PD4 bis PD7 am atmel gehen, RW auf PD2, RS PD3, und Enable auf PB0
> Der Schaltplan ist in meinem ersten post > http://www.pollin.de/shop/downloads/D810058B.PDF irgendwo in der Mitte > ist ein plan des Boards, und am ende eine Pinbelegung für ein LCD am EXT > Stecker. Du musst es wissen, ob du deinen aktuellen Aufbau zeigst oder irgendwas in der Mitte in verschiedenen Hersteller-PDFs zweier Baugruppen. Ich hätte die Frage anders gestellt bzw. nach einer Rückfrage schleunigst den Schaltplan beigeschafft ;-) > Doppel Belegung sollte nicht sein die LCD Daten pins DB4 bis DB7 sollten > auf die pins PD4 bis PD7 am atmel gehen, RW auf PD2, RS PD3, und Enable > auf PB0 Der Kommentar im Code sagt was anderes. Der Kommentar stammt aus der Originalsource aus dem AVR-GCC-Tutorial. Es könnte natürlich sein, dass du im eigentlichen LCD-Code umprogrammiert hast und nur den Kommentar unverändert übernommen hast. Ich habe im Code nachgesehen, ob dementsprechende Kommentare vorhanden sind. Das ist nicht der Fall. Eine weitere Analyse habe ich deshalb (und weil der Schaltplan nicht vorliegt) nicht gemacht.
Ich habe den code umgeschrieben um auf die höheren bits des Ports zu schreiben, ich habe nichts kommentiert und auch die alten Kommentare unverändert gelassen da das alles es eher schell und provisorisch war. Ich hoffe das das so stimmt, weis aber nicht mit Sicherheit ob ich da alles richtig umgeändert habe. Der Schaltplan entspricht zu 100% der Beschreibung im PDF damit das dann auch mit der originalen firmware kompatibel ist falls ich aus irgendeinem Grund wieder den kleineren Atmega 32 mit der Pollin Software reinsetzen möchte.
habe das jetzt mit eigenem code am LPT port halbwegs zum laufen gebracht, leider funtzt die 2te zeile immer noch nicht, und wen ich am anfang 0011 auf die daten pins lege so wie im tutorial beschrieben kommt kein bild. Hat wer ne idee wie man das ding zum laufen kebommen kan?
1 | #define LCD_EN 0
|
2 | #define LCD_RS 2
|
3 | |
4 | void EN(int x) |
5 | {
|
6 | UCHAR value = DlPortReadPortUchar(0x37A); |
7 | if(!x) // ACHTUNG INVERTIERT! |
8 | value |= (1<<LCD_EN); |
9 | else
|
10 | value &= ~(1<<LCD_EN); |
11 | DlPortWritePortUchar(0x37A,value); |
12 | }
|
13 | |
14 | void RS(int x) |
15 | {
|
16 | UCHAR value = DlPortReadPortUchar(0x37A); |
17 | if(x) |
18 | value |= (1<<LCD_RS); |
19 | else
|
20 | value &= ~(1<<LCD_RS); |
21 | DlPortWritePortUchar(0x37A,value); |
22 | }
|
23 | |
24 | __inline void _delay_us(int c) |
25 | {
|
26 | for(int i=0;i<c*800;i++) |
27 | __noop; |
28 | }
|
29 | |
30 | __inline void _delay_ms(int c) |
31 | {
|
32 | Sleep(c); |
33 | }
|
34 | |
35 | // erzeugt den Enable-Puls
|
36 | void lcd_enable(void) |
37 | {
|
38 | // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen
|
39 | // http://www.mikrocontroller.net/topic/81974#685882
|
40 | EN(1); |
41 | _delay_us(1); |
42 | // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
|
43 | // http://www.mikrocontroller.net/topic/80900
|
44 | EN(0); |
45 | }
|
46 | |
47 | void lcd_send(unsigned char temp1, unsigned char rs) |
48 | {
|
49 | unsigned char temp2 = temp1; |
50 | |
51 | RS(rs); // RS auf x setzen |
52 | |
53 | temp1 = temp1 >> 4; // oberes Nibble holen |
54 | temp1 = temp1 & 0x0F; // maskieren |
55 | |
56 | UCHAR value = DlPortReadPortUchar(0x378); |
57 | value &= 0x0F; |
58 | value |= temp1 << 4; // setzen |
59 | DlPortWritePortUchar(0x378,value); |
60 | lcd_enable(); |
61 | |
62 | temp2 = temp2 & 0x0F; // unteres Nibble holen und maskieren |
63 | value &= 0x0F; |
64 | value |= temp2 << 4; // setzen |
65 | DlPortWritePortUchar(0x378,value); |
66 | lcd_enable(); |
67 | |
68 | _delay_us(42); |
69 | }
|
70 | |
71 | void lcd_nibble(unsigned char temp1) |
72 | {
|
73 | UCHAR value = DlPortReadPortUchar(0x378); |
74 | value &= 0x0F; |
75 | value |= temp1 << 4; // setzen |
76 | DlPortWritePortUchar(0x378,value); |
77 | lcd_enable(); |
78 | }
|
79 | |
80 | int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) |
81 | {
|
82 | |
83 | #if 1
|
84 | EN(0); |
85 | RS(0); |
86 | |
87 | // lcd_nibble(3); - wen das an ist gibts kein bild
|
88 | |
89 | _delay_ms(5); |
90 | lcd_enable(); |
91 | _delay_ms(5); |
92 | lcd_enable(); |
93 | _delay_ms(5); |
94 | |
95 | |
96 | lcd_nibble(2); // Enable 4-bit mode |
97 | |
98 | Sleep(140); |
99 | |
100 | lcd_send(0x06,0); // inkrement / kein Scrollen |
101 | lcd_send(0x0C,0); // Display ein / Cursor aus / kein Blinken |
102 | //lcd_send(0x28,0); //4 Bit Operation,2 Line,5x7 Font 5 -- wen das an ist gibts kein bild
|
103 | |
104 | |
105 | lcd_send(0x01,0); // Clear Display |
106 | |
107 | Sleep(500); |
108 | |
109 | // Write Line 1
|
110 | lcd_send(0x80,0); // Line 1 |
111 | |
112 | lcd_send('0',1); |
113 | lcd_send('1',1); |
114 | lcd_send('2',1); |
115 | lcd_send('3',1); |
116 | lcd_send('4',1); |
117 | lcd_send('5',1); |
118 | lcd_send('6',1); |
119 | lcd_send('7',1); |
120 | lcd_send('8',1); |
121 | lcd_send('9',1); |
122 | lcd_send('A',1); |
123 | lcd_send('B',1); |
124 | lcd_send('C',1); |
125 | lcd_send('D',1); |
126 | lcd_send('E',1); |
127 | lcd_send('F',1); |
128 | |
129 | // Write Line 2
|
130 | lcd_send(0xC0,0); // Line 2 (does not work yet) |
131 | |
132 | lcd_send('f',1); |
133 | lcd_send('e',1); |
134 | lcd_send('d',1); |
135 | lcd_send('c',1); |
136 | lcd_send('b',1); |
137 | lcd_send('a',1); |
138 | lcd_send('9',1); |
139 | lcd_send('8',1); |
140 | lcd_send('7',1); |
141 | lcd_send('6',1); |
142 | lcd_send('5',1); |
143 | lcd_send('4',1); |
144 | lcd_send('3',1); |
145 | lcd_send('2',1); |
146 | lcd_send('1',1); |
147 | lcd_send('0',1); |
148 | |
149 | Sleep(5000); |
150 | |
151 | // Clear Diaplay x2
|
152 | lcd_send(0x01,0); |
153 | lcd_send(0x01,0); |
> leider funtzt die 2te zeile immer noch nicht Das ist ein Indiz dafür, dass die Softwareresetsequenz des LCDs nicht funktioniert, bei dem die Anzahl der Zeilen eingestellt wird. Der Kommentar > //lcd_send(0x28,0); //4 Bit Operation,2 Line,5x7 Font 5 > -- wen das an ist gibts kein bild passt dazu. Insgesamt kann das mehrere Ursachen haben: 1/ Die Hardwareresetsequenz des LCDs ist noch nicht angeschlossen, wenn versucht wird, per Sofware zu resetten und auf 2 Zeilen zu initialisieren. Hier könnte eine längere Wartezeit (mehrere 100 ms) vor dem lcd_init() helfen. 2/ Das Timing zwischen den einzelnen Befehlen an das LCD stimmt nicht. Wenn mit Warteschleifen gearbeitet wird, müssen diese auch funktionieren. D.h. bei _delay_us und _delay_ms muss Optimierung eingeschaltet sein usw. Die Zeiten an sich müssen mit dem Datenblatt übereinstimmen. Die LCD-Library aus dem AVR-GCC-Tutorial hat z.B. auch einen Kommentar zur Länge des EN-Pulses... 3/ Die Befehle an sich müssen stimmen. Es gibt unterschiedliche LCD-Controller, die unterschiedlich behandelt werden müssen. 4/ Die Verdrahtung muss passen. Die originale LCD-Library aus dem AVR-GCC-Tutorial berücksichtigt z.B. die R/W Leitung nicht, sondern arbeitet mit festen Warteschleifen. Umgekert heisst das diese Leitung muss auf "Dauerwrite" stehen, d.h. über einen Pulldown auf LOW gezogen werden. Mit http://www.pollin.de/shop/downloads/D120060D.PDF kann man das Timing und die Befehle nicht kontrollieren, weil sie einfach darin nicht angegeben sind. Und für vergleichbare Datenblätter fehlt die Angabe welcher LCD-Controller verbaut ist.
Also auf PCB des LCD'S sind 2 chips verbaut: OKI M5839b 4152B04-2 und Hitahi 2h2 hd44780a00 ich nähme mal stark an das der hd44780a00 der relevante hier ist.
Richtig, der HD44780 ist es. Das ist eigentlich der Klassiker. Die LCD-Library im Tutorial ist darauf zugeschnitten. Teste mal mit den drei Änderungen: 1/ Längere Wartezeit vor lcd_int() 2/ _delay_us(4); statt _delay_us(1); in lcd_enable() 3/ R/W Leitung über 10K Pulldown an GND gebunden Wenn es geht, markiere die Zeilen im Code, die du geändert hast. Dann braucht man nicht zwei Dateien miteinander zu vergleichen.
1 | void lcd_enable(void) |
2 | {
|
3 | LCD_PORT_EX |= (1<<LCD_EN); |
4 | _delay_us(4); // kurze Pause (geändert) |
5 | // _delay_us(1); // kurze Pause (Original)
|
6 | LCD_PORT_EX &= ~(1<<LCD_EN); |
7 | }
|
Man auch oben in der Datei ein Symvol definieren und das entsprechend wahr oder falsch setzen. Ich mache das normalerweise so, weil ich dann einfach zwischen Originalcode und geändertem Code umschalten kann: #define NEUER_CODE 1 ... #if NEUER_CODE // hier neuer Code _delay_us(4); // kurze Pause (geändert) #else // hier alter Code _delay_us(1); // kurze Pause (Original) #endif /* NEUER_CODE */ Viel Arbeit? Denk mal so: Wenn dir diese Arbeit beim Schreiben des Codes bereits zuviel ist, wieviel Arbeit mag sich der potentielle Problemlöser beim Lesen des Codes machen?
Also mit dem Code im Anhang funtzt die erste Zeile vom LCD, und der code sollte jetzt lesbarer sein ;) Die Wartezeiten haben nichts geändert, R/W ist auf GND, und ich habe etwas die Pinbelegung geändert so das nur noch Port D benutzt wird, aber wie vorher in Umgekehrte nibble folge. Pin #-LCD Bezeichnung-LCD Pin-µC 1 Vss GND 2 Vcc 5V 3 Vee GND 4 RS PD3 am AVR 5 RW GND 6 E PD2 am AVR 7 DB0 offen 8 DB1 offen 9 DB2 offen 10 DB3 offen 11 DB4 PD4 am AVR 12 DB5 PD5 am AVR 13 DB6 PD6 am AVR 14 DB7 PD7 am AVR lcd_command(0x28); // 4Bit 2 Zeilen 5x7 wird nun akzeptiert jedoch geht wie vorher nur eine Zeile in der soft Reset Routine musste ich das 0x30 mit einem 0x20 wie bei auf 4-bit setzen tauschen sonst kein bild laut der Seite da: http://www.geocities.com/dinceraydin/lcd/commands.htm ist 0x20 4-bit 1 Zeile und 0x28 4-bit 2 Zeilen kann es sein das da das LCD jetzt immer auf eine Zeile initialisiert und sich danach nicht mehr auf 2 umstellen lässt? Ich könnte mal versuchen DB3 auf +5v mit einem 10k zu setzen so das solange das teil am initialisieren ist und noch im 8 bit Modus es sofort auf 4 bit 2 Zeilen gesetzt wird also mit einem 0x28, glaubst Du das ist ne gute Idee?
PS: DB3 auf High hat leider keinen erfolg gebracht. Ne Idee was ich da weiter machen könnte damit dieses teil endlich so Funktioniert wie es sollte?
Trax Xavier wrote: > Ne Idee was ich da weiter machen könnte damit dieses teil endlich so > Funktioniert wie es sollte? Ein bewährter Code: http://www.mikrocontroller.net/attachment/30300/lcd_drv.zip Peter
Auch mit dem lcd_driver code das selbe Problem: So wie er da steht geht es nicht, erst wen ich in der Reset Routine 0x30 mit 0x20 Ersätze, dann aber eben geht nur eine Zeile. Was für ein behämmertes Display ist den das?
Hat niemand ne idee wie ich das ding endlich unter Kontrolle bekommen könnte? es kann dich nicht sein das sonst niemand dieses model hat, wird ja von Pollin vertrieben.
>> Die Wartezeiten haben nichts geändert, R/W ist auf GND, und ich habe
Arbeitet die Routine mit Busy ???
Das wird dann so nichts.
Falls R/W an GND liegt mußt Du striktes Timing einhalten.
Ich schreibe konstant mit 1ms nach dem Init.
Für den Init 5ms. (ist an der Grenze )
Also zwischen jedem nibble oder jeden 2 nibbles ein MS pause? und 5ms pause nach dem init, oki, noch was? bei dem code hier: http://www.mikrocontroller.net/attachment/30300/lcd_drv.zip was würdest du alles ändern? bzw: wo gibtes ein sample welches das Busy evaluiert?
Trax Xavier wrote: > bzw: wo gibt es ein sample welches das Busy evaluiert? "R/W Leitung vom Text-LCD ist fix mit GND verbunden und die Ansteuerung mit der LCD/AVR-Library von Peter Fleury funktioniert nicht! Was ist los? Die Fleury LCD Library erwartet, dass R/W nicht fix ist, sondern vom Programm gesteuert werden kann. Das muss auch so sein, denn Peter liest das Busy Flag aus, um Warteschleifen zu vermeiden." http://www.mikrocontroller.net/articles/LCD#FAQ
Naja, wie könnte es den anders sein auch mit dem auslesen des busy flag funtzt das kack teil nicht!!! erst wen ich die Zeile: LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // _BV(LCD_FUNCTION_8BIT)>>4; mit der LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // _BV(LCD_FUNCTION_8BIT)>>4; Ersätze funtzt die 1te Zeile, das selbe wie bei dem lcd_drv code ohne busy flag. Hat den niemand dieses model und könnte mir verraten wie man damit zurecht kommt?
>Hat den niemand dieses model und könnte mir verraten wie man damit >zurecht kommt? Folge dem Datenblatt und programmiere alles 1:1. Wenn es kein vernünftiges Datenblatt gibt dann schmeiss das Teil einfach weg. Besorg dir ein LCD für das es ein ausreichendes Datenblatt gibt. Vieleicht ist dein LCD bei deinen Versuchen beschädigt worden oder war schon defekt. Aber wer kann das schon wissen.
Naja, es ist 1:1 und ich bin normalerweise recht gut bei all solchen Basteleien und so, bis auf das kack LCD läuft alles bestens, falls niemand noch ne gute idee hat hohle ich mit am Montang oder so 'n neues, Geld ist ja dazu da das man es ausgibt ;)
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.