Forum: Mikrocontroller und Digitale Elektronik PROGMEM Array an Funktion übergeben


von Heribert B (Gast)


Lesenswert?

Hallo,

ich hab ein Led-Pattern

const uint8_t pattern PROGMEM = {0, 255, 255, 0, 255, 255, 0, 0};

welches ich an einer Funktion übergeben möchte. Angesteuert werden damit 
2 Leds. Bekomme das irgendwie nicht hin.
1
func(pattern);
2
3
void func(const uint8_t *pattern)
4
{
5
static uint8_t step = 0;
6
7
// falls ein pattern nicht ausreicehnd groß ist
8
if(sizeof(pattern) > step) step = 0;
9
10
ledvalue1 = pgm_read_byte(&pattern[step]);
11
ledvalue2 = pgm_read_byte(&pattern[(step+1);
12
13
step++;
14
}

von Schrumpfkopf (Gast)


Lesenswert?

>Bekomme das irgendwie nicht hin.

Das ist höchst bedauerlich.

Wenn Du allerdings Hilfe erwartest, solltest Du das Ist- und 
Sollverhalten genauer beschreiben.

Wolltest Du vielleicht statt

>step++;

nicht eher

step += 2;

schreiben?

von Heribert B (Gast)


Lesenswert?

So, hab noch ein bisschen getüfftelt.
Jedoch habe ich noch ein paar Probleme. Zum einen meckert der Compiler
'__progmem__' attribute ignored
Des weiteren kann ich mit sizeof(pattern) nicht die Größe auslesen. 
Ergebnis ist immer 1.
1
const uint8_t pattern PROGMEM = {0, 255, 255, 0, 255, 255, 0, 0};
2
3
func(pattern);
4
5
void func(const uint8_t *pattern)
6
{
7
static uint8_t step = 0;
8
uint8_t sizePattern = sizeof(pattern)/sizeof(pattern[0]);
9
ledValue1 = pgm_read_byte(patter[step]);
10
step++;
11
}

von Tom (Gast)


Lesenswert?

Bei der Übergabe an die  Funktion wird ein Array zu einem ordinären 
Pointer. Du musst also die Größe in main berechnen und mit übergeben.


http://c-faq.com/aryptr/index.html

von DirkB (Gast)


Lesenswert?

Heribert B schrieb:
> Des weiteren kann ich mit sizeof(pattern) nicht die Größe auslesen.
> Ergebnis ist immer 1.

Das sind absolute C-Grundlagen. Wenn das in deinem Tutorial/Buch nicht 
drin steht, dann entsorge dies und bedenke, dass da noch mehr 
Fehlinformationen drin sind.

Heribert B schrieb:
> func(pattern);
>
> void func(const uint8_t *pattern)

Bei der Deklaration sollte der Rückgabetyp mit angegeben werden, da 
sonst implizit int angenommen wird.
Desweiteren ist der Paramtername egal. Der Typ ist wichtig.
(Der Name hilft aber etwas als Dokumentation (wenn er gut gewählt ist)

void func(const uint8_t *pattern);

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Heribert B schrieb:
> So, hab noch ein bisschen getüfftelt.
Verwende bitte in Zukunft die passenden Tokens um den C-Code (wie knapp 
über der Edit-Box beschrieben):
1
[c]
2
  C-Code
3
[/c]

von Ulrich P. (uprinz)


Lesenswert?

Das Problem sind die Grundlagen...

Zuerst beschreibe doch, was Du erreichen willst:
1
typedef struct {
2
  uint8_t pattern;
3
  uint8_t value;
4
} tPATTERN;

Jetzt kennt der Compiler auch die Größe eines Elements Deines Arrays. 
Damit legst Du ein Array aus vielen Elementen dieser Art an:
1
const tPATTERN pattern[] = { 
2
  { 0, 255 },
3
  { 255, 0 },
4
... };

Nun, da der Compiler weiß, wie ein Element aussieht, kann er auch die 
Anzahl der Elemente bestimmen, ganz dynamisch zur Compile-Zeit:
1
#define PATTERNS (sizeof(pattern) / sizeof(pattern[0]))

Da Du Deiner Funktion nun einen Pointer auf ein Element bekannter Größe 
übergeben kannst, kann innerhalb der Funktion auch der Compiler selbst 
die korrekte Schrittweite der Pointer bestimmen:
1
void blubb( const tPATTERN *pattern) {
2
  static npat = 0;
3
  
4
  ledvalue1 = pgm_read_byte(&pattern[step]->pattern);
5
  ledvalue2 = pgm_read_byte(&pattern[step]->value);
6
7
  step++;
8
  if (step == PATTERNS) step = 0;
9
}

Ich persönlich finde, dass man gerade als Anfänger erst einmal 
ausführliche structe ausdenken und diese dann konsequent verwenden 
sollte, bevor man Assembler-artigen Code schreibt, den man selbst nach 
ein paar Tagen Pause nicht mehr versteht.
Außerdem bitte hier im Wiki noch mal nachlesen, einige dieser 
pgm_read_byte sind eventuell nicht mehr nötig, weil moderne AVRGCC 
Versionen das im Hintergrund erledigen können.

von Carl D. (jcw2)


Lesenswert?

Heribert B schrieb:
>
1
> const uint8_t pattern PROGMEM = {0, 255, 255, 0, 255, 255, 0, 0};
2
> 
3
> func(pattern);
4
> 
5
> void func(const uint8_t *pattern)
6
> {
7
> static uint8_t step = 0;
8
> uint8_t sizePattern = sizeof(pattern)/sizeof(pattern[0]);
9
> ledValue1 = pgm_read_byte(patter[step]);
10
> step++;
11
> }
12
>

Das grundlegendste Problem an diesem Stück Code ist, daß dem Array die 
[] fehlen.

> Des weiteren kann ich mit sizeof(pattern) nicht die Größe auslesen.
> Ergebnis ist immer 1.

Siehe oben.

von Falk B. (falk)


Lesenswert?

@  Heribert B (Gast)


>const uint8_t pattern PROGMEM = {0, 255, 255, 0, 255, 255, 0, 0};

>welches ich an einer Funktion übergeben möchte. Angesteuert werden damit
>2 Leds. Bekomme das irgendwie nicht hin.

Wenn man schon einen aktuellen Compiler hat (Atmelstudio mit avr gcc?), 
dann kann man es auch ein wenig komfortabler machen.

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Flash_mit_flash_und_Embedded-C
1
const __flash uint8_t pattern= {0, 255, 255, 0, 255, 255, 0, 0};
2
3
void func(const __flash uint8_t *pattern);
4
5
6
void func(const __flash uint8_t *pattern) {
7
  static uint8_t step = 0;
8
9
  if(step >= sizeof(pattern) ) step = 0;
10
  ledvalue1 = pattern[step];
11
  ledvalue2 = pattern[step+1];
12
  step++;
13
}

von Carl D. (jcw2)


Lesenswert?

Warum nicht einfach mal so versuchen:
1
const __flash uint8_t pattern[] = {0, 255, 255, 0, 255, 255, 0, 0};
2
3
void func(const __flash uint8_t *pattern);
4
5
6
void func(const __flash uint8_t *pattern) {
7
  static uint8_t step = 0;
8
9
  if(step >= sizeof(pattern) ) step = 0;
10
  ledvalue1 = pattern[step];
11
  ledvalue2 = pattern[step+1];
12
  step++;
13
}
mit Array!

Hat eigentlich der GCC sich nie über die Initialisierung von pattern 
beschwert?

von Falk B. (falk)


Lesenswert?

2 Dumme, 1 Gedanke ;-)

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.