Forum: Mikrocontroller und Digitale Elektronik EEPROM gibt nur 122 zurück


von Patrick R. (pat711)


Lesenswert?

Guten Tag zusammen,

ich versuche schon seit 2 Tagen den Fehler in meinem Programm zu finden, 
nun scheine ich dem Problem sehr nahe zu sein. in dem unten angehängten 
programmteil soll der wert einer variablen in den EEprom geschrieben 
werden und nacher wieder ausgelesen werden. wenn ich nun das programm 
starte wird aber als ausgelesener wert immer 122 angezeigt...
Irgendetwas stimmt mit dem Speicherort auf dem EEPROM nicht.
Kann mir vll jemand weiterhelfen?
Es soll der intern EEPROM verwendet werden.

Hardware:
ATmega8
16 MHz Quarz
LCD an PORTB
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <avr/eeprom.h>
6
#include <inttypes.h>
7
8
#ifndef EEMEM   // alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
9
#define EEMEM  __attribute__ ((section (".eeprom")))
10
#endif
11
12
#define u_int unsigned int
13
14
void long_delay(uint16_t ms)                                   
15
{
16
    for(; ms>0; ms--) _delay_ms(1);
17
}
18
19
int main (void)
20
{  
21
  lcd_init();
22
  u_int inhalt;    //inhalt welcher in EEPROM geschrieben wird
23
  u_int neu;      //Variable zur Aufnahme des Inhalts, welcher aus EEPROM gelesen wird   //
24
    
25
  for (uint8_t counter = 0; counter < 90; counter ++)
26
  {
27
    inhalt = counter * 10;
28
    eeprom_write_byte(&counter, inhalt);
29
  }
30
  for (uint8_t counter = 0; counter < 90; counter ++)
31
  {
32
    neu = eeprom_read_byte(&counter);
33
    char Buffer[20];
34
    itoa(counter, Buffer, 10); 
35
    set_cursor(1,1);
36
    lcd_string( Buffer );
37
    long_delay(500);
38
    itoa(neu, Buffer, 10); 
39
    set_cursor(10,1);
40
    lcd_string( Buffer );
41
    long_delay(500);
42
    itoa(inhalt, Buffer, 10); 
43
    set_cursor(8,2);
44
    lcd_string( Buffer );
45
    long_delay(500);
46
  }
47
}

von Stephan (Gast)


Lesenswert?

Hi

schau dir nochmal hier das AVR-GCC-Tutorial an!
Der erste Parameter der an read und write übergeben wird ist immer der 
Pointer auf die EEProm Variable und dann folgt beim write der neue Wert.

'counter' ist bei dir eine lokale Variable deshalb geht es nicht!
Und warum versuchst du an EINE Adresse ZEHN Werte zu schreiben???
Mein Vorschlag wäre ein Array!?!
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <avr/eeprom.h>
6
#include <inttypes.h>
7
8
#ifndef EEMEM   // alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
9
#define EEMEM  __attribute__ ((section (".eeprom")))
10
#endif
11
12
uint8_t eeCounter EEMEM;
13
14
#define u_int unsigned int
15
16
void long_delay(uint16_t ms)                                   
17
{
18
    for(; ms>0; ms--) _delay_ms(1);
19
}
20
21
int main (void)
22
{  
23
  char Buffer[20];
24
  u_int counter= 1;
25
  u_int inhalt;    //inhalt welcher in EEPROM geschrieben wird
26
  u_int neu;      //Variable zur Aufnahme des Inhalts, welcher aus EEPROM gelesen wird   //
27
    
28
  inhalt = 170;
29
  eeprom_write_byte(&eeCounter, inhalt);
30
  lcd_init();
31
  neu = eeprom_read_byte(&eeCounter);
32
  itoa(counter, Buffer, 10); 
33
  set_cursor(1,1);
34
  lcd_string( Buffer );
35
  long_delay(500);
36
  itoa(neu, Buffer, 10); 
37
  set_cursor(10,1);
38
  lcd_string( Buffer );
39
  long_delay(500);
40
  itoa(inhalt, Buffer, 10); 
41
  set_cursor(8,2);
42
  lcd_string( Buffer );
43
  while(1);
44
}

