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.
1 | void test() |
2 | {
|
3 | static unsigned int Time = 0; |
4 | |
5 | if (!Time) |
6 | Time = TimeReload_ee; |
7 | |
8 | Time--; |
9 | |
10 | bla bla |
11 | bla
|
12 | }
|
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:
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.
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 | 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.
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 | static unsigned int Time=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.
Gerhard schrieb: > Bis auf den Rückgabewert, der nicht 0 sein darf. Da ist kein Rückgabewert. Wo soll da einer sein?
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 :-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.