Forum: Mikrocontroller und Digitale Elektronik Speichern von langem Array in EEPROM


von Brian (Gast)


Lesenswert?

Guten Tag,

ich möchte mit meinem Mikrocontroller (Atmega644) eine Messreihe 
aufnehmen, um ein paar Sensoren abstimmen zu können.
Das Problem ist, dass meine einzige Schnittstelle nach außen die 
Programmierschnittstelle ist.
Nun dachte ich, die aufgenommenen Messdaten in den EEPROM zu legen und 
nachher am PC auszulesen.
Oder gibt es da noch andere Möglichkeiten?

Jede Messreihe wird als uint16_t-Array mit etwa 150 Werten gespeichert.
Wie müsste dann der Code aussehen?

Ich frage lieber mal nach, bevor ich meinen EEPROM mit Datenmüll fülle, 
weil ich irgendetwas falsch verstanden habe. ;)

Würde es so in etwa funktionieren oder hab ich was falsch verstanden?
Vorschlag (Vorlage aus AVG-GCC Tutorial dieser Seite):

#include <stdint.h>
#include <avr/eeprom.h>

int main(void)
{
uint16_t messreihe[150];
uint16_t eeFooWordArray1[150] EEMEM;


//Nehme zwischendurch eine Messreihe auf


eeFooWordArray1 EEMEM = messreihe;

//zum lesen
messreihe = eeprom_read_byte (&eeFooWordArray1);

while(1){};

von Brian (Gast)


Lesenswert?

Sorry, hier der Code nochmal formatiert:
1
#include <stdint.h>
2
#include <avr/eeprom.h>
3
4
int main(void)
5
{
6
uint16_t messreihe[150];
7
uint16_t eeFooWordArray1[150] EEMEM;
8
9
10
//Nehme hier eine Messreihe auf
11
12
13
eeFooWordArray1 EEMEM = messreihe;
14
15
//zum lesen
16
messreihe = eeprom_read_byte (&eeFooWordArray1);
17
18
while(1){};

von Karl H. (kbuchegg)


Lesenswert?

Brian schrieb:


das hier...

>
> eeFooWordArray1 EEMEM = messreihe;

... lässt du weg, wozu soll das gut sein? Zwischen den Variablen 
'messreihe' und 'eeFooWordArray1' gibt es sowieso keinen Zusammenhang, 
ausser das beide zufällig vom gleichen Datentyp und von gleicher 
Arraylänge sind.

und hier....

> messreihe = eeprom_read_byte (&eeFooWordArray1);

benutzt du eeprom_read_block (bzw. machst dir eines, wenn es diese 
Funktion noch nicht gibt), denn ein Array ist ja wohl eher ein 
Speicher-Block und kein einzelnes Byte. (Und auch einen uint16_t kann 
man wohl schwerlich als einzelnes Byte titulieren)

Aber abgesehen davon ist es perfekt.

von Brian (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Brian schrieb:
>
>
> das hier...
>
>>
>> eeFooWordArray1 EEMEM = messreihe;
>
> ... lässt du weg, wozu soll das gut sein? Zwischen den Variablen
> 'messreihe' und 'eeFooWordArray1' gibt es sowieso keinen Zusammenhang,
> ausser das beide zufällig vom gleichen Datentyp und von gleicher
> Arraylänge sind.

Ich dachte mir, dass eeFooWordArray1 im EEPROM liegt und ich darein nun 
meine Messreihe speicher.
Irgendwie müssen die Daten doch in den EEPROM kommen, wie du ja selbst 
bemerkt hast, gibt es zwischen den beiden Arrays ja sonst keinerlei 
Zusammenhang.

> und hier....
>
>> messreihe = eeprom_read_byte (&eeFooWordArray1);
>
> benutzt du eeprom_read_block (bzw. machst dir eines, wenn es diese
> Funktion noch nicht gibt), denn ein Array ist ja wohl eher ein
> Speicher-Block und kein einzelnes Byte. (Und auch einen uint16_t kann
> man wohl schwerlich als einzelnes Byte titulieren)

Ok, da hast du natürlich recht.
Passender währen da wohl die Funktionen:

eeprom_read_block (myWordBuffer, eeFooWordArray1, sizeof(myWordBuffer));

und

eeprom_write_block (myWordBuffer, eeFooWordArray1, 
sizeof(myWordBuffer));

> Aber abgesehen davon ist es perfekt.
Da abgesehen davon kaum etwas stand, verbuche ich das mal unter 
Sarkasmus.

von Karl H. (kbuchegg)


Lesenswert?

Brian schrieb:

> Ich dachte mir, dass eeFooWordArray1 im EEPROM liegt und ich darein nun
> meine Messreihe speicher.

Ja, ist auch ok

> Irgendwie müssen die Daten doch in den EEPROM kommen,

Genau.
Die Daten kommen ins EEPROM bzw aus dem EEPROM heraus, indem 
eeprom_read_block bzw. eeprom_write_block sie umkopiert.

Auf der einen Seite hast du ein Array im SRAM

  messreihe
  +------+
  |      |
  +------+
  |      |
  +------+
  |      |
  +------+
  |      |
  .      .
  .      .
  .      .
  |      |
  +------+
  |      |
  +------+


und auf der anderen Seite hast du ein Array im EEPROM

  messreihe (SRAM)
  +------+
  |      |                                eeFooWordArray1 (EEPROM)
  +------+                                +-------+
  |      |                                |       |
  +------+                                +-------+
  |      |                                |       |
  +------+                                +-------+
  |      |                                |       |
  .      .                                .       .
  .      .                                .       .
  .      .                                |       |
  |      |                                +-------+
  +------+                                |       |
  |      |                                +-------+
  +------+                                |       |
                                          +-------+

Das sind 2 voneinander getrennte Arrays, die nichts miteinander zu tun 
haben.

Und jetzt kommt die Funktion eeprom_read_block ins Spiel, die einen 
Speicherbereich aus dem EEPROM umkopiert in einen Speicherbereich im 
SRAM


  messreihe (SRAM)
  +------+  --+
  |      |    |                          eeFooWordArray1 (EEPROM)
  +------+    |                      +--  +-------+
  |      |    |                      |    |       |
  +------+    | <------------------  |    +-------+
  |      |    |   eeprom_read_block  |    |       |
  +------+    |                      |    +-------+
  |      |    |                      |    |       |
  .      .    |                      |    .       .
  .      .    |                      |    .       .
  .      .    |                      |    |       |
  |      |    |                      |    +-------+
  +------+    |                      |    |       |
  |      |    |                      |    +-------+
  +------+  --+                      |    |       |
                                     +--  +-------+

damit hast du die Daten an einer Stelle, an der du sie wie jede anderen 
Daten auch verändern kannst.

Und wenn du fertig bist, kommt eeprom_write_block zum Zug, welches die 
Daten wieder zurück ins EEPROM kopiert

  messreihe (SRAM)
  +------+  --+
  |      |    |                          eeFooWordArray1 (EEPROM)
  +------+    |                      +--  +-------+
  |      |    |                      |    |       |
  +------+    | ------------------>  |    +-------+
  |      |    |   eeprom_write_block |    |       |
  +------+    |                      |    +-------+
  |      |    |                      |    |       |
  .      .    |                      |    .       .
  .      .    |                      |    .       .
  .      .    |                      |    |       |
  |      |    |                      |    +-------+
  +------+    |                      |    |       |
  |      |    |                      |    +-------+
  +------+  --+                      |    |       |
                                     +--  +-------+


wo sie den nächsten Stromausfall überleben.

Anstelle das komplette Array umzukopieren, kann man natürlich auch die 
einzelnen Elemente des Arrays kopieren, die sich auch tatsächlich 
verändert haben. Aber das ist dann eine reine Frage der Programmierung, 
wie man das genau macht.

PS: Und anstelle von eeFooWordArray1 nimmst du natürlich einen 
vernünftigen Variablennamen :-)

von Karl H. (kbuchegg)


Lesenswert?

Brian schrieb:

>> Aber abgesehen davon ist es perfekt.
> Da abgesehen davon kaum etwas stand, verbuche ich das mal unter
> Sarkasmus.


Nicht ganz. Denn du hast immerhin erkannt, dass du eeprom_read_xxxx 
brauchst, welches Daten umkopiert. Und das ist schon mal die halbe Miete 
und nimmt dem ganzen den Nimbus des 'da passiert irgendwas Magisches im 
Hintergrund'.

Die Sache ist wirklich ganz einfach:
Auf der einen Seite stehen die Daten im EEPROM wo sie einen Stromausfall 
überleben aber nicht direkt aus dem Programm heraus wie andere Variablen 
angesprochen werden können.
Auf der anderen Seite stehen die Daten im SRAM, wo man sie zwar aus dem 
Programm heraus über Variablen ansprechen und verändern kann, wo sie 
aber einen Stromausfall nicht überleben.

Den Spaghat zwischen den beiden schafft man, in dem man die Daten 
einfach zwischen den Variablen hin und her kopiert. Und genau da kommen 
dann die eeprom_read_xxxx bzw. eeprom_write_xxxx Funktionen ins Spiel.

Und schon ist das ganze nicht mehr 'Magisch' sondern einfach nur eine 
Kopieraktion von einem Speicherbereich in einen anderen Speicherbereich, 
von denen einer eben 'zufällig' im EEPROM liegt. Mehr steckt da nicht 
dahinter.

von Brian (Gast)


Lesenswert?

Jetzt ist alles klar.
Das war mal eine sehr gute, ausführliche und gut verständliche Hilfe!
:)
Vielen Dank nochmal!

von Frank K. (fchk)


Lesenswert?

Brian schrieb:
> Guten Tag,
>
> ich möchte mit meinem Mikrocontroller (Atmega644) eine Messreihe
> aufnehmen, um ein paar Sensoren abstimmen zu können.
> Das Problem ist, dass meine einzige Schnittstelle nach außen die
> Programmierschnittstelle ist.
> Nun dachte ich, die aufgenommenen Messdaten in den EEPROM zu legen und
> nachher am PC auszulesen.
> Oder gibt es da noch andere Möglichkeiten?

Die ISP-Programmierschnittstelle ist im laufenden Betrieb eine 
SPI-Schnittstelle, die Du benutzen kannst. Du hast leider kein 
!CS-Signal, aber das sollte auch ohne gehen.

An diese SPI-Schnittstelle kannst Du irgendetwas anschließen, z.B. einen 
anderen Mikrocontroller, der die SPI-Daten per UART zum PC sendet. Oder 
DU baust einen Software-UART rein oder zwei Drahtbrücken zu den 
UART-Pins, wenn die noch frei sind,oder oder.

fchk

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.