Forum: Compiler & IDEs LCD-Problem (AVR ATMega644)


von Andreas del Galdo (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe ein Problem mit einer LCD-Steuerung eines Hitachi-kompatiblen 
LCDs. Im angehängten Code befinden sich in der lcd.c die init(), die 
send_data() und die send_cmd() Funktion. Wenn ich folgendermaßen einen 
String aufs Display bringen möchte funktioniert das wunderbar:
1
char hallo[lcd_max_col] = {'H','A','L','L','O','\0'};
2
lcd_send(hallo);  //es erscheint HALLO

Wenn ich jetzt aber mittels
1
lcd_send("Hallo!");
 Hallo! schreiben möchte, dann erhalten ich nur schwarze Kästchen. Im

Detail ruft die funktion lcd_send() für die größe des Strings die 
lcd_send_data-Funktion auf, die jeweils ein Byte, also ein Char sendet.

Hat einer vielleicht eine Erklärung, warum das so ist? Einen Ansatzpunkt 
wo ich weitersuchen könnte nehme ich auch gern ;)

Danke GALDO

von Johannes M. (johnny-m)


Lesenswert?

Was erwartet "lcd_send" denn für einen Parameter? Es wird ja vermutlich 
ein Zeiger sein. Aber worauf (v.a. welchen Speicher) zeigt dieser 
Zeiger? Je nach Einstellung werden konstante Strings (wie in der zweiten 
Version) generell im Flash abgelegt. Wenn die Funktion aber einen 
Pointer auf RAM haben möchte, dann knallts. Gibt es beim compilieren der 
zweiten Version keine Warnung?

von Andreas del Galdo (Gast)


Lesenswert?

1
void lcd_send_data(char data) {  
2
  //set data mode
3
  PORTD |= (1 << lcd_cmd_rs);
4
  PORTC = data;
5
  lcd_enable();
6
  _delay_ms(10);
7
}
8
9
void lcd_send(char *data) {
10
  while (*data) {
11
    lcd_send_data(*data);
12
    data=data+1;
13
    _delay_ms(2);
14
  }
15
}

die delays sind nur zu Testzwecken mit drin und wahrscheinlich nicht 
nötig ;)

Galdo

von Andreas D. (galdo)


Lesenswert?

Der Compiler meckert nicht - ist alles "normal"

Galdo

von Johannes M. (johnny-m)


Lesenswert?

Schön, das Problem dürfte aber tatsächlich darin bestehen, dass "Hallo" 
im Flash abgelegt wird, die Funktion die übergebene Adresse aber als 
RAM-Adresse interpretiert und dementsprechend an der Stelle im RAM 
nichts brauchbares findet, weil der String ja im Flash liegt... Du 
müsstest entweder den String explizit im RAM anlegen (was Du ja in 
Deiner ersten Version machst, was aber Speicherverschwendung ist) oder 
die Funktion so umschreiben, dass sie den übergebenen Parameter "Zeiger 
auf String" als "Zeiger auf String im Flash" interpretiert (und mit 
pgm_read_byte aus der pgmspace.h auf die Elemente zugreift).

von Karl H. (kbuchegg)


Lesenswert?

Johannes M. wrote:
> Schön, das Problem dürfte aber tatsächlich darin bestehen, dass "Hallo"
> im Flash abgelegt wird

Bei welchem Compiler?
Beim gcc in der Standardeinstellung auf einem AVR wird das
mit Sicherheit nicht gemacht.

von Johannes M. (johnny-m)


Lesenswert?

Karl heinz Buchegger wrote:
> Johannes M. wrote:
>> Schön, das Problem dürfte aber tatsächlich darin bestehen, dass "Hallo"
>> im Flash abgelegt wird
>
> Bei welchem Compiler?
> Beim gcc in der Standardeinstellung auf einem AVR wird das
> mit Sicherheit nicht gemacht.
Deshalb schrieb ich ja weiter oben auch "je nach Einstellung". 
Möglicherweise liegt der Hund tatsächlich woanders begraben, aber es 
"riecht" eben genau danach, dass der String irgendwo liegt, wo ihn die 
Funktion mit dem verwendeten Zeiger nicht findet, weil eben eine Adresse 
von Speicher X als Adresse von Speicher Y interpretiert wird.

von Karl H. (kbuchegg)


Lesenswert?

