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.
So etwas hier erzeugt zum Beispiel eine *.eep Datei mit vorbesetzten Werten im Sourcecode:
1 | // EEPROM values
|
2 | uint16_t ee_address1 __attribute__((section(".eeprom"))) = TimeStamp; |
3 | uint8_t ee_address2 __attribute__((section(".eeprom")))= MYCONSTANT; |
4 | uint8_t ee_address3 __attribute__((section(".eeprom"))) = 0b10001000; |
5 | uint8_t ee_address4 __attribute__((section(".eeprom"))) = 0xAA; |
Ansprechen kannst du sie dann mit ihren ee_xxxxx Adressen.
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 | void main() |
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 | case state_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 | case state_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 | case state_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 | case state_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 | case state_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 | case state_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 | case state_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 | case state_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 | int main() |
4 | {
|
5 | eeprom_write_float(&KF, 0.5); |
6 | eeprom_write_float(&UF, 0.5); |
7 | |
8 | |
9 | .... 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.
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
...ach ja, falls es sonst etwas am Code, genauer am Stil zu bemängeln gibt, ist mein Ohr offen. 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.
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.