Forum: Mikrocontroller und Digitale Elektronik ATmega EEPROM beschreiben/lesen


von Andreas H. (heilinger)


Lesenswert?

Hallo,

ich möchte Kalibrierwerte (Offset und Steigung) eines Sensors in ein 
EEPROM schreiben. Diese werden nach dem Starten des ATmega168PA dann 
wieder ausgelesen, um sie bei der Berechnung zu benutzen. Um zu prüfen, 
dass ich nicht Mist auslese, speichere ich zusätzlich noch eine einfach 
CRC in das EEPROM und lese die auch jedesmal aus.

Jetzt habe ich mal das EEPROM über AVR Studio ausgelesen. Dabei ist mir 
nun aufgefallen, dass nicht immer die gleiche Adresse beschrieben wird. 
Dementsprechend lese ich nicht die richtigen Werte aus.

Hier die Aufrufe zum Beschreiben:
1
EEPROM_schreiben (6, sint_Flow_Digits);
2
sint_crc = (sint_Flow_Digits%CRC_DIV);          //CRC bilden
3
EEPROM_schreiben (8, sint_crc);
4
5
EEPROM_schreiben (2, sint_offsetfehler);
6
sint_crc = (sint_offsetfehler%CRC_DIV);         //CRC bilden
7
EEPROM_schreiben (4, sint_crc);

Hier die Aufrufe zum Lesen:
1
sint_dummy = EEPROM_lesen(2);         //Adresse 2 im EEPROM lesen
2
sint_crc_check = EEPROM_lesen(4);     //Adresse 4 im EEPROM lesen    
3
  
4
  
5
  if ((sint_dummy%CRC_DIV == sint_crc_check) && ( sint_dummy != 0xFFFF))  //Bereits ein Speichervorgang in EEPROM?
6
    sint_offsetfehler = sint_dummy;
7
  else
8
    sint_offsetfehler = 0x3999;
9
10
  sint_dummy = EEPROM_lesen(6);         //Adresse 6 im EEPROM lesen 
11
  sint_crc_check = EEPROM_lesen(8);     //Adresse 8 im EEPROM lesen    
12
  
13
  if ((sint_dummy%CRC_DIV == sint_crc_check) && ( sint_dummy != 0xFFFF))  //Bereits ein Speichervorgang in EEPROM?
14
    sint_Flow_Digits = sint_dummy;
15
  else
16
    sint_Flow_Digits = 6700;


Hier die Funktionen:
1
void EEPROM_schreiben (unsigned int uint_Adresse, signed int sint_data)
2
{
3
  unsigned int uint_lowbyte;
4
  unsigned int uint_highbyte;
5
    
6
  uint_lowbyte = (sint_data & 0xFF);
7
  uint_highbyte = (sint_data >> 8);
8
  
9
  while (EECR & (1<<EEPE)) ;
10
  EEARL = uint_Adresse;
11
  EEDR = uint_highbyte;
12
13
  cli();
14
  EECR |= (1<<EEMPE);
15
  EECR |= (1<<EEPE);
16
  sei();
17
 
18
  
19
  while (EECR & (1<<EEPE)) ;  
20
  EEARL = (uint_Adresse+1);
21
  EEDR = uint_lowbyte;
22
23
  cli();
24
  EECR |= (1<<EEMPE);
25
  EECR |= (1<<EEPE);
26
  sei();
27
}
28
29
signed int EEPROM_lesen (unsigned int uint_Adresse)
30
{
31
  signed int Wert;
32
  unsigned int uint_lowbyte;
33
  unsigned int uint_highbyte;  
34
    
35
  while (EECR & (1<<EEPE)) ;
36
  EEARL = uint_Adresse;
37
38
  EECR |= (1<<EERE);
39
  uint_highbyte = EEDR;
40
  
41
42
  while (EECR & (1<<EEPE)) ;
43
  EEARL = (uint_Adresse+1);
44
45
  EECR |= (1<<EERE);
46
  uint_lowbyte = EEDR;
47
  
48
  Wert = (uint_highbyte << 8) | uint_lowbyte;  
49
  
50
  return Wert;
51
}

Und so sieht das EEPROM-File aus:

:10000000FFFFFFFFFFFF19AD000DFFFFFFFFFFFF29
:10001000FFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFEF
:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
:10008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
:1000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60
:1000B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50
:1000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
:1000D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30
:1000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
:1000F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10
:10010000FFFF39B5000519720002FFFFFFFFFFFF77
:10011000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF
:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF
:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF
:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF
:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF
:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F
:10017000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F
:10018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F
:10019000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F
:1001A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F
:1001B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F
:1001C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F
:1001D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F
:1001E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F
:1001F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F
:00000001FF

Normalerweise sollte ja da dann nur die erste Zeile beschrieben sein und 
die 2. und 17. sollte nur FF enthalten. Mit anderen Worten, mein Fehler 
müsste in der Schreibe-Funktion enthalten sein, oder?

Kann mir jemand weiterhelfen?

von Klaus T. (gauchi)


Lesenswert?

Schreib doch mal eine 0 in EEARH, wenn ich das Datenblatt richtig lese, 
ist der initial value nicht definiert, da könnte also auch eine 1 
drinstehen, dann würdest Du mit dem Schreibbefehl in der zweiten Hälfte 
landen.

von Andreas H. (heilinger)


Lesenswert?

oh, Danke!

"The initial value of EEAR is undefined", muss ich wohl übersehen haben.
Bin davon ausgegangen, dass da alle Bits auf 0 gesetzt sind, wenn man 
die net anfasst...

von Vlad T. (vlad_tepesch)


Lesenswert?

gernell sollte man aus c die 16bit register als 16-bit Wert ansprechen.

also
EEAR = &x;

Edit:
So kümmert sich auch der Kompiler um die richtige Reihenfolge, in der 
diese beschrieben/gelesen werden müssen.
(siehe Datenblatt unter ADC, Timer)

von Andreas H. (heilinger)


Lesenswert?

okay, habe ich auch gemacht, aber eine Frage:

Warum
"EEAR = &x;"
und nicht
"EEAR = x;"
?

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
Noch kein Account? Hier anmelden.