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
Gerhard schrieb:> static unsigned int Time=TimeRelaod_ee;
Wenn du einen Wert aus dem EEPRPOM haben willst musst
du ihn auch aus dem EEPROM lesen, nicht (so wie du es
jetzt machen willst) aus dem RAM.
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.
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:
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...
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.
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.
Wäre C++ für Dich eine Option? In C++ sind im Initializer einer
statischen lokalen Variable auch Funktionen zulässig:
1
intinit(){return13;}
2
3
intfoo()
4
{
5
staticinti=init();
6
returni;
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.
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.
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)
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...
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
staticunsignedintTime=TimeReload_ee();
heißen muss. Wobei gegen Rufus' Lösung natürlich auch nichts einzuwenden
ist.
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.
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 :-)