Hallo,
wie kann ich einen Wert im EEPROM beim allerersten Programmlauf ablegen?
Also vorbelegen quasi und beim nächsten Programmlauf wird die
Speicherzelle mit dem zur Laufzeit entstandenem Wert überschrieben?
Kann ich das auch im AVR Studio machen?
Gruß Artur
PS. die Befehle zu Schreiben/Lesen des EEPROMs sind mir bekannt, mir
geht es nur um den Trick.
Du kannst das EEPROM direkt aus dem Programmierdialog des AVR Studio
heraus beschreiben. Mit einer von dir ausgewählten Datei. Ebenso kannst
du es auch auslesen.
Jungfräuliche AVRs haben im EEPROM FF an allen Stellen. Beim allerersten
Programmstart kannst du ein zusätzliches Byte != FF setzen. Beim
nächsten Programmstart testest du dieses zusätzliche Byte und weißt
dann, das es bereits einen Programmstart gegeben hat. Von der Benutzung
der Speicherstelle bei 0x00 ist aus anderen Gründen abzuraten.
Hallo,
Danke Euch. Ich werde es mal probieren.
@DIL EMMA:
An sowas dachte ich, aber ich habe keine Vorstellung mit welcher
Sicherheit die Zellen den beschriebenen Zustand haben.
Es hat sich nun folgendes, neues Problem ergeben:
1
voidmain()
2
{
3
...
4
Kardan_Faktor=eeprom_read_float(&KF);
5
Umfang_Faktor=eeprom_read_float(&UF);
6
7
sei();//Interrupts an
8
9
//Hauptschleife
10
while(1)
11
{
12
13
switch(main_state)
14
{
15
casestate_Tacho:
16
17
zahl=f_Welle*Kardan_Faktor*Umfang_Faktor*3.6;;
18
Zahlenart=GANZ;
19
20
if(get_key_short(1<<KEY1))
21
main_state=state_OelTemp;
22
if(get_key_short(1<<KEY2))
23
main_state=state_U_Bat;
24
break;
25
26
casestate_U_Bat:
27
28
zahl=delta_V*MESSFAKTOR*ADC_result;
29
Zahlenart=DEZIMAL1;
30
31
if(get_key_short(1<<KEY1))
32
main_state=state_Tacho;
33
34
if(get_key_short(1<<KEY2))
35
main_state=state_Tages_km;
36
break;
37
38
casestate_Tages_km:
39
40
zahl=222;
41
Zahlenart=GANZ;
42
43
if(get_key_short(1<<KEY1))
44
main_state=state_U_Bat;
45
46
if(get_key_short(1<<KEY2))
47
main_state=state_Gesamt_km1;
48
break;
49
50
casestate_Gesamt_km1:
51
52
zahl=km_Stand/1000;
53
Zahlenart=GANZ;
54
55
if(get_key_short(1<<KEY1))
56
main_state=state_Tages_km;
57
58
if(get_key_short(1<<KEY2))
59
main_state=state_Gesamt_km2;
60
break;
61
62
casestate_Gesamt_km2:
63
64
km_int=km_Stand/1000;
65
zahl=(uint16_t)km_Stand-km_int*1000;
66
Zahlenart=GANZ;
67
68
if(get_key_short(1<<KEY1))
69
main_state=state_Gesamt_km1;
70
71
if(get_key_short(1<<KEY2))
72
main_state=state_Kardan;
73
break;
74
75
casestate_Kardan:
76
77
zahl=Kardan_Faktor;
78
Zahlenart=DEZIMAL2;
79
80
if(get_key_short(1<<KEY1))
81
main_state=state_Gesamt_km2;
82
83
if(get_key_short(1<<KEY2))
84
main_state=state_Umfang;
85
86
if(get_key_long(1<<KEY1))
87
Kardan_Faktor-=0.01;
88
89
if(get_key_long(1<<KEY2))
90
Kardan_Faktor+=0.01;
91
break;
92
93
casestate_Umfang:
94
95
zahl=Umfang_Faktor;
96
Zahlenart=DEZIMAL2;
97
98
if(get_key_short(1<<KEY1))
99
main_state=state_Kardan;
100
101
if(get_key_short(1<<KEY2))
102
main_state=state_OelTemp;
103
104
if(get_key_long(1<<KEY1))
105
Umfang_Faktor-=0.01;
106
107
if(get_key_long(1<<KEY2))
108
{
109
PORTC^=(1<<PC1);//LED toggle
110
Umfang_Faktor+=0.01;
111
}
112
break;
113
114
casestate_OelTemp:
115
116
zahl=777;
117
Zahlenart=GANZ;
118
119
if(get_key_short(1<<KEY1))
120
main_state=state_Umfang;
121
122
if(get_key_short(1<<KEY2))
123
main_state=state_Tacho;
124
125
if(get_key_long(1<<KEY2))
126
{
127
cli();//Interrupts aus
128
eeprom_write_float(&KF,Kardan_Faktor);
129
eeprom_write_float(&UF,Umfang_Faktor);
130
sei();//Interrupts an
131
}
132
break;
133
134
default:
135
136
zahl=999;
137
Zahlenart=GANZ;
138
139
break;
140
}
141
...
Wenn ich die Zeilen
Kardan_Faktor = eeprom_read_float(&KF);
Umfang_Faktor = eeprom_read_float(&UF);
einfüge lassen sich die Variablen Kardan_Faktor und Umfang_Faktor im
state_Kardan und state_Umfang nicht per Tastendruck verändern.
So habe ich es deklariert (Ausserhalb von main()):
float Kardan_Faktor = 0;
float KF EEMEM;
float Umfang_Faktor = 0;
float UF EEMEM;
arser schrieb:> state_Umfang nicht per Tastendruck verändern
Sind das denn richtig deklarierte Variablen? Die globale Deklaration
hast du ja nicht mitgepostet. Die 2te Frage ist, ob deine 'get_key_long'
Routine über jeden Verdacht erhaben ist. Toggelt denn die Test LED?
arser schrieb:> cli(); //Interrupts aus> eeprom_write_float(&KF, Kardan_Faktor);> eeprom_write_float(&UF, Umfang_Faktor);> sei(); //Interrupts an
Und du solltest da unbedingt noch
1
eeprom_busy_wait();
dazwischen machen. Beim Lesen braucht mans nicht, beim Schreiben aber
schon.
Hallo Mathias,
die Deklaration ist global, vor main().
Die Test LED toggelt.
Ich habe es auch versucht, dass ich die Variablen in andere zwei
kopiere, wahrscheinlich unsinnig, aber es hat nicht funktioniert.
Gruß Artur
arser schrieb:> Hallo,> Danke Euch. Ich werde es mal probieren.> @DIL EMMA:> An sowas dachte ich, aber ich habe keine Vorstellung mit welcher> Sicherheit die Zellen den beschriebenen Zustand haben.
Den haben sie, keine Sorge.
So ähnlich mach ichs auch, allerdings einfacher.
1
....
2
3
intmain()
4
{
5
eeprom_write_float(&KF,0.5);
6
eeprom_write_float(&UF,0.5);
7
8
9
....deinrestlicherCode
und hab dann die Werte im EEPROM, ehe das eigentliche Programm loslegt.
:-)
Wenn dann der Rest funktioniert, kommentiere ich einfach die beiden
Zeilen aus und fertig.
Arser schrieb:> Hallo Mathias,>> die Deklaration ist global, vor main().
Arser.
Bitte mach ed dir zur Regel, deinen Code einfach in Form eines C-Files
an das Psoting anzuhängen.
Beschreib nicht deinen Code, zeig ihn nicht in Auszügen, sondern häng
einfach den Code direkt an. Das ist für dich einfacher, das ist für uns
einfacher, viele Nachfragen nach Details entfallen und nicht zu letzt
zeigt sich immer wieder, dass das eigentliche Problem gar nicht in dem
Codestück sitzt, welches du in Ausschnitten gezeigt hast.
Hallo Karl Heinz,
hast recht, hätte ich gleich machen sollen. Wollte Euch einfach nicht
mit zuviel Code belasten.
Die entsprechende Stelle liegt auf Zeile 164/165 und ist kommentiert.
Wie gesagt, wenn ich die zwei Zeilen weglasse kann ich die Variablen
Kardan_Faktor und Umfang_Faktor zur Laufzeit per Tastendruck ändern,
sonst nicht.
Gruß Artur
Uiiiiiii, Tasten & Interrupts .... keine Spur von Entprellen.
Regel 1 mit Tasten :
Keine Interrupts. Es kommt ganz sicher nicht auf die Mikrosekunde an.
Regel 2 mit Tasten :
Ueber einen Timer-Tick, aber im Main, Entprellen.
Float ... sollte man vermeiden. Die bringen in 99% aller Faelle nichts.
Delays sollte man vermeiden, die machen das Programm schwer zu debuggen,
denn man weiss nicht genau wo es steht. Und kann es auch nicht
herausfinden
Viktor N. schrieb:> Uiiiiiii, Tasten & Interrupts .... keine Spur von Entprellen.
Red keinen Quatsch. Er benutzt die PeDa Entprellung. Das Beste was man
benutzen kann.
Den INT1_vect löst ein Hall-Sensor aus. Durch die Beschaltung ist
mehrmaliges Auslösen eigentlich nicht möglich. Ist auch getestet worden.
Die Entprellung der zwei Taster ist wie hier beschrieben realisiert:
http://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_.28nach_Peter_Dannegger.29
Die Qualität meines Guzzi-Tachos wäre um einiges schlechter ohne diese
Enprell-Lösung))
arser schrieb:> Die Entprellung der zwei Taster ist wie hier beschrieben realisiert:> http://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_.28nach_Peter_Dannegger.29
Dein Entprellen ist schon ok.
Allerdings hab ich mit den short bzw. long Funktionen auch keine
Erfahrung. Hab ich noch nie benutzt.
Ich seh allerdings auch keinen Zusammenhang, wie das jetzt mit den
EEPROM Funktionen zusammen hängen könnte.
OK, dass deine Multiplex-Anzeige verbesserungswürdig ist, darüber kann
man reden. Allerdings ist das jetzt erst mal nicht das Problem.
Den einzigen Zusammenhang den ich vielleicht herstellen könnte ist, dass
es einen Reset gibt und daher immer wieder derselbe Wert aus dem EEPROM
geholt wird. Aber ansonsten seh ich da nicht wirklich, wie das zusammen
hängen könnte.
Im übrigen würde ich den Wert sofort nach der Manipulation im EEPROM
ablegen und nicht erst auf einen Tastendruck vom Benutzer warten um das
Speichern anzustossen. Du kannst eine EEPROM Zelle mindestens 10000 mal
beschreiben, ehe sie kaputt geht. So oft stellst du diese Faktoren nicht
um! Oder fummelst du im Minutentakt, 24 Stunden am Tag, 2 Monate lang an
dieser Einstellung rum?
Natürlich nicht. Die Speicherung würde in den gleichen State verlegt
werden. Es würde dann abgespeichert werden wenn man zum
naächsten/vorherigen State umschaltet.
Zur Problemlösung wurde das Speichern "ausgelagert".
Ei Reset ist auszuschliesen, denn das Programm beginnt beim State Tach.
Oder ich habe Deine Vermutung falsch verstanden.
Was Multiplexen angeht bin ich natürlich auch gelehrig, funzt auch nicht
optimal. Die Anzeigen haben unterschiedliche Leuchtkraft, die dritte ist
die hellste, denn die ist am längsten an, da nach ih vermutlich mehr
Code abgearbeitet wird.
Das Problem ist scheinbar unabhängig davon, ob ich die Entprellfunktion
benutze.
Auch bei einfachster Pinabfrage lässt sich die Variable nicht verändern.
Karl Heinz Buchegger schrieb:> arser schrieb:>> Hallo,>> Danke Euch. Ich werde es mal probieren.>> @DIL EMMA:>> An sowas dachte ich, aber ich habe keine Vorstellung mit welcher>> Sicherheit die Zellen den beschriebenen Zustand haben.>> Den haben sie, keine Sorge.>> So ähnlich mach ichs auch, allerdings einfacher.> ....>> int main()> {> eeprom_write_float(&KF, 0.5);> eeprom_write_float(&UF, 0.5);>>> .... dein restlicher Code>> und hab dann die Werte im EEPROM, ehe das eigentliche Programm loslegt.> :-)> Wenn dann der Rest funktioniert, kommentiere ich einfach die beiden> Zeilen aus und fertig.
Man könnte ja den Speicher vorher auslesen und dann wie Du einen
konstanten Wert schreiben, aber vorher abfragen ob der ausgelesene Wert
EXAKT dem entspricht was reingeschrieben wurde. Wurde der Inhalt der
EEPROM-Zelle zur Laufzeit bereits verändert, findet beim nächsten Mal
das Beschreiben nicht mehr statt. Und sollte der Wert EXAKT dem
entsprechen womit initialisiert wurde ist ja nicht schlimm.
Ich habe die EEPROM-Funktionen ausgetauscht: float gegen word. mit der
byte Lese-/Schreibfunktion funktioniert es auch.
Leider bleibt das Problem für mich ungeloöst, mit einem Workaround durch
Umrechnung verkraftbar))
Vielen Dank an alle!
Gruß Artur
arser schrieb:> Leider bleibt das Problem für mich ungeloöst, mit einem Workaround durch> Umrechnung verkraftbar))
Es ist sicher sinnvoll, die Software generell auf Integermathmatik
umzubauen und lediglich für die Anzeige dann Dezimalzahlen zu verwenden.
Du wirst dich wundern, wieviel Platz plötzlich im Flash verfügbar ist
und kannst dann noch andere spassige Sachen mit einbauen.
http://www.mikrocontroller.net/articles/Festkommaarithmetik
Matthias Sch. schrieb:> Du wirst dich wundern, wieviel Platz plötzlich im Flash verfügbar ist
Die float Grundrechenarten belegen einmalig 1kB Flash (AVR-GCC).
Könnte beim ATtiny2313 ne Rolle spielen.
Ab ATmega168 würde ich mir aber keinen Kopp darum machen.
Den EEPROM benutze ich nie direkt, sondern ne Struct im SRAM.
Beim Reset wird im EEPROM ne CRC geprüft und bei Erfolg die Struct
geladen.
Bei falscher CRC bleibt die Vorbelegung der Struct gültig.
Erfolgt eine Bedienung, wird nur die Struct geändert. Nach Abschluß
erfolgt dann das Berechnen der CRC und Update des EEPROM.
Update schreibt nur geänderte Bytes, man macht es daher immer über die
gesamte Struct.