Forum: Mikrocontroller und Digitale Elektronik EEPROM will sich nicht schreiben/lesen lassen


von Christop (Gast)


Lesenswert?

Hallo....

ich habe eine PCB mit einem ATMega328. Dieser soll "default" Werte im 
EEPROM haben. Zugleich soll ein weiterer EEPROM Bereich zum Speichern 
der Werte da sein..

So das man bei einem Reset wieder die "default" Werte aus dem EEPROM 
holt.

Ok.

Jetzt habe ich in der main.c folgenden Inhalt....
1
#include "main.h"
2
#include "timer.h"
3
#include "twislave.h"
4
5
int main (void) {
6
7
  // Write Default EEPROM if not exist
8
  
9
  if (getEEDefaultExist() == 0) {
10
    writeDefaultEEPROM();
11
    updateEEDefaultExist();
12
  }
13
   
14
  i2c_readaddr_init();
15
  init_twi_slave(i2c_readaddr());
16
17
  // Init PWM
18
  pwm_init();
19
  init_pwmmodes();
20
21
  // Init Timer
22
  timer_init();
23
24
  // I2C Data
25
  init_address();
26
27
   // Init Data from EEPROM at First Start
28
   pwmchangemode = getEEPWMChangeMode();
29
   
30
   pwmchangetime = getEEPWMSoftModeChangeTime();
31
   pwmchangetimeR = getEEPWMSoftModeChangeTimeR();
32
   pwmchangetimeG = getEEPWMSoftModeChangeTimeG();
33
   pwmchangetimeB = getEEPWMSoftModeChangeTimeB();
34
  pwmchangetimeW = getEEPWMSoftModeChangeTimeW();
35
  pwmsoftlimit = getEEPWMSoftLimit();
36
37
............

Dazu habe ich den eeprom.c datei, diese sieht wie folgt aus:
1
#include "main.h"
2
3
uint8_t eeDefaultExist EEMEM             = 99;
4
5
// PWM Change Mode { 0 = Hard, 1 = Soft}
6
uint8_t eePWMChangeMode EEMEM           = 100;
7
8
// PWM Softmode Changetime
9
uint8_t eePWMSoftModeChangeTime EEMEM       = 101;
10
11
// PWM Softmode Changetime RED Channel
12
uint8_t eePWMSoftModeChangeTimeR EEMEM     = 102;
13
// PWM Softmode Changetime GREEN CHANNEL
14
uint8_t eePWMSoftModeChangeTimeG EEMEM     = 103;
15
// PWM Softmode Changetime BLUE CHANNEL
16
uint8_t eePWMSoftModeChangeTimeB EEMEM     = 104;
17
// PWM Softmode Changetime WHITE CHANNEL
18
uint8_t eePWMSoftModeChangeTimeW EEMEM     = 105;
19
20
// PWM Max Value (Softlimit for PWM)
21
uint8_t eePWMSoftLimit EEMEM             = 106;
22
23
uint8_t eeWs2812Count EEMEM             = 107;
24
25
void writeDefaultEEPROM(void) {
26
  updateEEPWMChangeMode(1);
27
  updateEEPWMSoftModeChangeTime(200);
28
  updateEEPWMSoftModeChangeTimeR(200);
29
  updateEEPWMSoftModeChangeTimeG(200);
30
  updateEEPWMSoftModeChangeTimeB(200);
31
  updateEEPWMSoftModeChangeTimeW(200);
32
  updateEEWS2812LedCount(10);
33
  updateEEPWMSoftLimit(255);
34
}
35
36
uint8_t getEEDefaultExist(void) {
37
  uint8_t retByte;
38
  retByte = eeprom_read_byte (&eeDefaultExist);
39
  return retByte;
40
}
41
42
uint8_t updateEEDefaultExist(void) {
43
  eeprom_update_byte(&eeDefaultExist, 1);
44
}
45
46
47
uint8_t getEEPWMChangeMode(void) {
48
  uint8_t retByte;
49
  retByte = eeprom_read_byte (&eePWMChangeMode);
50
  return retByte;
51
}
52
53
uint8_t updateEEPWMChangeMode(uint8_t newval) {
54
  eeprom_update_byte(&eePWMChangeMode, newval);
55
}
56
57
58
59
uint8_t getEEPWMSoftModeChangeTime(void) {
60
  uint8_t retByte;
61
  retByte = eeprom_read_byte (&eePWMSoftModeChangeTime);
62
  return retByte;
63
}
64
65
uint8_t updateEEPWMSoftModeChangeTime(uint8_t newval) {
66
  eeprom_update_byte(&eePWMSoftModeChangeTime, newval);
67
}
68
69
70
71
uint8_t getEEPWMSoftModeChangeTimeR(void) {
72
  uint8_t retByte;
73
  retByte = eeprom_read_byte (&eePWMSoftModeChangeTimeR);
74
  return retByte;
75
}
76
77
uint8_t updateEEPWMSoftModeChangeTimeR(uint8_t newval) {
78
  eeprom_update_byte(&eePWMSoftModeChangeTimeR, newval);
79
}
80
81
82
83
uint8_t getEEPWMSoftModeChangeTimeG(void) {
84
  uint8_t retByte;
85
  retByte = eeprom_read_byte (&eePWMSoftModeChangeTimeG);
86
  return retByte;
87
}
88
89
uint8_t updateEEPWMSoftModeChangeTimeG(uint8_t newval) {
90
  eeprom_update_byte(&eePWMSoftModeChangeTimeG, newval);
91
}
92
93
94
95
uint8_t getEEPWMSoftModeChangeTimeB(void) {
96
  uint8_t retByte;
97
  retByte = eeprom_read_byte (&eePWMSoftModeChangeTimeB);
98
  return retByte;
99
}
100
101
uint8_t updateEEPWMSoftModeChangeTimeB(uint8_t newval) {
102
  eeprom_update_byte(&eePWMSoftModeChangeTimeB, newval);
103
}
104
105
106
107
uint8_t getEEPWMSoftModeChangeTimeW(void) {
108
  uint8_t retByte;
109
  retByte = eeprom_read_byte (&eePWMSoftModeChangeTimeW);
110
  return retByte;
111
}
112
113
uint8_t updateEEPWMSoftModeChangeTimeW(uint8_t newval) {
114
  eeprom_update_byte(&eePWMSoftModeChangeTimeW, newval);
115
}
116
117
118
119
uint8_t getEEPWMSoftLimit(void) {
120
  uint8_t retByte;
121
  retByte = eeprom_read_byte (&eePWMSoftLimit);
122
  return retByte;
123
}
124
125
uint8_t updateEEPWMSoftLimit(uint8_t newval) {
126
  eeprom_update_byte(&eePWMSoftLimit, newval);
127
}
128
129
130
131
uint8_t getEEWS2812LedCount(void) {
132
  uint8_t retByte;
133
  retByte = eeprom_read_byte (&eeWs2812Count);
134
  return retByte;
135
}
136
uint8_t updateEEWS2812LedCount(uint8_t newval) {
137
  eeprom_update_byte(&eeWs2812Count, newval);
138
}

Jedoch sind die Werte leer... obwohl ich diese am Anfang der main immer 
erst schreibe..

also so...
1
#include "main.h"
2
#include "timer.h"
3
#include "twislave.h"
4
5
int main (void) {
6
7
  // Write Default EEPROM if not exist
8
  
9
  //if (getEEDefaultExist() == 0) {
10
  //  writeDefaultEEPROM();
11
  //  updateEEDefaultExist();
12
  //}
13
   
14
  i2c_readaddr_init();
15
  init_twi_slave(i2c_readaddr());
16
17
  // Init PWM
18
  pwm_init();
19
  init_pwmmodes();
20
21
  // Init Timer
22
  timer_init();
23
24
  // I2C Data
25
  init_address();
26
27
   // Init Data from EEPROM at First Start
28
  
29
   pwmchangemode = 1;
30
   
31
   pwmchangetime = 15;
32
   pwmchangetimeR = 15;
33
   pwmchangetimeG = 15;
34
   pwmchangetimeB = 15;
35
  pwmchangetimeW = 15;
36
  pwmsoftlimit = 250;
37
.............
38
.............

Vielleicht kann mir da ja der ein oder andere weiter helfen :)

von oweiowei (Gast)


Lesenswert?

Christop schrieb:
> Jetzt habe ich in der main.c folgenden Inhalt....

Ersten gehört so ein langer Soure-Text in einen Anhang (siehe:
Wichtige Regeln - erst lesen, dann posten!), zweitens ist das
Program nicht vollständig sodass wir nicht beurteilen können
ob du alles richtig machst.

von Christop (Gast)


Lesenswert?

Ja...

hier mal der komplette Code

https://github.com/pihome-dev/tempfolder

von Harald (Gast)


Lesenswert?

Code habe ich mir nicht angeschaut, aber für die Analyse gibt es 
Logic-Analyzer <10€ und leistungsstarke Software für 0€. Dank 
entsprechender Decoder für nahezu jeden Speicherbaustein in dieser 
Software bekommt man genau angezeigt, wo das Problem liegt.

Darüber hinaus kann der Schreibschutz ein Problem darstellen. Fast immer 
gibt es einen Pin, der muss natürlich richtig stehen. Weiterhin gibt es 
auch manchmal ein Configuration-Word in den EEP-Commands, das nochmals 
einen Schreibschutz beinhalten kann.

von holger (Gast)


Lesenswert?

>aber für die Analyse gibt es
>Logic-Analyzer <10€ und leistungsstarke Software für 0€

Na dann erklär mal wie man den Logic-Analyzer an den
Datenbus im ATMega zu seinem im Gehäuse verbauten EEPROM
anschliesst.

von Dumpfbacke (Gast)


Lesenswert?

Externes EEPROM.

Wer lesen kann ist klar im Vorteil.
Holger offensichtlich nicht.

von holger (Gast)


Lesenswert?

>   // Init Data from EEPROM at First Start
>
>   pwmchangemode = 1;

Man kann Werten im EEMEM nicht einfach im laufenden Programm
per Compiler einen Wert wie bei einer Variablen im RAM zuweisen
und dann denken dass das im EEPROM landet. Dazu musst du schon
irgendeine EEPromWrite Funktion benutzen müssen.

von holger (Gast)


Lesenswert?

>Externes EEPROM.

Wo steht da oben irgendwas von externem EEPROM?

von oweiowei (Gast)


Lesenswert?

holger schrieb:
> Wo steht da oben irgendwas von externem EEPROM?

Das darf man annehmen wenn er TWI Code und I2C Adressen verwendet.

von oweiowei (Gast)


Lesenswert?

oweiowei schrieb:
> Das darf man annehmen wenn er TWI Code und I2C Adressen verwendet.

Wenn sich der TO allerdings dessen nicht bewusst ist dann
ist Hopfen und Malz verloren und ich nehme alles zurück und
behaupte das Gegenteil.

von Harald (Gast)


Lesenswert?

holger schrieb:
> Wo steht da oben irgendwas von externem EEPROM?

Christop schrieb:
> Zugleich soll ein weiterer EEPROM Bereich zum Speichern
> der Werte da sein..

Zusätzlich die Verwendung von I2C im Code. Damit war es allem Anschein 
nach klar. Falls es doch anders gemeint war, Pech

von holger (Gast)


Lesenswert?

>> Wo steht da oben irgendwas von externem EEPROM?
>
>Das darf man annehmen wenn er TWI Code und I2C Adressen verwendet.

Nein darf man nicht. Am I2C kann sonst was hängen. EEMEM ist jedenfalls
kein EEPROM was am I2C angeschlossen ist.

von holger (Gast)


Lesenswert?

>Dieser soll "default" Werte im
>EEPROM haben. Zugleich soll ein weiterer EEPROM Bereich zum Speichern
>der Werte da sein..

>Zusätzlich die Verwendung von I2C im Code. Damit war es allem Anschein
>nach klar. Falls es doch anders gemeint war, Pech

Ich würde das so interpretieren das die "default" Werte in einem Bereich 
im EEPROM liegen der nie verändert wird. Dann gibt es noch einen Bereich 
wo man seine veränderlichen Werte speichert. Und das ganze im internen 
EEPROM vom ATMega. I2C komplett Latte.

von Holger L. (max5v)


Lesenswert?

Erst einmal könnte man die update Funktionen ohne return in der eeprom.c 
auf void anstelle von uint8_t setzen.

Zu dem sollte man auch darauf achten, das es sich wirklich um einen 
ATmega328 handelt und nicht um die P oder PB Version, das kann schnell 
mal zu unerwünschtem Verhalten führen.

Und zuletzt,
1
if (getEEDefaultExist() == 0) {
2
    writeDefaultEEPROM();
3
    updateEEDefaultExist();
4
  }

Sicher das der Speicherinhalt eines "jungfräulichem" EEprom 0x00 ist und 
nicht 0xFF?
Dieses hier wäre evtl. einen Versuch wert:
1
if (getEEDefaultExist() != 1) {
2
    writeDefaultEEPROM();
3
    updateEEDefaultExist();
4
  }

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> uint8_t eePWMChangeMode EEMEM = 100;

Das ist eine Integer Variable, die der Compiler in die .eeprom Sektion 
schreibt. Diese Information kann (muss nicht und ist auch eher ein 
Sonderfall) dazu verwendet werden, dass EEPROM zusammen mit dem FLASH zu 
initialisieren. Mehr kann man damit nicht anfangen.

Das C-Programm hat keinen direkten zugriff auf das EEPROM. Diese 
Variable kannst du also weder lesen noch schreiben. Sie haben aus Sicht 
des C Programm eine Adresse aber keinen Wert. Zugriff auf das EEPROM 
bekommst du nur indirekt über die eeprom_xxxx_xxxx() Funktionen.

Also z.B.:

> retByte = eeprom_read_byte (&eePWMChangeMode);

Hier liest du ein Byte aus dem EEPROM an irgendeiner Adresse, die der 
Compiler für eePWMChangeMode vorgegeben hat. eePWMChangeMode enthält 
also gar nicht den Wert von "PWMChangeMode" sondern nur dessen Adresse 
im EEPROM (nicht im RAM!).

Das gleiche Problem hast du auch mit allen anderen Variablen. Reduziere 
dein Beispielprogramm demnächst bitte auf möglichst wenige Zeilen, die 
das Problem noch demonstrieren. Dieses Programm sollte dann aber so 
vollständig sein, dass es compilierbar ist.

Änderungsvorschlag:

Anstelle von
> uint8_t eePWMChangeMode EEMEM = 100;

schreibst du

#define eePWMChangeMode 1

Damit legst du fest, dass der Wert für PWMChangeMode im EEprom an 
Adresse 1 gespeichert werden soll. Die nächste Variable kommt auf 
Adresse 2, dann 3, usw. So kannst du selber vorgeben, was wo hin kommt 
und musst dich nicht mehr oder weniger auf zufällige Vorgaben des 
Compilers verlassen die sich möglicherweise mal unerwartet ändern.

Holger L. schrieb:
> Sicher das der Speicherinhalt eines "jungfräulichem" EEprom 0x00 ist und
> nicht 0xFF?

Es ist 0xFF, guter Hinweis. Das wird der eigentliche Knackpunkt sein.

von Stefan F. (Gast)


Lesenswert?

> Ich würde das so interpretieren das

Ich glaube, der TO hat sein eigenes Programm nicht verstanden oder 
abgeschrieben.

Die Default werte stehen nicht im EEPROM, sondern im Quelltext. Und zwar 
in der Funktion writeDefaultEEPROM().

Das Programm schreibt diese Werte erstmalig ins EEPROM, wenn es danach 
aussieht, dass es noch nicht initialisiert wurde. Die Werte von den 
ganzen EEMEM Variablen werden überhaupt nicht verwendet. Es werden nur 
deren Adressen verwendet.

von Pete K. (pete77)


Lesenswert?

Und die Return-Werte der Funktionen werden nicht ausgewertet.
Programmieren anno 2020 ....

von Christoph (Gast)


Lesenswert?

Also wie schon richtig vermutet hat es mit dem externen eeprom nichts zu 
tun.

Wenn man sich den Code anschaut, sollte das aber klar sein.

Wie schon erkannt, soll der atmega, falls noch nicht vorhanden die 
default Werte schreiben. Userdaten werden woanders geschrieben.

Ich habe den eeprom Teil aus dem tutorial. Dort wird write, Update etc 
erklärt. Auch das Lesen aus dem eeprom.

Was ist nun bei mir anders als dem Code vom tutorial?

von Stefan F. (Gast)


Lesenswert?

Christoph schrieb:
> Was ist nun bei mir anders als dem Code vom tutorial?

1.) Wleches Tutorial?
2.) Vergleiche selbst. Die Knackpunkte wurden dir genannt.

Beitrag #6436798 wurde von einem Moderator gelöscht.
von Moot S. (mootseeker)


Lesenswert?

Harald schrieb:
> Code habe ich mir nicht angeschaut, aber für die Analyse gibt es
> Logic-Analyzer <10€ und leistungsstarke Software für 0€.

Wo gibt es anständige Logic-Analyzer unter 10€ ?

von Stefan F. (Gast)


Lesenswert?

Moot S. schrieb:
> Wo gibt es anständige Logic-Analyzer unter 10€ ?

Bei Amazon, Ebay, Aliexpress.

Ob sie "anständig" sind, ist Ansichtssache. Ich bin mit meinem 
zufrieden. Für das Geld man es selber nicht besser machen. Auch nicht 
für doppelt so viel Geld.

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.