Displayausgabe

OP #2930378
Lesenswert?

Hallo!

Ich versuche schon seit einigen Stunden etwas auf einem HD44780 
auszugeben.
Da ich noch Anfänger im µController programmieren bin verwendete ich 
dieses 
Tutorial:http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung

Bei mir gibt das Display jedoch komische Zeichen aus, statt Buchstaben 
und Sätze.

Verbindungen vom Display zu den Ports sollten stimmen.
Quarz wurde auf 1 MHz angepasst und es wurde wie im Tutorial PortD 
verwendet.

Kann mir bitte jemand weiterhelfen?
danke
Angehängte Dateien:
OP #2931116
Lesenswert?

Ich verwende, wie im Tutorial den 4-Bit Mode.
Ich hab einfach die Codes aus dem Tutorial kopiert und dann halt die 
Frequenz angepasst und auch den PortD verwendet.

Ich entschuldige mich wegen dem zu großen Bild. War mir nicht bewusst 
wie groß 2Mb wirklich sind.
Zum trollen bin ich hier nicht da, dafür gibt im Netz genügend andere 
Seiten.
Mich würde es wirklich nur interessieren, wieso das Display nur "ö" "o" 
und Pfeile ausgibt.

mfg
OP #2931457
Lesenswert?

lcd-routines.h
1
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
2
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
3
//
4

5
#ifndef LCD_ROUTINES_H
6
#define LCD_ROUTINES_H
7

8
////////////////////////////////////////////////////////////////////////////////
9
// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!
10

11
#ifndef F_CPU
12
#define F_CPU 1000000
13
#endif
14

15
////////////////////////////////////////////////////////////////////////////////
16
// Pinbelegung für das LCD, an verwendete Pins anpassen
17
// Alle LCD Pins müssen an einem Port angeschlossen sein und die 4
18
// Datenleitungen müssen auf aufeinanderfolgenden Pins liegen
19

20
//  LCD DB4-DB7 <-->  PORTD Bit PD0-PD3
21
#define LCD_PORT      PORTD
22
#define LCD_DDR       DDRD
23
#define LCD_DB        PD0
24

25
//  LCD RS      <-->  PORTD Bit PD4     (RS: 1=Data, 0=Command)
26
#define LCD_RS        PD4
27

28
//  LCD EN      <-->  PORTD Bit PD5     (EN: 1-Impuls für Daten)
29
#define LCD_EN        PD5
30

31
////////////////////////////////////////////////////////////////////////////////
32
// LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)
33

34
#define LCD_BOOTUP_MS           15
35
#define LCD_ENABLE_US           20
36
#define LCD_WRITEDATA_US        46
37
#define LCD_COMMAND_US          42
38

39
#define LCD_SOFT_RESET_MS1      5
40
#define LCD_SOFT_RESET_MS2      1
41
#define LCD_SOFT_RESET_MS3      1
42
#define LCD_SET_4BITMODE_MS     5
43

44
#define LCD_CLEAR_DISPLAY_MS    2
45
#define LCD_CURSOR_HOME_MS      2
46

47
////////////////////////////////////////////////////////////////////////////////
48
// Zeilendefinitionen des verwendeten LCD
49
// Die Einträge hier sollten für ein LCD mit einer Zeilenlänge von 16 Zeichen passen
50
// Bei anderen Zeilenlängen müssen diese Einträge angepasst werden
51

52
#define LCD_DDADR_LINE1         0x00
53
#define LCD_DDADR_LINE2         0x40
54
#define LCD_DDADR_LINE3         0x10
55
#define LCD_DDADR_LINE4         0x50
56

57
////////////////////////////////////////////////////////////////////////////////
58
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
59
void lcd_init( void );
60

61
////////////////////////////////////////////////////////////////////////////////
62
// LCD löschen
63
void lcd_clear( void );
64

65
////////////////////////////////////////////////////////////////////////////////
66
// Cursor in die 1. Zeile, 0-te Spalte
67
void lcd_home( void );
68

