Forum: Compiler & IDEs Variablen im EEProm ablegen


von Jörg B. (joerg-sh)


Lesenswert?

Ich möchte mit meinem STM32 diverse verschiedene Variablen im EEProm 
ablegen.
Schreiben und Lesen funktioniert schon.

Wie gestalte ich das am besten. Zu jeder Variablen brauche ich ja die 
Adresse im EEProm. Wie organisiert man so etwas am besten in C?


Grüße

Jörg

von Proteino (Gast)


Lesenswert?

Kommt darauf an aus wie vielen Funktionen und Modulen du auf EEProm 
zugreifen willst.

am einfachsten ist mit #define
1
// ein Struct was das und das macht
2
#define PLACE_STRUCT_1   0
3
#define SIZE_STRUCT_1    (sizeof(struct1))
4
5
// noch so ein tolles
6
#define PLACE_STRUCT_2   (PLACE_STRUCT_1 + SIZE_STRUCT_1)
7
#define SIZE_STRUCT_2    (sizeof(struct2))
8
9
//mal ein Array
10
#define PLACE_ARRAY_1    (PLACE_STRUCT_2 + SIZE_STRUCT_2)
11
#define SIZE_ARRAY_1     ( 2 * NUMBER_OF_ELEMENTS)

von Noname (Gast)


Lesenswert?

>Ich möchte mit meinem STM32 diverse verschiedene Variablen im EEProm
ablegen.

Also diverse Variablen wären ja kein Problem gewesen.
Verschiedene auch nicht.
Aber was zur H... sind diverse verschiedene Variablen.
Sind die schon tot?
Naja. Muss ich nicht wissen. ;-)

von (prx) A. K. (prx)


Lesenswert?

Jörg B. schrieb:

> Wie gestalte ich das am besten. Zu jeder Variablen brauche ich ja die
> Adresse im EEProm. Wie organisiert man so etwas am besten in C?

(1) Man kann den Compiler&Linker dazu überreden, eine bestimmte Section 
ins EEPROM zu legen. Muss man aber erst einmal rauskriegen wie das geht 
und wenn man Pech hat werden Adressen irgendwann bei Neuübersetzung neu 
gemischt.

(2) Man kann eine Struct definieren, die alle EEPROM Variablen enthält. 
Ob man die dann geschlossen da reinschmeisst, oder komponentenweise, das 
kann man sich aussuchen. Übersichtlich, gut reproduzierbar und man kann 
die Struct ins RAM legen. Leider nicht sonderlich modular, weil sehr 
zentral. Eignet sich nur dann auch für Flash, wenn die Anzahl Änderungen 
überschaubar bleibt.

(3) Man den Inhalt als einen Datenstrom aus getaggten Daten betrachtet. 
D.h. eine Variable besteht aus ID, Länge und Inhalt. Neue und geänderte 
werden überschrieben (EEPROM) oder angehängt (Flash). Bisschen 
umständlich, funktioniert aber insbesondere bei Flash als persistentem 
Speicher recht gut. Viele Controller haben kein EEPROM, unterstützen 
aber Flash als Variablenspeicher, natürlich mit gewissen Einschränkungen 
im Umgang.

von Jörg B. (joerg-sh)


Lesenswert?

@ noname

int, float, char usw. halt.


@ Proteino danke schon mal für deine Hilfe.

mein bisheriger Code sieht ja so aus
1
  /* First write in the memory followed by a read of the written data --------*/
2
    /* Write on I2C EEPROM from sEE_WRITE_ADDRESS1 */
3
    sEE_WriteBuffer(Tx1_Buffer, sEE_WRITE_ADDRESS1, BUFFER_SIZE1);
4
5
    /* Wait for EEPROM standby state */
6
    sEE_WaitEepromStandbyState();
7
8
    /* Set the Number of data to be read */
9
    NumDataRead = BUFFER_SIZE1;
10
11
    /* Read from I2C EEPROM from sEE_READ_ADDRESS1 */
12
    sEE_ReadBuffer(Rx1_Buffer, sEE_READ_ADDRESS1, (uint16_t *)(&NumDataRead));


Wie kann ich denn jetzt mit dem Struct mal so als Beispiel eine Int und 
eine Float Variable speichern.

von Proteino (Gast)


Lesenswert?

> (2) Man kann eine Struct definieren, die alle EEPROM Variablen enthält.
> Ob man die dann geschlossen da reinschmeisst, oder komponentenweise, das
> kann man sich aussuchen.

> (1) Man kann den Compiler&Linker dazu überreden, eine bestimmte Section
> ins EEPROM zu legen.

EEPROMs sind idR. langsam, ziehen ordentlich Strom (viele interne 
EEPROMs sind aus diesem Grund manchmal garnicht zu gebrauchen) und 
verkraften nur eine endliche Anzahl an Schreibzyklen.

