- LiTime Speicher und Akkus         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: mal wieder eine EEPROM Frage

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    17.11.2004
    Beiträge
    263

    mal wieder eine EEPROM Frage

    Anzeige

    Powerstation Test
    Hallo,
    ich habe ein Problem mit dem EEPROM (ATMega32) , und zwar habe möchte ich gerne Daten im EEPROM ablegen, bei jeden neustart des Gerätes sollen diese Daten ausgelesen werden.

    Ich habe bis jetzt im Datenblatt gelesen, auf http://www.mikrocontroller.net/artic...R-GCC-Tutorial und natürlich hier im Roboternetz gesucht. Vor allem der Thread https://www.roboternetz.de/phpBB2/ze...ghlight=eeprom scheint ganz gut zu sein, doch ich habe mit meinen eher mäßigen C Kenntnissen nicht alles verstanden.

    Ich habe bei mir ein "char h_wert[15][4];"
    Bei starten des gerätes sollen daten aus dem EEPROM gelesen werden und in das Feld h_wert geschrieben werden. Wenn das Gerät erstmal läuft, sollen abundzu bestimmte werte aus h_feld wieder in den EEPROM gespeichert werden...

    Könnte jemand versuchen, mit zu erklären wie genau das funktioniert? Schonmal Danke im Voraus

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    17.11.2004
    Beiträge
    263
    So, habe selber nochmal weitergemacht:

    Code:
    void speicherwerte() {
    	globalInterruptEnable(false);			// Interrupts deaktivieren
    	for (i=0;i<15;i++) {
    		for (j=0;j<4;j++) {
     			while(EECR & (1<<EEWE)) 		// warten bis Schreiben beendet
    			EEAR=(i*4+j);					// adresse setzen
    			EEDR=wert;						// Date
    			EECR |= (1<<EEMWE);			// MWE
    			EECR |= (1<<EEWE);				// Schreiben starten
    		}
    	}
    	globalInterruptEnable(true);			// Interrupts aktivieren
    }
    
    void ladewerte() {
    	int i,j;  
    	
            globalInterruptEnable(false);			// Interrupts deaktivieren
    	for (i=0;i<15;i++) {
    		for (j=0;j<4;j++) {
    			while(EECR & (1<<EEWE)) 		// warten bis Schreiben beendet
    			eear=(i*4+j);
    			EECR |= (1<<EERE);				// Lesen starten
    			h_wert[i][j]=EEDR;				// byte lesen
    		}
    	}
    	globalInterruptEnable(true);			// Interrupts aktivieren
    	
    }
    Habe im Moment aber keinen ISP da, könnte evt, jemand drüberschauen, ob das so funktionieren könnte?

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Nehmem wir mal an, dein h_feld und dein h_feld_EE haben die gleiche Größe, etwa
    Code:
    #include <avr/io.h>
    #include <avr/eeprom.h>
    
    #define EEMEM __attribute__((section(".eeprom")))
    
    char h_feld[15][4];
    const char h_feld_EE[15][4]  EEMEM = 
    {
       {1, 2, 3, 4},
       {5, 6, 7, 8},
       {9, 10, 11, 12},
       {13, 14, 15, 16},
       ...	
    };
    In neueren avr-gcc gibt's schon den Define EEMEM, dann musste das nich mehr selber definen.

    Code:
    void init_h_held()
    {
       eeprom_read_block (h_feld, h_feld_ee, sizeof (h_feld));
    }
    Disclaimer: none. Sue me.

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651

    Bitte um Hilfe bei EEPROMfragen: EE.., Foo, Arrays ..

    Ich möchte mehrere Vektoren im EEPROM (m)eines Controllers - mega.. - ablegen, Bytes und Words. Ich möchte die auf ganz bestimmten Stellen ablegen, damit ich nach einem Flashen das EEPROM nicht neu beschreiben muss bzw. damit ich nach dem Flashen auf die "alten" EEPROM-Werte auch wieder zugreifen kann, da es sich um Einstell- und Justagedaten dreht.

    Anmerkung: habe den alten Thread wegen des genau passenden Titels wieder aufgewärmt.

    Variable kann ich im EEPROM an einer bestimmten Stelle ablegen und auch wieder auslesen, auch nach dem neu Programmieren, das läuft problemlos. Ein Array der Art

    /* Byte-Array */
    uint8_t eeFooByteArray1[] EEMEM = { 18, 3, 70 };
    uint8_t eeFooByteArray2[] EEMEM = { 30, 7, 79 };

    kommt dann aber möglicherweise an einen Speicherplatz, der variieren kann. So gehts mir jedenfalls bei einem früheren, winzigen Projekt. Von diesem Projekt habe ich etwa diesen Stand:

    Textfeld, das ins EEPROM beim Flashvorgang geschrieben wird.
    unsigned char TestTimedOut[] EEMEM = "Timeout!";

    Definition einer (EINER!) Bytevariablen auf die Adresse 0x004
    #define EE_VALUE2 0x004 // Bytevariable

    Wert dieser Variablen
    [EE_VALUE2] = 0xFF

    und so eine Schreibroutine
    Code:
    // ============================================================================== =
      void DEEsch (int8_t data, uint8_t EEPadd)    // Datum wegschreiben auf Adresse
     {                              // 
    //      Evtl Parameter : (unsigned short address, unsigned char data)
    // - - - - - - - - - - - - - - -//  cli ();
      while (EECR & (1<<EEPE));     // Schreiben möglich ? vorheriger Zugriff zu Ende?
      EEAR           = EEPadd;      // Setze Adresse
      EEDR           = data;        // Schreib Datum ins EEPROM-Data register
      EECR          |= (1<<EEMPE);  // 
      EECR          |= (1<<EEPE);   // Starte Schreibzugriff
      sei ();                       //
    // - - - - - - - - - - - - - - -//
     }                              //
    // ===  Ende DEEsch (uint8_t dat, uint8_t EEPadd)
    // ============================================================================== =

    Bitte jetzt um Hilfe/Erläuterung zu diesen Fragen, der Vollständigkeit halber auch ein paar Anfängerfragen. Danke schon jetzt für die Antworten.

    Wie definiere ich den GENAUEN Ort eines Datenfeldes im EEPROM?

    Was bedeutet dieses ..foo.., ..Foo.. das ich bei EEPROM-Themen immer wieder lese?

    Was bedeutet in den Zeilen
    // schreiben
    eeprom_write_word (&eeFooWord, 2222);
    dieses &eeFooWord? Word verstehe ich (vermute ich), aber & und Foo ? ?
    Geändert von oberallgeier (11.01.2013 um 10:35 Uhr)
    Ciao sagt der JoeamBerg

  5. #5
    Erfahrener Benutzer Roboter-Spezialist Avatar von sast
    Registriert seit
    30.11.2004
    Alter
    53
    Beiträge
    502
    Zu Foo siehe http://de.wikipedia.org/wiki/Metasyntaktische_Variable
    Variablennamen sind der künstlerischen Freiheit und dem Einfal(l/t)sreichtum der Programmierer ausgeliefert. Darüber sollte man nicht allzusehr grübeln.

    Wenn du EEMEM verwendest, dann übergibst du dem Compiler die Obhut über deine EEPROM Variablen. Es geht auch ohne, dann musst du dich nur selbst um die Ablage im Speicher kümmern und, dass du nicht unbeabsichtigte Überschneidungen hast, weil du dann doch mal einen Datentyp änderst.

    Könnte mir allerdings vorstellen, dass bei gleicher Reihenfolge im Code auch das EEPROM immer genau so belegt wird. Aber das hab ich jetzt nur geraten und ich würde meine Hand dafür nicht ins Feuer legen.

    sast

    雅思特史特芬
    开发及研究

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    36
    Beiträge
    1.225
    Es gibt für diese "Wo liegt das Zeug im EEPROM"-Problematik auch eine schönere Lösung. Bestehend aus einem Headerfile in das du deine Konfigurationsdatenstruktur reinschreibst, ein Sourcefile und einem Anwendungsbeispiel.

    config.h
    PHP-Code:
    typedef struct {
        
    int foo// Eigene Konfigurationsvariablen hier unterbringen
    Config_Data_t;

    extern Config_Data_t * const config
    config.c
    PHP-Code:
    #include <avr/eeprom.h>

    #define EEPROM_SIZE (E2END + 1)

    typedef struct {
        
    uint8_t firstByteDummy;

        
    Config_Data_t config;

        
    uint8_t aligmentDummy[EEPROM_SIZE sizeof(Config_Data_t) - 1];
    Config_Data_Container_t;

    EEMEM Config_Data_Container_t container = {
                    .
    config = {
                        .
    foo 42 // Beispielinitialisierung
                        
    }, };

    Config_Data_t * const config = &container.config
    Anwendungsbeispiel
    PHP-Code:
    #include "config.h"
    #include <avr/eeprom.h>

    eeprom_read_word(&config->foo
    Erklärung: Config_Data_Container_t belegt den ganzen EEPROM. Vollständig. Das erste Byte wird ausgespart (angeblich kann es ungewollt bei Ausfällen der Stromversorgung o.ä. überschrieben werden), den Rest hinter der eigentlichen Nutzdatenstruktur belegt ein Dummy-Array. Dadurch bleibt die Adresse der Daten immer gleich da der Compiler gar keinen Spielraum zum umorganisieren hat, außer man nimmt selbst Änderungen vor. Auf die Daten zugreifen kann man über einen Pointer der direkt auf den Anfang der Nutzdaten zeigt. Müssen die Daten nicht vorinitialisiert werden, kann auf den entsprechenden Abschnitt in config.c verzichtet werden.

    @sast: Die Reihenfolge in der die Variablen im Speicher liegen kannst du nicht beeinflussen, das gilt für den RAM genauso wie für den EEPROM. Wenn du ein sicheres Speicherlayout haben möchtest, musst du das ganze als struct ablegen.

    mfG
    Markus
    Geändert von markusj (12.01.2013 um 17:22 Uhr) Grund: Hinweis zum Sourcefile entfernt
    Tiny ASURO Library: Thread und sf.net Seite

  7. #7
    Erfahrener Benutzer Roboter-Spezialist Avatar von sast
    Registriert seit
    30.11.2004
    Alter
    53
    Beiträge
    502
    Deshalb hatte ich ja auch geschrieben, dass ich meine Hand dafür nicht ins Feuer legen würde.

    Am Ende machst du hier das, was ich vorgeschlagen hatte. Du bestimmst selbst die Ablage der Daten im Speicher.
    Sehr schönes ausführliches Beispiel. Besonders, da du die Möglichkeit von Überschneidungen schon mit abgefangen hast.

    sast

    雅思特史特芬
    开发及研究

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    Zitat Zitat von markusj Beitrag anzeigen
    Es gibt ... eine schönere Lösung ... ein Sourcefile das du nicht anfassen musst und ...
    @sast - danke für die Hilfe, Markus - danke für Deine schöne Aufstellung und Deine Erläuterungen dazu. Dein Vertrauen in meine Kenntnisse ist aber zu groß. Ich habe erstmal gestern das Thema struct im Kernighan&R durchgeackert, stundenlang nach dem Sinn von * und & geinternettet, habe halbwegs begriffen dass "container" nicht nur in C++ vorkommen und laaaangsam erhellt sich der Horizont (aber z.B. "extern Config_Data_t * const config;" kapier ich immer noch nicht). Egal. (Erkenntnis: Interessant, mit wie wenig C-Kenntnissen man funktionierende Programme schreiben kann.)

    Das bisschen, das ich kapiert hatte, hab ich trotzdem mal ausprobiert (experimentelle Softwareentwicklung :-/ ).

    Zum Beispiel:
    PHP-Code:
    uint8_t firstByteDummy EEMEM;
    int16_t eeSeroff[12EEMEM// Offset Servovorgabe 
    dazu noch der Dummy - und das EEPROM ist voll *ggg*.

    Nur wenn ich den Offset für Servo 10 abspeichern will :
    PHP-Code:
    ...
    eeprom_busy_wait();
    eeprom_write_word ((int16_t)eeSeroff[10], );
    ... 
    führt das zu der Warnung "passing argument 1 of '__eewr_word_m328p' makes pointer from integer without a cast" - und egal wo ich ein * oder ein & hinpappe (auch deren Sinn und Zweck war mir bis gestern nicht bekannt) - es klappt nicht.

    Daher schon wieder die Bitte/Frage - wo gehts lang ?
    Ciao sagt der JoeamBerg

  9. #9
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    36
    Beiträge
    1.225
    Ich zweifle nicht an deinen Fähigkeiten, aber auch Dritte mit weniger Erfahrung sollten den Code verwenden können, daher das ganze. Besagten Passus zum Sourcefile habe ich inzwischen gelöscht, weil er nicht korrekt ist wenn man den EEPROM vorinitialisieren möchte.

    Zu deinem Problem: eeSeroff[10] greift auf ein Element im Speicher zu, eeprom_write_word erwartet aber eine Adresse. Ergo musst du die Adresse Organisieren, das macht &
    Korrekt wäre also:
    PHP-Code:
    eeprom_write_word (&eeSeroff[10], ); 
    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  10. #10
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    Danke für den Zuspruch - ich zweifle bei neuen Abschnitten von C schon öfters an meinen Fähigkeiten. Und danke für Deine Hilfe.

    PHP-Code:
          int16_t muell;
          
    muell     7;
          
    eeprom_busy_wait();
          
    eeprom_write_word ( &eeSeroff[10], muell ); 
    Sorry, das mit dem Adressoperator hatte ich vermutet, nein, das hatte ich in Beispielen schon gesehen. Da gibt er mir nur leider auch ne Warnung ab:
    pointer targets in passing argument 1 of '__eewr_word_m328p' differ in signedness

    In der Zwischenzeit habe ich entgegen meinen Gepflogenheiten das Ganze geflasht - trotz Warnungen sowohl beim EEPROM-Schreiben als auch beim EEPROM-Lesen. In der Ausführung bringt der Lesezugriff die Bestätigung, dass das Schreiben erfolgreich und korrekt war. Anm.: Den Schreibwert setze ich nach dem Schreibbefehl zu 0 um Selbstbetrug zu vermeiden - und die Gleichheit der Typdeklaration(en) der Beteiligten ist auch geprüft.

    Bleibt also (nur) die Frage - was bewegt den Compiler zu dieser Warnung. Klappen tuts ja
    Geändert von oberallgeier (12.01.2013 um 19:25 Uhr)
    Ciao sagt der JoeamBerg

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus