www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik EEPROM lesen funktioniert nicht


Autor: Melanie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein Problem. Ich möchte Daten im EEPROM ablegen und per ISP 
aufspielen. Das klappt auch soweit. Ich definiere einen Array mit 5 
Bytes, die .eep hat diese auch.
Im Programm lade ich mir die Daten aus dem EEPROM in eine Variable aus 
dem Flash. Leider übernimmt diese Variable die Werte aus dem EEPROM 
nicht. Wieso?
Ich lase mir die Werte mit einer LED anzeigen. Das abgespeckte Programm 
ist anbei.
Wenn ich vom meinem Programm aus eeprom_write_block() benutze, übernimmt 
das EEPROM die Werte. Wenn ich diese dann wieder lese aus dem EEPROM und 
in meine Flash Variable schreibe mit eeprom_read_block() liegen diese 
auch richtig in der Flash Variable. Nur zu Beginn liest er mir die Werte 
aus dem EEPROM nicht in die Flash Variable ein... bin ratlos.
#ifndef F_CPU
#define F_CPU           9600000UL                   // processor clock frequency 9,6Mhz
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <inttypes.h>      // Makros für int Datentypen                      

//Define für EEPROM
#ifndef EEMEM
// alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
#define EEMEM __attribute__ ((section (".eeprom")))
#endif



// ------------------------------------------------------------------------------------------
// Variabelen im EEPROM
// ------------------------------------------------------------------------------------------
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };


uint8_t Array[5] = { 0 };  // Flash Variable

     
// main prog
int main(void)
{
  eeprom_read_block(Array,eeArray,sizeof(Array));
  
    // Ports initialisieren
  init();   

  while (1)
  {
  // hier erfolgt eine Ausgabe von Array
  } 
}
 /* 
 * Funktion init(): Initialisierung des µC 
 */ 
void init(void) 
{
  DDRB = 0; 
  return;
}


Autor: Melanie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Folgendes Neues habe ich herausgefunden.
Angenommen ich beschreibe das EPPROM manuell über eeprom_write_block() 
in den eeArray mit den Werten { 2,2,1,1,1 }. Danach lese ich das EPPROM 
über ISP aus.
Ich lösche den µC und spiele das ausgelesene EPROM ein. Das Programm 
funktioniert.
Irgendwie stimmt die Adresse der Zuweisung
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };
 nicht mit dem später zugegriffenen EPPROM Stelle überein. Daher liest 
mir das zunächst wohl nur "Schrott" aus.

Das ausgelesene EEPROM Image entspricht nicht dem, was mir der Compiler 
aus der Zuweisung erzeugt: der Zuweisung
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };
 die HEX-Datei oder die .eep Datei sind unterschiedlich.
Hat einer eine Idee wieso?

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bist du sicher, dass die Initialisierung so funktioniert:
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };

Wird das wirklich beim Start des Programms in das EEPROM geschrieben?

uint8_t Array[5] = { 0 };  // Flash Variable
Das liegt im Ram, nicht im Flash, ist aber nur ein Fehler im Kommentar.

Grüße,

Peter

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Soweit ich das verstehe, muss man die Initialisierung des EEPROMS immer 
selber machen, also vom Compiler ein eep. file erzeugen lassen, in dem 
die Initialisierungswerte stehen und das nach der Programmierung des 
Programmspeichers separat programmieren. Nur so stehen die 
Initialisierungswerte korrekt im EEPROM.

Grüße,

Peter

Autor: Melanie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

ja, das macht der Compiler auch.
Dieses EEPROM File spiele auch per ISP auf den µC. Nur wenn ich das 
generierte EEPROM File auspiele, stehen dort nicht die Werte drin.

Programmiere ich das EEPROM aber über die Funktion eeprom_write_block() 
direkt im Programm mit gleichen Werten und lese dann die EEPROM Datei 
per ISP aus. Danach lösche ich den µC und spiele die ausgelesene Datei 
auf und das ganze funktioniert.

Kann es damit zusammenhängen, dass bei der direkt vom Compiler erzeugten 
.eep Datei die Werte bei der ersten Adresse im EEPROM anfangen?
Wenn ich die vom Compiler erzeugte Datei lade ist der erste Wert in 
Bascom 3A.
Lade ich mir die ausgelesen durch eeprom_write_block() in Bascom, so 
steht in der ersten Adresse ein 00.
Ich habe nämlich im Tutorial gelesen, dass die erste Adresse nicht 
beschrieben werden sollte, aber scheinbar macht der Compiler das. Kann 
es sein, dass dort der Wurm sich versteckt? Und wenn ja, wie erzeuge ich 
dann direkt vom Compiler eine Datei, die nicht direkt bei der ersten 
Adresse beginnt?

Autor: Melanie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Melanie schrieb:
> Hallo Peter,
>
> ja, das macht der Compiler auch.
> Dieses EEPROM File spiele auch per ISP auf den µC. Nur wenn ich das
> generierte EEPROM File auspiele, stehen dort nicht die Werte drin.

bzw. die Werte stehen bestimmt drin, bloß er liest nicht nicht korrekt 
aus bzw. die Stelle wird wohl nicht stimmen.

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dir ist klar, daß es die EESave Fuse bei einigen Controllern gibt, die 
das Löschen des EEProms beim Flashen steuert ? Es wäre doch immerhin 
möglich, daß der Compiler zuerst das EEProm beschreibt, dann das Flsah 
und dabei wieder das EEProm gelöscht wird.

Autor: Melanie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Funktion besagt ja nur, wenn ich den Chip lösche, ob das EEPROM mit 
gelöscht wird oder nicht.
Da ich den Chip lösche, das Flash aufspiele und dann die EEPROM Datei, 
spielt das keine Rolle.
Es wäre nur relevant, wenn ich die EEPROM Datei nicht neu immer auspiele 
und ständig ein geändertes Programm in den Flash schiebe.

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das bedeutet, der Compiler erwartet die Daten im EEPROM an einer anderen 
Adresse als er sie in der eep. Datei hinlegt?

Das ist schon seltsam.

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wenn ich die vom Compiler erzeugte Datei lade ist der erste Wert in
>Bascom 3A.
>Lade ich mir die ausgelesen durch eeprom_write_block() in Bascom, so
>steht in der ersten Adresse ein 00.


Das ist aber doch beides falsch?

Nach der Initialisierung:
uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };

sollte doch an der ersten Adresse 2 stehen.

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Es wäre nur relevant, wenn ich die EEPROM Datei nicht neu immer auspiele
> und ständig ein geändertes Programm in den Flash schiebe.

Kommt darauf an, wie das Aufspielen des Codes und des EEproms im 
Einzelnen vor sich geht. Das Beschreiben des EEProms und das Flashen des 
Codes sind zwei unterschiedliche Prozesse, das passiert nicht auf 
einmal. Deswegen einfach mal die Fuse ändern und sehen was passiert ;-)

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn man die Programmierschritte manuell ausführt, sollte die Fuse kein 
Problem sein. Nur beim automatischen Programmierablauf wird der 
Masserase automatisch durchgeführt.

Ich würde mir mal gerne das map-file anschauen, kannst du mal schnell 
eins erzeugen?

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn man die Programmierschritte manuell ausführt, sollte die Fuse kein
> Problem sein. Nur beim automatischen Programmierablauf wird der
> Masserase automatisch durchgeführt.

Das wäre logisch. Nur ist's ein kleiner Klick und schon weis man, ob's 
daran hängt.

Autor: Melanie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im MAP File steht bezüglich des EEPROMS folgendes:

.eeprom         0x00810000        0x5
 *(.eeprom*)
 .eeprom        0x00810000        0x5 attiny13.o
                0x00810000                eeArray
                0x00810005                __eeprom_end = .

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

