Hallo Ihr,
ein Anfänger hat ein Problem mit einem Stringarray im Flash.
Randbedingungen:
Compiler Avr-GCC
MCU: Atmega103
-------Code-------
const char text1[] PROGMEM = "Parameter laden ";
const char text2[] PROGMEM = "Parameter ändern ";
const char text3[] PROGMEM = "Parameter senden ";
PGM_P dmenu[9] PROGMEM = { text1, text2, text3};
int main(void)
{
char buffer[10];
strcpy_P( buffer, dmenu[1] );
lcd_putc(buffer)
for(;;);
}
So funktioniert es, wenn ich nun aber das Array im Progmem nicht direkt
anspreche [1], sondern über einen Variablenindex [var], dann geht es
nicht mehr.
Also so:
int main(void)
{
unsigned int disp;
char buffer[10];
disp=1;
strcpy_P( buffer, dmenu[disp] );
lcd_putc(buffer)
for(;;);
}
Kann mir jemand helfen,was ich falsch mache?
Gruss Günter
Sorry,
mit nicht funktionieren meine ich, dass der String der aufs Display
geschrieben wird versaut ist. Also irgendwelche zeichen, aber nicht die
gewollten. Also zugriffsfehler im Speicher.
Das hier:
dmenu[1]
will etwas aus dem RAM lesen. Du hast aber explizit gesagt,
daß das im ROM sein solle. Da mußt Du Dich vorher mit __lpm_inline
drum kümmern, daß es aus dem ROM erstmal in (temporären) RAM
kommt.
Oder aber, Du läßt zwar die Strings selbst im ROM, aber das
Array nicht. 6 Bytes RAM dafür sind ja nicht gerade viel.
Du würdest mehr RAM sparen, wenn Du das nicht erst mit
strcpy_P() in einen temporären RAM-Puffer kopieren müßtest,
sonder gleich ein lcd_putc_P() noch lieferst, das die Strings
direkt aus dem Flash verarbeiten kann.
Hallo Jörg,
nun hast Du mich ganz verwirrt...
Aber trotzdem mal:
Hab die LCD-Routinen von Peter Fleury verwendet. Dort ist ja auch ein
lcd_puts_p dabei, das ein String stück für stück aus dem Progmem liest
und dann aufs Display schickt.
Aber auch da hab ich das selbe Problem.
Soll heissen, ich kann mein Stringarray direkt addressieren, in dem ich
die lcd_putc_p routine, wie auch oben beim strcpy_P, mit ner Zahl als
Index aufrufe. Aber sobald ich die Zahl mit ner variablen ersetze,
springt er mir zum Teufel...
Begreif das im Moment noch nicht... wo ist der Unterschied zwischen
dmenu(2) und dmenu(test), mit test=2;
Oder steh ich jetzt so gnadenlos auf dem Schlauch?
Gruss Günter
Nein, was Du noch nicht begriffen hast ist, daß Du das
Herauspopeln aus dem Flash grundsätzlich erstmal selbst
vornehmen mußt, wenn Du etwas im Flash ablegst. Der Compiler
tut das nicht für Dich. Von daher ist es keine sonderlich
praktische Idee, das Array selbst im Flash anzulegen, sondern
laß für das Array all die PROGMEM & Co weg, dann funktioniert
es.
Für dieses kleine Array kann es schon sinnvol sein, das Array im RAM
abzulegen. Aber z.B. bei einer komplexen Menu-Struktor sollte das Array
und der Text im Flash abgelegt werden.
Wenn der Index eine konstante ist (dmenu[2]), kann der Compiler der
Flash-Adresse einfügen:
lcd_puts_p( dmenu[1] );
Wenn der Index aber eine Variable ist, muss man die Adresse
mittels LPM Befehlen herauslesen:
for (i=0; i<3; i++) lcd_puts_p( PRG_RDW(&dmenu[i]) );
Im <avr/pgmspace.h> gibt es zwar ein PRG_RDB() Makro, aber kein
PRG_RDW() Makro, ich habe deshalb folgendes definiert:
#define PRG_RDW(a) (PRG_RDB((a))+0x100*PRG_RDB((uint16_t)(a)+1))
Besser wäre allerding wenn man PRG_RDW() als Inline-Asm realiseren würde
und <avr/pgmspace.h> ergänzen würde.
p = (char *)PRG_RDW(&menu[menuState].text);
lcd_puts_p(p);
Hallo Joerg und Peter,
vielen Dank fürs "unter die Arme Greifen"... nun hab ichs geschnallt...
und siehe da: ES funktioniert! Jubel.
Nochmals Danke....
Grüssle Günter
Eine eigene Frage?
Dieser Thread ist über 23 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.