www.mikrocontroller.net

Forum: Compiler & IDEs PROGMEN Array in Schleife verarbeiten


Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
const uint8_t MENUSTR[] PROGMEM ={
3, 
7, 
3, 
0, 
};

...
main:
uint8_t sub=0;

//Schleife, die nicht funktioniert:
for(uint8_t j=0; j==1; j++){
sub= &MENUSTR[j] + sub);
}
    

//soll das gleiche machen:
    
uint8_t j=0;
sub= &MENUSTR[j] + sub;
j++;
sub= &MENUSTR[j] + sub;
//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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Vergleichsbedingung in der for Schleife ist falsch, Du willst wohl:
uint8_t sub=0;

//Schleife, die nicht funktioniert:
for(uint8_t j=0; j<=1; j++){
sub= &MENUSTR[j] + sub);
}

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

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

Autor: Stefan Ernst (sternst)
Datum:

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

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab dann mal noch angepasst. Die Beiträge habe ich leider erst etwas 
später gesehen.
const uint8_t MENUSTR[] PROGMEM ={
3, 
7, 
3, 
0, 
};

const uint8_t *PTMENUSTR PROGMEM = MENUSTR;

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

War es so gemeint wegen der automatischen Optimierung?

Gruß
Alex

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex (Gast)
Datum:

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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint8_t sub=0;

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

So würde er dann aussehen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist richtig. Was genau klappt damit nicht?

Autor: Alex (Gast)
Datum:

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

In meinem Beispiel:
const uint8_t MENUSTR[] PROGMEM ={
3, 
7, 
3, 
0, 
};

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steht nicht so viel mehr drin:
#include <stdio.h>
#include <string.h>

// AVR include files
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

//P.Fleury
#include "lcd.h"

uint8_t sub=0;

const uint8_t MENUSTR[] PROGMEM ={
3, 
7, 
3, 
0, 
};


int  main()
{  
DDRG &=(1<<PG2);
DDRA &=(1<<PA4) & (1<<PA5) & (1<<PA6) & (1<<PA7);


//Werden noch nicht benötigt
PORTG |= (1<<PG2);  // Taster Pullups
PORTA |= (1<<PA4) | (1<<PA5) | (1<<PA6) | (1<<PA7); // Taster Pullups




//   LCD Initialisierung
  lcd_init (LCD_DISP_ON);
        lcd_clrscr();

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

lcd_gotoxy(1,1);

//Hier kann ich die Ergebnisse mit LCD Ausgabe prüfen

if(sub==10){
  lcd_puts("ok");
}else{
  lcd_puts("nicht ok");
}

  for (;;){}
}

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

#include <stdio.h>
#include <string.h>

// AVR include files
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

//P.Fleury
#include "lcd.h"

uint8_t sub=0;

const uint8_t MENUSTR[] PROGMEM ={
  3, 
  7, 
  3, 
  0, 
};

void lcd_puti( int number )
{
  char buffer[10];

  itoa( number, buffer, 10 );
  lcd_puts( buffer );
}

int  main()
{  
  DDRG &=(1<<PG2);
  DDRA &=(1<<PA4) & (1<<PA5) & (1<<PA6) & (1<<PA7);

  //Werden noch nicht benötigt
  PORTG |= (1<<PG2);  // Taster Pullups
  PORTA |= (1<<PA4) | (1<<PA5) | (1<<PA6) | (1<<PA7); // Taster Pullups

  //   LCD Initialisierung
  lcd_init (LCD_DISP_ON);
  lcd_clrscr();

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

  lcd_gotoxy( 1, 1 );
  lcd_puti( sub );

  if( sub == 10 ) {
    lcd_puts("ok");
  }
  else {
    lcd_puts("nicht ok");
  }

  for (;;)
  {
  }
}

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.