69
////////////////////////////////////////////////////////////////////////////////
70
// Cursor an eine beliebige Position
71
void lcd_setcursor( uint8_t spalte, uint8_t zeile );
72

73
////////////////////////////////////////////////////////////////////////////////
74
// Ausgabe eines einzelnen Zeichens an der aktuellen Cursorposition
75
void lcd_data( uint8_t data );
76

77
////////////////////////////////////////////////////////////////////////////////
78
// Ausgabe eines Strings an der aktuellen Cursorposition
79
void lcd_string( const char *data );
80

81
////////////////////////////////////////////////////////////////////////////////
82
// Definition eines benutzerdefinierten Sonderzeichens.
83
// data muss auf ein Array[8] mit den Zeilencodes des zu definierenden Zeichens
84
// zeigen
85
void lcd_generatechar( uint8_t code, const uint8_t *data );
86

87
////////////////////////////////////////////////////////////////////////////////
88
// Ausgabe eines Kommandos an das LCD.
89
void lcd_command( uint8_t data );
90

91

92
////////////////////////////////////////////////////////////////////////////////
93
// LCD Befehle und Argumente.
94
// Zur Verwendung in lcd_command
95

96
// Clear Display -------------- 0b00000001
97
#define LCD_CLEAR_DISPLAY       0x01
98

99
// Cursor Home ---------------- 0b0000001x
100
#define LCD_CURSOR_HOME         0x02
101

102
// Set Entry Mode ------------- 0b000001xx
103
#define LCD_SET_ENTRY           0x04
104

105
#define LCD_ENTRY_DECREASE      0x00
106
#define LCD_ENTRY_INCREASE      0x02
107
#define LCD_ENTRY_NOSHIFT       0x00
108
#define LCD_ENTRY_SHIFT         0x01
109

110
// Set Display ---------------- 0b00001xxx
111
#define LCD_SET_DISPLAY         0x08
112

113
#define LCD_DISPLAY_OFF         0x00
114
#define LCD_DISPLAY_ON          0x04
115
#define LCD_CURSOR_OFF          0x00
116
#define LCD_CURSOR_ON           0x02
117
#define LCD_BLINKING_OFF        0x00
118
#define LCD_BLINKING_ON         0x01
119

120
// Set Shift ------------------ 0b0001xxxx
121
#define LCD_SET_SHIFT           0x10
122

123
#define LCD_CURSOR_MOVE         0x00
124
#define LCD_DISPLAY_SHIFT       0x08
125
#define LCD_SHIFT_LEFT          0x00
126
#define LCD_SHIFT_RIGHT         0x04
127

128
// Set Function --------------- 0b001xxxxx
129
#define LCD_SET_FUNCTION        0x20
130

131
#define LCD_FUNCTION_4BIT       0x00
132
#define LCD_FUNCTION_8BIT       0x10
133
#define LCD_FUNCTION_1LINE      0x00
134
#define LCD_FUNCTION_2LINE      0x08
135
#define LCD_FUNCTION_5X7        0x00
136
#define LCD_FUNCTION_5X10       0x04
137

138
#define LCD_SOFT_RESET          0x30
139

140
// Set CG RAM Address --------- 0b01xxxxxx  (Character Generator RAM)
141
#define LCD_SET_CGADR           0x40
142

143
#define LCD_GC_CHAR0            0
144
#define LCD_GC_CHAR1            1
145
#define LCD_GC_CHAR2            2
146
#define LCD_GC_CHAR3            3
147
#define LCD_GC_CHAR4            4
148
#define LCD_GC_CHAR5            5
149
#define LCD_GC_CHAR6            6
150
#define LCD_GC_CHAR7            7
151

152
// Set DD RAM Address --------- 0b1xxxxxxx  (Display Data RAM)
153
#define LCD_SET_DDADR           0x80
154

155
#endif

Display.c
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3
#include <util/delay.h>
4