versuche mal das, habs aber nicht getestet.
Du müsstest 1, 170, 170 sehen.

mfg
Stephan

von Patrick R. (pat711)


Lesenswert?

thx für die Antwort.

Was bewirkt denn der Anhang EEMEM?

und das mit dem array hab ich auch schon probiert werd ich dann wohl 
auch wieder umstellen.

Was mich noch ein wenig wundert, warum hast du gemeint ich will 10 werte 
auf einen Speicherplatz schreiben? ich habe den schribvorgang ja in 
einer for schleife, der counter wird jedes mal um 1 erhöht. Dieser dient 
ja auch als angabe de Speicherortes, also wird dieser auch jedes mal um 
1 erhöht.

Mfg Pat

von Patrick R. (pat711)


Lesenswert?

hab den code nun ein wenig umgeschrieben, aber das ganze funktioniert 
immer noch nicht. auf dem display wird folgendes angezeigt:
0*0             0*1
*20             *40

an den stellen wo ich das * eingesetzt habe sind undefinierbare zeichen 
der größtteil ist schwarz und es sind alle 4 gleich

hier noch der neue Code:
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <avr/eeprom.h>
6
#include <inttypes.h>
7
8
#ifndef EEMEM   // alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
9
#define EEMEM  __attribute__ ((section (".eeprom")))
10
#endif
11
12
uint8_t ee_test1 EEMEM, ee_test2 EEMEM;
13
uint8_t counter;
14
15
#define u_int unsigned int
16
17
void long_delay(uint16_t ms)                                   
18
{
19
    for(; ms>0; ms--) _delay_ms(1);
20
}
21
22
void auslesen (void)
23
{
24
  u_int buffer1 = 0, buffer2 = 0;
25
  char Buffer[20];
26
  
27
  ee_test1 = counter * 2;
28
  ee_test2 = counter * 2 +1;
29
30
  buffer1 = eeprom_read_byte(&ee_test1);
31
  buffer2 = eeprom_read_byte(&ee_test2);
32
33
  itoa(ee_test1, Buffer, 10);   
34
  set_cursor(1,1);
35
  lcd_string( Buffer );
36
    
37
  itoa(ee_test2, Buffer, 10); 
38
  set_cursor(12,1);
39
  lcd_string( Buffer );
40
  
41
  itoa(buffer1, Buffer, 10); 
42
  set_cursor(1,2);
43
  lcd_string( Buffer );
44
  
45
  itoa(buffer2, Buffer, 10); 
46
  set_cursor(12,2);
47
  lcd_string( Buffer );
48
}
49
50
int main (void)
51
{  
52
  lcd_init();
53
  long_delay(2000);
54
  while (1)
55
  {
56
    lcd_clear();
57
    u_int var1 = 20, var2 = 40;
58
    uint8_t counter = 0;
59
    
60
    ee_test1 = counter * 2;
61
    ee_test2 = counter * 2 +1;
62
    
63
    eeprom_write_byte(&ee_test1, var1);
64
    eeprom_write_byte(&ee_test2, var2);
65
    
66
    auslesen();
67
    
68
    counter ++;
69
    if (counter == 220)
70
    {
71
      counter = 1;
72
    }
73
    
74
    long_delay(1000);
75
  }
76
77
}

Mfg Pat

von Stefan E. (sternst)


Lesenswert?

Du hast praktisch zwei Möglichkeiten, die Daten im EEPROM zu verwalten:

1) Der Compiler übernimmt die Verwaltung:
1
uint8_t EE_daten[10] EEMEM;   // 10 Bytes im EEPROM, genaue Adresse legt der Compiler fest
2
3
// alle zehn Bytes lesen (genaue Adresse interessiert uns nicht)
4
uint8_t byte; 
5
for (uint8_t i = 0; i < 10; i++) {
6
    byte = eeprom_read_byte(&EE_daten[i]);
7
    ...
8
}

2) Du selbst übernimmst die Verwaltung:
1
uint16_t ee_adr;   // Adresse für den EEPROM-Zugriff
2
3
// die ersten 10 Bytes lesen (Adresse 0-9) 
4
uint8_t byte; 
5
for (ee_adr = 0; ee_adr < 10; ee_adr++) {
6
    byte = eeprom_read_byte((uint8_t*)ee_adr);
7
    ...
8
}

Du hast in deinem Code einen wilden Mischmasch aus beidem, der nicht 
funktionieren kann.

von Stephan (Gast)


Lesenswert?

Hi Patrick

du hast dir das Tutorial scheinbar nicht ausreichend angesehen.
1
ee_test1 = counter * 2;
2
ee_test2 = counter * 2 +1;

Das geht NICHT!!! Du kannst nicht direkt auf Vars im EEProm zugreifen, 
dafür sind ja die Funktionen da.
1
eeprom_read_byte
2
eeprom_write_byte

>Was bewirkt denn der Anhang EEMEM?
Das sorgt dafür das die Variable nicht im RAM sondern im EEProm landet.
Und damit ist die Variable nicht mehr für dich zugänglich. (s.o)

>Was mich noch ein wenig wundert, warum hast du gemeint ich will 10 werte
>auf einen Speicherplatz schreiben? ich habe den Schreibvorgang ja in
>einer for schleife, der counter wird jedes mal um 1 erhöht.
Also du Veränderst den Wert in der Variable 'counter' aber der 
Speicherort (Adresse) bleibt immer konstant.

in deinem 2. Beispiel das selbe!
1
    ee_test1 = counter * 2;
2
    ee_test2 = counter * 2 +1;
3
    
4
    eeprom_write_byte(&ee_test1, var1);
5
    eeprom_write_byte(&ee_test2, var2);
Hier schreibst du jedes mal an die Adresse von 'ee_test1' und 
'ee_test2' den Wert von 'var1' und 'var2'.
Und DAS zeigt dir auch deine Ausgabe. ( 20 und 40 )

mfg
Stephan

PS: hier noch etwas Hilfe
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=38417

von Patrick R. (pat711)


Lesenswert?

Guten Morgen zusammen,

ich glaub in dieser zEILE LIEGT DER fEHLER.
1
    ee_test1 = counter * 2;
2
    ee_test2 = counter * 2 +1;

mein ziel war es hier den counter, welcher bei jedem durchlauf um 1 
erhöht wird so zu verarbeiten, dass ich den EEPROM fortlaufend 
beschreibe. Also im ersten Durchlauf, wenn der counter noch 0 ist:
Adresse für var1: counter = 0 mal 2 = 0
Adresse für var2: counter = 0 mal 2 plus 1 = 1
Also wären die Adressen in diesem ersten Durchlauf 0 und 1.
Im 2. Durchlauf wären Sie dann folglich wenn counter = 1 dann 2 und 3

Die Adresse würden dann eben so berechnet werden und dann mit dem 
verfahren, welches Stefan Ernst beschrieben hat beschrieben werden.


Mfg, Pat

von Patrick R. (pat711)


Lesenswert?

ich glaub ich hab eh noch ein Problem mit der Größe meiner Variablen, da 
die gar nicht auf eine Adresse passen, oder passte der Compiler das dann 
so weit an?

von Stephan (Gast)


Lesenswert?

was meinst du?

von Patrick R. (pat711)


Lesenswert?

nun die Variable wird ja in einem Byte auf dem EEPROM gespeichert, wenn 
sie nun aber so groß ist, dass sie beispielsweise 2 Byte belegt wird ja 
das nachfolgende auch belegt. wenn zum beispiel nun das erste byte die 
adresse 1 hat, hat das 2. ja im normalfall die 2 oder wird das dann so 
angepasst, dass die 2 erst nach diesem block kommt?

