LCD-Tutorial.:)

Gast #772780
Lesenswert?

hi, ich bin gerade dabei das LCD-Tutorial zu testen.

ich bekomme das Display im 4Bit Modus ans laufen, heisst der Cursor 
blinkt an der ersten stelle, aber mehr auch nicht.
1
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
2
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
3
//
4
// Die Pinbelegung ist über defines in lcd-routines.h einstellbar
5
 
6
#include <avr/io.h>
7
#include "lcd-routines.h"
8
#include <util/delay.h>
9
 
10
// sendet ein Datenbyte an das LCD
11
 
12
void lcd_data(unsigned char temp1)
13
{
14
   unsigned char temp2 = temp1;
15
 
16
   LCD_PORT |= (1<<LCD_RS);        // RS auf 1 setzen
17
 
18
   temp1 = temp1 >> 4;
19
   temp1 = temp1 & 0x0F;
20
   LCD_PORT &= 0xF0;
21
   LCD_PORT |= temp1;               // setzen
22
   lcd_enable();
23
 
24
   temp2 = temp2 & 0x0F;
25
   LCD_PORT &= 0xF0;
26
   LCD_PORT |= temp2;               // setzen
27
   lcd_enable();
28
   
29
   _delay_us(42);
30
}
31
 
32
// sendet einen Befehl an das LCD
33
 
34
void lcd_command(unsigned char temp1)
35
{
36
   unsigned char temp2 = temp1;
37
 
38
   LCD_PORT &= ~(1<<LCD_RS);        // RS auf 0 setzen
39
 
40
   temp1 = temp1 >> 4;              // oberes Nibble holen
41
   temp1 = temp1 & 0x0F;            // maskieren
42
   LCD_PORT &= 0xF0;
43
   LCD_PORT |= temp1;               // setzen
44
   lcd_enable();
45
 
46
   temp2 = temp2 & 0x0F;            // unteres Nibble holen und maskieren
47
   LCD_PORT &= 0xF0;
48
   LCD_PORT |= temp2;               // setzen
49
   lcd_enable();
50
   
51
   _delay_us(42);
52
}
53
 
54
// erzeugt den Enable-Puls
55
void lcd_enable(void)
56
{
57
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen
58
   // http://www.mikrocontroller.net/topic/81974#685882
59
   LCD_PORT |= 1<<LCD_EN;
60
    _delay_us(1);                   // kurze Pause
61
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
62
   // http://www.mikrocontroller.net/topic/80900
63
   LCD_PORT &= ~1<<LCD_EN;
64
}
65
 
66
// Initialisierung: 
67
// Muss ganz am Anfang des Programms aufgerufen werden.
68
 
69
void lcd_init(void)
70
{
71
   LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | 1<<LCD_EN ;   // Port auf Ausgang schalten
72
 
73
   // muss 3mal hintereinander gesendet werden zur Initialisierung
74
 
75
   _delay_ms(15);
76
   LCD_PORT &= 0xF0;
77
   LCD_PORT |= 0x03;            
78
   LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0
79
   lcd_enable();
80
 
81
   _delay_ms(5);
82
   lcd_enable();
83
 
84
   _delay_ms(1);
85
   lcd_enable();
86
   _delay_ms(1);
87
 
88
   // 4 Bit Modus aktivieren 
89
   LCD_PORT &= 0xF0;
90
   LCD_PORT |= 0x02;
91
   lcd_enable();
92
   _delay_ms(1);
93
 
94
   // 4Bit / 2 Zeilen / 5x7
95
   lcd_command(0x28);
96
    
97
   // Display ein / Cursor aus / kein Blinken
98
   lcd_command(0x0C); 
99
 
100
   // inkrement / kein Scrollen
101
   lcd_command(0x06);
102
 
103
   lcd_clear();
104
}
105
 
106
// Sendet den Befehl zur Löschung des Displays
107
 
108
void lcd_clear(void)
109
{
110
   lcd_command(CLEAR_DISPLAY);
111
   _delay_ms(5);
112
}
113
 
114
// Sendet den Befehl: Cursor Home
115
 
116
void lcd_home(void)
117
{
118
   lcd_command(CURSOR_HOME);
119
   _delay_ms(5);
120
}
121
 
122
// setzt den Cursor in Zeile y (1..4) Spalte x (0..15)
123
 
124
void set_cursor(uint8_t x, uint8_t y)
125
{
126
  uint8_t tmp;
127
 
128
  switch (y) {
129
    case 1: tmp=0x80+0x00+x; break;    // 1. Zeile
130
    case 2: tmp=0x80+0x40+x; break;    // 2. Zeile
131
    case 3: tmp=0x80+0x10+x; break;    // 3. Zeile
132
    case 4: tmp=0x80+0x50+x; break;    // 4. Zeile
133
  }
134
  lcd_command(tmp);
135
}
136
 
