Variablen im EEProm ablegen

OP #2597678
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
Gast #2597849
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)
Gast #2597866
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. ;-)
#2597925
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.
OP #2597929
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.
Gast #2598315
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);
OP #2598331
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.
Gast #2598531
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.
Gast #2598536
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren