-         

Ergebnis 1 bis 6 von 6

Thema: eeprom_read_byte eeprom_write_byte Problem

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von vohopri
    Registriert seit
    11.09.2004
    Ort
    südlich der Alpen
    Beiträge
    1.708

    eeprom_read_byte eeprom_write_byte Problem

    Anzeige

    Hallo,

    jetzt hab ich versucht, Parameter ins eeprom eines ATmega8zu schreiben und wieder aus zu lesen.

    Nachdem die Werte nicht richtig zurückgelesen werden, hab ich mein Programm auf ein kleines Testprogramm zurückgestutzt, das immer noch diesen Fehler zeigt.

    Ich teste 2x. Unmittelbar nach dem Schreiben im Programmteil nach receiveloop und nach dem reset des MC im Programmteil Testloop.

    Irgend etwas habe ich da nicht oder falsch verstanden und bitte um Hinweise, wo da der Hund begraben ist.
    Code:
    // Test
    #include <avr/io.h>
    #include <avr/interrupt.h> 
    #include <avr/eeprom.h>
    #include <util/delay.h>  // Für Testzwecke
    // Parametervariablen im EEPROM
    uint8_t * eeWaitTimeSteps   EEMEM;
    uint8_t * eeTrailerTimeSteps  EEMEM;
    uint8_t * eeTrailerMode   EEMEM;
    // Vorlauf
    volatile uint8_t WaitTimeSteps = 0;
    // Laufzeitbegrenzung
    // Betriebsart
    volatile uint8_t TrailerMode = 0;
    #define TModeTime   0
    #define TModeFactor 1
    volatile uint8_t TrailerTimeSteps = 0;
    volatile uint8_t FactorSelector = 0;
    volatile uint16_t TrailerTable[8] = {0, 25, 50, 100, 150, 200, 250, 300 };    
    // bei Jumper                        0   1   2    3    4    5    6    7    
    void TestSignal(uint8_t x)
     {
      unsigned char i;
      //Test zählt immer 1 dazu, damit man die Null sieht:
      for (i=0;i<=x;i++)
      //for (i=0;i<=5;i++)
       {
       {PORTD |=  (1 << 5);} // setzt debug led
       _delay_ms(200);
       {PORTD &= ~(1 << 5);}// löscht debug led
       _delay_ms(300);
       }
      _delay_ms(500);
      }
    void ReceiveParams()
     {
     unsigned char Ready;
     Ready=0;
     
     while((PIND & 0b0100)==0); //Warteschleife auf strobe high
     _delay_ms(1000);   // Entprellen
     while(!Ready)    // Receive Loop
      {
      // Übernahme getestet, OK
      WaitTimeSteps =  ((~(PINB >> 1)) & 0b00000111);
      TrailerTimeSteps =  ((~(PINB >> 4)) & 0b00000111);
      TrailerMode =   ((~(PINB >> 7)) & 0b00000001);
      //abspeichern
      if ((PIND & 0b0100)==0)
       {
       eeprom_busy_wait();
       eeprom_update_byte (eeWaitTimeSteps, WaitTimeSteps);
       eeprom_busy_wait();
       eeprom_update_byte (eeTrailerMode, TrailerMode);
       eeprom_busy_wait();
       eeprom_update_byte (eeTrailerTimeSteps, TrailerTimeSteps);   
       //*/
       Ready = 1; 
       }
      }   // Receive Loop
     while(1)// final loop
      {
      TestSignal(WaitTimeSteps);
      TestSignal(TrailerMode);
      TestSignal(TrailerTimeSteps); // bis hier OK
      _delay_ms(1000);
       eeprom_busy_wait();
      TestSignal(eeprom_read_byte (eeWaitTimeSteps));
       eeprom_busy_wait();
      TestSignal(eeprom_read_byte (eeTrailerMode));
       eeprom_busy_wait();
      TestSignal(eeprom_read_byte (eeTrailerTimeSteps));
      _delay_ms(5000);
      } // final loop
     }  // function receiveparams 
    // Hauptprogramm =====================================================================
    int main(void)
     { 
     // GPIO Einstellungen ------------------------------------------------------------
     DDRB  =  0b00000000; // Port B input für Jumper Einlesen und Licht
     PORTB |= 0b11111111; // Port B Pullup intern für Jumpers und OC Stufe Licht
     // debug2
     DDRD |= (0b00001000 << 2);  // Port D5 output für Test
        DDRD &= ~(0b00000111 << 2); // Port D2 D3 D4 input für Parametriermodus
     PORTD |= (0b00000111 << 2); // Port D2 D3 D4 Pullup intern
     // Abfrage Parametrierstecker
     if (!(PIND & (0b00000100 << 2)))  {ReceiveParams();} 
    /* basic Test OK
    for(;;)
       {
       if (!(PIND & (0b00000100 << 2)))
       {PORTD |=  (1 << 5);} // setzt debug led
       else 
       {PORTD &= ~(1 << 5);}// löscht debug led
       }
    //*/
    //*
     while(1) // Test loop
      {
      TestSignal(WaitTimeSteps);
      TestSignal(TrailerMode);
      TestSignal(TrailerTimeSteps);
      TestSignal(FactorSelector);// Bis hier OK
      _delay_ms(100);
       eeprom_busy_wait();
      TestSignal(eeprom_read_byte (eeWaitTimeSteps));
       eeprom_busy_wait();
      TestSignal(eeprom_read_byte (eeTrailerMode));
       eeprom_busy_wait();
      TestSignal(eeprom_read_byte (eeTrailerTimeSteps));
      _delay_ms(2000);
      }
     return 0;
     } // main
    Wenn ich über das GPIO die Werte 0 0 0 einlese, dann werden die richtig erkannt, nach dem Abspeichern richtig zurück gelesen und nach dem reset richtig aus dem eeprom geholt.
    Wenn ich 2 1 3 einlese, dann wird das richtig erkannt, nach dem Abspeichern aus dem eeprom falsch zurück gelesen (den genauen Wert kann ich mit dem Blinklämpchen nicht feststellen) und nach dem Reset bekomme ich die Werte 2 3 3 aus dem eeprom

    Was mich noch verwundert, ist, dass der Compiler 6 byte im eeprom belegt meldet, wo ich nur 3 Stk verwende.

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Hi,

    also ich mache das Lesen und Schreiben des EEProms so:
    Code:
    uint16_t Value1Adress = 10;
    uint16_t Value2Adress = 12;
    
    int16_t Value1;
    int16_t Value2;
    
    //Lesen:
    Value1 = (int16_t)eeprom_read_word(Value1Adress);
    Value2 = (int16_t)eeprom_read_word(Value2Adress);
    
    //Schreiben:
    eeprom_write_word(Value1Adress, (uint16_t)Value1);
    eeprom_write_word(Value2Adress, (uint16_t)Value2);
    Durch den TypeCast (uint16_t) kann ich auch int16_t Variablen bequem speichern.

    Ich hoffe, es hilft dir.
    Gruß
    Chris

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Kandel
    Alter
    29
    Beiträge
    1.220
    Zitat Zitat von vohopri Beitrag anzeigen
    Code:
    // Parametervariablen im EEPROM
    uint8_t * eeWaitTimeSteps   EEMEM;
    uint8_t * eeTrailerTimeSteps  EEMEM;
    uint8_t * eeTrailerMode   EEMEM;
    Daher kommt der Fehler. Du speicherst im EEPROM drei Zeiger auf uint8_t. Wenn du die Sternchen weglässt und beim Zugriff auf die EEPROM-Variablen dann den addressof-Operator & verwendest, funktioniert der Code.

    Nachtrag:
    Zitat Zitat von Che Guevara Beitrag anzeigen
    also ich mache das Lesen und Schreiben des EEProms so:
    Du kannst den Compiler die EEPROM-Adressen auch verwalten lassen, damit schließt du eine Fehlerquelle aus.

    Grüße,
    Markus

    Grüße,
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Zitat Zitat von vohopri Beitrag anzeigen
    ... Parameter ins eeprom ... schreiben und ... lesen ...
    Kleine Ergänzung. In mehreren, unterschiedlichen (www-) Quellen wird das erste EEPROM-Byte als nicht zuverlässig deklariert und ein entsprender Puffer empfohlen. Ich habs gemacht - ohne eigene Gegenprobe - und habe keinerlei Fehler feststellen können. Bei meinen nicht ununterbrochenen EEPROM-Aktivitäten. Meine Organisation sieht deshalb typisch etwa so aus:

    Code:
    // ###>>> Byte-Array, das erste Byte des EEPROMS gilt als nicht vertrauenswürdig
    uint8_t firstByteDummy EEMEM; 
    uint8_t eeBytes [12] EEMEM; // Allzweckbytes
    uint16_t eeSrvoff[12] EEMEM; // Servo-Position - Offset
    uint8_t SVdef [][6] // Die folgende Liste, Servo # 0 .. 10
    EEMEM = { " ", "Ko \003", "Kor/l", "KoNir", "KoNil", "ALdur",
    "ALdul", "- nc", "ALd o", "Au rl", "Au \003" } ;
    
    unsigned char LCD[] EEMEM = "LCD "; // LCD
    unsigned char LI01[] EEMEM = "UART-T1, LCD-T2"; // Meldetext
    unsigned char LuU[] EEMEM = "LCD und UART "; // L u U
    unsigned char ML1[] EEMEM = "Taster gedrückt!"; // Meldetext
    unsigned char ML2[] EEMEM = "Start T2 Skip T1"; // Meldetext
    Geändert von oberallgeier (08.11.2013 um 15:21 Uhr) Grund: Code-Endetag war vermurkst
    Ciao sagt der JoeamBerg

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von vohopri
    Registriert seit
    11.09.2004
    Ort
    südlich der Alpen
    Beiträge
    1.708
    Hallo nochmals und danke,

    Beide Vorschläge funktionieren.
    Beim Verwenden von fixen Adressen, wie Chris das gemeint hat, habe ich nur die Definition verändern müssen in:
    // Parameterzeiger für EEPROM
    uint8_t * eeWaitTimeSteps =(uint8_t *)1;
    uint8_t * eeTrailerMode =(uint8_t *)2;
    uint8_t * eeTrailerTimeSteps =(uint8_t *)3;
    alles andere ist gleich geblieben.

    Und der Vorschlag von Markus hat genau so funktioniert, wie oben von ihm beschrieben.
    Die Erklärungen von Markus waren recht hilfreich, das Ganze auch zu verstehen.

    Der EEPROM Inhalt sieht nach letzterem Vorgehen so aus:
    :20000000020301FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFF7
    :20002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFE0
    :20004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFC0
    :20006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFA0
    :00000001FF

    020301 sind die 3 richtig geschriebenen Parameter.

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.03.2011
    Beiträge
    1.397
    Zitat Zitat von oberallgeier Beitrag anzeigen
    Kleine Ergänzung. In mehreren, unterschiedlichen (www-) Quellen wird das erste EEPROM-Byte als nicht zuverlässig deklariert und ein entsprender Puffer empfohlen.
    So ist also das Internet, schlimmer als der "Flurfunk". Im "ATmega103L Rev. F/G Errata Sheet" findet man
    Klicke auf die Grafik für eine größere Ansicht

Name:	Selection_041.jpg
Hits:	8
Größe:	39,8 KB
ID:	26692
    das Datum diese Dokuments ist aus dem vorigen Jahrtausend. Ich hab das zwar nicht verfolgt, gehe aber davon aus, daß Atmel diesen Bug, wie auch andere längst beseitigt hat. Trotzdem vermutet jeder, der ein Problem mit irgendeinem EEPROM hat, das dies die Ursache seines Problems ist.

    Es gab übrigens auch mal einen "floating point bug" bei Intelprozessoren, und obwohl der längst beseitigt ist, kommt trotzdem bei machen Programmen Unsinn raus.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

Ähnliche Themen

  1. ATMega32 UART problem --> Problem gelöst
    Von ChristophB im Forum C - Programmierung (GCC u.a.)
    Antworten: 3
    Letzter Beitrag: 12.03.2010, 19:45
  2. eeprom_write_byte
    Von hacker im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 26.09.2009, 14:23
  3. Problem mit Atmega644P Erkennung (Bascom-Versions-Problem)
    Von Rohbotiker im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 11.08.2008, 19:52
  4. eeprom_write_byte und bootloader
    Von baracuda im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 23.11.2005, 01:40

Berechtigungen

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