137
// Schreibt einen String auf das LCD
138
 
139
void lcd_string(char *data)
140
{
141
    while(*data) {
142
        lcd_data(*data);
143
        data++;
144
    }
145
}
146

147

148
 
149
int main(void)
150
{
151
    lcd_init();
152
 
153
    lcd_data('T');
154
    lcd_data('e');
155
    lcd_data('s');
156
    lcd_data('t');
157
 
158
    set_cursor(0,2);
159
 
160
    lcd_string("Hello World!");
161
 
162
    while(1)
163
    {
164
    }
165
 
166
    return 0;
167
}

beim Compilen bekomme ich folgende Fehlermeldung:

"../lcd-routines.c:126: warning: 'tmp' may be used uninitialized in this 
function"

versteh ich nicht so ganz...
#772800
Lesenswert?

@  Warhammer (Gast)

>ich bekomme das Display im 4Bit Modus ans laufen, heisst der Cursor
>blinkt an der ersten stelle, aber mehr auch nicht.

Was? Ausgabe von Zeichen nicht möglich?

Und du musst den Code des tutorials nicht in voller Länge hier posten, 
das ist sinnlos.

>beim Compilen bekomme ich folgende Fehlermeldung:

>"../lcd-routines.c:126: warning: 'tmp' may be used uninitialized in this
>function"

Kann man hier ignorien. Oder schreib einfach

uint8_t tmp=0;

Dann ist die Warnung weg.

MFG
Falk
Gast #773640
Lesenswert?

öööhm makefile?

ich hab im avr studio als device den atmega88 ausgewählt.(GCC)

dann habe ich ein lcd-routines.c datei erstellt, und den inhalt aus dem 
tutorial kopiert, und das main file unten dran gehängt.

dann habe ich im gleichen ordner noch ein lcd-routines.h erstellt und 
die frequenz auf 4Mhz gestellt, und die Ports auf PORTB.

...
#define F_CPU 4000000

#define CLEAR_DISPLAY 0x01
#define CURSOR_HOME   0x02

#define LCD_PORT      PORTB
#define LCD_DDR       DDRB
#define LCD_RS        PB4
#define LCD_EN        PB5;

dann alles Compeliert und an das STK 500 übertragen. Verbindungen hab 
ich schon 2mal durchgemessen.

achja fuse bits.

da ist nur SPIEN an
BODLEVEL steht auf protection disable
und SUT_CKSEL steht auf Ext. Crystal 3-8mhz,....+65ms

mehr hab ich nicht gemacht...
Persönliche Seite #775025
Lesenswert?

Ich an deiner Stelle würde das Datenblatt vom Display und vom darin 
genannten LCD-Controller peinlich genau lesen und 
Initialisierungssequenz und -timing checken. Hast du den Namen des 
Displays und Link zu den Datenblättern schon gepostet?

Das derzeitige Hochfahren kann das normale Hardware-Hochfahren vom 
Display nach Power-Up sein und deine ganzen Kommandos seitens des µC 
versickern im Silizium. Hast du Messmöglichkeiten, um Reaktionen des 
Displays zu checken (Busyflag) und das Power-up von µC und LCD zu 
überwachen/steuern?
Persönliche Seite #777156
Lesenswert?

Man erkennt, dass beim KS0066U der grünmarkierte Teil nicht vorhanden 
ist und dass zwischen den anderen Befehlen bestimmte Wartezeiten 
einzuhalten sind. Ähnliche Wartezeiten sind auch beim HD44780 vorhanden, 
allerdings sind diese in einer anderen Tabelle (table 6) aufgeführt.

Die nächste Aufgabe ist ein Vergleich mit dem Tutorial-Code.
Angehängte Dateien:
Persönliche Seite #777201
Lesenswert?

Dies ist die originale lcd_init aus dem Tutorial
1
void lcd_init(void)
2
{
3
   LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | 1<<LCD_EN ;   // Port auf Ausgang schalten
4
 
5
   // muss 3mal hintereinander gesendet werden zur Initialisierung
6
 
7
   _delay_ms(15);
8
   LCD_PORT &= 0xF0;
9
   LCD_PORT |= 0x03;            
10
   LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0
11
   lcd_enable();
12
 
13
   _delay_ms(5);
14
   lcd_enable();
15
 
16
   _delay_ms(1);
17
   lcd_enable();
18
   _delay_ms(1);
19
 
20
   // 4 Bit Modus aktivieren 
21
   LCD_PORT &= 0xF0;
22
   LCD_PORT |= 0x02;
23
   lcd_enable();
24
   _delay_ms(1);
25
 
26
   // 4Bit / 2 Zeilen / 5x7
27
   lcd_command(0x28);
28
    
29
   // Display ein / Cursor aus / kein Blinken
30
   lcd_command(0x0C); 
31
 
32
   // inkrement / kein Scrollen
33
   lcd_command(0x06);
34
 
35
   lcd_clear();
36
}

