Forum: Compiler & IDEs unverstänliche Effekte beim Schreiben ins EEPROM


von Egon M. (kpc)


Lesenswert?

Hallo

Daten ins EEPROM zu schreiben gelingt mir mit den Funktionen aus 
eeprom.h nicht so recht:
wenn ich einen Wert schreibe, geht es noch gut, aber mit zweien klappt 
es nicht mehr:
1
void zumeeprom(uint16_t wert, uint16_t i)  
2
{
3
  eeprom_write_word(&adr[i],700);  //700 - beliebige Zahl (Test)    
4
//  while (EECR & (1<<EEPE))    // wait for completion
5
                               // of previous write
6
//  ;
7
8
    eeprom_write_word(&adr[i+2], 555);  //555 - beliebige Zahl (Test)
9
//    while (EECR & (1<<EEPE))    // wait for completion
10
                          // of previous write
11
//    ;
12
  
13
return ;
14
}
Die Funktion eeprom_write_(....) stammt aus der Headerdatei, wie ich 
gelesen, aber nicht nachgeprüft habe, sollte die Funktion die nötigen 
Verzögerungen für den Schreibvorgang schon enthalten.
Die while-Schleifen (aus dem Manual) sollten also entbehrlich sein. Wie 
dem auch sei, es funktioniert mit und ohne while und auch mit reinem 
_delay_ms(xx) nicht.

Zu erwarten wäre ein EEPROM-Inhalt
188,2,255,255,43,2,188,255,255,2,43,2  ... usw (Endlsoschleife)
(188,2 = 700,     255,255 weil i+2,    43,2 = 555)

Ich bekomme aber
188,2,188,2,188,2,... gelgentlich mal 43,2,43,2,188,2....

Anfangs hatte ich den Eindruck, den Code richtig an meine Bedürfnisse 
angepaßt zu haben, da es funktionierte. Nach den Versuchen, mehrere 
Zahlen ins EEPROM zu schreiben, bin ich mir nicht mehr sicher.
Den Code aus dem Manual habe ich noch nicht ausprobiert, weil ich meine, 
mit dem aus eeprom.h müßte man mehrere Werte hintereinander  schreiben 
können.
Was mache ich falsch?
Gruß
Egon

von →ø← (Gast)


Lesenswert?

>188,2,188,2,188,2,... gelgentlich mal 43,2,43,2,188,2....
hmm, gelegentlich.
vielleicht mal brown out detector anschalten um sicher zu sein das es 
nicht an der schaltung liegt.

von Stefan E. (sternst)


Lesenswert?

Egon Müller schrieb:
> Was mache ich falsch?

Das, was viele hier falsch machen: zu wenig Code zu posten.

Wie ist adr deklariert?
Wie sieht diese Endlosschleife aus, in der die Funktion aufgerufen wird?

Denn die erste Vermutung bei diesem hier
> Ich bekomme aber
> 188,2,188,2,188,2,
ist schlicht, dass du in der Schleife den Index nicht korrekt weiter 
zählst.

von Egon M. (kpc)


Lesenswert?

Stefan Ernst schrieb:
> Egon Müller schrieb:
>> Was mache ich falsch?
>
> Das, was viele hier falsch machen: zu wenig Code zu posten.
>
Dabei hatte ich mir so viel Mühe gegeben, die nur wichtigsten Passagen 
zu zitieren und den übrigen Wust, durch den sich jemand, der mir 
freundlicherweise helfen will, nicht durchwühlen sollte, wegzulassen.

Hier also der nicht so stark gekürzte Code, der alleine "läuft". Laufen 
soll heißen, er stürzt nicht gerade ab, aber er produziert den erwähnten 
Mist.
1
#include <avr/io.h>           
2
#include <stdint.h>    
3
#include <stdio.h>
4
#include <util/delay.h>  
5
#include <stdlib.h>
6
#include <avr/iom644p.h>   
7
#include <avr/eeprom.h>
8
9
10
uint16_t adr[1000] EEMEM;       // EEPROM-Adressen
11
12
13
// testweise sollen zwei x-beliebige Zahlen u. die letzte
14
// Adresse ins EEPROM geschrieben werden - mit zwei Bytes Zwischenraum
15
16
void zum_eeprom(uint16_t wert, uint16_t k)  
17
{
18
  eeprom_write_word(&adr[k],700);      
19
20
    eeprom_write_word(&adr[k+2], 555); 
21
  
22
  eeprom_write_word(&adr[k+4], adr[k+2]);
23
24
  return ;
25
} 
26
27
28
int main(void)                     
29
{      
30
        
31
  uint16_t n=0;        // Index für eeprom-Adresse adr            
32
 
33
      while(1)         // Endlosschleife für EEPROM-Einträge
34
  {
35
        _delay_ms(1000);
36
        zum_eeprom(999,n);
37
        n=n+1;
38
    if (n > 1000)
39
    n=0;
40
41
  } /* Ende while   */
42
43
    return (0) ;
44
}