5
////////////////////////////////////////////////////////////////////////////////
6
// Erzeugt einen Enable-Puls
7
static void lcd_enable( void )
8
{
9
  LCD_PORT |= (1<<LCD_EN);     // Enable auf 1 setzen
10
  _delay_us( LCD_ENABLE_US );  // kurze Pause
11
  LCD_PORT &= ~(1<<LCD_EN);    // Enable auf 0 setzen
12
}
13

14
////////////////////////////////////////////////////////////////////////////////
15
// Sendet eine 4-bit Ausgabeoperation an das LCD
16
static void lcd_out( uint8_t data )
17
{
18
  data &= 0xF0;                       // obere 4 Bit maskieren
19
  
20
  LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
21
  LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
22
  lcd_enable();
23
}
24

25
////////////////////////////////////////////////////////////////////////////////
26
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
27
void lcd_init( void )
28
{
29
  // verwendete Pins auf Ausgang schalten
30
  uint8_t pins = (0x0F << LCD_DB) |           // 4 Datenleitungen
31
  (1<<LCD_RS) |                // R/S Leitung
32
  (1<<LCD_EN);                 // Enable Leitung
33
  LCD_DDR |= pins;
34
  
35
  // initial alle Ausgänge auf Null
36
  LCD_PORT &= ~pins;
37
  
38
  // warten auf die Bereitschaft des LCD
39
  _delay_ms( LCD_BOOTUP_MS );
40
  
41
  // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
42
  lcd_out( LCD_SOFT_RESET );
43
  _delay_ms( LCD_SOFT_RESET_MS1 );
44
  
45
  lcd_enable();
46
  _delay_ms( LCD_SOFT_RESET_MS2 );
47
  
48
  lcd_enable();
49
  _delay_ms( LCD_SOFT_RESET_MS3 );
50
  
51
  // 4-bit Modus aktivieren
52
  lcd_out( LCD_SET_FUNCTION |
53
  LCD_FUNCTION_4BIT );
54
  _delay_ms( LCD_SET_4BITMODE_MS );
55
  
56
  // 4-bit Modus / 2 Zeilen / 5x7
57
  lcd_command( LCD_SET_FUNCTION |
58
  LCD_FUNCTION_4BIT |
59
  LCD_FUNCTION_2LINE |
60
  LCD_FUNCTION_5X7 );
61
  
62
  // Display ein / Cursor aus / Blinken aus
63
  lcd_command( LCD_SET_DISPLAY |
64
  LCD_DISPLAY_ON |
65
  LCD_CURSOR_OFF |
66
  LCD_BLINKING_OFF);
67
  
68
  // Cursor inkrement / kein Scrollen
69
  lcd_command( LCD_SET_ENTRY |
70
  LCD_ENTRY_INCREASE |
71
  LCD_ENTRY_NOSHIFT );
72
  
73
  lcd_clear();
74
}
75

76
////////////////////////////////////////////////////////////////////////////////
77
// Sendet ein Datenbyte an das LCD
78
void lcd_data( uint8_t data )
79
{
80
  LCD_PORT |= (1<<LCD_RS);    // RS auf 1 setzen
81
  
82
  lcd_out( data );            // zuerst die oberen,
83
  lcd_out( data<<4 );         // dann die unteren 4 Bit senden
84
  
85
  _delay_us( LCD_WRITEDATA_US );
86
}
87

88
////////////////////////////////////////////////////////////////////////////////
89
// Sendet einen Befehl an das LCD
90
void lcd_command( uint8_t data )
91
{
92
  LCD_PORT &= ~(1<<LCD_RS);    // RS auf 0 setzen
93
  
94
  lcd_out( data );             // zuerst die oberen,
95
  lcd_out( data<<4 );           // dann die unteren 4 Bit senden
96
  
97
  _delay_us( LCD_COMMAND_US );
98
}
99

100
////////////////////////////////////////////////////////////////////////////////
101
// Sendet den Befehl zur Löschung des Displays
102
void lcd_clear( void )
103
{
104
  lcd_command( LCD_CLEAR_DISPLAY );
105
  _delay_ms( LCD_CLEAR_DISPLAY_MS );
106
}
107