Gerade dein erster Vorschlag ist deswegen für Anfänger nicht zu 
empfehlen da die idR. nicht wissen was sie tun ;)

Jörg B. schrieb:
> mein bisheriger Code sieht ja so aus
>...

Ich kenne nicht die Prototypen deiner Funktionen aber das
(uint16_t *)(&NumDataRead)
in dem Funktionsaufruf
sEE_ReadBuffer(Rx1_Buffer, sEE_READ_ADDRESS1, (uint16_t 
*)(&NumDataRead));
sieht komisch aus.

ansonsten:
1
typedef struct
2
{
3
    uint8_t  stunde
4
    uint8_t  minute
5
    uint8_t  sekunde
6
}ST_UHRZEIT
7
8
#define POS_UHRZEIT_START  0
9
#define SIZE_UHRZEIT_START sizeof(ST_UHRZEIT)
10
11
#define POS_UHRZEIT_ENDE   (POS_UHRZEIT_START + SIZE_UHRZEIT_START)
12
#define SIZE_UHRZEIT_ENDE  sizeof(ST_UHRZEIT)
13
14
ST_UHRZEIT aktuelle_uhrzeit;
15
get_time(&aktuelle_uhrzeit);
16
17
...
18
19
if(irgendwas)
20
{
21
    sEE_WriteBuffer( (char*)&aktuelle_uhrzeit, POS_UHRZEIT_ENDE, SIZE_UHRZEIT_ENDE);
22
...
23
}

möglicherweise geht auch
1
sEE_WriteBuffer( &aktuelle_uhrzeit, POS_UHRZEIT_ENDE, SIZE_UHRZEIT_ENDE);

von Jörg B. (joerg-sh)


Lesenswert?

Prototype der Funktion:
1
void sEE_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite)

Ich denke ich habe es jetzt prinzipiell verstanden.

Werde es morgen mal versuchen umzusetzen.

In der Typedef kann ich sicher auch unterschiedliche Typen verwenden.

Hinter uint8_t* pBuffer versteckt sich ein Zeiger oder? Ich glaube 
darüber schon mal etwas gelesen zu haben.

von (prx) A. K. (prx)


Lesenswert?

Proteino schrieb:

> Gerade dein erster Vorschlag ist deswegen für Anfänger nicht zu
> empfehlen da die idR. nicht wissen was sie tun ;)

Vorschlag (1) dient nur der Adresszuordnung. Unter den mir bekannten 
Controller ist sowieso keiner, der es erlaubt, direkt per adressiertem 
Schreibbefehl ins EEPROM zu schreiben.

von dude (Gast)


Lesenswert?

hi,

such mal bei ST nach eeprom emulation für den STM32. Da gibts ne 
Application note und ne lib. Dann schreibst du dir deinen Flash auch 
nicht so schnell kaputt..

gruß

von Jörg B. (joerg-sh)


Lesenswert?

@dude,
ist mir bekannt. Es geht ja auch nicht ums schreiben sondern adressieren 
der Daten...

von Proteino (Gast)


Lesenswert?

Jörg B. schrieb:
> Prototype der Funktion:
>
1
> void sEE_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t
2
> NumByteToWrite)
3
>
>
> Ich denke ich habe es jetzt prinzipiell verstanden.
>
> Werde es morgen mal versuchen umzusetzen.
>
> In der Typedef kann ich sicher auch unterschiedliche Typen verwenden.
>
> Hinter uint8_t* pBuffer versteckt sich ein Zeiger oder? Ich glaube
> darüber schon mal etwas gelesen zu haben.

Ja. du musst also die Daten die du schreiben willst auf einen uint8_t* 
casten.

z.B. hast du ein Array aus uint16:
uint16_t array[5];

sind also insgesamt 10 Byte.
Zuerst holst du dir jetzt die Adresse des Arrays mit "&array[0]" oder 
"array".
Dannach behauptest du noch, es wären 8Bit unsigned int die sich hinter 
dem Zeiger verbergen mit:
"(uint8_t*)&array[0]" oder
"(uint8_t*)array"
damit deine eeprom-Funktion diese schreiben kann:
1
sEE_WriteBuffer( (uint8_t*)array, POSITION, 10);

Bei Enums, Structs und Unions funktioniert das im Prinzip dann genau so.

von Proteino (Gast)


Lesenswert?

Nachtrag:

Jörg B. schrieb:
> (uint16_t *)(&NumDataRead)

Das ist tatsächlich Quatsch und müsste eigentlich zu einem Fehler oder 
zumindest einer Warnung bei Compilieren führen.

Mit dem Code übergibst du nämlich einen Zeiger und nicht die Zahl die an 
der Position hinterlegt ist. Lass das (uint16_t *)(& ) weg.

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.