Forum: Mikrocontroller und Digitale Elektronik Problem mit Strukturen


von Pal .. (pal)


Lesenswert?

Hallo,

ich habe mir eine Struktur mit eeprom-Speicherstellen angelegt. Leider 
nervt mich der Compiler mit einem Fehler - ich sehe nur nicht was er von 
mir will.

Kann mir jemand sagen wo mein Problem ist?
1
/* EEPROM Speicher */
2
uint16_t eeBetr_h       EEMEM = 2;                      // Aktuelle Betriebsstunden aus EEPROM
3
uint8_t  eeBetr_min_1600  EEMEM = 3;                      // Aktuelle Betriebsminuten bis 1600h aus EEPROM
4
uint8_t  eeBetr_min_3200  EEMEM = 4;                      // Aktuelle Betriebsminuten bis 3200h aus EEPROM
5
uint8_t  eeBetr_min_4800  EEMEM = 5;                      // Aktuelle Betriebsminuten bis 4800h aus EEPROM
6
uint8_t  eeBetr_min_6400  EEMEM = 6;                      // Aktuelle Betriebsminuten bis 6400h aus EEPROM
7
uint8_t  eeBetr_min_8000  EEMEM = 7;                      // Aktuelle Betriebsminuten bis 8000h aus EEPROM
8
uint8_t  eeBetr_min_9600  EEMEM = 8;                      // Aktuelle Betriebsminuten bis 9600h aus EEPROM
9
uint8_t  eeBetr_min_11200 EEMEM = 9;                      // Aktuelle Betriebsminuten bis 11200h aus EEPROM
10
uint8_t  eeBetr_min_12800 EEMEM = 10;                      // Aktuelle Betriebsminuten bis 12800h aus EEPROM
11
12
/* Übersetzungstabelle für EEPROM Speicherstellen */
13
struct numSel
14
{
15
  uint16_t memcycl;                                // Speicherzyklen
16
  uint8_t  memory;                                // Speicherplatz
17
};
18
19
struct numSel numMemSel[] =
20
{
21
  { 1600,  eeBetr_min_1600  },
22
  { 3200,  eeBetr_min_3200  },
23
  { 4800,  eeBetr_min_4800  },
24
  { 6400,  eeBetr_min_6400  },
25
  { 8000,  eeBetr_min_8000  },
26
  { 9600,  eeBetr_min_9600  },
27
  { 11200, eeBetr_min_11200 },
28
  { 12800, eeBetr_min_12800 },
29
};
30
31
#define ARRAY_SIZE(x)  (sizeof(x)/sizeof(*x))


Die Fehlermeldung lautet:
1
../betrStd.c:41: error: initializer element is not constant
2
../betrStd.c:41: error: (near initialization for 'numMemSel[0].memory')
3
../betrStd.c:42: error: initializer element is not constant
4
../betrStd.c:42: error: (near initialization for 'numMemSel[1].memory')
5
../betrStd.c:43: error: initializer element is not constant
6
../betrStd.c:43: error: (near initialization for 'numMemSel[2].memory')
7
../betrStd.c:44: error: initializer element is not constant
8
../betrStd.c:44: error: (near initialization for 'numMemSel[3].memory')
9
../betrStd.c:45: error: initializer element is not constant
10
../betrStd.c:45: error: (near initialization for 'numMemSel[4].memory')
11
../betrStd.c:46: error: initializer element is not constant
12
../betrStd.c:46: error: (near initialization for 'numMemSel[5].memory')
13
../betrStd.c:47: error: initializer element is not constant
14
../betrStd.c:47: error: (near initialization for 'numMemSel[6].memory')
15
../betrStd.c:48: error: initializer element is not constant
16
../betrStd.c:48: error: (near initialization for 'numMemSel[7].memory')

von Karl H. (kbuchegg)


Lesenswert?

pal ... schrieb:

> ../betrStd.c:41: error: initializer element is not constant

Na ja. So schwer ist das dann auch wieder nicht.
Da wird etwas initialisiert. Und das, womit es initialisiert wird, muss 
eine Konstante sein. Also

   int i = 5;

ist eine korrekte Initialisierung, weil 5 eine Konstante ist.


   int j = sqrt( k );

ist nicht korrekt, weil sqrt(k) keine Konstante ist.