108
////////////////////////////////////////////////////////////////////////////////
109
// Sendet den Befehl: Cursor Home
110
void lcd_home( void )
111
{
112
  lcd_command( LCD_CURSOR_HOME );
113
  _delay_ms( LCD_CURSOR_HOME_MS );
114
}
115

116
////////////////////////////////////////////////////////////////////////////////
117
// Setzt den Cursor in Spalte x (0..15) Zeile y (1..4)
118

119
void lcd_setcursor( uint8_t x, uint8_t y )
120
{
121
  uint8_t data;
122
  
123
  switch (y)
124
  {
125
    case 1:    // 1. Zeile
126
    data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
127
    break;
128
    
129
    case 2:    // 2. Zeile
130
    data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
131
    break;
132
    
133
    case 3:    // 3. Zeile
134
    data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
135
    break;
136
    
137
    case 4:    // 4. Zeile
138
    data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
139
    break;
140
    
141
    default:
142
    return;                                   // für den Fall einer falschen Zeile
143
  }
144
  
145
  lcd_command( data );
146
}
147

148
////////////////////////////////////////////////////////////////////////////////
149
// Schreibt einen String auf das LCD
150

151
void lcd_string( const char *data )
152
{
153
  while( *data != '\0' )
154
  lcd_data( *data++ );
155
}
156

157
////////////////////////////////////////////////////////////////////////////////
158
// Schreibt ein Zeichen in den Character Generator RAM
159

160
void lcd_generatechar( uint8_t code, const uint8_t *data )
161
{
162
  // Startposition des Zeichens einstellen
163
  lcd_command( LCD_SET_CGADR | (code<<3) );
164
  
165
  // Bitmuster übertragen
166
  for ( uint8_t i=0; i<8; i++ )
167
  {
168
    lcd_data( data[i] );
169
  }
170
}
171

172

173

174

175

176

177
int main(void)
178
{
179
  // Initialisierung des LCD
180
  // Nach der Initialisierung müssen auf dem LCD vorhandene schwarze Balken
181
  // verschwunden sein
182
  lcd_init();
183
  
184
  // Text in einzelnen Zeichen ausgeben
185
  lcd_data( 'T' );
186
  lcd_data( 'e' );
187
  lcd_data( 's' );
188
  lcd_data( 't' );
189
  
190
  // Die Ausgabemarke in die 2te Zeile setzen
191
  lcd_setcursor( 0, 2 );
192
  
193
  // erneut Text ausgeben, aber diesmal komfortabler als String
194
  lcd_string("Hello World!");
195
  
196
  while(1)
197
  {
198
  }
199
  
200
  return 0;
201
}
#2931493
Lesenswert?

Hallo niko,

noch ein Hinweis, in das TEXTFELD gehört Text und nicht das gesamte 
Programmlisting. Dafür gibt es ja den Dateianhang.

Warum verwendest Du nicht schon erprobte LCD Routinen, P. Fleury oder 
von Peter Danneger (PeDa) ?

[1] http://homepage.hispeed.ch/peterfleury/avr-software.html
[2] 
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=102296
[3] Beitrag "LCD Routine von Peter Danneger für 4x20"

_
OP #2933597
Lesenswert?

Karl Heinz Buchegger schrieb:
> Prüf mal auf Kurzschlüsse.
> Das sieht so aus, als ob 2 Datenleitungen einen Schluss hätten, oder
> vertauscht sind.

Du hast recht!
Ich hab mir mal die Entwicklungsumgebung von unten angesehn und stellt 
fest, dass PD1 und PD2 durch zusammengelötet waren (Die 
Entwicklungsumgebung habe ich mir von einem Lehrer aus meiner Schule 
geborgt, die er selbst entwickelt hat)

Vielen Dank an alle, die versucht haben mein Problem zu lösen!

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