Forum: Mikrocontroller und Digitale Elektronik Problem mit LCD an ATMega 644


von Trax X. (trax)


Angehängte Dateien:

Lesenswert?

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.

von ... .. (docean) Benutzerseite


Lesenswert?

wird F_CPU gesetzt? (über define)

Was sagt der Compiler beim Neuerstellen?

von Trax X. (trax)


Angehängte Dateien:

Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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).

von TraxXavier (Gast)


Lesenswert?

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

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> 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.

von TraxXavier (Gast)


Lesenswert?

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.

von Trax X. (trax)


Lesenswert?

Niemand ne idee?

von Trax X. (trax)


Lesenswert?

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);

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> 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.

von Trax X. (trax)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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?

von Trax X. (trax)


Angehängte Dateien:

Lesenswert?

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?

von Trax X. (trax)


Lesenswert?

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?

von Peter D. (peda)


Lesenswert?

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

von Trax X. (trax)


Lesenswert?

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?

von Trax X. (trax)


Lesenswert?

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.

von Stephan H. (stephan-)


Lesenswert?

>> 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 )

von Trax X. (trax)


Lesenswert?

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?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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

von Trax X. (trax)


Lesenswert?

Joa,
ich teste die lib morgen mal durch...

von Trax X. (trax)


Lesenswert?

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?

von holger (Gast)


Lesenswert?

>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.

von Trax X. (trax)


Lesenswert?

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
Noch kein Account? Hier anmelden.