www.mikrocontroller.net

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


Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht 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
#include <avr/io.h>
#include "lcd-routines.h"
#include <util/delay.h>
#include <stdlib.h>
#include <avr/eeprom.h>
#include <inttypes.h>

#ifndef EEMEM   // alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
#define EEMEM  __attribute__ ((section (".eeprom")))
#endif

#define u_int unsigned int

void long_delay(uint16_t ms)                                   
{
    for(; ms>0; ms--) _delay_ms(1);
}

int main (void)
{  
  lcd_init();
  u_int inhalt;    //inhalt welcher in EEPROM geschrieben wird
  u_int neu;      //Variable zur Aufnahme des Inhalts, welcher aus EEPROM gelesen wird   //
    
  for (uint8_t counter = 0; counter < 90; counter ++)
  {
    inhalt = counter * 10;
    eeprom_write_byte(&counter, inhalt);
  }
  for (uint8_t counter = 0; counter < 90; counter ++)
  {
    neu = eeprom_read_byte(&counter);
    char Buffer[20];
    itoa(counter, Buffer, 10); 
    set_cursor(1,1);
    lcd_string( Buffer );
    long_delay(500);
    itoa(neu, Buffer, 10); 
    set_cursor(10,1);
    lcd_string( Buffer );
    long_delay(500);
    itoa(inhalt, Buffer, 10); 
    set_cursor(8,2);
    lcd_string( Buffer );
    long_delay(500);
  }
}

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!?!
#include <avr/io.h>
#include "lcd-routines.h"
#include <util/delay.h>
#include <stdlib.h>
#include <avr/eeprom.h>
#include <inttypes.h>

#ifndef EEMEM   // alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
#define EEMEM  __attribute__ ((section (".eeprom")))
#endif

uint8_t eeCounter EEMEM;

#define u_int unsigned int

void long_delay(uint16_t ms)                                   
{
    for(; ms>0; ms--) _delay_ms(1);
}

int main (void)
{  
  char Buffer[20];
  u_int counter= 1;
  u_int inhalt;    //inhalt welcher in EEPROM geschrieben wird
  u_int neu;      //Variable zur Aufnahme des Inhalts, welcher aus EEPROM gelesen wird   //
    
  inhalt = 170;
  eeprom_write_byte(&eeCounter, inhalt);
  lcd_init();
  neu = eeprom_read_byte(&eeCounter);
  itoa(counter, Buffer, 10); 
  set_cursor(1,1);
  lcd_string( Buffer );
  long_delay(500);
  itoa(neu, Buffer, 10); 
  set_cursor(10,1);
  lcd_string( Buffer );
  long_delay(500);
  itoa(inhalt, Buffer, 10); 
  set_cursor(8,2);
  lcd_string( Buffer );
  while(1);
}

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

mfg
Stephan

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <avr/io.h>
#include "lcd-routines.h"
#include <util/delay.h>
#include <stdlib.h>
#include <avr/eeprom.h>
#include <inttypes.h>

#ifndef EEMEM   // alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
#define EEMEM  __attribute__ ((section (".eeprom")))
#endif

uint8_t ee_test1 EEMEM, ee_test2 EEMEM;
uint8_t counter;

#define u_int unsigned int

void long_delay(uint16_t ms)                                   
{
    for(; ms>0; ms--) _delay_ms(1);
}

void auslesen (void)
{
  u_int buffer1 = 0, buffer2 = 0;
  char Buffer[20];
  
  ee_test1 = counter * 2;
  ee_test2 = counter * 2 +1;

  buffer1 = eeprom_read_byte(&ee_test1);
  buffer2 = eeprom_read_byte(&ee_test2);

  itoa(ee_test1, Buffer, 10);   
  set_cursor(1,1);
  lcd_string( Buffer );
    
  itoa(ee_test2, Buffer, 10); 
  set_cursor(12,1);
  lcd_string( Buffer );
  
  itoa(buffer1, Buffer, 10); 
  set_cursor(1,2);
  lcd_string( Buffer );
  
  itoa(buffer2, Buffer, 10); 
  set_cursor(12,2);
  lcd_string( Buffer );
}

int main (void)
{  
  lcd_init();
  long_delay(2000);
  while (1)
  {
    lcd_clear();
    u_int var1 = 20, var2 = 40;
    uint8_t counter = 0;
    
    ee_test1 = counter * 2;
    ee_test2 = counter * 2 +1;
    
    eeprom_write_byte(&ee_test1, var1);
    eeprom_write_byte(&ee_test2, var2);
    
    auslesen();
    
    counter ++;
    if (counter == 220)
    {
      counter = 1;
    }
    
    long_delay(1000);
  }

}

Mfg Pat

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast praktisch zwei Möglichkeiten, die Daten im EEPROM zu verwalten:

1) Der Compiler übernimmt die Verwaltung:
uint8_t EE_daten[10] EEMEM;   // 10 Bytes im EEPROM, genaue Adresse legt der Compiler fest

// alle zehn Bytes lesen (genaue Adresse interessiert uns nicht)
uint8_t byte; 
for (uint8_t i = 0; i < 10; i++) {
    byte = eeprom_read_byte(&EE_daten[i]);
    ...
}

