Forum: Mikrocontroller und Digitale Elektronik AVR PSTR mit gegebenem String nutzen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Martin (mlorbach1)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche, einen einer Funktion als Parameter übergebenen String mit 
dem Makro PSTR aus der <avr/pgmspace.h> im Flash eines AVR 
Microcontrollers zu speichern.

Als Fehlermeldung bekomme ich (in Microchip Studio) "invalid 
initializer".

Sobald man PSTR einen String der Form "..." übergibt, funktioniert es.

Im Web konnte ich zu diesem Problem nichts finden, daher wäre ich sehr 
dankbar für Hilfe.

Am Ende würde ich gerne die Funktion im Anhang nutzen, um den String auf 
einem LCD Display auszugeben.

Beste Grüße,

von Walter T. (nicolas)


Lesenswert?

Dann wäre es wohl sinnvoll, die Zeile, auf die sich die Fehlermeldung 
"invalid initializer" bezieht genau anzusehen.

Der Funktionsprototyp passt übrigens auch nicht zu einem PSTR-String. 
Schau Dir mal die Deklaration einer bestehenden Funktion an, z.B. von 
strcpy_P().

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ich versteh die Frage nicht. Im Code gibt es überhaupt kein PSTR:

> void lcd_writeProgString(const char *string) {
>    char c;
>    while ((c = (char)pgm_read_byte(string++))) {
>        lcd_writeChar(c);
>    }
> }

von Martin (mlorbach1)


Lesenswert?

Danke für die schnelle Antwort.
Ich werde versuchen, das Problem genauer zu beschreiben.

Die Funktion die ich angehängt habe, versuche ich mit einem im Flash 
gespeicherten String aufzurufen.
Während es mit lcd_writeProgString(PSTR("Test")) klappt, funktioniert es 
nicht, sobald ich einen bereits existierenden String übergeben zu 
versuche, also etwas wie
1
 void func(const char *str) {
2
3
lcd_writeProgrString(PSTR(str));
4
5
}

Die Zeilenangabe der Fehlermeldung bezieht sich genau auf die Zeile, in 
der lcd_writeProgString aufgerufen wird.

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

1
#include <Streaming.h> // die Lib findest du selber ;-)
2
Print &cout = Serial; // cout Emulation für "Arme"
3
4
5
const char test[] PROGMEM = "qwertzui";
6
7
8
void writeProgString(const char *string) {
9
    char c;
10
    while ((c = (char)pgm_read_byte(string++))) {
11
       //lcd_writeChar(c);
12
       cout << c;
13
    }
14
}
15
16
17
void setup() 
18
{
19
  Serial.begin(9600);
20
  cout << F("Start: ") << F(__FILE__) << endl;
21
  writeProgString(test);
22
  cout <<  endl;
23
}
24
25
void loop() 
26
{
27
28
}

von Falk B. (falk)


Lesenswert?

Martin schrieb:
> Danke für die schnelle Antwort.
> Ich werde versuchen, das Problem genauer zu beschreiben.
>
> Die Funktion die ich angehängt habe, versuche ich mit einem im Flash
> gespeicherten String aufzurufen.

Das geht, aber nicht so.

> Während es mit lcd_writeProgString(PSTR("Test")) klappt, funktioniert es
> nicht, sobald ich einen bereits existierenden String übergeben zu
> versuche, also etwas wie

Logisch. PSTR ist für Konstanten da.
Eher so. Du gibst ja nur den Zeiger auf den String im Flash an eine 
andere Funktion weiter.
1
void func(PGM_P str) {
2
  lcd_writeProgrString(str);
3
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Martin schrieb:
1
> void func (const char *str)
2
> {
3
>    lcd_writeProgrString (PSTR(str));
4
> }

1) PSTR ist nur auf String-Literale anwendbar.  str ist kein 
String-Literal.

2) PSTR kann nur innerhalb von Funktionen und Methoden verwendet werden.

Punkt 2) ist gegeben, der Fehler ist also Verletzung von 1).

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Martin schrieb:
> ich versuche, einen einer Funktion als Parameter übergebenen String mit
> dem Makro PSTR aus der <avr/pgmspace.h> im Flash eines AVR
> Microcontrollers zu speichern.

Funktioniert nicht.

Welche Sprache?
C oder C++?