Viele Grüße
Egon

von Stefan E. (sternst)


Lesenswert?

Und da haben wir doch schon das von mir befürchtete. Wenn du n in der 
Schleife immer nur um 1 erhöhst, wie kannst du dann irgendetwas anderes 
erwarten, als
> Ich bekomme aber
> 188,2,188,2,188,2,
?

1. Schreiben:  188,   2,   x,   x,  43,   2
2. Schreiben:            188,   2,   x,   x,  43,   2
3. Schreiben:                      188,   2,   x,   x,  43,   2
4. Schreiben:                                188,   2,   x,   x,
...
Ergebnis:      188,   2, 188,   2,  188,  2, 188, ...

von Egon M. (kpc)


Lesenswert?

Stefan Ernst schrieb:
> Und da haben wir doch schon das von mir befürchtete. Wenn du n in der
> Schleife immer nur um 1 erhöhst, wie kannst du dann irgendetwas anderes
> erwarten, als .....

Ja, natürlich, ich war auf das Unterprogramm fixiert und habe übersehen, 
daß ich in main den Index wieder zurückstelle.

Ich kann mich dem hierzulande gebräuchlichen Gebet anschließen: "Herr, 
wirf Hirn runter".

Eine Verständnisfrage hätte ich noch, weil ich den Tutorials keine 
Antwort gefunden habe: überlasse ich es eigentlich mit dem Zusatz EEMEM 
zu meiner Variablen dem Compiler, sich irgendwelchen absoluten Adressen 
kreuz und quer im EEPROM herauszusuchen, oder legt er die fortlaufend 
an?

Ich habe das Programm korrigiert und hatte erwartet, daß die dritte 
eeprom_write-Zeile wenigstens  m e i n e  Adress-Indices in 
aufsteigender Folge zusammenhängend wiedergibt, was durchaus nicht der 
Fall ist.

Egon

von Hoppla (Gast)


Lesenswert?

Lesen musst Du aus dem EEPROM auch mit einer der avr-libc-Funktionen.

von Stefan E. (sternst)


Lesenswert?

Egon Müller schrieb:

> Ich habe das Programm korrigiert und hatte erwartet, daß die dritte
> eeprom_write-Zeile wenigstens  m e i n e  Adress-Indices in
> aufsteigender Folge zusammenhängend wiedergibt, was durchaus nicht der
> Fall ist.

Die dritte Zeile schreibt nur Müll ins EEPROM. "adr[k+2]" ist der Inhalt 
eines Array-Elements. Da du dieses Array-Element aber nicht mit den 
EEPROM-Funktionen liest, kommt der geschriebene Wert aus dem RAM, nicht 
dem EEPROM.

Den Kommentaren nach vermute ich mal, dass du in der dritten Zeile auch 
gar nicht ein Array-Element (adr[k+2]) in ein anderes (adr[k+4]) 
kopieren willst, sondern wohl eher die Adresse eines Array-Elements 
schreiben willst, also:
1
eeprom_write_word(&adr[k+4], (uint16_t)&adr[k+2]);

von Egon M. (kpc)


Lesenswert?

Stefan Ernst schrieb:
> Den Kommentaren nach vermute ich mal, dass du in der dritten Zeile auch
> gar nicht ein Array-Element (adr[k+2]) in ein anderes (adr[k+4])
> kopieren willst, sondern wohl eher die Adresse eines Array-Elements
> schreiben willst, also:eeprom_write_word(&adr[k+4], (uint16_t)&adr[k+2]);

In der Tat, ich wollte die letzte Adresse erfassen und sie in eine 
ansonsten unbenutzte Ecke des EEPROM's schreiben, wo sie einen 
Stromausfall überstehen und nach Neustart das Weiterschreiben an der 
richtigen Stelle erlauben sollte.
Bei meiner Aufzeichnungsfrequenz reicht das für 5000 Betriebsstunden, 
dann müßte ich zur nächsten Adresse umziehen.

Schöner wäre es natürlich, wenn man man einer EEPROM-Adresse ansehen 
könnte, ob die Zelle "leer" ist (=0xFF) oder ob der Wert 0xFF 
hineingeschrieben wurde. So, wie ich das verstehe, ist das aus EECR 
nicht herauszulesen.

Gruß
Egon

von holger (Gast)


Lesenswert?

>Schöner wäre es natürlich, wenn man man einer EEPROM-Adresse ansehen
>könnte, ob die Zelle "leer" ist (=0xFF) oder ob der Wert 0xFF
>hineingeschrieben wurde. So, wie ich das verstehe, ist das aus EECR
>nicht herauszulesen.

Das geht nicht. Den Wert 0xFF musst du irgendwie vermeiden.

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.