Für das KS0066U würde man es z.B. so anpassen. Ich habe allerdings kein 
LCD mit KS0066U zur Hand, um das zu testen.

Beim Ändern der Wartezeiten unbedingt die Dokumentation zu _delay_ms 
beachten. Je nach Prozessortakt gibt es Grenzen für den erlaubten Wert 
und längere Wartezeiten müssen in mehrere kleinere Wartezeiten 
aufgeteilt werden. 30ms im Einzelaufruf funktioniert nur unterhalb von 
8,734 MHz!

Statt 30ms auch mal mit 100ms experimentieren.
1
#define KS0066U 
2

3
void lcd_init(void)
4
{
5
   LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | 1<<LCD_EN ;   // Port auf Ausgang schalten
6

7
#ifdef KS0066U 
8
   // 30ms (Einzelaufruf nur unterhalb F_CPU 8,734 MHz möglich)
9
   _delay_ms(10);  // lt. Datenblatt längere Wartezeit nach Power-On 
10
   _delay_ms(10);
11
   _delay_ms(10);
12
#else
13
   _delay_ms(15);
14

15
   // muss 3mal hintereinander gesendet werden zur Initialisierung
16
   LCD_PORT &= 0xF0;
17
   LCD_PORT |= 0x03;            
18
   LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0
19
   lcd_enable();
20
 
21
   _delay_ms(5);
22
   lcd_enable();
23
 
24
   _delay_ms(1);
25
   lcd_enable();
26
   _delay_ms(1);
27
#endif 
28
 
29
   // 4 Bit Modus aktivieren 
30
   LCD_PORT &= 0xF0;
31
   LCD_PORT |= 0x02;
32
   lcd_enable();
33
   _delay_ms(1);
34

35
   // 4Bit / 2 Zeilen / 5x7
36
   lcd_command(0x28);
37
    
38
   // Display ein / Cursor aus / kein Blinken
39
   lcd_command(0x0C); 
40

41
#ifdef KS0066U 
42
   _delay_ms(2);
43
#endif 
44
 
45
   // inkrement / kein Scrollen
46
   lcd_command(0x06);
47
 
48
   lcd_clear();
49
}
Gast #777865
Lesenswert?

joa erstmal vielen dank, das du dir soviel mühe gemacht hast.

funktioniert leider immernoch nicht.

was mit bis jetzt aufgefallen ist.

wenn ich die spannung zuschalte ist es totaler zufall was auf dem 
display erscheint...habs jetzt so 10mal gemacht und 3-4mal hatte ich 
wieder den cursor am blinken 2mal hatte ich an der sten stelle einen 
buchstaben, ein "F" und noch einen, und im restlichen gar nix.

ich habe gerade nochmal testweise ein programm für die datenübertragung 
mit rs232 übertragen und ausprobiert(wollte den takt von 4MHz testen) 
das funktioniert einwandfrei.

noch ne idee?

und noch ne frage, wo hast du die schönen blockdiagramme und das wissen 
über die verwendetetn controller her? ich hab in den datenblättern 
keinen hinweis gefunden(allerdings steht da auch nur die PIN belegung 
und die Abmessungen)

achja
_delay_ms(10);
hab ich am anfang 10x hinternanter eingetragen...
auch keine änderung
Persönliche Seite #777881
Lesenswert?

Die Datenblätter findet man, wenn man in dem Datenblatt des Displays den 
Namen des LCD-Controllers herausfischt und dann mit diesem Namen eine 
Datenblattsuche macht (einfach über Google mit Namen und filetype:pdf) 
oder auf den verlinkten Seiten beim Wikiartikel LCD

Das Buntmalen habe ich mit einem Grafikprogramm gemacht, hatte heute 
mittag Langeweile ;-)

Im Moment habe ich auch keine bessere Idee (Verlängerung der Wartezeit 
vor dem ersten Kommando hast du ja schon gemacht).

In meiner Praxis habe ich festgestellt, dass eine ungültige 
Initialisierung den LCD-Controller blockieren kann. Also vor einem neuen 
Versuch mit neuem Programm das Targetboard und das LCD-Display stromlos 
machen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren