www.mikrocontroller.net

Forum: Compiler & IDEs EEPROM Probleme


Autor: Dirk R. (dira)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider ich hier im Forum bisher keine Lösung gefunden... darum noch ein 
Fred von mir.
Ich programmiere nen AT90CAN128 und will nun den EEPROM schreiben und 
lessen

Ich nutze die Fkt der eeprom.h(WinAVR)

unsigned char var_1=0x01; //oder so
  cli();
  Value = eeprom_read_byte(&var_1);
  sei();  


Value ist immer 0xFF obwohl was anderes drinsteht, habe den EEPROM per 
JTAG ausgelesen...
 Gruß Dirk

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk R. wrote:
> unsigned char var_1=0x01; //oder so
Was heißt hier "oder so"? Du musst dem Compiler auch mitteilen, dass die 
Variable im EEPROM angelegt werden soll!
unsigned char EEMEM var_1=0x01;

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Dirk R. (dira)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Oliver: Bit hatte ich schon mit AVR-Studio gesetzt also "Preserve 
EEPROM memory through the Chip Erase cycle" aktiviert, also EEPROM wird 
nicht gelöscht.
Richtig oder Falsch verstanden ??

Tja und bei
unsigned char EEMEM var_1=0x01;
bekomme ich als Fehler:
../functions.c:17: error: section attribute cannot be specified for 
local variables
 will ich die Sache dann Global machen dann bekommen ich:
../LPK_AT90CAN128.h:13: error: expected '=', ',', ';', 'asm' or 
'__attribute__' before 'var_1'


HM, und nun ?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, das ist wieder mal ein typisches Besipiel dafür, wie sinnfrei es 
ist, völlig zusammenhanglose einzelne Codezeilen zu posten, aus denen 
nichts hervorgeht! Woher sollen wir denn bitteschön wissen, was Du da 
wirklich geschrieben hast? Wenn ich gewusst hätte, dass das eine lokale 
Variable ist, hätte ich Dir das auch gleich sagen können, dass 
EEPROM-Variablen natürlich immer global sind. Und was Du da bei dem 
zweiten Fehler gemacht hast, kann man auch nicht hellsehen...

Autor: Dirk R. (dira)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich nehme die Zeile:
unsigned char EEMEM var_1=0x01;
packe Sie in die Headerdatei meiner Main.c (wo auch die anderen Globalen 
stehen ) und mehr nicht.
Und warum ist der Obere Teil sinnfrei

es sind funktionaufrufe drin ( cli(); und sei(); ) also wo soll es dann 
stehen ausser in einer Funktion...? aber ich werde mich bessern.
Danke für die Tipps, aber Problem ist wie gesagt noch vorhanden ich 
werde mal mein projekt anhängen...
Wenns hilft

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Header-Datei ist kein so guter Platz dafür. So läufst du Gefahr, 
die Variable mehrfach zu definieren. Und der Fehler rührt wohl daher, 
dass du eeprom.h wahrscheinlich erst nach dieser Header-Datei includest.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk R. wrote:
> Und warum ist der Obere Teil sinnfrei
Nicht der Code ist sinnfrei, sondern es ist sinnfrei, eine Codezeile 
ohne ihren Kontext zu posten, weil der Fehler hier nicht in der Zeile an 
sich steckt! Aber Stefan hat ja schon die vermutliche Ursache für die 
Fehlermeldungen genannt.

In einer .h-Datei sollte man übrigens keine Definitionen, sondern nur 
Deklarationen unterbringen, aber das nur am Rande. Und man muss 
natürlich dafür sorgen, dass verwendete Attribute zum Zeitpunkt ihrer 
Verwendung bekannt sind.

Autor: Dirk R. (dira)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm Kratz...
Habe die deklaration jetzt in den Header:

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

unsigned char EEMEM EEvar;
.
.
.
#endif


und bekomme viel "tolle" Fehler:
BUILD:
avr-gcc.exe -mmcu=at90can128  LPK_AT90CAN128.o can_lib.o can_drv.o 
functions.o   -L"N:\SystemTest\STA 
(System_Test_Automation)\Rabaschus\SignalSIM\AVR\Quellcode\LPK_AT90CAN12 
8\lib_mcu"  -L"N:\SystemTest\STA 
(System_Test_Automation)\Rabaschus\SignalSIM\AVR\Q
uellcode\LPK_AT90CAN128\lib_mcu\can"   -o LPK_AT90CAN128.elf

