Hallo!
Vielleicht könnt ihr mir weiterhelfen.
Ich benutze das Programmierboard STK500, MC-Typ AtMega8535,Software AVR
Studio 4 und WinAVR.
Ich möchte habe mir ein LCD von Reichelt gekauft mit 4x16
Zeichen; KS0070B Controller. Als Heaader-Datei nutze ich die von Peter
Fleury, die ich im Anhang eingefügt und schon auf mein LCD abgeändert
habe.
Mein Programm sieht so aus:
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <util/delay.h>
#include "lcd.h"
int main(void)
{
lcd_init(LCD_DISP_ON_CURSOR);
lcd_clrscr(); lcd_puts("Hallo");
}
Beim Compilieren kommen zwei Warnungen:
C:/Programme/WinAVR/avr/include/util/delay.h:136:3: warning: #warning
"F_CPU not defined for <util/delay.h>"
../lcd_chris.c: In function `main':
../lcd_chris.c:17: warning: control reaches end of non-void function
Build succeeded with 2 Warnings...
Wenn ich auf BUILD gehe dann kommen drei Fehlermeldungen:
lcd_chris.o: In function `main':
../lcd_chris.c:14: undefined reference to `lcd_init'
../lcd_chris.c:15: undefined reference to `lcd_clrscr'
../lcd_chris.c:16: undefined reference to `lcd_puts'
make: *** [lcd_chris.elf] Error 1
Build failed with 3 errors and 0 warnings...
Kann mir jemand weiterhelfen? Was habe ich falsch gemacht?
Die Datei lcd.h habe ich auf der linken Seite bei AVR-Studio als
Header-Datei im Projektbaum mit drin.
Christoph G. wrote:
> C:/Programme/WinAVR/avr/include/util/delay.h:136:3: warning: #warning> "F_CPU not defined for <util/delay.h>"
Vor dem #include<util/delay.h> muss F_CPU definiert sein. Entweder mit
einem Makro oder (besser) im AVRStudio in den Configuration Options die
Taktfrequenz einstellen.
> ../lcd_chris.c: In function `main':> ../lcd_chris.c:17: warning: control reaches end of non-void function> Build succeeded with 2 Warnings...
Du hast keine Endlosschleife am Ende von main().
> lcd_chris.o: In function `main':> ../lcd_chris.c:14: undefined reference to `lcd_init'> ../lcd_chris.c:15: undefined reference to `lcd_clrscr'> ../lcd_chris.c:16: undefined reference to `lcd_puts'> make: *** [lcd_chris.elf] Error 1> Build failed with 3 errors and 0 warnings...
Das heißt, dass der Linker die genannten Funktionen nicht findet,
vermutlich, weil Du die lcd.c nicht zum Projekt hinzugefügt hast. Die
muss aber auch compiliert werden, die lcd.h allein reicht nicht! Also in
den Projekteinstellungen die Datei hinzufügen.
> Kann mir jemand weiterhelfen? Was habe ich falsch gemacht?> Die Datei lcd.h habe ich auf der linken Seite bei AVR-Studio als> Header-Datei im Projektbaum mit drin.
Aber offensichtlich nicht die lcd.c...
Von vorne:
>C:/Programme/WinAVR/avr/include/util/delay.h:136:3: warning: #warning>"F_CPU not defined for <util/delay.h>"
delay.h braucht das F_CPU-define, sonst stimmen alle Zeiten nicht.
Solltest du unter Projekt/Configuration options im Feld "Frequency"
eintragen.
>../lcd_chris.c:17: warning: control reaches end of non-void function
Da fehlt ein return mit Wert.
>../lcd_chris.c:14: undefined reference to `lcd_init'>../lcd_chris.c:15: undefined reference to `lcd_clrscr'>../lcd_chris.c:16: undefined reference to `lcd_puts'
Du musst nicht nur die .h-Dateien links eintragen (das ginge auch ohne),
sondern vor allem im Ordner "Source files" die .c-Dateien. Die fehlen
zur Zeit, und da meckert der Linker.
Oliver
Hallo!
Danke für die schnelle Antwort. Die Warnungen und die Fehlermeldungen
habe ich wegbekommen, doch jetzt ist ein neuer Fehler aufgetaucht:
gcc plug-in: Error: Object file not found on expected location
M:\Mikrocontroller\lcd_chris\default\lcd_chris.elf
Was muss ich jetzt machen. Muss ich an der lcd.c, die ich im
Source-Files hinzugefügt habe noch was ändern, denn in lcd.h musste ich
was ändern?
> gcc plug-in: Error: Object file not found on expected locationhttp://www.mikrocontroller.net/articles/WinAVR#gcc_plug-in:_Error:_Object_file_not_found_on_expected_location
Alle Einstellarbeiten sollten nur in lcd.h gemacht werden und in lcd.c
sollte nichts zu ändern sein.
Du könntest ein Build Clean und dann ein Rebuild All versuchen. Dabei
auf Meldungen in den Fenstern Build und Messages achten unf ggf. hier
für weitere Hilfe posten.
Wenn alles nichts hilft, kannst du dein Projekt mal komplett in ein ZIP
archivieren und hier anhängen.
Ich habe jetzt mal den Quelltext con lcd.c als neues Projekt eingefügt
und dann ist dieser Fehler aufgetreten. Kann es mit dem anderen Fehler
zusammenhängen? Wie beseitige ich den Fehler?
In Anhang habe ich mal mein komplettes Projekt als zip bereitgestellt.
C:/Programme/Christoph/WinAVR/bin/../lib/gcc/avr/3.4.6/../../../../avr/l
ib/avr4/crtm8535.o: In function `__vectors':
../../../../../avr-libc-1.4.4/crt1/gcrt1.S:51: undefined reference to
`main'
make: *** [lcd_test.elf] Error 1
Build failed with 1 errors and 0 warnings...
1/ Ich weiss nicht, ob es hier eine Rolle spielt, aber ich bin darauf
gestossen, weil ich dein Projekt anpassen muss, damit es bei mir läuft
(dämliche absolute Pfade in AVR Studio. Ich habe kein M:...):
Dein Projektpfad ist
d:/winavr/bin/../avr/include/util/delay.h:90:3: warning: #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed" (##1##)
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:356: multiple definition of `lcd_command' (##2##)
9
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:356: first defined here
10
lcd.o: In function `lcd_data':
11
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:368: multiple definition of `lcd_data'
12
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:368: first defined here
13
lcd.o: In function `lcd_gotoxy':
14
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:382: multiple definition of `lcd_gotoxy'
15
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:382: first defined here
16
lcd.o: In function `lcd_getxy':
17
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:409: multiple definition of `lcd_getxy'
18
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:409: first defined here
19
lcd.o: In function `lcd_clrscr':
20
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:418: multiple definition of `lcd_clrscr'
21
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:418: first defined here
22
lcd.o: In function `lcd_home':
23
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:427: multiple definition of `lcd_home'
24
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:427: first defined here
25
lcd.o: In function `lcd_putc':
26
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:438: multiple definition of `lcd_putc'
27
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:438: first defined here
28
lcd.o: In function `lcd_puts':
29
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:486: multiple definition of `lcd_puts'
30
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:486: first defined here
31
lcd.o: In function `lcd_puts_p':
32
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:503: multiple definition of `lcd_puts_p'
33
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:503: first defined here
34
lcd.o: In function `lcd_init':
35
E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:522: multiple definition of `lcd_init'
36
lcd_chris.o:E:\Elektronik\sb_avr\lcd_chris\default/../lcd.c:522: first defined here
37
make: *** [lcd_chris.elf] Error 1
3/ Fehlerkorrektur
##1##: Optimierung unter Project Configuration Options einschalten (z.B.
-Os statt -O0)
##2##: Die Zeile #include "lcd.c" in lcd_chris.c ist zuviel. Das
Einbinden von lcd.c wird automatisch gemacht, wenn lcd.c unter den
Source Files aufgelistet ist.
4/ Zweiter Kompilierversuch
Danke für die schnelle Antwort.
Ich habe es jetzt auch hinbekommen!
Jetzt habe ich ein anderes Problem und zwar habe ich das LCD so
verdrahtet, wie es im Tutorial steht. Es hängt PORTD. Jetzt zeigt es mir
die 2. und 4. Zeile nur schwarze Balken an, wenn ich es einschalte. Das
ist doch nicht korrekt oder? Liegt es vielleicht daran, das RW an GND
hängt. Im Forum habe ich gelesen, dass es bei der Fleury Lib auf E mit
drauf sein soll. Was ist jetzt richtig? Muss ich in der Fleury Lib lcd.h
noch was anderes ändern?
Wenn nur Zeile 1 und 3 initialisiert sind, ist das ein Zeichen, dass das
LCD im Einzeilen-Modus läuft. Intern sind Zeile 1+3 und Zeile 2+4
zusammengeschaltet. Die Zweizeilen-Initialisierung ist also nicht
korrekt oder nicht erfolgreich.
Hast du eine Kopie oder einen Link zu einem Datenblatt des KS0070B
Controller? Kontrolliere ob diese Zeilen aus lcd.h zu deinem LCD
Controller passen:
#define LCD_LINE_LENGTH 0x40 /**< internal line length of the
display */
#define LCD_START_LINE1 0x00 /**< DDRAM address of first char of
line 1 */
#define LCD_START_LINE2 0x40 /**< DDRAM address of first char of
line 2 */
#define LCD_START_LINE3 0x10 /**< DDRAM address of first char of
line 3 */
#define LCD_START_LINE4 0x50 /**< DDRAM address of first char of
line 4 */
Im Moment initialisierst du für einen KS0073 Controller.
#define LCD_CONTROLLER_KS0073 1 /**< Use 0 for HD44780 controller, 1
for KS0073 controller */
Ohne Controller Datenblatt und genauere Analyse, könntest du probieren,
mal als Standard HD44780 Controller zu initialisieren.
#define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1
for KS0073 controller */
Christoph G. wrote:
> Liegt es vielleicht daran, das RW an GND> hängt.
Das ist ein Problem. Die Fleury-Lib erwartet, dass RW gesteuert werden
kann, um gelegentlich DB7 auszulesen, ob das LCD beschäftigt ist (BUSY)
oder neue Befehle entgegennehmen kann. Steht auch so im LCD Abschnitt
vom AVR GCC Tutorial.
> Im Forum habe ich gelesen, dass es bei der Fleury Lib auf E mit> drauf sein soll.
Verstehe ich inhaltlich nicht.
So habe ich das LCD verdrahtet:
Pin #-LCD Bezeichnung-LCD Pin-μC
1 Vss GND
2 Vcc 5V
3 Vee GND
4 RS PD4 am AVR
5 RW GND
6 E PD5 am AVR
7 DB0 offen
8 DB1 offen
9 DB2 offen
10 DB3 offen
11 DB4 PD0 am AVR
12 DB5 PD1 am AVR
13 DB6 PD2 am AVR
14 DB7 PD3 am AVR
Habe alle Veränderungen, außer die Umverdrahtung von RW auf DB7,
durchgeführt doch das LCD bleibt unverändert.
Muss ich denn hier auch noch was ändern?
#define LCD_PORT PORTD /**< port for the LCD lines */
#define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN 0 /**< pin for 4bit data bit 0 */
#define LCD_DATA1_PIN 1 /**< pin for 4bit data bit 1 */
#define LCD_DATA2_PIN 2 /**< pin for 4bit data bit 2 */
#define LCD_DATA3_PIN 3 /**< pin for 4bit data bit 3 */
#define LCD_RS_PORT LCD_PORT /**< port for RS line */
#define LCD_RS_PIN 4 /**< pin for RS line */
#define LCD_RW_PORT LCD_PORT /**< port for RW line */
#define LCD_RW_PIN 5 /**< pin for RW line */
#define LCD_E_PORT LCD_PORT /**< port for Enable line */
#define LCD_E_PIN 6 /**< pin for Enable line */
Christoph G. wrote:
> Habe alle Veränderungen, außer die Umverdrahtung von RW auf DB7,> durchgeführt doch das LCD bleibt unverändert.
Dann besteht das Problem weiterhin.
Das RW-Signal zwischen µC und LCD wird auch nicht auf DB7 umverdrahtet,
sondern erhält einen eigenen IO-Pin am AVR. In der allerersten lcd.h
oben ist eingetragen, dass die RW Leitung Pin 5 an Port B belegt. Bei
dir ist RW mit GND verbunden.
Diese LCD-Library von Fleury braucht eben eine RW Leitung, die man
zwischen HIGH/Lesen (Abfrage seitens µC über DB7 ob LCD Busy) und
LOW/Schreiben (Daten auf DB4-Db7 fürs LCD) umschalten kann.
Den Lesen-Fall mit RW HIGH schliesst du aus, weil die RW konstant auf
LOW (GND) gelegt hast. somit funktioniert die Library nicht. Ändere das
in der Hardware oder suche dir eine andere LCD Library, die RW nicht
benötigt, z.B. den lcd-routines.c/lcd-routines.h Code aus dem
AVR-GCC-Tutorial.
Danke!
In lcd.h gibt es diesen unten aufgeführten Abschnitt. Da definiere ich
PORTD als LCD-PORT. Muss ich denn bei den anderen auch aus LCD_PORT
PORTD machen?
#define LCD_PORT PORTD /**< port for the LCD lines */
#define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN 0 /**< pin for 4bit data bit 0 */
#define LCD_DATA1_PIN 1 /**< pin for 4bit data bit 1 */
#define LCD_DATA2_PIN 2 /**< pin for 4bit data bit 2 */
#define LCD_DATA3_PIN 3 /**< pin for 4bit data bit 3 */
#define LCD_RS_PORT LCD_PORT /**< port for RS line */
#define LCD_RS_PIN 4 /**< pin for RS line */
#define LCD_RW_PORT LCD_PORT /**< port for RW line */
#define LCD_RW_PIN 5 /**< pin for RW line */
#define LCD_E_PORT LCD_PORT /**< port for Enable line */
#define LCD_E_PIN 6 /**< pin for Enable line */
Nein, das ist nicht nötig (schadet aber auch nicht)
#define LCD_PORT PORTD /**< port for the LCD lines */
bewirkt, dass bei folgendem Auftreten von LCD_PORT LCD_PORT durch PORTD
ersetzt wird.
#define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */
bewirkt, dass beim folgenden Auftreten von LCD_DATA0_PORT LCD_DATA0_PORT
durch LCD_PORT ersetzt wird, welches aber durch das vorangegangene
Define bereits durch PORTD ersetzt wird...
Danke für die schnelle Antwort. Ich werde das heute abend ausproberen.
Hast du dir schon mal das Datenblatt meines LCD´s angeschaut?
Peter Fleury nutzt KS7003 und mein LCD KS700B. Macht das einen
Unterschied?
> Peter Fleury nutzt KS7003 und mein LCD KS700B. Macht das einen
KS0073 oder KS0070 heissen die ;-)
Das KS0073 ist bekannt dafür, dass es eine Sonderbehandlung braucht. Das
ist auch gut in lcd.c zu sehen.
Um dein Datenblatt habe ich micht nicht weiter gekümmert, solange du die
Verdrahtung der RW-Leitung nicht geändert hast, weil ohne besteht keine
Chance diese Library zu benutzen. Hast du jetzt RW anders beschaltet?
Die Zeilenanfangsadressen, die ich oben schon mal abgefragt habe,
stimmen laut Datenblatt.
Im Datenblatt ist aber die Initialisierung des 4-bit-Interface Modus
nicht erklärt. Man müsste nochmal extra das Datenblatt vom KS0070B
suchen
(http://www.pacificdisplay.com/ics_app%20notes/samsung/KS0070B_V0.pdf)
und nachsehen, ob der KS0070B ähnlicher zu dem HD44780
(http://www.pacificdisplay.com/ics_app%20notes/hitachi/HD44780.pdf) ist
oder zu dem KS0073
(http://www.pacificdisplay.com/ics_app%20notes/samsung/KS0073.pdf) ist
und dann entsprechend lcd.h anpassen. Oder ausprobieren ;-)
1/ Bist du sicher, dass du die Änderungen zu PORTD in deinem lcd.h drin
hast? In dem Projektarchiv letztens war alles noch auf PORTB gestellt.
Hier in der Diskussion habe ich PORTD gesehen, aber dafür war dort die
RW Leitung nicht korrekt definiert.
2/ Bist du sicher, dass dein Atmega8535 mit 8MHz läuft, so dass es zur
XTAL Einstellung in lcd.h und zur 8000000 Hz Einstellung in AVR Studio
Projekt Copfiguration Options passt? Ab Werk macht der das nicht. Du
müsstest die AVR Fuses umgestellt haben, damit das funktioniert und
eventuell das STK500 so eingestellt haben, dass ein externer 8 MHz Quarz
den AVR antreibt. Näheres in den STK500 Unterlagen.
3/ Hast du beide Varianten ausprobiert? Also die Variante
#define LCD_CONTROLLER_KS0073 1 /**< Use 0 for HD44780 controller, 1
for KS0073 controller */
und die Variante
#define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1
for KS0073 controller */
Ich gebe der zweiten Variante die grössere Erfolgsaussicht. Ich sehe
nämlich im KS0070B Datenblatt (Seite 22) nichts von dem Extended
Function Set, so wie es im KS0073 Datenblatt (Seite 26) beschrieben ist.
Versuch macht kluch.
4/ In lcd_init() in lcd.c ist das erste Warten nach Power-On
delay(16000); /* wait 16ms or more after power-on */.
Das erscheint mir zu knapp für den KS0070B. Im Datenblatt sind nämlich
auf Seite 32 30 ms nach Erreichen von 4,5V angegeben. Berücksichtigt
man, dass der AVR vielleicht schon deutlich unter 4,5V losrennt (welches
Brownout hast du eingestellt? Keinen, 2,7V oder 4,0V? Siehe AVR
Datenblatt Seite 39), wird das Timing noch ungünstiger. Also
versuchsweise länger warten bevor das lcd_init() abgesetzt wird. Alle
Timinggeschichten setzen voraus, dass Punkt 2/ sauber ist.
z.B. lcd_chris.c
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include"lcd.h"
4
5
intmain(void)
6
{
7
{
8
// länger warten nach Power-On als in lcd.c
9
// 5*20ms = 100ms
10
unsignedcharcount=5;
11
while(count--)
12
_delay_ms(20);
13
}
14
15
lcd_init(LCD_DISP_ON_CURSOR);/*Displ on, Cursor on*/
Stefan "stefb" B. wrote:
> 3/ Hast du beide Varianten ausprobiert? Also die Variante>> #define LCD_CONTROLLER_KS0073 1 /**< Use 0 for HD44780 controller, 1> for KS0073 controller */>> und die Variante>> #define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1> for KS0073 controller */>> Ich gebe der zweiten Variante die grössere Erfolgsaussicht. Ich sehe> nämlich im KS0070B Datenblatt (Seite 22) nichts von dem Extended> Function Set, so wie es im KS0073 Datenblatt (Seite 26) beschrieben ist.> Versuch macht kluch.
Ein Indiz dafür, dass Variante 2 (#define LCD_CONTROLLER_KS0073 0)
korrekt sein könnte, ist Beitrag "Probleme mit LCD-Ausgabe von Peter Fleury"
Die dortige lcd.h ist älter und kennt somit noch keine Spezialbehandlung
für KS0073, funktioniert aber grundsätzlich mit einem KS0070-basierten
Display.
Ja, ich habe alles auf PORTD und die Zuweisungen geändert. Die Fuse-bits
habe ich auf 8Mhz eingestellt. Ich habe auch schon andere Programme
damit getestet, z.B das Tastenentprellen und das hat alles funktioniert.
Ich nutze aber noch den internen Oszilator.
Was ist Brownout und wo stelle ich es ein?
Ist das eigentlich normal, das das LCD ohne Programm auf den uC die 2.
und 4. Zeile mit schwarzen Balken füllt?
Ich habe jetzt mal die lcd.h aus dem anderen Projekt genommen, die du
verlinkt hattest und dein Programm mit "Hallo". Jetzt sind zumindest die
schwarzen Balken weggegangen, aber "Hallo" wird nicht angezeigt. Mein
Brownout steht bei 2,7V. Weißt du vielleicht noch etwas?
Hast du an der neuen lcd.h XTAL richtig eingestellt? Und ich würde auch
das passende lcd.c dazu nehmen. Hast du schon am Kontrast gedreht, ob
die Zeichen Hallo einfach nur zu kontrastschwach sind?