Johannes M. wrote:
> Karl heinz Buchegger wrote:
>> Johannes M. wrote:
>>> Schön, das Problem dürfte aber tatsächlich darin bestehen, dass "Hallo"
>>> im Flash abgelegt wird
>>
>> Bei welchem Compiler?
>> Beim gcc in der Standardeinstellung auf einem AVR wird das
>> mit Sicherheit nicht gemacht.
> Deshalb schrieb ich ja weiter oben auch "je nach Einstellung".

Hmm. Hast du eine Idee, welche Option das sein könnte?
Ich hab jetzt mal in der WinAVR-gcc Doku geschmökert,
mir ist aber keine Option aufgefallen, die sowas bewirken
würde.

> Möglicherweise liegt der Hund tatsächlich woanders begraben, aber es
> "riecht" eben genau danach, dass der String irgendwo liegt, wo ihn die
> Funktion mit dem verwendeten Zeiger nicht findet, weil eben eine Adresse
> von Speicher X als Adresse von Speicher Y interpretiert wird.

Geb ich die recht, es riecht tatsächlich danach. Kann
aber eigentlich nicht sein.


von Johannes M. (johnny-m)


Lesenswert?

Karl heinz Buchegger wrote:
> Hmm. Hast du eine Idee, welche Option das sein könnte?
> Ich hab jetzt mal in der WinAVR-gcc Doku geschmökert,
> mir ist aber keine Option aufgefallen, die sowas bewirken
> würde.
Mir jetzt auch nicht wirklich. Ich glaub ich stecke noch zu sehr in 
anderen Compilern drin (CodeVision), die konstante Strings ohne zu 
zögern ins Flash schreiben...

> Geb ich die recht, es riecht tatsächlich danach. Kann
> aber eigentlich nicht sein.
Ist immer blöd, wenn es zwar die wahrscheinlichste Lösung ist, aber 
andererseits auch wieder nicht sein kann... Dann müssen wir wohl weiter 
suchen.

von Andreas D. (galdo)


Lesenswert?

Es muss tatsächlich mit den "" zusammenhängen - ich gehe aber nicht 
davon aus, dass Strings per Standard im Flash gespeichert werden (wär ja 
per se Blödsinn)...

Ich hab also keine Idee :(

Wenn jemand noch nen Geistesblitz hat, bitte her damit. Ich verwenden 
den AVR-GCC in der Version 4.2.0
1
Es werden eingebaute Spezifikationen verwendet.
2
Ziel: avr
3
Konfiguriert mit: ./configure --disable-libssp --enable-languages=c --target=avr --prefix=/usr/local/avr
4
Thread-Modell: single
5
gcc-Version 4.2.0

in der avr/version.h steht folgendes:
1
#ifndef _AVR_VERSION_H_
2
#define _AVR_VERSION_H_
3
4
/** \ingroup avr_version
5
    String literal representation of the current library version. */
6
#define __AVR_LIBC_VERSION_STRING__ "1.4.6"
7
8
/** \ingroup avr_version
9
    Numerical representation of the current library version.
10
11
    In the numerical representation, the major number is multiplied by
12
    10000, the minor number by 100, and all three parts are then
13
    added.  It is intented to provide a monotonically increasing
14
    numerical value that can easily be used in numerical checks.
15
 */
16
#define __AVR_LIBC_VERSION__        10406UL
17
18
/** \ingroup avr_version
19
    String literal representation of the release date. */
20
#define __AVR_LIBC_DATE_STRING__    "20070514"
21
22
/** \ingroup avr_version
23
    Numerical representation of the release date. */
24
#define __AVR_LIBC_DATE_            20070514UL
25
26
/** \ingroup avr_version
27
    Library major version number. */
28
#define __AVR_LIBC_MAJOR__          1
29
30
/** \ingroup avr_version
31
    Library minor version number. */
32
#define __AVR_LIBC_MINOR__          4
33
34
/** \ingroup avr_version
35
    Library revision number. */
36
#define __AVR_LIBC_REVISION__       6
37
38
#endif /* _AVR_VERSION_H_ */

Danke GALDO

von Andreas D. (galdo)


Lesenswert?

Hat denn keiner mehr ne Idee :(

Galdo

von Philipp B. (philipp_burch)


Lesenswert?

Wenn du
1
char hallo[] = "Hallo!";
2
lcd_send(hallo);
schreibst, dann geht's auch, oder? Poste doch mal das Disassembly von 
beiden Versionen, das sollte Klarheit schaffen.
Die Delays sind übrigens durchaus erforderlich, allerdings nicht in der 
Länge. Siehe Datenblatt des Displays.

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.