Wie einer static-Variablen einen Eeprom-Startwert zuweisen?

Gast #4628587
Lesenswert?
• ▲
▼
Steh gerade ein wenig auf dem Schlauch...

Eine Funktion, die jede Sekunde aufgerufen wird, soll mit einem 
Eeprom-Wert beginnen.

void test ()
{static unsigned int Time=1000;
Time--;
bla
bla
bla
if (!Time)
    Time=TimeReload_ee;
}

Eine Möglichkeit wäre natürlich, Time von 0 bis TimeReload_ee laufen zu 
lassen. Ich hätte es aber gern als Abwärtszähler.

static unsigned int Time=TimeRelaod_ee;
führt zu einem (nicht unerwarteten) Fehler: must be constant expression
Gast #4628603
Lesenswert?
• ▲
▼
Es geht nur um den allerersten Aufruf.
Ist Time abgelaufen, wird es ja aus dem Eeprom nachgeladen.

Ursprünglich war der Startwert fest, nachträglich soll das jetzt ein 
einstellbarer Parameter sein.
Moderator Persönliche Seite #4628622
Lesenswert?
• ▲
▼
Gerhard schrieb:
> Es geht nur um den allerersten Aufruf.

Hat Rufus doch gelöst! Beim ersten Aufruf von test() wird Time mit dem 
EEPROM-Wert initialisiert, nämlich hier:
1
  if (!Time) 
2
    Time = TimeReload_ee;

Rufus nutzt hier aus, dass der Time-Wert aus dem EEPROM niemals 0 sein 
kann. Daher initialisiert er Time = 0 (was übrigens bei statics Default 
ist). Und damit wird auch beim ersten Aufruf der EEPROM-Wert geladen.

Allgemein macht man eine Laufzeitinitialisierung von Statics zum 
Beispiel so:
1
test ()
2
{
3
    static unsigned char already_called = 0;
4
    static int mystatic;
5

6
    if (! already_called)
7
    {
8
        mystatic = mein_initialwert_aus_eeprom_oder_sonstwoher;
9
        already_called = 1;
10
    }
11

12
   ...
13
}

Ist hier bei diesem trivialen Problem aber nicht notwendig.
Gast #4628638
Lesenswert?
• ▲
▼
Wenn die Variable beim Start, aus einem EEPROM, vorbesetzt werden soll, 
dann ist eine lokale statische vermutlich das falsche Mittel!
Zumindest arg unelegant.


Wäre es nicht schöner diese Variable global anzulegen und vor dem 
Main-Loop zu initialisieren...
Moderator Persönliche Seite #4628647
Lesenswert?
• ▲
▼
U. F. schrieb:
> Wäre es nicht schöner diese Variable global anzulegen und vor dem
> Main-Loop zu initialisieren...

Es reicht, wenn der Start- bzw. Wiederholungswert global ist, also 
TimeReload_ee. Genau das ist der Fall.

Nach der Zählvariablen Time fragt keine Sau^H^H^Handere Funktion, 
deshalb ist eine lokale static-Variable auch hier die korrekte Lösung.
Gast #4628648
Lesenswert?
• ▲
▼
Ich finde das nicht unelegant.

Immerhin ist die Variable dort hingeschrieben worden, wo sie verwendet 
wird und sie ist auch nur innerhalb dieser einen Funktion sichtbar.

Klar macht es umgekehrt auch einen gewissen Sinn, alle EEprom variablen 
woanders zsuammen zu fassen. Ist halt Geschmacks-Sache.
#4628679
Lesenswert?
• ▲
▼
Wäre C++ für Dich eine Option? In C++ sind im Initializer einer 
statischen lokalen Variable auch Funktionen zulässig:

1
int init() { return 13; }
2

3
int foo()
4
{
5
        static int i = init();
6
        return i;
7
}