Bewertung
0 lesenswert
nicht lesenswert
Hier noch die beiden EEPROMS im Vergleich.
Einmal das direkt vom Compiler erzeugte und einmal, wenn ich das EEPROM 
mit gleichen Werten mauell über eeprom_write_block() beschreibe.

Autor: Melanie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MWS schrieb:
> Das wäre logisch. Nur ist's ein kleiner Klick und schon weis man, ob's
> daran hängt.

Das habe ich auch versucht, bringt leider keine Änderung.

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stell mal bitte die beiden fraglichen eep files online, das was da im 
Bild zu sehen ist, ist völliger Unsinn.

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

Bewertung
0 lesenswert
nicht lesenswert
Das attiny13.eep ist das vom Compiler erzeugte.
Das eeprom.HEX ist das von mir ausgelesene nach eeprom_write_block() mit 
gleichen Werten.

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, das stimmt mit dem überein, was deine Programmiersoftware anzeigt.

Aber es passt nicht zum Mapfile und auch nicht zum Quelltext.

Kannst du das ganze Projekt hochladen?

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich seh' die Sequenz "2,2,1,1,1" nirgends in diesen Dateien, 
genauso wenig wie auf den Bascom Programmer Screenshots.

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sag ich doch, passt nicht zum Quelltext...
Und zum Mapfile auch nicht, welches behauptet, dass die section 5 byte 
lang ist.

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

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

so, ich habe das Program mal wirklich auf ein absolutes Minimum 
reduziert und wie folgt geschrieben:
#ifndef F_CPU
#define F_CPU           9600000UL                   // processor clock frequency 9,6Mhz
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <inttypes.h>      // Makros für int Datentypen                      

// ------------------------------------------------------------------------------------------------
// DEFINES
// ------------------------------------------------------------------------------------------------

//Define für EEPROM
#ifndef EEMEM
// alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
#define EEMEM __attribute__ ((section (".eeprom")))
#endif

void init(void);
// ------------------------------------------------------------------------------------------
// Variabelen im EEPROM
// ------------------------------------------------------------------------------------------
uint8_t eeArray[] EEMEM = { 0,0,1,1,1 }; // Vorgabe Code im EEPROM


     
// main prog
int main(void)
{
    // Ports und Interrupts initialisieren
  init();   
  
    while (1)
  {
  
  }

}
 /* 
 * Funktion init(): Initialisierung des µC 
 */ 
void init(void) 
{
  // --------------------------------------------------------------------------------------------
  // PORTB konfigurieren
  //
  // --------------------------------------------------------------------------------------------
  DDRB = 0; 
  DDRB |= (1 << PB1) | (1 << PB2) ;    
  PORTB |= (1<<PB2) | (1 << PB4);      
    

  // --------------------------------------------------------------------------------------------
  // Timer 0 (8-Bit) 
  // --------------------------------------------------------------------------------------------
  TCCR0A |= (1<<WGM01);   // CTC Mode OC0A
  TCCR0B |= (1<<CS01);  // Prescaler 8
  TIMSK0 |= (1<<OCIE0A);  // Enable Compare Match A des Timers
  OCR0A = 149;      // Compare Register
   TCNT0 = 0;         // Counter auf 0 initialisieren
 
  
   sei();          // setzt globales Interrupt Enable Bit
  return;
}

Das Programm enthält lediglich die Initialisierng meiner benötigten 
Register, sowie die Vorbelegung des EEPROMS Array eeArray mit 5 Werten 
{0,0,1,1,1}.
Die erzeugte EEPROM .eep Datei enthält diese Werte jedoch nicht.
Anbei das Program in in einer .c Datei, die entstandene .eep Datei und 
das Makefile.

Ich hoffe jemand kann helfen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Melanie schrieb:

> Das Programm enthält lediglich die Initialisierng meiner benötigten
> Register, sowie die Vorbelegung des EEPROMS Array eeArray mit 5 Werten
> {0,0,1,1,1}.
> Die erzeugte EEPROM .eep Datei enthält diese Werte jedoch nicht.

Wie kommst du da drauf?
:050000000000010101F8
:00000001FF