Wenn C++, dann kann man Funktionen überladen. Arduino verwendet die 
"incomplete Class" FlashStringHelper um zwischen Flash oder RAM Strings 
zu unterscheiden.
Hört sich teuer an, ist aber kostenlos zu haben, da das nur Pointer 
Konvertierungen sind, welche keine zusätzliche Rechenzeit/Code zur 
Laufzeit benötigen.

von Sebastian W. (wangnick)


Lesenswert?

Martin schrieb:
> ich versuche, einen einer Funktion als Parameter übergebenen String mit
> dem Makro PSTR aus der <avr/pgmspace.h> im Flash eines AVR
> Microcontrollers zu speichern.

Der Makro PSTR wirkt bei der Übersetzung des Programms, nicht zur 
Laufzeit. Um zur Laufzeit einen String aus dem flüchtigen Speicher in 
den Flash zu programmieren müsstest du anders vorgehen. Das geht zwar, 
dauert aber recht lange, und macht bei häufiger Benutzung auch zügig den 
Flash kaputt. Das nur zu tun, weil eine Bibliotheksfunktion nur 
Flash-Strings akzeptiert, nicht aber solche im flüchtigen Speicher, 
macht wenig Sinn.

LG, Sebastian

von Oliver S. (oliverso)


Lesenswert?

Martin schrieb:
> ich versuche, einen einer Funktion als Parameter übergebenen String mit
> dem Makro PSTR aus der <avr/pgmspace.h> im Flash eines AVR
> Microcontrollers zu speichern.

Wirklich? Aber egal.

Dann wirst du dich mit den Funktionen aus boot.h der avrlibc befassen 
müssen, und dazu ausführlich mit dem Datenblatt des Prozessors.

Gehen geht das, es erfordert aber ein grundlegendes Verständnis des 
Prozessors und der avrlibc, was du dir halt noch erarbeiten musst.

Oliver

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Oliver S. schrieb:
> Gehen geht das, es erfordert aber ein grundlegendes Verständnis des
> Prozessors und der avrlibc, was du dir halt noch erarbeiten musst.

Oder man schaut sich einfach an, wie bereits bestehende Funktionen 
implementiert sind. strcpy_P() bietet sich an, weil es mit beiden Arten 
des Speichers arbeitet - da kann man sich eigentlich alles abgucken.

von Oliver S. (oliverso)


Lesenswert?

Walter T. schrieb:
> strcpy_P() bietet sich an, weil es mit beiden Arten des Speichers
> arbeitet - da kann man sich eigentlich alles abgucken.

Hm. Ich sag mal, knapp daneben ist auch vorbei.

Keine der _P-Funktionen schreibt ins Flash. Die lesen alle nur daraus.

Flash schreiben ist was anderes.

Oliver

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Oliver S. schrieb:
> Flash schreiben ist was anderes.
Ja!
Bis auf ganz wenige Ausnahmen (z.B. Upload, AMForth) meist eine 
Dummheit.

von Walter T. (nicolas)


Lesenswert?

Oliver S. schrieb:
> Keine der _P-Funktionen schreibt ins Flash.

Das ist irgendwie richtig, aber auch ungenau. Richtig wäre:

Keine Funktion außerhalb des Bootloaders schreibt ins Flash.

Edit: Achje, dass man das so lesen kann, dass der TO das Flash als 
EEPROM-Ersatz mißbrauchen will, sehe ich erst jetzt. Die 
Beispielfunktion sah so aus, als wolle er Daten aus dem Flash ans LCD 
schicken.

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Walter T. schrieb:
> Beispielfunktion sah so aus, als wolle er Daten aus dem Flash ans LCD
> schicken.

Habe ich auch so gesehen, darum auch mein Beispiel.
Ihm versuchts nur mit dem falschen Hebel.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Walter T. schrieb:
> Die Beispielfunktion sah so aus, als wolle er Daten aus dem
> Flash ans LCD schicken.

Mit avr-gcc dann einfach do:
1
void lcd_writeProgString (const __flash char *string)
2
{
3
    char c;
4
    while ((c = *string++))
5
    {
6
        lcd_writeChar (c);
7
    }
8
}
oder
1
void lcd_writeProgString (const __flash char *string)
2
{
3
    for (const __flash char *s = string; *s != '\0'; ++s)
4
        lcd_writeChar (*s);
5
}

AVR-GCC-Tutorial: Flash mit flash und Embedded-C

: Bearbeitet durch User
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.