Oh mann ich muss des tut nommel anschaun

Mfg Pat

von Patrick R. (pat711)


Lesenswert?

ok ich hab nun um das ganze etwas übersichtlicher zu machen den Code so 
umgeschrieben, dass er funktioniert.

Hier ist die Funktion welche die beiden Zeilen
1
ee_test1 = counter * 2;
2
ee_test2 = counter * 2 +1;
übernehmen sollen vielleicht etwas besser sichtbar und es ist glaub auch 
einleuchtend warum ich das nicht für 5 * 50 Adressen machen möchte xD.

Code:
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <avr/eeprom.h>
6
#include <inttypes.h>
7
8
#ifndef EEMEM   // alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
9
#define EEMEM  __attribute__ ((section (".eeprom")))
10
#endif
11
uint8_t counter = 0;
12
uint8_t ee_test1[20], ee_test2[20];
13
14
15
#define u_int unsigned int
16
17
void long_delay(uint16_t ms)                                   
18
{
19
    for(; ms>0; ms--) _delay_ms(1);
20
}
21
22
void auslesen (void)
23
{
24
  uint8_t buffer1 = 0, buffer2 = 0;
25
  char Buffer[20];
26
  
27
28
  buffer1 = eeprom_read_byte(&ee_test1[counter]);
29
  buffer2 = eeprom_read_byte(&ee_test2[counter]);
30
31
  itoa(ee_test1[counter], Buffer, 10);   
32
  set_cursor(1,1);
33
  lcd_string( Buffer );
34
    
35
  itoa(ee_test2[counter], Buffer, 10);
36
  set_cursor(12,1);
37
  lcd_string( Buffer );
38
  
39
  itoa(buffer1, Buffer, 10); 
40
  set_cursor(1,2);
41
  lcd_string( Buffer );
42
  
43
  itoa(buffer2, Buffer, 10); 
44
  set_cursor(12,2);
45
  lcd_string( Buffer );
46
  
47
  itoa(counter, Buffer, 10); 
48
  set_cursor(8,2);
49
  lcd_string( Buffer );
50
}
51
52
int main (void)
53
{  
54
  ee_test1[0] = 0;        //dieser Riesen Block soll durch die 2 Zeilen ersetzt werden.
55
  ee_test2[0] = 1;
56
  
57
  ee_test1[1] = 2;
58
  ee_test2[1] = 3;
59
  
60
  ee_test1[2] = 4;
61
  ee_test2[2] = 5;
62
  
63
  ee_test1[3] = 6;
64
  ee_test2[3] = 7;
65
  
66
  ee_test1[4] = 8;
67
  ee_test2[4] = 9;
68
  
69
  ee_test1[5] = 10;
70
  ee_test2[5] = 11;
71
  
72
  ee_test1[6] = 12;
73
  ee_test2[6] = 13;
74
  
75
  ee_test1[7] = 14;
76
  ee_test2[7] = 15;
77
  
78
  ee_test1[8] = 16;
79
  ee_test2[8] = 17;
80
  
81
  ee_test1[9] = 18;
82
  ee_test2[9] = 19;
83
  
84
  ee_test1[10] = 20;
85
  ee_test2[10] = 21;
86
  
87
  ee_test1[11] = 22;
88
  ee_test2[11] = 23;
89
  
90
  ee_test1[12] = 24;
91
  ee_test2[12] = 25;
92
  
93
  ee_test1[13] = 26;
94
  ee_test2[13] = 27;
95
  
96
  ee_test1[14] = 28;
97
  ee_test2[14] = 29;
98
  
99
  ee_test1[15] = 30;
100
  ee_test2[15] = 31;
101
  
102
  ee_test1[16] = 32;
103
  ee_test2[16] = 33;
104
  
105
  ee_test1[17] = 34;
106
  ee_test2[17] = 35;
107
  
108
  ee_test1[18] = 36;
109
  ee_test2[18] = 37;
110
  
111
  ee_test1[19] = 38;
112
  ee_test2[19] = 39;
113
  
114
  lcd_init();
115
  long_delay(2000);
116
117
  while (1)
118
  {
119
    lcd_clear();
120
    uint8_t var1 = counter -1, var2 = counter +1;  
121
    
122
    
123
    eeprom_write_byte(&ee_test1[counter], var1);
124
    eeprom_write_byte(&ee_test2[counter], var2);
125
    
126
    auslesen();
127
    
128
    counter ++;
129
    if (counter == 20)
130
    {
131
      counter = 0;
132
    }
133
    
134
    long_delay(1000);
135
  }
136
137
}