functions.o:(.eeprom+0x0): multiple definition of `EEvar'
LPK_AT90CAN128.o:(.eeprom+0x0): first defined here
make: *** [LPK_AT90CAN128.elf] Error 1
Build succeeded with 1 Warnings...

MESSAGE:
gcc plug-in: Error: Object file not found on expected location 
N:\SystemTest\STA 
(System_Test_Automation)\Rabaschus\SignalSIM\AVR\Quellcode\LPK_AT90CAN12 
8\default\LPK_AT90CAN128.elf


Ich Checke das nicht...

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für eine Deklaration fehlt da noch ein "extern".

Autor: Dirk R. (dira)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok zu "extern unsigned char EEMEM EEvar;" geändert und nun merkert er :
N:\(geheim)\LPK_AT90CAN128\default/../functions.c:16: undefined 
reference to `EEvar'
functions.o: In function `eeprom_read_byte':
// functons.c
#include "default.h"
#include "config.h"
#include "LpPin_Define.h"
#include "LPK_AT90CAN128.h"
#include <can_drv.h>
#include <can_lib.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include "functions.h"


uint8_t getOverCTime()
{ // Zeile 16 der Fehlermeldung
uint8_t EEAdress=0, Value=0;
EEvar=0x01; //oder so
  cli();

  //Value = eeprom_rd_byte(&var_1);
  Value = eeprom_read_byte(&EEvar);
  sei();  
  return 5/*Value*/;
}

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> EEvar=0x01; //oder so
Das geht sowieso nicht! EEvar soll doch im EEPROM liegen, also musst Du 
da auch mit eeprom_write_byte() drangehen...

Autor: Dirk R. (dira)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok ich werds probieren, komme leider morgen erst dazu ( programmiert 
wird auf der Arbeit...)
kann es sein, dass das was ihr mir hier erklärt nichts mit dem in dem 
GCC-Tutorial zutun hat ? ( also ich meine steht es da falsch oder wie ?? 
)

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk R. wrote:
> ok ich werds probieren, komme leider morgen erst dazu ( programmiert
> wird auf der Arbeit...)
> kann es sein, dass das was ihr mir hier erklärt nichts mit dem in dem
> GCC-Tutorial zutun hat ? ( also ich meine steht es da falsch oder wie ??
> )
Wieso? Was steht denn im Tut anders als es hier erklärt wurde? Konkretes 
Beispiel?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> N:\(geheim)\LPK_AT90CAN128\default/../functions.c:16: undefined
> reference to `EEvar'

Jetzt fehlt offensichtlich die Definition. Zusätzlich zur Deklaration in 
der Header-Datei musst du sie auch einmal in einer C-Datei definieren.

Autor: Dirk R. (dira)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ups das mit dem EEMEM im Tut sehe ich jetzt erst...Sorry...

Also defniert werden soll die Varible ja durch den Inhalt des EEPROM, 
also durch lesen...
Wie gesagt ich teste das ganze morgen mal.
Vielen Dank bis hier her, ich gebe euch dann morgen eine Statusmeldung..
Gruß

Autor: Besserwisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Also definiert werden soll die Variable ja durch den Inhalt des EEPROM,
Das ist ein Missverständnis:
Die Worte "definieren" und "deklarieren" haben im Zusammenhang mit C als 
Programmiersprache eine besondere Bedeutung.

Deklarieren heisst soviel wie dem Compiler sagen, das da irgendwo eine 
Variable existiert. Es wird aber kein Speicherplatz belegt.
Definieren heisst, das eine Variable existiert und das der Compiler wenn 
er die Definition liest tatsächlich dafür Speicherplatz belegt.

In einem einfachen Programm, das nur aus einer Datei, ohne include 
besteht reicht immer eine Definition :
unsigned char EEMEM EEvar;

Besteht Dein Programm aus mehreren C-Dateien, dann deklariert man 
üblicherweise in einer include-Datei
extern unsigned char EEMEM EEvar;
und included diese in jeder C-Datei die diese Variable verwendet.

Die originale Definition muss natürlich bestehen bleiben, damit nach 
wie vor dafür Speicherplatz reserviert wird.

Klar?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk R. wrote:

> Also defniert werden soll die Varible ja durch den Inhalt des EEPROM,
> also durch lesen...

Jetzt verwechselst du wohl Definition mit Initialisierung.
Ok, also mal etwas ausführlicher:

Deklaration:
extern unsigned char EEMEM EEvar;
Damit wird nur der Compiler informiert, dass eine solche Variable 
irgendwo existiert. Wird normalerweise in eine Header-Datei gepackt. 
Wenn die Variable aber nur in einer C-Datei benutzt wird, kann man das 
auch komplett weglassen.

Definition:
unsigned char EEMEM EEvar;
Hier wird die Variable tatsächlich angelegt, also z.B. auch der Speicher 
reserviert. Ohne Definition gibt es die Variable gar nicht. Kommt in 
eine C-Datei.

Definition + Initialisierung:
unsigned char EEMEM EEvar = 42;
Hier bekommt die Variable auch gleich einen Startwert. Im Falle von 
EEMEM wird dieser Wert beim Programmieren des Chips in das EEPROM 
geschrieben.

