Forum: Mikrocontroller und Digitale Elektronik Displayausgabe


von niko s. (kionage)


Angehängte Dateien:

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

von Mobilist (Gast)


Lesenswert?

niko stern schrieb:
> P1019770.JPG
> 2,3 MB, 22 Downloads

Ist es wirklich so schwierig, Bilder auf das wesentliche zu 
konzentrieren und auf eine dem Inhalt angemessene Größe zu bringen?

von Michael A. (Gast)


Lesenswert?

niko stern schrieb:
> Da ich noch Anfänger im µController programmieren bin verwendete ich
> dieses
> Tutorial:http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Und welchen Mode (4/8-Bit) glaubst du zu benutzen? Deine Zeichen sehen 
so aus, als ob der Controller als Low-Nibble immer 0xF versteht. Was 
hast du ihm denn geschickt?

von Tipp (Gast)


Lesenswert?

Auch wenns dein Problem nicht löst, hab ich noch eine Tipp für dich:
Nimm weniger Lötzinn oben bei der Stiftleiste.

von bla (Gast)


Lesenswert?

Mobilist schrieb:
> Ist es wirklich so schwierig, Bilder auf das wesentliche zu
> konzentrieren und auf eine dem Inhalt angemessene Größe zu bringen?

Ist nicht schwierig. Du bist auf einen Trollversuch hereingefallen!

von tribel (Gast)


Lesenswert?

Mobilist schrieb:

>
> Ist es wirklich so schwierig, Bilder auf das wesentliche zu
> konzentrieren und auf eine dem Inhalt angemessene Größe zu bringen?

Als ob es nix anderes gibt als Bildformate!!!!!

von niko s. (kionage)


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

von Stephan W. (stipo)


Lesenswert?

Etwas Code wäre hilfreicher um Fehler zu erkennen.

von ?? (Gast)


Lesenswert?

Code
Schaltplan
?

von niko s. (kionage)


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
}

von Uwe (de0508)


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"

_

von holger (Gast)


Lesenswert?

Da ist irgendwas falsch angeschlossen.

von holger (Gast)


Lesenswert?

Um welchen Controller geht es eigentlich?
Sind die Fuses auch auf 1MHz eingestellt?

von holger (Gast)


Lesenswert?

>Deine Zeichen sehen
>so aus, als ob der Controller als Low-Nibble immer 0xF versteht.

Was darauf hindeuten könnte das das Display immer noch im 8Bit Modus 
ist.

von niko s. (kionage)


Lesenswert?

holger schrieb:
> Da ist irgendwas falsch angeschlossen.

Ganz sicher?
Also von der Software müsste es passen?

holger schrieb:
> Um welchen Controller geht es eigentlich?
> Sind die Fuses auch auf 1MHz eingestellt?

Um einen ATmega16.
Er war schon auf 1MHz eingestellt und hab ihn dabei belassen und dann 
habe ich, wie gesagt die Headerdatei auf 1MHz angepasst

von holger (Gast)


Angehängte Dateien:

Lesenswert?

>> Da ist irgendwas falsch angeschlossen.
>
>Ganz sicher?

Im Moment nicht mehr. Probier mal meine HEX Datei aus.

von niko s. (kionage)


Lesenswert?

holger schrieb:
> Im Moment nicht mehr. Probier mal meine HEX Datei aus.

Das gleiche Problem, nur etwas anders von der Anordnung der Zeichen.

Also müssen die Anschlüsse falsch sein?
Ich habe aber erneut geprüft, und konnte keinen Fehler festellen.
Habe sogar mit einem Multimeter die Verbindungen auf Durchgang geprüft.

von Karl H. (kbuchegg)


Lesenswert?

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

von niko s. (kionage)


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!

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.