Hallo Leute,
ich habe folgendes Problem und finde seit ca. 2 Tagen keine Lösung
dafür:
Ich bin gerade dabei ein LCD (16x2 Zeichen) anzusteuern. Initialisieren
funktioniert und auch das beschreiben mit einzelnen Zeichen, also etwas
wie
send_char('L');
send_char('i');
send_char('n');
send_char('i');
send_char('e');
send_char(' ');
send_char('1');
zeigt "Linie 1" auf dem Display. Da das etwas umständlich ist, will ich
das am besten mit einem "buffer", sprintf() und send_string(buf);
machen.
Allerdings bringt
sprintf(buf, "Linie 2");
send_string(buf);
nur mehrere komplett gefüllte Chars aufs Display, (also jeder Buchstabe
ist 0xff anstelle der jeweilichen ASCII-Zeichen)
Auch
strcpy(buf, "Linie 2\0");
bringt das gleiche Ergebnis, nur wenn ich den Buffer umständlich über
buf[x++] = 'L';
buf[x++] = 'i';
buf[x++] = 'n';
buf[x++] = 'i';
buf[x++] = 'e';
buf[x++] = ' ';
buf[x++] = '2';
buf[x++] = 0;
beschreibe funktioniert es.
Die ganzen Beiträge die ich finden konnte handelten immer von
Float-Problemen und (s)printf, aber bei mir wird ja noch nicht mal
einfacher Text angezeigt.
Meine Includes sind:
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
µController: ATMega2560
Atmel Studio Version 6.2
Hat jemand eine Idee woran das liegen könnte?
Pyromaniac schrieb:> strcpy(buf, "Linie 2\0");
string.h eingebunden?
Das \0 ist überflüssig, da der Compiler bei Stringliteralen automatisch
ein '\0' anhängt.
Wie sieht es bei
Dirk B. schrieb:> string.h eingebunden?
Jep, als ich strcpy() zum Testen benutzt habe, danach habe ich es wieder
gelöscht da ich strcpy ja eigentlich nicht benutzen will.
Dirk B. schrieb:> Wie sieht es bei
1
charbuf[32]="Linie 2";
> oder
1
send_string("Linie 2");
> aus?
Beides führt zu dem immer selben Ergebnis wie auch schon bei sprintf().
für Kommandos? (Genau deswegen hasse ich so einen Binärscheiss. Man
sieht einfach nicht auf Anhieb, was da passiert).
Hintergrund: je nachdem, was das für ein Kommando ist, kann die
Ausführung auf dem LCD einige Zeit dauern. Wenn das Kommando zu lange
dauert, könnte es eine 'Interferenz' mit der nachfolgenden Ausgabe per
lcd_string geben.
Du könntest mal probieren, nur probehalber, hier
1
voidenable_impuls()
2
{
3
PORTK|=0b00000100;
4
_delay_us(30);
5
PORTK&=0b11111011;
6
_delay_us(30);
7
}
den 2-ten delay mal wesentlich höher zu setzen. Dann geht zwar die
Ausgabe momentan erst mal langsamer, aber es ist unwahrscheinlich, dass
es dann noch zu gegenseitigen Beeinflussungen kommt. Falls das der Fall
sein sollte.
Habe die Änderungen durchgeführt, also die delays von "µs" auf "ms"
geändert. Man sieht nun den Aufbau auf dem Display, aber das Ergebnis
ist leider noch das gleiche.
Die binär-Kommandos waren "erste Zeile" und "zweite Zeile". Wenn man das
Datenblatt gerade nicht im Kopf hat ist es natürlich nicht eindeutig :)
habe ich nun aber auch deutlicher gemacht im Quellcode.
Komisch, ich sehe keine Grund, warum strcpy() und sprintf() nicht
funktionieren.
Aber mir ist etwas anderes aufgefallen:
strcpy(buf, "Linie 2");
Diese Zweile belegt gleich dreifach Speicher:
- "Linie 2" steht im Programmspeicher.
- Der String wird automatisch vor main() ins RAM kopiert.
- Dein Code kopiert ihn nochmal, nämlich in den Buffer.
Alternative:
strcpy_P(buf,PSTR("Linie 2"));
So liegt der Quellstring nicht im RAM, sondern er wird direkt aus dem
Programmspeicher gelesen.
kast schrieb:> was passiert bei:>> sprintf(buf, "Linie %d", 2);
Hi kast, das übliche, siehe Foto.
Stefan us schrieb:> Komisch, ich sehe keine Grund, warum strcpy() und sprintf() nicht> funktionieren.>> Aber mir ist etwas anderes aufgefallen:>> strcpy(buf, "Linie 2");>> Diese Zweile belegt gleich dreifach Speicher:> - "Linie 2" steht im Programmspeicher.> - Der String wird automatisch vor main() ins RAM kopiert.> - Dein Code kopiert ihn nochmal, nämlich in den Buffer.>> Alternative:>> strcpy_P(buf,PSTR("Linie 2"));>> So liegt der Quellstring nicht im RAM, sondern er wird direkt aus dem> Programmspeicher gelesen.
Damit erhalte ich dann folgende Fehler:
Error 2 ld returned 1 exit status collect2.exe 0 0 16x2 LCD
Error 1 undefined reference to `PSTR' E:\Ei...D\Debug\16x2 LCD.c 1
1 16x2 LCD
@kast: Einen kleinen Unterschied gibt es doch. Wenn ich
1
sprintf(buf,"Linie 2");
benutze, dann werden da zwei dieser Blöcke weniger dargestellt.
Vielleicht ist das ein wichtiger Hinweis? Mir sagt es nichts, hätte
gedacht dass es identisch sein sollte.
Ich nehme eher an, dass es ein Problem in den Initialisierung des
LCD-Displays ist und nicht ein Compilerproblem. Sonst würde
die Ausgabe "Line 1" nicht erscheinen.
Ich benutze die Lib von Fleury und da sehen die Commands für die zweite
Zeile etwas anders aus.
Ich würde dort suchen und nicht beim Compiler.
1
#define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */
2
#define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */
3
#define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */
4
#define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */
Hm, das glaube ich eigentlich weniger. Wenn die Initialisierung
fehlgeschlagen wäre, dann würde das Display weder Zeile 1, noch Zeile 2
anzeigen.
Ich habe auch schon versucht die Zeilen zu tauschen, das Ergebnis ist
das gleiche, nur eben mit vertauschten Zeilen.
1
#define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */
2
#define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */
3
#define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */
4
#define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */
Das ist soweit richtig, denn das sind ja die ADRESSEN. Um nun die
Adresse zu ändern, muss das "command" (0x80) und die "adress"
miteinander oder-verknüpft werden, was zu dem 0x80 (0x00 | 0x80) für
Zeile 1 und 0xC0 (0x40 | 0x80) für Zeile 2 führt.
Mit dem Code hier
Ich habe jetzt das Display genommen und mit einem Breadboard an einen
ATTiny26 gehängt. Der Code ist 1:1 identisch (in AVR natürlich auch auf
ATTINY26 geändert), compiliert, hochgeladen: GEHT!
Also entweder hat der ATMEGA2560 einen schuss. Aber es ist eigentlich
neu und das Display-Programm ist das erste das drauf geladen wurde.
Oder aber das Atmel Studio übersetzt den Quellcode nicht richtig?
Was meint ihr?
So, heute ein weiterer Test: Wenn ich den generierten string "buf" über
die serielle Schnittstelle sende, dann kommt beim Empfänger ebenfalls
nur müll raus. Es liegt also definitiv nicht am Display, sondern an
etwas anderem. Ich vermute immernoch dass das Atmel Studio den Code
falsch generiert/übersetzt. Wie könnte man das denn überprüfen?
Hi Leute,
ich habe mich gerade wieder dem Thema angenommen und bin immer noch
davon überzeugt, dass AVR-Studio den Code falsch übersetzt (warum sonst
sollte es beim Attiny26 problemlos funktioniert, aber beim ATMEGA2560
weder über LCD noch Seriell?)
Hat keiner eine Idee wie ich den compilierten Code dahingehend
überprüfen kann, dass man sagen kann, dass der ASM-Code für die
"sprintf"-Funktion korrekt aus der C/C++-Funktion übersetzt wurde?
Oder hat sonst noch jemand eine Idee woran es liegen könnte? Ich bin für
alles offen, mittlerweile auch für Voodoo-Zeugs ;-)
Pyromaniac schrieb:> Hat keiner eine Idee wie ich den compilierten Code dahingehend> überprüfen kann, dass man sagen kann, dass der ASM-Code für die> "sprintf"-Funktion korrekt aus der C/C++-Funktion übersetzt wurde?
sprintf() – wie auch die verwandte Prozedur printf() – braucht sehr viel
Speicherplatz. Könnte mit vorstellen, dass es hier zu einem Überlauf des
Stacks kommt – oder irgendwas Ähnliches. Kannst du den Speicherbereich
für den Stack testweise vergrößern? Aber ok, ist nur eine vorsichtige
Vermutung.
sprintf() würde ich ohne Not sowieso nicht verwenden, es frisst einfach
zu viele Ressourcen. Klappt es mit einer selbstgeschriebenen Prozedur?
Z.B. so:
Markus Weber schrieb:> sprintf() – wie auch die verwandte Prozedur printf() – braucht sehr viel> Speicherplatz. Könnte mit vorstellen, dass es hier zu einem Überlauf des> Stacks kommt – oder irgendwas Ähnliches. Kannst du den Speicherbereich> für den Stack testweise vergrößern? Aber ok, ist nur eine vorsichtige> Vermutung.>> sprintf() würde ich ohne Not sowieso nicht verwenden, es frisst einfach> zu viele Ressourcen. Klappt es mit einer selbstgeschriebenen Prozedur?> Z.B. so:>
1
void sendstr(const char* sp) {
2
while(*sp!=0) send_char(*sp++);
3
}
4
5
...
6
7
sendstr("Linie 2");
>
ich hab in deinem Code bei "const char sp" noch ein * eingefügt, dann
wurde es compiliert, soweit ging es also schonmal. allerdings wird auch
hierbei nichts vernünftiges angezeigt. vielleicht hast du recht und es
liegt am stack, allerdings habe ich noch nie an den einstellungen
rumgespielt. wo findet man denn die einstellungen für den stack?
Stefan Us schrieb:>>> strcpy_P(buf,PSTR("Linie 2"));>> Damit erhalte ich dann folgende Fehler:>> undefined reference to `PSTR'>> Hast du denn die include Datei avr/pgmspace.h eingebunden?> http://www.nongnu.org/avr-libc/user-manual/group__...
Ja jetzt schon :) sorry, hatte das nicht weiter verfolgt. Das Ergebnis
ist leider das gleiche wie bei den anderen.
Was mir auch noch gerade eingefallen ist: Was, wenn der Programmer das
Problem ist? Ich benutzen den "khazama AVR Programmer" für meine
"USBasp" Box. Ich werde gleich mal sehen ob ich mit einer anderen
Software vielleicht andere Effekte oder gleich die Lösung des Problemes
haben...
Hat keiner mehr eine Idee oder Vorschläge? Wie sieht es denn mit dem
Stack aus? Lohnt es sich die Idee weiter zu verfolgen? Über Google habe
ich leider nichts brauchbares gefunden :-\
> Das Ergebnis ist leider das gleiche wie bei den anderen.
Das dachte mir schon. Es war nur ein Vorschlag, etwas RAM zu sparen. Zu
deinem eigentlichen Problem fällt mir leider auch nichts mehr ein.
Hey Stefan,
ich habe jetzt mal die "release"- und die "debug"-Versionen der
lss-Dateien dran gehängt.
Ich hoffe du (oder ein anderer) wird daraus schlau. Ich wundere mich nur
dass in der release-version von der lss-Datei kein "sprinft" auftaucht
:-\