init wird genau einmal aufgerufen und zwar bevor das Ausführen des 
Funktionsblockes von foo zum ersten Mal beginnt. (Es sei denn, init 
wirft eine Exception. In dem Fall gilt i als nicht initialisiert und 
die Funktion wird beim nächste Eintritt in foo erneut aufgerufen.)

Möglicherweise kann ein neuerer C-Standard das ja auch? Ob und ggfs. 
Welche Einschränkungen es bei Mikrocontrollern gibt, kann ich allerdings 
nicht sagen.
#4628710
Lesenswert?
• ▲
▼
Noch eine andere Anregung:
Wenn du jede Sekunde einen Wert aus dem EEPROM liest, wird es in kurzer 
Zeit nicht mehr gehen. Wenn du pro uC ca. 100'000 Zugriffe hast, hast du 
nach gut einem Tag die 100'000 verbraucht, danach ist es nicht mehr 
garantiert, dass du weiter zugreifen kannst.

(Kommt auf den uC an)
Moderator Persönliche Seite #4628718
Lesenswert?
• ▲
▼
TM F. schrieb:
> Wenn du jede Sekunde einen Wert aus dem EEPROM liest, wird es in kurzer
> Zeit nicht mehr gehen.

Häh? Seit wann nutzt das Lesen eines EEPROMs dieses ab? Du meinst eher 
wohl das Schreiben! Das ist hier aber gar nicht der Fall.

Außerdem liegt der Wert des EEPROMs bereits im RAM vor, nämlich als 
TimeReload_ee.

Unglaublich, was hier spekuliert wird...
#4628720
Lesenswert?
• ▲
▼
Frank M. schrieb:
> A. H. schrieb:
>> Wäre C++ für Dich eine Option? In C++ sind im Initializer einer
>> statischen lokalen Variable auch Funktionen zulässig:
>
> Das löst hier aber nicht die Aufgabe, die Zählvariable immer wieder neu
> zu setzen, nämlich wenn sie runter auf 0 gelaufen ist. Rufus' Lösung ist
> hier schon die richtige.

Es war zumindest das, was der TO vorhatte:

> static unsigned int Time=TimeRelaod_ee;
> führt zu einem (nicht unerwarteten) Fehler: must be constant expression

Mit C bekomme ich den gleichen Fehler, mit C++ funktioniert 's 
problemlos. Wobei es genaugenommen natürlich

1
  static unsigned int Time=TimeReload_ee();

heißen muss. Wobei gegen Rufus' Lösung natürlich auch nichts einzuwenden 
ist.
Gast #4628749
Lesenswert?
• ▲
▼
Frank M. schrieb:
> Hat Rufus doch gelöst! Beim ersten Aufruf von test() wird Time mit dem
> EEPROM-Wert initialisiert, nämlich hier:

Das war die Antwort an den Arduinoquäler, Rufus' Antwort hatte ich noch 
gar nicht gesehen.

Gut, hätte ich noch dazu schreiben können, Time interessiert schon. Wird 
zurückgegeben an die aufrufende Funktion und wird auch weiterverwendet. 
Deshalb wollte ich auch nicht einfach die Zählrichtung ändern.

Und, nein, als globale Variable will ich den Zähler nicht haben. 
TimeReload_ee ist eine globale Variable, und die liegt im Eeprom.

Rufus Lösung ist (fast) genau das, was ich suchte. Bis auf den 
Rückgabewert, der nicht 0 sein darf. Aber das bekomme ich jetzt schon 
hin :-)

C++, hm. Noch nie damit beschäftigt, also eher nein.

Also, vielen Dank an alle, Problemchen gelöst.
Gast #4628844
Lesenswert?
• ▲
▼
Wie schon gesagt, in echt ist der vorhanden, tat aber zum eigentlichen 
Problem nichts zur Sache, deshalb weggelassen.
0 ist bei mir ein Fehlercode, 1 der minimale Rückgabewert.
Bei deinem Beispiel wäre 0 der kleinste Rückgabewert. Konntest du 
natürlich nicht wissen.

Alles ist gut :-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren