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.
:
Verschoben durch User
Dennis schrieb: > Hallo alle zusammen, > > bräuchte kurz mal Hilfe. möglich. Aber nicht in der Codesammlung
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. ?
Code sieht folgendermaßen aus, unsigned long uart_baud, rf_baud; unsigned char channel; uint8_t bandwidth_1; uint8_t environment_1; uint8_t threshold_1; uint8_t threshold_1_eeprom EEMEM; uint8_t environment_1_eeprom EEMEM; uint8_t bandwidth_1_eeprom EEMEM; //******************************configurationsmodus void configmode(void) { unsigned char c; uart_init(UART_BAUD_SELECT(CONFIG_BAUD, F_CPU)); for(;;) { //threshold_1=THRESHOLD; uart_puts_P("\r\n\r\n"); uart_puts_P("RFM12 RS232 bridge v1.2\r\n"); uart_puts_P("(c) by Benedikt\r\n"); uart_puts_P("Config Menue\r\n\r\n"); uart_puts_P("Current Settings:\r\n"); uart_puts_P("\r\nRS232 baudrate: "); show_number(uart_baud); uart_puts_P("\r\nRFM12 baudrate: "); show_number(rf_baud); uart_puts_P("\r\nchannel: "); show_number(channel); uart_puts_P("\r\nDRSSI threshold: "); uart_putc(threshold_1); uart_puts_P("\r\nEnvironment: "); uart_putc(environment_1); uart_puts_P("\r\nBandwidth: "); uart_putc(bandwidth_1); uart_puts_P("\r\n\r\n"); uart_puts_P("(1) set RS232 baudrate\r\n"); uart_puts_P("(2) set RFM12 baudrate\r\n"); uart_puts_P("(3) set RFM12 channel\r\n"); uart_puts_P("(4) set DRSSI threshold\r\n"); uart_puts_P("(5) set Environment\r\n"); uart_puts_P("(6) set Bandwidth\r\n"); uart_puts_P("\r\n"); uart_puts_P("(0) exit menu without saving\r\n"); uart_puts_P("(s) exit menu and save settings\r\n"); uart_puts_P("\r\n"); //threshold_1=THRESHOLD; for(;;) { c=uart_getchar(); if (c=='0') return; else if (c=='s') { uart_puts_P("saved !\r\nLeaving config mode...\r\n"); save_settings(); _delay_ms(10); return; } else if (c=='1') { uart_puts_P("Enter RS232 baudrate (300-150000)\r\n"); uart_baud=read_number(300,150000); break; } else if (c=='2') { uart_puts_P("Enter RFM12 baudrate (700-65000)\r\n"); rf_baud=read_number(700,65000); break; } else if (c=='3') { uart_puts_P("Enter RFM12 channel (0-3)\r\n"); channel=read_number(0,3); break; } else if (c=='4') { uart_puts_P("Enter threshold (6-1) where (6 low sensitivity & 1 high sensitivity)\r\n"); threshold_1=uart_getchar(); uart_putc(threshold_1); break; } else if (c=='5') { uart_puts_P("Enter environment (1-3) where (1 quite environment & 3 noisy environment)\r\n"); environment_1=uart_getchar(); uart_putc(environment_1); break; } else if (c=='6') { uart_puts_P("Enter Bandwidth (1-6) where (1=400kHz, 2=340kHz, 3=270kHz, 4=200kHz, 5=134kHz, 6=67kHz) \r\n"); bandwidth_1=uart_getchar(); uart_putc(bandwidth_1); break; } else break; } } } //***************************das sind die Schreib bzw. Leseroutinen void load_settings(void) { if (eeprom_read_byte((void *)1)!=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((void *)2); eeprom_read_block(&rf_baud,(void *)3,4); eeprom_read_block(&uart_baud,(void *)7,4); threshold_1 = eeprom_read_byte(&threshold_1_eeprom); // lesen environment_1 = eeprom_read_byte(&environment_1_eeprom); // lesen } void save_settings(void) { eeprom_write_byte((void *)1,0xAA); eeprom_write_byte((void *)2,channel); eeprom_write_block(&rf_baud,(void *)3,4); eeprom_write_block(&uart_baud,(void *)7,4); eeprom_write_byte(&threshold_1_eeprom, threshold_1); // schreiben eeprom_write_byte(&environment_1_eeprom, environment_1);//schreiben }
(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.
Schau Dir das mal an: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=91306 Klein und einfach. Peter
@ 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_t threshold_1_eeprom EEMEM; |
2 | uint8_t environment_1_eeprom EEMEM; |
3 | uint8_t bandwidth_1_eeprom EEMEM; |
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_t threshold_1_eeprom EEMEM; |
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_t magicWord_eeprom EEMEM; |
2 | |
3 | uint8_t threshold_1_eeprom EEMEM; |
4 | uint8_t environment_1_eeprom EEMEM; |
5 | uint8_t bandwidth_1_eeprom EEMEM; |
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.
Hab jetzt folgendes geändert, #define CHANNEL 2 #define RF_BAUDRATE 20000 #define UART_BAUDRATE 19200 #define THRESHOLD 1 #define BANDWIDTH 4 { // unsigned long uart_baud, rf_baud; // unsigned char channel; uint16_t uart_baud, rf_baud; //da vorher unsigned long, jetzt als //uint16_t uint8_t channel; uint8_t bandwidth_1; uint8_t environment_1; uint8_t threshold_1; //uint8_t data_in_eeprom; uint8_t data_in_eeprom EEMEM; uint8_t threshold_1_eeprom EEMEM; uint8_t environment_1_eeprom EEMEM; uint8_t bandwidth_1_eeprom EEMEM; uint16_t uart_baud_eeprom EEMEM; uint16_t rf_baud_eeprom EEMEM; uint8_t channel_eeprom EEMEM; } void load_settings(void) { 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 } void save_settings(void) { eeprom_write_byte(&data_in_eeprom,0xAA); eeprom_write_byte(&channel_eeprom,channel); eeprom_write_word(&rf_baud_eeprom,rf_baud); eeprom_write_word(&uart_baud_eeprom,uart_baud); eeprom_write_byte(&threshold_1_eeprom, threshold_1); // schreiben eeprom_write_byte(&environment_1_eeprom, environment_1);// schreiben } stimmt es soweit? habe den "block" Teil als "word" definiert. das config menue habe ich soweit gleich gelassen. Komischer weise komme ich nicht mehr ins ConfigMenue :? Gruß
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
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.