Was soll
1
struct numSel numMemSel[] =
2
{
3
  { 1600,  eeBetr_min_1600  },
in diesem Zusammenhang "eeBetr_min_1600" sein?
Es müsste eigentlich eien Konstante sein, deren Wert der COmpiler zur 
Compilierzeit ermitteln kann. Und weil er das nicht kann, darum setzt es 
ein:
error: initializer element is not constant

Das Problem an dieser Stelle ist aber nicht, dass das irgendein 
Schreiweisen-Problem wäre, sondern es ist ein prinzipielles Problem: Du 
hast hier nichts verwendet was konstant wäre. Daher die Meldung.

von Oliver (Gast)


Lesenswert?

pal ... schrieb:
> Die Fehlermeldung lautet:../betrStd.c:41: error: initializer element is >not 
constant
> ../betrStd.c:41: error: (near initialization for 'numMemSel[0].memory')

Steht doch alles da.

pal ... schrieb:
> struct numSel numMemSel[] =
> {
>   { 1600,  eeBetr_min_1600  },

Zur Initialisierung von structs sind in C nur echte Konstanten erlaubt, 
keine Variablen (selbst, wenn sie const wären, nicht).

Allerdings ist mir sowieso nicht ganz klar, was du da genau machen 
willst. eeBetr_min_1600 liegt schließlich im eeprom...

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Ich kann nur raten, was du da eigentlich vor hattest. Du wolltest dir in 
dieser STruktur die Speicheradressen der Teile im EEPROM ablegen. Hast 
es aber nicht getan.

Die ganze Idee ist aber "flawed". Das machst du ganz anders. Und das 
beginnt damit, dass du den Compiler das EEPROM verwalten lässt.

Du legst dir eine Struktur an
1
struct ConfigValues
2
{
3
  uint16_t eeBetr_h;              // Aktuelle Betriebsstunden
4
  uint8_t  eeBetr_min_1600;       // Aktuelle Betriebsminuten
5
  uint8_t  eeBetr_min_3200;       // Aktuelle Betriebsminuten bis 3200h
6
  ...
7
};

und von dieser Struktur, gibt es 2 Instanzen.
Die eine existiert im EEPROM
1
struct ConfigValues eepromValue EEMEM;

und die andere im SRAM
1
struct ConfigValues Values;

und beim Hochfahren des Programms kopierst du die komplette Struktur aus 
dem EEPROM ins SRAM, bzw. bei Veränderung aus dem SRAM wieder zurück ins 
EEPROM

AVR-GCC-Tutorial: Block lesen/schreiben

von Pal .. (pal)


Lesenswert?

danke für die Antworten...

Der Gedanke dabei ist, je nachdem welche betr_std ich erhalte schreibe 
ich auf einen anderen eeprom-speicherplatz

Die zugehörige Funktion lautet:
1
/*
2
 * Regelt das Lesen / Schreiben der Betriebsminuten
3
 * aus / in das EEPORM
4
 *
5
 * rw = 0  (read)
6
 * rw = 1  (write)
7
 */
8
void eeManagerMin(uint8_t rw) {
9
10
  for(uint8_t i = 0; i < ARRAY_SIZE(numMemSel); i++) {
11
12
    if(betr_h < numMemSel[i].memcycl) {
13
14
      if(rw == 0) {                            // read
15
        betr_min = eeprom_read_byte(&numMemSel[i].memory);
16
        if(betr_min == 255) {
17
          betr_min = 0;
18
          eeprom_write_byte(&numMemSel[i].memory, betr_min);      // Defaultwert setzen
19
        }
20
      } else if(rw == 1) {                        // write
21
        if(betr_min >= 60) {
22
          eeprom_write_byte(&numMemSel[i].memory, 0);
23
        } else {
24
          eeprom_write_byte(&numMemSel[i].memory, betr_min);
25
        }
26
      }
27
    }
28
  }
29
30
}

@Karl Heinz: Ich versuche einen Betriebsstundenzähler zu progr und 
möchte jede Minute ins eeprom schreiben.
Aus diesem Grund möchte ich nur einzelne Speicher beschreiben, wenn 
diese ca 100000mal beschrieben sind gehe ich zur nächsten Stelle.

von Karl H. (kbuchegg)


Lesenswert?

pal ... schrieb:

> Der Gedanke dabei ist, je nachdem welche betr_std ich erhalte schreibe
> ich auf einen anderen eeprom-speicherplatz

Dazu brauchst du aber die Adresse unter der der Wert im EEPROM abgelegt 
wurde. Also musst du dir auch die entsprechende Adresse in deiner 
Struktur aufheben. Und diese Adresse ist dann auch eine Compiletime 
Konstante.

1
struct numSel
2
{
3
  uint16_t memcycl;                                // Speicherzyklen
4
  uint8_t* memory;                                // Speicherplatz
5
};
6
7
struct numSel numMemSel[] =
8
{
9
  { 1600,  &eeBetr_min_1600  },
10
11
....
12
13
14
         betr_min = eeprom_read_byte( numMemSel[i].memory );

von Pal .. (pal)


Lesenswert?

Danke Karl Heinz das ist mir nicht aufgefallen.

Nur zur Vollständigkeit:
Das Schreiben erfolgt ebenfalls nach dem gleichen Schema
1
eeprom_write_byte(numMemSel[i].memory, betr_min);

Danke!!!

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.