Forum: Mikrocontroller und Digitale Elektronik AVR: Fehler bei Ausgabe von Strings auf LCD


von Michael L. (eagle87)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
ich habe ein Problem bei der Ausgabe von Strings auf einem LC-Display. 
Als Grundlage für die LCD-Routine verwende ich die Vorlage aus 
AVR-GCC-Tutorial/LCD-Ansteuerung. Das komische dabei ist, dass die 
Ausgabe mit lcd_data('x'); ohne Probleme funktioniert. Aber bei 
lcd_string("Test"); wird je nach Fuseeinstellungen entweder ein oder 
mehrere kryptische Zeichen ausgegeben.

Die CPU-Frequenz ist richtig eingestellt. Das hab ich durch toggeln an 
PA0 und einem Osszi getestet. Auch habe ich mein Programm schon an einem 
anderen Controllertyp (ATtiny2313 statt ATmega324A) und Display 
getestet. Da hat es einwandfrei funktioniert. Nur das Display oder nur 
den Controller zu tauschen geht nicht auf die schnelle, da muss ich erst 
was umlöten. Aber daran dürfte es ja eigentlich nicht liegen.

Woran könnte der Fehler liegen?

1
int main (void)
2
{
3
  lcd_init();
4
5
  lcd_data('D');
6
  lcd_data('e');
7
  lcd_data('r');
8
  lcd_data(' ');
9
10
  lcd_string("Test");
11
12
  while(1){}
13
  return 0;
14
}

Hier der Controller mit den aktuellen Einstellungen:
Controller= ATmega324A
lfuse= 0xEE
hfuse= 0x99 (default)
efuse= 0xFF (default)

Quarz: 8MHz

Programme: AVR-GCC, AVRDUDE
Programmer: STK500

Achja, da der ATmega324A für AVRDUDE unbekannt war, habe ich in der 
Datei avrdude.conf den Eintrag vom ATmega324PA kopiert und die 
Controllerbezeichnungen und -signatur entsprechend angepasst.
1
#------------------------------------------------------------
2
# ATmega324A
3
#------------------------------------------------------------
4
5
# similar to ATmega324PA
6
7
part
8
    id               = "m324a";
9
    desc             = "ATmega324A";
10
    has_jtag         = yes;
11
    stk500_devcode   = 0x82; # no STK500v1 support, use the ATmega16 one
12
    avr910_devcode   = 0x74;
13
    signature        = 0x1e 0x95 0x15;
Alles was nach obigem Auszug kommt habe ich so belassen wie es beim 
ATmega324PA war. Das P steht ja nur für Pico Power, weswegen sich die 
beiden Controller nicht so sehr unterscheiden dürften. Im Datenblatt hab 
ich bisher nur Unterschiede bei Bezeichnung und Signatur gefunden.

Gruß
Michael

von Karl H. (kbuchegg)


Lesenswert?

Könnte ein Hinweis dafrauf sein, dass der Wert für
LCD_WRITEDATA_US
ein klein wenig zu klein ist.

rufst du selbst in main lcd_data auf, dann kann der Compiler nicht 
inlinen und durch den tatsächlich durchzuführenden Funktionsaufruf 
'gewinnt' das LCD das bischen Zeit, das es braucht.
lcd_string steht aber in den lcd Funktionen, d.h. der Compiler kann 
inlinen, der Funktionsaufruf findet nicht statt und das abschliessende 
delay in lcd_data ist für diesen Fall ein bischen zu kurz.

von Michael (Gast)


Lesenswert?

Wie sollen dein Delays richtig funktionieren, wenn du F_CPU erst nach 
dem Include von delay.h setzt?

von Karl H. (kbuchegg)


Lesenswert?

> #ifndef F_CPU
> #define F_CPU F_OSC
> #endif


Je mehr verschiedene Präprozessor Makros es für ein und dieselbe Sache 
gibt, desto größer wird die Gefahr, dass man sich selber ins Knie 
schiesst.

Schmeiss den Dreck raus. Es gibt nur ein Makro für die Taktfrequenz. 
Dieses Makro heißt F_CPU und wird in den Projekt-Optionen (bzw. im 
Makefile) eingestellt. Alles andere ist: möglichst wirkungsvoll Fehler 
vestecken bzw. verschleiern bzw. undurchsichtig machen, wie und wo 
dieser Wert eingestellt wird und welcher Codeteil jetzt welche 
Einstellung benutzt.

Und das #ifndef macht die Sache auch nicht besser. Dieses Makro ist 
eines von zentraler Bedeutung für die meisten µC-Programme. Da sollte es 
keinen Default geben. Wenn in den Projekt-OPtionen F_CPU nicht 
eingestellt wurde, dann sollte man das als Fehler werten und nicht 
irgendwelche Annahmen treffen. (AUch dann nicht, wenn eine Warnung 
ausgegeben wird. Denn die Warnungen liest keiner)

von holger (Gast)


Lesenswert?

