Forum: Compiler & IDEs PROGMEN Array in Schleife verarbeiten


von Alex (Gast)


Lesenswert?

Habe ein Array im Speicher hinterlegt, mit dem ich später in einer 
Schleife arbeiten möchte. Je nach dem, welchen Wert ich wähle, sollen 
alle vorherigen Werte aufaddiert werden.

Wähle ich also Wert 1 soll 7+3=10 raus kommen. s.u.
1
const uint8_t MENUSTR[] PROGMEM ={
2
3, 
3
7, 
4
3, 
5
0, 
6
};

...
main:
1
uint8_t sub=0;
2
3
//Schleife, die nicht funktioniert:
4
for(uint8_t j=0; j==1; j++){
5
sub= &MENUSTR[j] + sub);
6
}

1
//soll das gleiche machen:
2
    
3
uint8_t j=0;
4
sub= &MENUSTR[j] + sub;
5
j++;
6
sub= &MENUSTR[j] + sub;
7
//funktioniert

Ich habe nun einfach mit einem festen Wert gearbeitet. Anscheinend kommt 
allerdings bei der Schleife immer der Initialwert von sub heraus. Also 
im Beispiel 0.
Wenn ich direkt hintereinander Schreibe, was die Schleife machen soll, 
funktioniert es allerdings.

Woran denke ich nicht?

Würde mich über Hilfe freuen.

Gruß
Alex

von Stefan E. (sternst)


Lesenswert?

Auf Werte im Flash kannst du nicht direkt zugreifen. Du musst sie mit 
den dafür vorgesehenen Funktionen aus dem Flash lesen. Das die eine 
Variante auch mit direktem Zugriff zu funktionieren scheint, liegt 
daran, dass der Optimierer hier gleich die Zugriffe durch die 
entsprechenden Werte ersetzt.

von Bernhard M. (boregard)


Lesenswert?

Die Vergleichsbedingung in der for Schleife ist falsch, Du willst wohl:
1
uint8_t sub=0;
2
3
//Schleife, die nicht funktioniert:
4
for(uint8_t j=0; j<=1; j++){
5
sub= &MENUSTR[j] + sub);
6
}

von ... .. (docean) Benutzerseite


Lesenswert?

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29

Wenn es ein AVR + GCC ist, was mir meine Glaskugel sagt... *Zaunpfahl 
wink*

von Stefan E. (sternst)


Lesenswert?

Und nachdem ich nochmal drauf geschaut habe, wage ich auch zu 
bezweifeln, dass die funktionierende Variante tatsächlich so mit den '&' 
darin funktioniert.

von Alex (Gast)


Lesenswert?

Da sieht mans mal. Den Wald vor lauter Bäumen nicht gesehen. Danke für 
den Anstoß. Vergleichsbedinung war natürlich falsch.

Gruß
Alex

von Alex (Gast)


Lesenswert?

Hab dann mal noch angepasst. Die Beiträge habe ich leider erst etwas 
später gesehen.
1
const uint8_t MENUSTR[] PROGMEM ={
2
3, 
3
7, 
4
3, 
5
0, 
6
};
7
8
const uint8_t *PTMENUSTR PROGMEM = MENUSTR;

und bei der Schleife
1
for(uint8_t j=0; j<=1; j++){
2
    sub= PTMENUSTR+j + sub;
3
    }

War es so gemeint wegen der automatischen Optimierung?

Gruß
Alex

von Stefan E. (sternst)


Lesenswert?

Alex schrieb:

> War es so gemeint wegen der automatischen Optimierung?

Was meinst du mit "automatischen Optimierung"?

Bei der Schleifen-Variante führt kein Weg an den Flash-Funktionen 
vorbei.

von Alex (Gast)


Lesenswert?

Ob das die gewünschten Funktionen sind, mit denen man die Werte korrekt 
aus dem Flash liest?

von Stefan E. (sternst)


Lesenswert?

Alex schrieb:
> Ob das die gewünschten Funktionen sind, mit denen man die Werte korrekt
> aus dem Flash liest?

Ich sehe in dem Code gar keine Funktionen.

Sieh dir den Link an, den docean gepostet hat.

von gast (Gast)


Lesenswert?

wenn du

const char buffer[] PROGMEM = { 1,2,3,4]};

hast


must du mit

char wert=0;
for( char i=0; i<=3 , i++)
  {
    wert += pgm_read_byte( &buffer[i]);
  }


zugreifen


oder so ähnlich ^^ kein plan ob das gehen würde

von Alex (Gast)


Lesenswert?

pgm_read_byte klappt allerdings nicht und mit dem Geschriebenen wird 
genau auf die Werte im Array zugegriffen.
Also meine Frage:
Wie wird dieses wegoptimiert, was ich geschrieben habe. Bzw. wie sollte 
der Code aussehen? Aus dem Tutorial konnte ich leider nicht mehr 
gewinnen.

von Stefan E. (sternst)


Lesenswert?

Alex schrieb:
> pgm_read_byte klappt allerdings nicht

Dann hast du es falsch benutzt.
Wie sieht dein Code dazu aus?

Und ich verstehe nicht, was du jetzt die ganze Zeit mit dem "Optimieren" 
meinst. Der Optimierer hat nur unbeabsichtigterweise dafür gesorgt, dass 
ein Teil deines Codes zufällig funktioniert hat, obwohl er eigentlich 
fehlerhaft war.

von Alex (Gast)


Lesenswert?

1
uint8_t sub=0;
2
3
for(uint8_t j=0; j<=1; j++){
4
sub= pgm_read_byte(&MENUSTR[j]) + sub;
5
}

So würde er dann aussehen.