Lesen:
SomeVar = eeprom_read_byte(&EEvar);

Schreiben:
eeprom_write_byte(&EEvar,88)

Autor: Besserwisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab's zuerst geschrieben. :-)

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um den Besserwisser und Stefan zu ergänzen:
Wenn man sich merkt, dass eine Variable genau einmal definiert 
werden muss, aber beliebig oft deklariert werden darf, dann kann 
eigentlich nichts schiefgehen. Wenn eine Variable in mehreren Sourcen 
verwendet werden soll, dann wird sie in einer Source-Datei definiert 
und in allen anderen Sourcen, die sie verwenden sollen, deklariert , 
wobei letzteres z.B. in einer Headerdatei geschehen kann. Für Funktionen 
gilt im Prinzip dasselbe, nur dass man in dem Fall bei der Deklaration 
auf das extern verzichten kann, da es bei Funktionen (im Unterschied 
zu Variablen) möglich ist, von der Syntax her zu erkennen, ob es sich um 
eine Definition oder um eine Deklaration ("Prototyp") handelt.

Grundsätzlich ist es am sinnvollsten, bei der Erstellung eines Projektes 
zu jeder Source-Datei eine Headerdatei zu erstellen, die die 
Deklarationen aller Variablen und Funktionen, die auch von anderen 
Sourcen verwendet werden sollen, enthält. Diese Headerdatei wird dann 
einfach von jeder anderen Sourcedatei, die Variablen und Funktionen 
daraus nutzen soll, mit #include eingebunden. Die Source-Dateien an sich 
werden ja dem Compiler direkt bekanntgegeben und von ihm separat 
übersetzt, d.h., der Compiler sieht immer nur die Source-Datei, die er 
gerade übersetzt. Und das ist eben der Grund, weshalb man die 
Deklarationen und Headerdateien braucht...

Autor: Dirk R. (dira)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So jetzt geht es hatt noch nen anderen Fehler drin. Die Namen die ich 
als Varialblen hatte, hatte ich auch in "#define" verwendet.... schwere 
Geburt:
Aber jetzt geht es.

VIELEN DANK AN ALLE BETEILIGTEN !!!

Und falls euch langweilig ist... ich habe noch nen Problem mit der ISR 
für das Empfangen von CAN-Daten.... :-)

so und hier nochmal der Code in auszügen und das Projekt dran, fals 
jemand Interesse hat.

Header für alle
#ifndef LPK_H //#include "LPK_AT90CAN128.h"
#define LPK_H


extern uint8_t  EEMEM EECANAdress;
extern uint8_t  EEMEM EEOverCTime;
extern uint8_t  EEMEM EEOverCCount;

volatile uint8_t iMyAdress;
volatile uint16_t iTimercount;
volatile bool bNewMsg;
volatile uint8_t iAktStatus;
volatile uint8_t iLedTimer;
volatile uint8_t iLeftOverCurrent;
volatile bool bOverCurrent;


#endif
Source für die Funktionen
// functons.c
#include "default.h"
#include <avr/eeprom.h>
#include "config.h"
#include "LpPin_Define.h"
#include "LPK_AT90CAN128.h"
#include <can_drv.h>
#include <can_lib.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include "functions.h"
//#include <eeprom_drv.h>
//#include <eeprom_lib.h>

uint8_t EECANAdress EEMEM;
uint8_t EEOverCTime EEMEM;
uint8_t EEOverCCount EEMEM; 


uint8_t getOverCTime()
{
uint8_t Value=0;

  Value = eeprom_read_byte(&EEOverCTime);
  sei();  
  return Value;
}

uint8_t getOverCCount()
{
uint8_t Value=0;
  cli();
  Value = eeprom_read_byte(&EEOverCCount);
  sei();
  return Value;
}
uint8_t getEEAdress()
{
uint8_t Value=0;

  cli();
  Value = eeprom_read_byte(&EECANAdress);
  sei();
  return Value;
}
//....
uint16_t setMaxOvercurrent(uint16_t iValue)
{
uint8_t /*EEAdress=0,*/ Value=0;
  cli();
  //schreibe value( 2x8-Bit) in eeprom
  Value = ( iValue & 0xff00 ) >> 8;
  eeprom_write_byte(&EEOverCTime,Value);
    
  Value = ( iValue & 0x00ff ) ;
  eeprom_write_byte(&EEOverCCount,Value);
  sei();
  return iValue;
}
uint16_t getMaxOvercurrent()
{
uint16_t  iValue = getOverCCount();
  iValue |= ( getOverCTime() << 8 );
   //lese value( 2x8-Bit) in eeprom
  return iValue;
}

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.