>Wie sollen dein Delays richtig funktionieren, wenn du F_CPU erst nach
>dem Include von delay.h setzt?

Oder gar nicht wie in lcd-routines.c.
Immer schön die warnings ignorieren und dann hier
mit Fragen aufschlagen.

von Michael L. (eagle87)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Könnte ein Hinweis dafrauf sein, dass der Wert für
> LCD_WRITEDATA_US
> ein klein wenig zu klein ist.
Laut Datenblatt stimmt die eingestellte Zeit. Und eine Vergrößerung hat 
nichts gebracht.

Michael schrieb:
> Wie sollen dein Delays richtig funktionieren, wenn du F_CPU erst nach
> dem Include von delay.h setzt?
Bisher hatte ich dadurch noch nie Probleme und das Vertauschen von 
beidem hat auch nicht geholfen. Aber ich werds in Zukunft 
berücksichtigen.

Karl Heinz Buchegger schrieb:
> Je mehr verschiedene Präprozessor Makros es für ein und dieselbe Sache
> gibt, desto größer wird die Gefahr, dass man sich selber ins Knie
> schiesst.

> Schmeiss den Dreck raus. Es gibt nur ein Makro für die Taktfrequenz.
> Dieses Makro heißt F_CPU und wird in den Projekt-Optionen (bzw. im
> Makefile) eingestellt.
Ok, habe das #define F_CPU überall gelöscht und im Makefile F_CPU = 
8000000 eingetragen. Die Fehler sind immernoch da.
Zum Test habe ich in lcd-routines.h nochmal das Makro mit ifndef 
eingetragen.
1
#ifndef F_CPU
2
#define F_CPU 8000000
3
#warning F_CPU war nicht definiert, wird jetzt mit 8M definiert
4
#endif
Die Warning wurde beim kompilieren sowohl für main.c, als auch für 
lcd-routines.c ausgegeben. Das Makro im Makefile hat also nicht 
funktioniert. Kannst du noch etwas genauer erklären wie ich F_CPU im 
Makefile definieren kann?

holger schrieb:
> Immer schön die warnings ignorieren und dann hier
> mit Fragen aufschlagen.
Es gab überhaupt keine Warnings.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Sicher, das im Makefile das richtig steht? Hier mal ein Auszug aus 
einem:
1
## Compile options common for all C compilation units.
2
CFLAGS = $(COMMON)
3
CFLAGS += -Wall -gdwarf-2 -std=gnu99   -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
4
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d

von Stefan E. (sternst)


Lesenswert?

Michael L. schrieb:
> Das komische dabei ist, dass die
> Ausgabe mit lcd_data('x'); ohne Probleme funktioniert. Aber bei
> lcd_string("Test"); wird je nach Fuseeinstellungen entweder ein oder
> mehrere kryptische Zeichen ausgegeben.
> ...
> Controller= ATmega324A

Welche avr-gcc-Version? Vielleicht 4.5?

von Michael L. (eagle87)


Lesenswert?

@Matthias Sch.:
War falsch im Makefile eingetragen. Nun funktioniert zumindest der Teil
1
# Compiler flags.
2
CFLAGS = -g$(DEBUG)
3
.
4
.
5
.
6
CFLAGS += -DF_OSC=$(F_OSC)
7
CFLAGS += -DF_CPU=8000000UL
btw. Kennt ihr eine gute Anleitung zum Thema Makefiles, die nicht nur 
auf Mikrocontroller bezogen ist?

Die Funktion lcd_string() geht immer noch nicht.

von Michael L. (eagle87)


Lesenswert?

Version AVR-GCC: 4.5.3

von Stefan E. (sternst)


Lesenswert?

Michael L. schrieb:
> Version AVR-GCC: 4.5.3

Entweder du wechselst auf >= 4.6.2, oder du suchst im Makefile den 
Abschnitt "Linker flags" und ergänzt dort folgende Zeile:
1
LDFLAGS += -Wl,-Tdata=0x800100

von Michael L. (eagle87)


Lesenswert?

Endlich funktionierts! Mit
1
LDFLAGS += -Wl,-Tdata=0x800100
wird der String richtig angezeigt.

Kannst du mir noch sagen was diese Zeile genau bewirkt? Ich würd gern 
den Sinn dahinter verstehen.

Danke für die Hilfe
Michael

von Stefan E. (sternst)


Lesenswert?

Michael L. schrieb:
> Kannst du mir noch sagen was diese Zeile genau bewirkt?

Ein wenig vereinfacht ausgedrückt, die Option Tdata sagt dem Linker, wo 
das RAM anfängt.
Die avr-gcc zwischen 4.5 und 4.6.1 (inklusive) haben einen Fehler, der 
dafür sorgt, dass bei manchen Controllern (und der Mega324A gehört dazu) 
als Default fälschlicherweise 0x800060 (statt 0x800100) an den Linker 
weitergereicht wird. Die obige Option "übersteuert" diesen falschen 
Default-Wert.

von Michael L. (eagle87)


Lesenswert?

Ok, Danke für die Info

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.