Forum: Mikrocontroller und Digitale Elektronik LCD funktioniert nich


von Philipp K. (flipsie)


Lesenswert?

Hallo,

ich bin neu :)
Stelle mich kurz vor, ich heiße Philipp und habe auch schon einfrage zu 
einem LCD Programm ;-)

Ich habe genau das selbe gemacht wie es in dem Tutorial LCD Ansteuerung 
beschrieben ist.
Wenn ich den Code aber Debug, kommt das hier:
1
Warning  1  #warning "F_CPU not defined for <util/delay.h>"
2
Error  2  undefined reference to `lcd_init()'
3
Error  3  undefined reference to `lcd_data(unsigned char)'  
4
Error  4  undefined reference to `lcd_data(unsigned char)'  
5
Error  5  undefined reference to `lcd_data(unsigned char)'  
6
Error  6  undefined reference to `lcd_data(unsigned char)'    
7
Error  7  undefined reference to `lcd_setcursor(unsigned char, unsigned char)'
8
Error  8  undefined reference to `lcd_string(char const*)'
woran liegt das? :-/

Hier habe ich mal den Quelltext angehangen

Schonmal danke für eure Antworten :)

-----------------------------------------------------------------------

main.cpp
1
#include <stdlib.h>
2
#include <avr/io.h>
3
4
#include "lcd-routines.h"
5
 
6
int main(void)
7
{
8
  lcd_init();
9
10
  lcd_data( 'T' );
11
  lcd_data( 'e' );
12
  lcd_data( 's' );
13
  lcd_data( 't' );
14
 
15
  lcd_setcursor( 0, 2 );
16
 
17
  lcd_string("Hello World!");
18
 
19
  while(1)
20
  {
21
  }
22
 
23
  return 0;
24
}
------------------------------------------------------------------------ 
--
lcd_routines.h
1
#ifndef LCD_ROUTINES_H
2
#define LCD_ROUTINES_H
3
 
4
#ifndef F_CPU
5
#define F_CPU 16000000L
6
#endif
7
 
8
//  LCD DB4-DB7 <-->  PORTD Bit PD0-PD3
9
#define LCD_PORT      PORTD
10
#define LCD_DDR       DDRD
11
#define LCD_DB        PD0
12
 
13
//  LCD RS      <-->  PORTD Bit PD4     (RS: 1=Data, 0=Command)
14
#define LCD_RS        PD4
15
 
16
//  LCD EN      <-->  PORTD Bit PD5     (EN: 1-Impuls für Daten)
17
#define LCD_EN        PD5
18
 
19
 
20
#define LCD_BOOTUP_MS           15
21
#define LCD_ENABLE_US           20
22
#define LCD_WRITEDATA_US        46
23
#define LCD_COMMAND_US          42
24
 
25
#define LCD_SOFT_RESET_MS1      5
26
#define LCD_SOFT_RESET_MS2      1
27
#define LCD_SOFT_RESET_MS3      1
28
#define LCD_SET_4BITMODE_MS     5
29
 
30
#define LCD_CLEAR_DISPLAY_MS    2
31
#define LCD_CURSOR_HOME_MS      2
32
 
33
 
34
#define LCD_DDADR_LINE1         0x00
35
#define LCD_DDADR_LINE2         0x40
36
#define LCD_DDADR_LINE3         0x10
37
#define LCD_DDADR_LINE4         0x50
38
 
39
40
void lcd_init( void );
41
42
void lcd_clear( void );
43
44
void lcd_home( void );
45
46
void lcd_setcursor( uint8_t spalte, uint8_t zeile );
47
 
48
void lcd_data( uint8_t data );
49
50
void lcd_string( const char *data );
51
 
52
void lcd_generatechar( uint8_t code, const uint8_t *data );
53
 
54
void lcd_command( uint8_t data );
55
56
#define LCD_CLEAR_DISPLAY       0x01
57
 
58
#define LCD_CURSOR_HOME         0x02
59
60
#define LCD_SET_ENTRY           0x04
61
 
62
#define LCD_ENTRY_DECREASE      0x00
63
#define LCD_ENTRY_INCREASE      0x02
64
#define LCD_ENTRY_NOSHIFT       0x00
65
#define LCD_ENTRY_SHIFT         0x01
66
67
#define LCD_SET_DISPLAY         0x08
68
 
69
#define LCD_DISPLAY_OFF         0x00
70
#define LCD_DISPLAY_ON          0x04
71
#define LCD_CURSOR_OFF          0x00
72
#define LCD_CURSOR_ON           0x02
73
#define LCD_BLINKING_OFF        0x00
74
#define LCD_BLINKING_ON         0x01
75
 
76
#define LCD_SET_SHIFT           0x10
77
 
78
#define LCD_CURSOR_MOVE         0x00
79
#define LCD_DISPLAY_SHIFT       0x08
80
#define LCD_SHIFT_LEFT          0x00
81
#define LCD_SHIFT_RIGHT         0x04
82
83
#define LCD_SET_FUNCTION        0x20
84
 
85
#define LCD_FUNCTION_4BIT       0x00
86
#define LCD_FUNCTION_8BIT       0x10
87
#define LCD_FUNCTION_1LINE      0x00
88
#define LCD_FUNCTION_2LINE      0x08
89
#define LCD_FUNCTION_5X7        0x00
90
#define LCD_FUNCTION_5X10       0x04
91
 
92
#define LCD_SOFT_RESET          0x30
93
94
#define LCD_SET_CGADR           0x40
95
 
96
#define LCD_GC_CHAR0            0
97
#define LCD_GC_CHAR1            1
98
#define LCD_GC_CHAR2            2
99
#define LCD_GC_CHAR3            3
100
#define LCD_GC_CHAR4            4
101
#define LCD_GC_CHAR5            5
102
#define LCD_GC_CHAR6            6
103
#define LCD_GC_CHAR7            7
104
105
#define LCD_SET_DDADR           0x80
106
 
107
#endif
-------------------------------------------------------------------
lcd_routines.c
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include "lcd-routines.h"
4
5
static void lcd_enable( void )
6
{
7
    LCD_PORT |= (1<<LCD_EN);     // Enable auf 1 setzen
8
    _delay_us( LCD_ENABLE_US );  // kurze Pause
9
    LCD_PORT &= ~(1<<LCD_EN);    // Enable auf 0 setzen
10
}
11
 
12
static void lcd_out( uint8_t data )
13
{
14
    data &= 0xF0;                       // obere 4 Bit maskieren
15
 
16
    LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
17
    LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
18
    lcd_enable();
19
}
20
 
21
void lcd_init( void )
22
{
23
    // verwendete Pins auf Ausgang schalten
24
    uint8_t pins = (0x0F << LCD_DB) |           // 4 Datenleitungen
25
                   (1<<LCD_RS) |                // R/S Leitung
26
                   (1<<LCD_EN);                 // Enable Leitung
27
    LCD_DDR |= pins;
28
 
29
    LCD_PORT &= ~pins;
30
 
31
    _delay_ms( LCD_BOOTUP_MS );
32
 
33
    lcd_out( LCD_SOFT_RESET );
34
    _delay_ms( LCD_SOFT_RESET_MS1 );
35
 
36
    lcd_enable();
37
    _delay_ms( LCD_SOFT_RESET_MS2 );
38
 
39
    lcd_enable();
40
    _delay_ms( LCD_SOFT_RESET_MS3 );
41
 
42
    // 4-bit Modus aktivieren 
43
    lcd_out( LCD_SET_FUNCTION |
44
             LCD_FUNCTION_4BIT );
45
    _delay_ms( LCD_SET_4BITMODE_MS );
46
 
47
    // 4-bit Modus / 2 Zeilen / 5x7
48
    lcd_command( LCD_SET_FUNCTION |
49
                 LCD_FUNCTION_4BIT |
50
                 LCD_FUNCTION_2LINE |
51
                 LCD_FUNCTION_5X7 );
52
 
53
    // Display ein / Cursor aus / Blinken aus
54
    lcd_command( LCD_SET_DISPLAY |
55
                 LCD_DISPLAY_ON |
56
                 LCD_CURSOR_OFF |
57
                 LCD_BLINKING_OFF); 
58
 
59
    // Cursor inkrement / kein Scrollen
60
    lcd_command( LCD_SET_ENTRY |
61
                 LCD_ENTRY_INCREASE |
62
                 LCD_ENTRY_NOSHIFT );
63
 
64
    lcd_clear();
65
}
66
67
void lcd_data( uint8_t data )
68
{
69
    LCD_PORT |= (1<<LCD_RS);    // RS auf 1 setzen
70
 
71
    lcd_out( data );            // zuerst die oberen, 
72
    lcd_out( data<<4 );         // dann die unteren 4 Bit senden
73
 
74
    _delay_us( LCD_WRITEDATA_US );
75
}
76
77
void lcd_command( uint8_t data )
78
{
79
    LCD_PORT &= ~(1<<LCD_RS);    // RS auf 0 setzen
80
 
81
    lcd_out( data );             // zuerst die oberen, 
82
    lcd_out( data<<4 );           // dann die unteren 4 Bit senden
83
 
84
    _delay_us( LCD_COMMAND_US );
85
}
86
 
87
void lcd_clear( void )
88
{
89
    lcd_command( LCD_CLEAR_DISPLAY );
90
    _delay_ms( LCD_CLEAR_DISPLAY_MS );
91
}
92
 
93
void lcd_home( void )
94
{
95
    lcd_command( LCD_CURSOR_HOME );
96
    _delay_ms( LCD_CURSOR_HOME_MS );
97
}
98
 
99
void lcd_setcursor( uint8_t x, uint8_t y )
100
{
101
    uint8_t data;
102
 
103
    switch (y)
104
    {
105
        case 1:    // 1. Zeile
106
            data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
107
            break;
108
 
109
        case 2:    // 2. Zeile
110
            data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
111
            break;
112
 
113
        case 3:    // 3. Zeile
114
            data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
115
            break;
116
 
117
        case 4:    // 4. Zeile
118
            data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
119
            break;
120
 
121
        default:
122
            return;                                   // für den Fall einer falschen Zeile
123
    }
124
 
125
    lcd_command( data );
126
}
127
 
128
void lcd_string( const char *data )
129
{
130
    while( *data != '\0' )
131
        lcd_data( *data++ );
132
}
133
 
134
void lcd_generatechar( uint8_t code, const uint8_t *data )
135
{
136
    // Startposition des Zeichens einstellen
137
    lcd_command( LCD_SET_CGADR | (code<<3) );
138
 
139
    // Bitmuster übertragen
140
    for ( uint8_t i=0; i<8; i++ )
141
    {
142
        lcd_data( data[i] );
143
    }
144
}/*

von Max H. (hartl192)


Lesenswert?

> Forum: Projekte & Code
> Hier könnt ihr eure Projekte, Schaltungen oder Codeschnipsel
> vorstellen und diskutieren. Bitte hier keine Fragen posten!
Fällt dir was auf?


Hast du die LCD.h auch in Projektordner?
Definiere F_CPU. Wenn du z.B. einen 16MHz Quarz hast:
1
#define F_CPU 16000000

von Philipp K. (flipsie)


Lesenswert?

Danke für die schnelle Antwort.
Ich habe die lcd_routines.h in meinem Projektordner.

Ich habe einen Atmega328, also 16MHz?

LG

von Max H. (hartl192)


Lesenswert?

Philipp K. schrieb:
> Ich habe einen Atmega328, also 16MHz?
Das hängt von den Fuses ab. Genaueres kann ich dir nicht sagen, da ich 
bis jetzt nur PIC programmiert habe.

von Philipp K. (flipsie)


Lesenswert?

ich habe die Fehler jetzt weg bekommen. Aber mein Display zeigt mir 
immer noch nix an :(

von Dominic S. (Firma: Privat) (dominics)


Lesenswert?

Was zeigt es denn an? Schwarze Balken oder gar nichts?

Es ist möglich das du es falsch angeschlossen hast. Es ist wichtig das 
die Kontrastspannung stimmt, zudem solltest du am LCD die Datenleitungen 
an 4-7 (je nach zähl weise 5-8) anschließen.

Die Frage ist vielleicht dumm, aber hast du den Code wirklich als 3 
Dateien?

Du solltest auch die Fuses nochmal ansehen. Versuch es doch fürs erste 
mal mit dem internen 8MHz Quarz (den sollte jeder AVR haben).

- Fals es gar nichts zeigt liegt der Fehler im Anschluss.

- Wenn es schwarze Balken bringt, liegt es eher beim AVR.

von Max H. (hartl192)


Lesenswert?

Dominic Styblo schrieb:
> internen 8MHz Quarz (den sollte jeder AVR haben).
Nein, den hat keiner. Aber viele AVR haben einen internen 8MHz 
RC-Oszillator.

von Philipp K. (flipsie)


Lesenswert?

Anzeigen tut es nix.
Wenn ich den Kontrast einstelle, werden alle Schwarzen Balken entweder 
dunkel oder hell mehr leider nich.

Beim Anschließen habe ich D4-D7 (vom Display) an PD0-PD3 (meine Adrduino 
UNO Boards) Angeschlossen.
"RS" (vom Display) liegt an PD4 (des Adrduino).
"E" (vom Display) geht an PD5 (des Arduino).
VSS - Masse
VDD - 5V
VEE - Poti
R/W - Masse


Habe alles in einer Datei gehabt und dann habe ich es mal aufegteilt.

von Max H. (hartl192)


Lesenswert?

Versuch mal so lange an Kontrast zu drehen, bist die erste Zeile schwarz 
wird. Das Display darfst du vorher nicht initialisieren.

von Philipp K. (flipsie)


Lesenswert?

Sorry für die späte Antwort.
Wenn ich am Poti drehe seh ich die änderung der Balken aber nix von dem 
programm :-(
Aber richtig angeschlossen habe ich ich es ja...
Oder muss ich im code noch was ändern?
Kann mir vielleicht jemand schritt für schritt erklären wie ihr es macht 
mit code und anschließen, vielleicht finde ich dann den fehler :-(

von dummy (Gast)


Lesenswert?

>Aber richtig angeschlossen habe ich ich es ja...

Das haben hier schon einige behautptet.
Und dann war doch noch irgendwo ein Dreher oder
Kurzschluss drin.

von Christian (Gast)


Lesenswert?

Zeig am besten mal deinen Schaltplan und besser noch ein Bild von deinem 
Aufbau.

von Philipp K. (flipsie)


Angehängte Dateien:

Lesenswert?

Hier habe ich mal 2 Bilder von meinem Aufbau.
Hoffe ihr könnte es einigermaßen erkennen :)

von Teo D. (teoderix)


Lesenswert?

Sag mal, Du hast doch nich wirklich die Kabel nur is Display 
gesteckt ?

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

wird denn dein Arduino auch mit Spannung versorgt?

von Philipp K. (flipsie)


Lesenswert?

Keine angst, die kabel sind auf der rückseite alle angelötet ;-)

Naja nur die spannung die er aus dem usb port herausgibt

von leluno (Gast)


Lesenswert?

langes Delay in code einbauen und mit einem Messgerät prüfen, ob die 
einzelnen Programmbefehle wirklich am lcd ankommen.

von Mike (Gast)


Lesenswert?

Philipp K. schrieb:
> Hier habe ich mal den Quelltext angehangen

Und warum nicht als Dateianhang?
Und bei Originalbiliotheken reicht ein Link. Und falls deine 
Bibliotheken nicht im (bewährten) Originalzustand sind, solltest du 
genau angeben, was du geändert hast.

Wie sieht es mit einem Arduino Beispiele zum LCD, z.B. 
LiquidCrystal/HelloWord.c aus? Läuft das?

von Philipp K. (flipsie)


Lesenswert?

Wenn ich es in arduino programmiere mit LiquidCristal funktioniert ea da 
habe ich keine probleme.
Ich schicke nachher mal das programm als anhang hier rein, war mir 
anfangs nicht bewusst ;-)

von Philipp K. (flipsie)


Angehängte Dateien:

Lesenswert?

So habe im Anhang mal das Programm drin.
Hoffe hier könnt dort was herausfinden ;-)

von Karl H. (kbuchegg)


Lesenswert?

Auf deinem Bild beginnt die Riege der benutzten Ausgangspins mit PD0 (am 
Port D)

Hier jedoch
1
#define LCD_PORT      PORTD
2
#define LCD_DDR       DDRD
3
#define LCD_DB        PD2
4
 
5
//  LCD RS      <-->  PORTD Bit PD4     (RS: 1=Data, 0=Command)
6
#define LCD_RS        PD6
7
 
8
//  LCD EN      <-->  PORTD Bit PD5     (EN: 1-Impuls für Daten)
9
#define LCD_EN        PD7
ist von PD0 nichts zu sehen.


Ich hab die Pinbelegung der Arduino Klemmen nicht rausgesucht. Aber 
irgendeine der beiden Angaben, Bild oder Code, muss falsch sein.

von Philipp K. (flipsie)


Lesenswert?

Sorry das war die andere teat datei. Da hatte ich es mal an anderen 
ports ausprobiert.
Anfangs habe ich mit PD0 angefangen, wo es auch nich ging.

Eine idee woran das problem liegen kann?

von Stephan (Gast)


Lesenswert?

4 Bit Modus und 8 Leitungen ?

von Cyblord -. (cyblord)


Lesenswert?

Philipp K. schrieb:

> Eine idee woran das problem liegen kann?

Ich hab da ne Idee. Aber ich soll nich mehr zu Arduino Themen schreiben, 
und schon gar nicht meine Meinung. grmpf

von Philipp K. (flipsie)


Lesenswert?

8 Leitungen?
Habe doch nur 4Datenleitungen die anderen 4 sind frei.

@ cyblord: wieso das?

von Hubert G. (hubertg)


Lesenswert?

Auf PD0 und PD1 liegen RX und TX, bin mir nicht sicher ob der 16U2 das 
ganz wegschaltet.
Also besser erst bei PD2 beginnen.
Außerdem mal kurz getestet, auf PD2 begonnen, funktioniert einwandfrei.
Du musst da einen HW-Fehler haben.

von Hubert G. (hubertg)


Angehängte Dateien:

Lesenswert?

Funktioniert von PD0 beginnend auch.
Hab mal die *.hex angehängt. Vielleicht hakt es beim Compilieren.

von Philipp K. (flipsie)


Lesenswert?

Wenn ich die datei mit avr öffne oder mit was anderen bekomme ich da nur 
ein haufen zahlen :-/
Kannst du mir das vielleicht nochmal als txt schicken? :-)

von Cyblord -. (cyblord)


Lesenswert?

Philipp K. schrieb:
> Wenn ich die datei mit avr öffne oder mit was anderen bekomme ich da nur
> ein haufen zahlen :-/
> Kannst du mir das vielleicht nochmal als txt schicken? :-)

Das ist ja auch ne hex datei, also das compilierte programm. das muss 
binär sein. Das kannst du direkt flashen. Das ist nicht zum angucken.

von Philipp K. (flipsie)


Lesenswert?

ahhh sorry mein fehler ^^ ich war gerade irgendwie bei ner header datei 
;)
ES FUNKTIONIERT!!!!!!!!
Wie und was hast du gemacht :)

von Hubert G. (hubertg)


Lesenswert?

Ich habe deine Dateien mit dem AVR-Studio 4.19 kompiliert.
Womit hast du es gemacht?

von Philipp K. (flipsie)


Lesenswert?

ich mache das mit dem AVR Studio 5.1

von Hubert G. (hubertg)


Lesenswert?

Entweder lädst du eine falsche Datei oder du hast was falsch 
eingestellt.
Was es genau ist kann ich dir nicht sagen.

von Philipp K. (flipsie)


Angehängte Dateien:

Lesenswert?

du hast genau die dateien die ich da oben eingestellt habe bei dir rein 
kopiert. einmal als main datei, dann eine als lcd.h und eine als lcd.c?
genauso wie die dort oben sind?

Habe mal ein paar bilder gemacht wie ich es erstellt habe.
das müsste ja auch richtig sein
#define F_CPU 16000000UL
(habe ein Arduino UNO)

von Philipp K. (flipsie)


Angehängte Dateien:

Lesenswert?

du hast genau die dateien die ich da oben eingestellt habe bei dir rein 
kopiert. einmal als main datei, dann eine als lcd.h und eine als lcd.c?
genauso wie die dort oben sind?

Habe mal ein paar bilder gemacht wie ich es erstellt habe.
das müsste ja auch richtig sein
#define F_CPU 16000000UL
(habe ein Arduino UNO)

von Hubert G. (hubertg)


Lesenswert?

Ich habe genau deine Dateien genommen und kompiliert.
Mit einem Arduino UNO und einem LCD mit HD44780 Controller getestet.

von Philipp K. (flipsie)


Lesenswert?

bin ich doch so bescheuert O.o   ...
und was hast du bei dem "Uploader" eingegeben 115200?

von Hubert G. (hubertg)


Lesenswert?

Ja, 115200, du musst doch am UNO die Leds flimmern sehen beim Laden.

von Philipp K. (flipsie)


Lesenswert?

genau die das ist bei mir auch so.
Wenn ich die 1600000UL zu 1600000 oder zu 1600000L oder so ändere bringt 
er mir irgendwelche zahlen und buchstaben aber bei 1600000UL nix.

Habe mal Bilder gemacht wo ich genau zeige wie ich das mache, also bei 
Bild "neu" erstelle ich das Projekt mit dem was gelb markiert ist, dnach 
das Bild "neu1" da suche ich den Atmega aus und nehme den der markiert 
ist, danach kopiere ich alle 3 Datei also die Main.c, lcd.c und die 
lcd.h in das Projekt rein. danach speicher ich alles und drücke auf 
Build Projekt.
Dann gehe ich in das upload Programm und suche den Ordner wo es drin ist 
nach der erstellten HEX datei, geben dann unten 115200 ein und mache 
upload...
das müsste doch alles eigentlich genauso sein oder?

von Philipp K. (flipsie)


Angehängte Dateien:

Lesenswert?

hab die Bilder ganz vergessen ;)

von Mr. A. (Gast)


Lesenswert?

Philipp K. schrieb:
> Kannst du mir das vielleicht nochmal als txt schicken? :-)

Das ist eine Textdatei.
Jede Zeile beginnt mit Doppelpunkt. Dann folgen die Längenangabe, die 
Speicheradresse, die Daten und eine Prüfsumme.

von Hubert G. (hubertg)


Lesenswert?

Ich habe mit dem AVR-Studio5 oder AVR-Studio6 noch nicht gearbeitet, 
kann dir daher nicht helfen.
Der Fehler liegt aber sicher in einer falschen Einstellung oder du lädst 
konsequent eine falsche *.hex.

Ein Tipp noch, gibt deinen Projekten einen aussagekräftigen Namen. In 
zwei Monaten weisst du nicht mehr was du unter AVRGCC2 gemacht hast.

von Philipp K. (flipsie)


Lesenswert?

jetzt funktioniert es mit meinem auch  ;)
Danke für eure Hilfe :)

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.