von Stefan E. (sternst)


Lesenswert?

Ist richtig. Was genau klappt damit nicht?

von Alex (Gast)


Lesenswert?

Es wird nicht der Wert an der Stelle j benutzt sondern irgendwas 
anderes.

In meinem Beispiel:
1
const uint8_t MENUSTR[] PROGMEM ={
2
3, 
3
7, 
4
3, 
5
0, 
6
};

sollte dann an der Stelle j=0 der Wert 3 benutzt werden. Wird er aber 
nicht. Bekomme dann nur komisches Zeug raus. Wenn ich allerdings 
pgm_read_byte weg lasse kommt alles richtig heraus.

Hatte es vorher ja auch mit pgm_read_byte versucht aber dann einfach mal 
weg gelassen. Und es ging.

Gruß
Alex

von Karl H. (kbuchegg)


Lesenswert?

Alex schrieb:

> Hatte es vorher ja auch mit pgm_read_byte versucht aber dann einfach mal
> weg gelassen. Und es ging.

Zeig mal dein ganzes Programm mit dem du testest.

von Alex (Gast)


Lesenswert?

Steht nicht so viel mehr drin:
1
#include <stdio.h>
2
#include <string.h>
3
4
// AVR include files
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
9
//P.Fleury
10
#include "lcd.h"
11
12
uint8_t sub=0;
13
14
const uint8_t MENUSTR[] PROGMEM ={
15
3, 
16
7, 
17
3, 
18
0, 
19
};
20
21
22
int  main()
23
{  
24
DDRG &=(1<<PG2);
25
DDRA &=(1<<PA4) & (1<<PA5) & (1<<PA6) & (1<<PA7);
26
27
28
//Werden noch nicht benötigt
29
PORTG |= (1<<PG2);  // Taster Pullups
30
PORTA |= (1<<PA4) | (1<<PA5) | (1<<PA6) | (1<<PA7); // Taster Pullups
31
32
33
34
35
//   LCD Initialisierung
36
  lcd_init (LCD_DISP_ON);
37
        lcd_clrscr();
38
39
for(uint8_t j=0; j<=1; j++){
40
    sub= &MENUSTR[j] + sub;
41
    }
42
43
lcd_gotoxy(1,1);
44
45
//Hier kann ich die Ergebnisse mit LCD Ausgabe prüfen
46
47
if(sub==10){
48
  lcd_puts("ok");
49
}else{
50
  lcd_puts("nicht ok");
51
}
52
53
  for (;;){}
54
}

von Stefan E. (sternst)


Lesenswert?

Sorry, aber das funktioniert so nie und nimmer. Nicht nur, dass der 
richtige Flashzugriff fehlt, du addierst auch Pointer auf. Wenn du ein 
"ok" bekommst, ist das reiner Zufall.

von Karl H. (kbuchegg)


Lesenswert?

Tja.
Und aus der Ausgabe 'OK' bzw. 'Nicht OK' kann man so wunderbare 
Rückschlüsse darauf ziehen, was denn das Problem ist. :-)

Warum lässt du dir denn nicht einfach mal sub ausgeben!
Aus dem Zahlenwert sieht man doch viel mehr als aus einer OK/Nicht OK 
Meldung.


for(uint8_t j=0; j<=1; j++){
    sub= &MENUSTR[j] + sub;
    }

Das ist Unsinn!
Du MUSST über pgm_read_byte gehen.
Alles andere kann ev. das Richtige ergeben (weil ja immer an jeder 
Speicherstelle irgendetwas drinnen steht und jedes Teil eine Adresse 
hat), aber das ist dann Zufall!

Und achte ein bischen auf die äußere Form deines Programmes. 
Interessanterweise sind es nämlich meistens die 
Hässlichen-Kraut-und-Rüben Programme, die solch seltsame sporadische 
Fehler aufweisen.

1
#include <stdio.h>
2
#include <string.h>
3
4
// AVR include files
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
9
//P.Fleury
10
#include "lcd.h"
11
12
uint8_t sub=0;
13
14
const uint8_t MENUSTR[] PROGMEM ={
15
  3, 
16
  7, 
17
  3, 
18
  0, 
19
};
20
21
void lcd_puti( int number )
22
{
23
  char buffer[10];
24
25
  itoa( number, buffer, 10 );
26
  lcd_puts( buffer );
27
}
28
29
int  main()
30
{  
31
  DDRG &=(1<<PG2);
32
  DDRA &=(1<<PA4) & (1<<PA5) & (1<<PA6) & (1<<PA7);
33
34
  //Werden noch nicht benötigt
35
  PORTG |= (1<<PG2);  // Taster Pullups
36
  PORTA |= (1<<PA4) | (1<<PA5) | (1<<PA6) | (1<<PA7); // Taster Pullups
37
38
  //   LCD Initialisierung
39
  lcd_init (LCD_DISP_ON);
40
  lcd_clrscr();
41
42
  sub = 0;
43
  for( uint8_t j = 0; j <= 1; j++ ) {
44
    sub = sub + pgm_read_byte( &MENUSTR[j] );
45
  }
46
47
  lcd_gotoxy( 1, 1 );
48
  lcd_puti( sub );
49
50
  if( sub == 10 ) {
51
    lcd_puts("ok");
52
  }
53
  else {
54
    lcd_puts("nicht ok");
55
  }
56
57
  for (;;)
58
  {
59
  }
60
}

von Alex (Gast)


Lesenswert?

Stimmt. Ich werds mal ausgiebig testen. Werde aber erst nächste Woche 
wieder dazu kommen. Bis hier hin schon mal Danke an alle Helfer.

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.