sieht doch toll aus oder xD nur dass der Code nun doppelt so lang ist ^^

von Stephan (Gast)


Angehängte Dateien:

Lesenswert?

Ok!

hier mal meine Version für dich.
Ich habe es aus dem Kopf gemacht, ich kann es hier nicht Übersetzen, 
also könnte Schreibfehler vorhanden sein.

Melde dich nochmal wenn du es hin bekommen hast.

mfg
Stephan

von Patrick R. (pat711)


Lesenswert?

Vielen Dank, dass du die Geduld hast mir das ganze zu erklären. Nur hat 
mich das mit deinem Dirkter Zugriff nicht möglich!! Und ich weiß nun 
auch was du damit meintest. Aber ziel dieser Zeile war es nicht den 
Inhalt anzuzeigen sondern die Adresse. Also die Variable, welche die 
Adresse angibt.

Dein Code läuft soweit auch nur, dass der counter stetig hochzählt und 
der Inhalt jedes 2. Mal 255 ist. werd mich mal auf fehlersuche machen 
und dann endlich was funktionsfähiges zusammenbauen ^^

MfG Pat

von Stephan (Gast)


Lesenswert?

Hi
und test1 und test2 werden nicht ausgegeben??

von Patrick R. (pat711)


Lesenswert?

doch auch und zwar eine zeile höher als die dazugehörige Adresse

MfG Pat

von Stephan (Gast)


Lesenswert?

Hi

:-(
da kann ich dir erstmal so nicht weiter helfen. (mehr Infos)
Du bist sicher das deine Ausgabe (LCD) läuft?

Zum Test könntest du mal den Funktionsaufruf 'auslesen()' mit dem hier 
ersetzen 'auslesen2()' und dieses in dein Programm einfügen. (vor Main)
1
#include <stdio.h>
2
3
void auslesen2(void)
4
{
5
    set_cursor(1,1);
6
    sprintf_P( ITOA_Buffer, "Counter=%d", counter);
7
    lcd_string( ITOA_Buffer );
8
}

Wenn die Ausgabe richtig läuft, solltest du:
Counter=0, Counter=1 ... sehen.

mfg
Stephan

von Patrick R. (pat711)


Lesenswert?

jaja das funzt alles so weit der code, den ich gepostet habe 
funktioniert nun auch, und zwar auch mit dieser lösung:
1
ee_test1 = counter * 2;
2
ee_test2 = counter * 2 +1;

^^
thx nochmal, bin grad an meim großen coede das ganze zu verbessern, da 
wird das ausm EEPROM dann per UART versendet. das einzige prob is noch 
dasses nimme aufhört zu senden xD, dass also zu viel in den EEPROM 
gespeichert wurde ^^

aber das wird noch, da is bestimmt irgendwo bloß ne schleife oder so ^^

MfG Pat

von Stephan (Gast)


Lesenswert?

;-)

gut
dann noch viel Spass

mfg
Stephan

von Patrick R. (pat711)


Lesenswert?

na danke xD der Code hat fast 800 Zeilen da kann des alles mögliche sein 
xD

MfG und Thx

Pat

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.