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,
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
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); > } > }
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
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 | }
|
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 | }
|
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
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.
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
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
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.
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
Oliver S. schrieb: > Flash schreiben ist was anderes. Ja! Bis auf ganz wenige Ausnahmen (z.B. Upload, AMForth) meist eine Dummheit.
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.