PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : eeprom_read_byte eeprom_write_byte Problem



vohopri
08.11.2013, 14:46
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.

// 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.

Che Guevara
08.11.2013, 14:52
Hi,

also ich mache das Lesen und Schreiben des EEProms so:


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

markusj
08.11.2013, 15:02
// 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:

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

oberallgeier
08.11.2013, 15:14
... 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:


// ###>>> 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

vohopri
08.11.2013, 15:55
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.

Klebwax
08.11.2013, 16:44
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
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