2) Du selbst übernimmst die Verwaltung:
uint16_t ee_adr;   // Adresse für den EEPROM-Zugriff

// die ersten 10 Bytes lesen (Adresse 0-9) 
uint8_t byte; 
for (ee_adr = 0; ee_adr < 10; ee_adr++) {
    byte = eeprom_read_byte((uint8_t*)ee_adr);
    ...
}

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

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Patrick

du hast dir das Tutorial scheinbar nicht ausreichend angesehen.
ee_test1 = counter * 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.
eeprom_read_byte
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!
    ee_test1 = counter * 2;
    ee_test2 = counter * 2 +1;
    
    eeprom_write_byte(&ee_test1, var1);
    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&f...

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen zusammen,

ich glaub in dieser zEILE LIEGT DER fEHLER.
    ee_test1 = counter * 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

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was meinst du?

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht 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
ee_test1 = counter * 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:
#include <avr/io.h>
#include "lcd-routines.h"
#include <util/delay.h>
#include <stdlib.h>
#include <avr/eeprom.h>
#include <inttypes.h>

#ifndef EEMEM   // alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
#define EEMEM  __attribute__ ((section (".eeprom")))
#endif
uint8_t counter = 0;
uint8_t ee_test1[20], ee_test2[20];


#define u_int unsigned int

void long_delay(uint16_t ms)                                   
{
    for(; ms>0; ms--) _delay_ms(1);
}

void auslesen (void)
{
  uint8_t buffer1 = 0, buffer2 = 0;
  char Buffer[20];
  

  buffer1 = eeprom_read_byte(&ee_test1[counter]);
  buffer2 = eeprom_read_byte(&ee_test2[counter]);

  itoa(ee_test1[counter], Buffer, 10);   
  set_cursor(1,1);
  lcd_string( Buffer );
    
  itoa(ee_test2[counter], Buffer, 10);
  set_cursor(12,1);
  lcd_string( Buffer );
  
  itoa(buffer1, Buffer, 10); 
  set_cursor(1,2);
  lcd_string( Buffer );
  
  itoa(buffer2, Buffer, 10); 
  set_cursor(12,2);
  lcd_string( Buffer );
  
  itoa(counter, Buffer, 10); 
  set_cursor(8,2);
  lcd_string( Buffer );
}

int main (void)
{  
  ee_test1[0] = 0;        //dieser Riesen Block soll durch die 2 Zeilen ersetzt werden.
  ee_test2[0] = 1;
  
  ee_test1[1] = 2;
  ee_test2[1] = 3;
  
  ee_test1[2] = 4;
  ee_test2[2] = 5;
  
  ee_test1[3] = 6;
  ee_test2[3] = 7;
  
  ee_test1[4] = 8;
  ee_test2[4] = 9;
  
  ee_test1[5] = 10;
  ee_test2[5] = 11;
  
  ee_test1[6] = 12;
  ee_test2[6] = 13;
  
  ee_test1[7] = 14;
  ee_test2[7] = 15;
  
  ee_test1[8] = 16;
  ee_test2[8] = 17;
  
  ee_test1[9] = 18;
  ee_test2[9] = 19;
  
  ee_test1[10] = 20;
  ee_test2[10] = 21;
  
  ee_test1[11] = 22;
  ee_test2[11] = 23;
  
  ee_test1[12] = 24;
  ee_test2[12] = 25;
  
  ee_test1[13] = 26;
  ee_test2[13] = 27;
  
  ee_test1[14] = 28;
  ee_test2[14] = 29;
  
  ee_test1[15] = 30;
  ee_test2[15] = 31;
  
  ee_test1[16] = 32;
  ee_test2[16] = 33;
  
  ee_test1[17] = 34;
  ee_test2[17] = 35;
  
  ee_test1[18] = 36;
  ee_test2[18] = 37;
  
  ee_test1[19] = 38;
  ee_test2[19] = 39;
  
  lcd_init();
  long_delay(2000);

  while (1)
  {
    lcd_clear();
    uint8_t var1 = counter -1, var2 = counter +1;  
    
    
    eeprom_write_byte(&ee_test1[counter], var1);
    eeprom_write_byte(&ee_test2[counter], var2);
    
    auslesen();
    
    counter ++;
    if (counter == 20)
    {
      counter = 0;
    }
    
    long_delay(1000);
  }

}

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

Autor: Stephan (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
und test1 und test2 werden nicht ausgegeben??

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
doch auch und zwar eine zeile höher als die dazugehörige Adresse

MfG Pat

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)
#include <stdio.h>

void auslesen2(void)
{
    set_cursor(1,1);
    sprintf_P( ITOA_Buffer, "Counter=%d", counter);
    lcd_string( ITOA_Buffer );
}

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

mfg
Stephan

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jaja das funzt alles so weit der code, den ich gepostet habe 
funktioniert nun auch, und zwar auch mit dieser lösung:
ee_test1 = counter * 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

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
;-)

gut
dann noch viel Spass

mfg
Stephan

Autor: Patrick R. (pat711)
Datum:

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

MfG und Thx

Pat

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.