sieht doch gut aus!

:05           Anzahl der Daten-Bytes, stimmt auffallend mit deinen
              Daten überein

00 00 00      dann kommen 3 Bytes, von denen 2 die Startadresse
              im EEPROM darstellen. Allesamt 0, d.h. auf jeden Fall
              mal Startadresse 0.
              Wo das 3.te Byte hingehört weiß ich jetzt nicht auswendig
              kann auch sein, dass das eigentlich zum Bytezähler
              gehört (das erste der 3). Kann aber auch sein, dass das
              letzte der Bytes so was wie eine Recordtyp Kennung ist,
              denn immerhin ist dieses Byte im anderen Datensatz 1
              und nicht wie hier 0.
              die 0 könnte also "Daten" bedeuten, während die 1 im
              anderen Datensatz "End of File" bedeutet.
              Ist aber nicht soooooo wichtig, das jetzt genau
              auzuschlüsseln

00 00 01 01 01  und hier sind sie: Deine Datenbytes aus dem Source Code

F8            noch eine Prüfsumme drüber und fertig ist der Datensatz



Aber:
Wenn wir uns mal deinen Screenshot ansehen, dann stellen wir fest, dass 
das Programmiertool mit dem EEP File nichts anzufangen wusste. Das hat 
das ganze als stink normales ASCII Textfile eingelesen.
Benutz doch bitte eine vernünftige Programmiersoftware, die auch weiß, 
dass ein EEP File einfach nur ein INTEL-Hex File mit einer anderen 
Dateiendung ist.

Autor: Melanie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Aber:
> Wenn wir uns mal deinen Screenshot ansehen, dann stellen wir fest, dass
> das Programmiertool mit dem EEP File nichts anzufangen wusste. Das hat
> das ganze als stink normales ASCII Textfile eingelesen.
> Benutz doch bitte eine vernünftige Programmiersoftware, die auch weiß,
> dass ein EEP File einfach nur ein INTEL-Hex File mit einer anderen
> Dateiendung ist.

Dann wird das wohl der Fehler sein. Das Programm ist dann wohl in 
Ordnung, nur die Programmiersoftware ist für diesen Zweck Müll. Dann 
werde ich wohl auf PonyProg umsteigen...

Danke.

Autor: Jobst M. (jobstens-de)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Kann aber auch sein, dass das
> letzte der Bytes so was wie eine Recordtyp Kennung ist

Record-Type - Korrekt!


Gruß

Jobst

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wenn wir uns mal deinen Screenshot ansehen, dann stellen wir fest, dass
>das Programmiertool mit dem EEP File nichts anzufangen wusste.

Mist, das ist mir auch nicht aufgefallen, gleicher Fehler, bloß nicht 
mit Bascom, sondern mit dem Galep.

Lösung: Die .eep-Datei in .hex umbenennen.

Für weitere Verwirrung hat gesorgt, dass sich die Initialisierung von

uint8_t eeArray[] EEMEM = { 2,2,1,1,1 };

nach

uint8_t eeArray[] EEMEM = { 0,0,1,1,1 }; // Vorgabe Code im EEPROM

geändert hat.


Grüße,

Peter

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das Programm ist dann wohl in Ordnung, nur die Programmiersoftware ist für
> diesen Zweck Müll

Naja, Bascom weis schon was es mit dem von ihm selbst erzeugten EEP File 
anzufangen hat, denn es wird dort als Binärddatei erzeugt und im 
Programmer auch so (richtig) geschrieben. Diese Info ist u.A. unter 
$EEPROMHEX zu finden, hättest halt mal auch Hilfe zu Bascom lesen 
sollen, bevor Du es einsetzt.

Versteh' allerdings auch nicht wieso Du Bascom verwendest, wenn Du C 
programmieren willst. Für C würde ich das AVR Studio zum Programmieren 
nehmen, das reicht locker und man braucht kein Pony-Prog, außer 
vielleicht für exotische Programmer-HW.

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.