Hallo alle zusammen,
bräuchte kurz mal Hilfe.
Und zwar möchte ich einige Daten in den EEPROM Speicher schreiben, damit
die nach dem Neustart noch ausgelesen werden könnten. Nur habe ich
Schwierigkeiten mit der Schreib-Leseprozedur.
Code sieht etwa folgendermaßen aus:
#define EEMEM _attribute_ ((section (".eeprom")))
.
.
.
unsigned char threshold_1 EEMEM;
//threshold_1 bekommt einen Wert über die eingabe zugewiesen, dieser
soll //gespeichert werden
eeprom_write_byte(&threshold_1, threshold_1);
//beim Neustart möchte ich diesen auslesen
void load_data(void)
{
threshold_1 = eeprom_read_byte(&threshold_1);
}
//später, ausgeben
uart_putc(threshold_1);
das ist grob der Aufbau. Habe mich an das Tutorial gehalten, nur
irgendwie klappt es net so richtig.
Dennis schrieb:> Code sieht etwa folgendermaßen aus:>> #define EEMEM _attribute_ ((section (".eeprom")))
Warum definierst du das selber?
> unsigned char threshold_1 EEMEM;>> //threshold_1 bekommt einen Wert über die eingabe zugewiesen,
ganz sicher nicht.
treshold_1 ist keine Variable im eigentlichen Sinne, sondern ein
Platzhalter für eine Position im EEPROM.
Den Rest deines Postings berücksichtigend, kann daher treshold_1 gar
keinen Wert über die Eingabe zugewiesen bekommen haben.
> void load_data(void)> {> threshold_1 = eeprom_read_byte(&threshold_1);> }
Du brauchst 2 Dinge
* Eine Variable, die tatsächlich im SRAM residiert. Das ist eine ganz
normale Variable, so wie jede andere auch
* Eine EEMEM vereinbarte 'Variable', mit der du im Prinzip nur Platz im
EEPROM reservierst.
Mit den read und write Funktionen wird dann von dem einen zum anderen
umkopiert.
> Habe mich an das Tutorial gehalten, nur> irgendwie klappt es net so richtig.
Dann sieh dir nochmal das Tutorial an. Dort wirst du genau diese
Struktur immer wieder wiederfinden: SRAM Variable + Platzhalter im
EEPROM
Hallo, habe immer noch schwierigkeiten mit der Sache.
So wie ich es verstanden habe, soll es folgendermaßen ausschaun,
uint8_t threshold_1_eeprom EEMEM; //platzreservierung für eeprom
uint8_t environment_1_eeprom EEMEM; //platzreservierung für eeprom
threshold_1=3; //Beispielwerte, werden ubers Interface angegeben
environment_1=3;
eeprom_write_byte(&threshold_1_eeprom, threshold_1); // schreiben
eeprom_write_byte(&environment_1_eeprom, environment_1); // schreiben
threshold_1 = eeprom_read_byte(&threshold_1_eeprom); // lesen
environment_1 = eeprom_read_byte(&environment_1_eeprom); // lesen
nachdem ich den Reset Knopf an meinem Board betätige, werden die Werte
leider nicht wieder angezeigt, d.h. müssen neu eingegeben werden. Wenn
ich aber z.B. nur einen Wert speichere "threshold_1", dann kann bekomme
ich den Wert nach dem Reset wieder ausgegeben.
Dennis schrieb:> nachdem ich den Reset Knopf an meinem Board betätige, werden die Werte> leider nicht wieder angezeigt, d.h. müssen neu eingegeben werden.
Dann zeig mal etwas mehr Code.
Dein Verständnis davon, wie die read bzw. write Funktion zu benutzen
ist, scheint jetzt richtig zu sein. Also wirst du wohl in der Verwendung
irgendwo einen Fehler machen.
> Wenn> ich aber z.B. nur einen Wert speichere "threshold_1", dann kann bekomme> ich den Wert nach dem Reset wieder ausgegeben.
?
(Auf die SChnelle beim Drüberscrollen gesehen)
Autsch
1
eeprom_write_byte((void*)1,0xAA);
2
eeprom_write_byte((void*)2,channel);
Entweder du überlässt dem Compiler die Entscheidung, wo er welche
"Variable" im EEPROM hinlegt, oder du machst das selber.
Wenn Compiler: dann musst du ihm das für alle "Variablen" überlassen!
Wenn selber: dann musst du das für alle "Variablen" selber machen!
Aber mischen ist immer schlecht!
Dein Compiler kann nicht Gedanken lesen welche EEPROM Zellen du für
andere Zwecke benutzt und mit direkter Adresse ansprichst.
@ Karl
könntest du mir eventuell mal nen Link geben, wo die automatische
Speicherzuweisung beschrieben ist, das ganze verwirrt mich immer noch
ein bisschen, und da ich mehrere Parameter abspeichern möchte, wäre das
ja optimal,
eeprom_write_byte((void *)1,0xAA);
eeprom_write_byte((void *)2,channel);
@ peter
danke für den Link, nur ist es für mich ein bisschen schwierig den Code
nachzuvollziehen, hab den eingebunden, bekomme aber Fehler beim
Compilieren.
Gruß
Dennis
Dennis schrieb:> @ Karl>> könntest du mir eventuell mal nen Link geben, wo die automatische> Speicherzuweisung beschrieben ist
Was brauchst du da beschrieben?
Wenn du schreibst
1
uint8_tthreshold_1_eepromEEMEM;
2
uint8_tenvironment_1_eepromEEMEM;
3
uint8_tbandwidth_1_eepromEEMEM;
dann verwaltet der Compiler/Linker das EEPROM und verteilt die
"Variablen" da drinn. Wo genau ist Sache des Compilers/Linkers. Geht
dich nichts an wo genau, willst du auch gar nicht wissen.
Fertig. Mehr gibt es dazu nicht zu sagen
> das ganze verwirrt mich immer noch> ein bisschen, und da ich mehrere Parameter abspeichern möchte, wäre das> ja optimal,>> eeprom_write_byte((void *)1,0xAA);> eeprom_write_byte((void *)2,channel);
Nein, das wäre nicht optimal.
Denn mit dem (void*)1 sagt du explizit aus: Ich will an die EEPROM
Adresse 1 den Wert 0xAA gespeichert haben.
Du weißt aber nicht, ob nicht der Compiler an dieser Stelle im EEPROM zb
die Variable
1
uint8_tthreshold_1_eepromEEMEM;
angesiedelt hat. Der Compiler weiß ja nicht, dass du mit der
Speicherzelle 1 im EEPROM irgendwas spezielles vor hast. Also wird er,
pragmatisch wie er ist, die von dir angeforderten EEMEM 'Variablen' auch
einfach beginnend von vorne im EEPROM ansiedeln.
Und schon machts klatsch: Der Compiler hat entschieden zb die 'Variable'
threshold_1_eeprom an die Speicherstelle 1 im EEPROM zu legen und du
schreibst dann da einfach 0xAA drauf. Das das ein Durcheinander gibt,
braucht man nicht extra betonen.
Mach dir doch einfach noch eine Variable ins EEPROM
1
uint8_tmagicWord_eepromEEMEM;
2
3
uint8_tthreshold_1_eepromEEMEM;
4
uint8_tenvironment_1_eepromEEMEM;
5
uint8_tbandwidth_1_eepromEEMEM;
und überlass es dem Compiler die irgendwo im EEPROM anzulegen.
Du greifst zu mittels
1
eeprom_write_byte(&magicWord_eeprom,0xAA);
(bzw. umgekehrt natürlich beim read genauso)
und schon kommst du mit deinen speziellen Bytes dem Compiler nicht mehr
in die Quere.
Wenn der Compiler die Kontrolle über das EEPROM haben soll, dann musst
du sie ihm auch vollständig geben und nicht nur halb! Das heißt: Der
Compiler/Linker legt für ALLES fest, wo es im EEPROM angesiedelt ist und
du hältst dich als Programmierer da raus und verwendest keine absoluten
Adressen im EEPROM!
(Für deine restlichen Dinge im EEPROM, die du mit absoluten Adressen
ansprichst gilt genau das gleiche in Grün)
Oder aber umgekehrt: Du kümmerst dich selbst komplett darum, die
einzelnen 'Variablen' im EEPROM zu verteilen, d.h. du legst selber fest
an welcher Adresse im EEPROM welche Variable angesiedelt ist. Aber dann
musst du das für alle machen und du bist dafür verantwortlich, dass es
zu keinen Überschneidungen kommt.
Aber nicht mischen!
Wenn du selber einen Teil des EEPROMS verwaltest und einn Teil macht der
Compiler und beide wissen nichts voneinander, dann gibts Chaos.
Dennis schrieb:> stimmt es soweit?
sieht gut aus
> das config menue habe ich soweit gleich gelassen. Komischer weise komme> ich nicht mehr ins ConfigMenue :?
Das hängt jetzt aber nicht mit diesen EEPROM-Routinen an sich zusammen
Dennis schrieb:> if (eeprom_read_byte(&data_in_eeprom)!=0xAA)> {>> rf_baud=RF_BAUDRATE;> uart_baud=UART_BAUDRATE;> channel=CHANNEL;> threshold_1=THRESHOLD;> environment_1=QUIET;> bandwidth_1=_BANDWIDTH_;> save_settings();> }>> channel=eeprom_read_byte(&channel_eeprom);> rf_baud=eeprom_read_word(&rf_baud_eeprom);> uart_baud=eeprom_read_word(&uart_baud_eeprom);> threshold_1 = eeprom_read_byte(&threshold_1_eeprom); // lesen> environment_1 = eeprom_read_byte(&environment_1_eeprom); // lesen
Fehlt da kein else nach dem if-Block? Du überknallst Dir unten wieder
alle Variablen.
Gruß,
Frank
Eigentlich nachdem die if-Anweisung an "save_settings()" angekommen ist,
werden ja alle Daten gespeichert, d.h. die nachfolgenden Zuweisungen von
"channel"-"environment" enthalten schon die richtigen Werte.
Sollte eigentlich alles stimmen. Das einzige Problem is jetzt nur der
Zugriff auf das ConfiMenue.
Gruß
Dennis
Habs jetzt, ch weiss nicht genau warum, aber nachdem ich den Config
Aufrug mit einem Ausrufezeichen negiert habe, bekamm ich plötzlich mein
ConfigMenue angezeigt. Is zwar n bissi merkwürdig, aber solange es
funzt.
Danke für die Hilfe & Gruß
Dennis
Dennis schrieb:> Habs jetzt, ch weiss nicht genau warum, aber nachdem ich den Config> Aufrug mit einem Ausrufezeichen negiert habe, bekamm ich plötzlich mein> ConfigMenue angezeigt.
Dem solltest du aber nachgehen. Solange bis du es weißt.
> Is zwar n bissi merkwürdig, aber solange es> funzt.
Schlechte Idee.
'solange es funzt' ist eine schlechte Begründung, für eine Änderung die
man nicht versteht bzw. die vollkommen unlogisch erscheint. Da kann sich
auch ein Bug dahinter verstecken, der sich momentan eben so sichtbar
macht. Bei der nächsten Programmänderung springt der Bug woanders hin
und schon gehen die Ratespielchen wieder von vorne los.
Also das ConfigMenue is bei mir folgens defieniert
#define CONFIG PINB_1 // Pin fuer Config Jumper (DDR beachten)
if (!CONFIG) //vorher war es nicht negiert
configmode(); //ConfigMenue Aufruf
also PB1 ist bei mir mit dem Taster_1 verbunden, teoretisch, sollte ich
den Taster betätigen dann muesste mein Menue erscheinen. Leider
erscheint das Menue nur wenn ich den Reset Knopf drücke und auch nur
dann, wenn der Aufruf negiert ist.
Bin momentan überfragt :?
Dennis schrieb:> Also das ConfigMenue is bei mir folgens defieniert>> #define CONFIG PINB_1 // Pin fuer Config Jumper (DDR beachten)>
Wie ist PINB_1 definiert?
Dennis schrieb:> bekomme aber Fehler beim> Compilieren.
Und was nun?
Rück mal ein Stück zur Seite, damit mein Astralkörper die Fehlermeldung
auf Deinem Bildschirm auch sehen kann.
Peter
@ Karl
struct bits {
char b0:1;
char b1:1;
char b2:1;
char b3:1;
char b4:1;
char b5:1;
char b6:1;
char b7:1;
} __attribute__((_packed_));
.
.
.
#define PINB_1 ((*(volatile struct bits*)&PINB).b1)
.
.
.
mehr habe ich zum PINB_1 net stehn.
@ Peter
.
.
.
EECR |= 1<<EEMPE;
EECR |= 1<<EEPE;
.
.
. Fehler: EEMPE, EEPE-undeclared (first use in this function)
ka. was der von mir moechte?
Dennis schrieb:> @ Karl>>> struct bits {> char b0:1;> char b1:1;> char b2:1;> char b3:1;> char b4:1;> char b5:1;> char b6:1;> char b7:1;> } __attribute__((_packed_));> .> .> .>> #define PINB_1 ((*(volatile struct bits*)&PINB).b1)
ok.
Also direkte Port Pin Abfrage.
* Wie sind deine Taster angeschlossen
* ist ein Pullup an den Tastern notwendig/vorhanden/eingeschaltet
* wie sieht der Rest des Programms aus?
Bitte akzeptiere, dass es in einem Programm immer viele Möglichkeiten
gibt, wie ein Effekt entstehen kann. Letztendliche Klarheit kann man
daher in manchen Fällen nur dann erhalten, wenn man alle Fakten
vollständig kennt.
Oftmals ist es so, dass man mit einem kleinen Programmausschnitt die
eigentlich Ursache erraten kann. Oftmals ist es aber auch so, dass eben
genau das nicht geht.
Dennis schrieb:> .> EECR |= 1<<EEMPE;> EECR |= 1<<EEPE;> .> .> . Fehler: EEMPE, EEPE-undeclared (first use in this function)>> ka. was der von mir moechte?
Das Bit wird auf deinem µC ein klein wenig anders heißen.
Ins Datenblatt schauen, die Beschreibung vom EECR Register raussuchen.
Nachsehen ob es in dem ein Bit gibt, welches fast so heißt wie EEMPE.
Zur Sicherheit auch noch die anderen EEPROM Register kontrollieren, ob
nicht das EEMPE Bit bei deinem µC in einem anderen Register angesiedelt
wurde.
Oftmals, aber nicht immer, kann man Code unbeschadet von einem Prozessor
zu einem anderen transportieren ohne etwas ändern zu müssen. Aber in
manchen Fällen hat Atmel dem einen Riegel vorgeschoben, in dem die Dinge
bei unterschiedlichen Porzessoren ein klein wenig anders heißen.
Welchen AVR-Typ benutzt Du denn?
Bei den neueren AVRs heißen die Bits:
Bit 2 – EEMPE: EEPROM Master Program Enable
Bit 1 – EEPE: EEPROM Program Enable
Peter