www.mikrocontroller.net

Forum: Compiler & IDEs Problem mit eeprom_read_byte


Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen,
ich habe ein kleines Problem mit den EEPROM-Routinen.

Controller ATMEGA8,
AVR Studio und aktuelle Version Win-AVR.

Das Problem habe ich mit folgendem Aufruf:
uint8_t eeChannel EEMEM = 5;  // Grundzustand
uint8_t Channel;

uint8_t readValueFromEprom( void )
{
   return eeprom_read_byte(&eeChannel);
}

int main( void )
{
    channel = 1;
    // funktioniert nicht
    channel = readValueFromEprom();

    // funktioniert
    channel = eeprom_read_byte(&eeChannel)
}


Warum funktioniert dieser Aufruf nicht? Die Werte werden nicht aus dem
EEPROM gelesen. eep-Datei wurde korrekt zum Controller übertragen.

Irgendwie verstehe ich da was nicht.

Könnt Ihr helfen?

Gruß
Frank

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

Bewertung
0 lesenswert
nicht lesenswert
Channel != channel...

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Johannes,
ist nur ein Schreibfehler an dieser Stelle. Im Orginalcode ist das schon 
korrekt.

Gruß
Frank

Autor: Jupp Van de balken (mng)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...probiers mal mit

volatile uint8_t Channel;

Autor: Jupp Van de balken (mng)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...und funktionieren tut's wahrscheinlich nicht, weil der Compiler 
erkennt, dass nirgends mit dem Inhalt von channel gearbeitet wird, und 
er daher alle Zuweisungen außer der letzten wegoptimiert..

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jupp,
ne, dass ist nur ein Auszug aus dem gesamten Code. Ich hatte das nur 
beispielhaft aufgeführt. Den gesamten Code findest Du in der 
Codesammlung
unter 'Platine und Software für ALPS-Motorpotentiometer' ganz unten in 
der Version 1.1.

Das gleiche Problem habe ich auch mit eeprom_read_block.

Gruß Frank

Autor: Jupp Van de balken (mng)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist mir dann allerdings auch ein Rätsel. Im Simulator funktioniert 
die Funktion, nachdem man sie in Deinen Quelltext eingefügt hat, 
zumindest einwandfrei... genau wie eeprom_read_block auch.

Autor: Frank Link (franklink)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Genau die Erfahrung habe ich auch gemacht. Lade ich das ganze auf meinen 
ATEMAG8 mit 4 MHZ funktioniert es leider nicht mehr. Und ich habe schon 
alle Varianten die ich im Internet in Bezug auf die eeprom_read_block 
gefunden habe ausprobiert.
Ich vermutet es ist irgendeine Kleinigkeit -:(
Irgendwann werde ich es finden oder ich bekomme den entscheidenden Tip.

Aber ohne diese Funktionen funktioniert leider auch die Lernfunktion 
nicht.

Vieleicht noch eine Merkwürdigkeit, der Programmer gibt mir folgende 
Meldung aus, wenn ich das eep-File ins EPROM schreibe:

'Data in file does not fit in EEPROM. Proceed and programm all bytes 
that fit'

Im Anhang mal das eep-File. Man könnte meinen, dass der AVRprog mit den 
Daten nicht umgehen kann. Als Processor ist der ATMEGA8 eingestellt.

Gruß und Danke für die Hilfe
Frank

Autor: Jupp Van de balken (mng)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Fehlermeldung klingt schon bedenklich. Hast Du das Eeprom nach dem 
Beschreiben selber noch einmal ausgelesen und geprüft, ob es tatsächlich 
die angeblich korrekt geschrieben Daten enthält?
Falls AVRprog es nicht auf die Reihe bekommt, versuche doch mal, das 
Eeprom von Deinem Programm selbst beim ersten Start mit den gewünschten 
Werten initialisieren zu lassen.

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jupp,
ich habe gestern mal einige andere Varianten getestet.

Unteranderem habe ich mal ein anderes Werkzeug zum Programmieren und 
Auslesen des EEPROMS verwendet. Die Daten werden korrekt im EEPROM 
abgelegt. Die Fehlermeldung, die ich innerhalb des Studio 4 bei Nutzung 
des AVRprog beim Brennen der eep-Datei bekomme, erhalte ich dann nicht.

Ich habe dann mal versuchsweise einen der Werte aus den Arrays die im 
EEPROM liegen auszulesen. Mache ich das über einen Funktionsaufruf, der 
interne das eeprom_read_bytw aufruft, bekomme ich nach wie vor falsche 
Werte.

Dann habe ich ein Testprogramm geschrieben, dass die Arrays direkt im 
main programm initialisiert und ausliesst, dann funktionierts.

Ich bin mittlerweile mit meinem Latein vollständig am Ende -:((

WARUM KANN ICH DEN SCHEI.. NICHT INNERHALB EINES UNTERPROGRAMMS 
INITIALISIEREN??????

Gruß
Frank

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klopft da eventuell ein Interrupt rein?

MW

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Michael,
es könnte sein, obwohl ich das sei() erst einige Zeilen später mache, 
erfolgt die Definition vorher.

Hier ein Auszug:
Dies ist nur ein Auschnitt. Der vollständige Quellcode ist zu finden in der Codesammlung unter 'Platine und Software für ALPS-Motorpotentiometer' ganz unten in
der Version 1.1.


int main( void )
{
  uint i;  
  uint key;            
  uint device;            
  int toggle;            
  int oldtoggle;            
  uint ir_on;            
  int oldkey;                         
  volatile uint8_t channel;
      
  TCCR0  = 1<<CS02;  
  TCCR1B = 1<<CS10;    
  TIMSK  = 1<<TOIE0^1<<TOIE1;  

  // stoppt Timer 1
  stopTimer();
  
  UBRRL = bauddivider;    
  UBRRH = bauddivider >> 8;
  UCSRA = 0;                       
  UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;  
  UCSRB = 1<<RXEN^1<<TXEN;
  
  key = 0x01;               
  oldkey = key;    
  oldtoggle = -1;  
  ir_on = IR_INIT;              
  DDRD  = CHANNEL1_INIT;
  PORTD = CHANNEL1_INIT;
            
  // lesen aus dem EEPROM
  initArrays();            
  channel = 0;                
  channel = eeprom_read_byte(&eeChannel);

  if ( channel < 1 )          
  {              
    channel = 1;
  }
  if ( channel > MAX_CHANNELS )
  {
    channel = MAX_CHANNELS;
  }
  currentChannel = channel;
  sei();              

  /* Main-Loop */

Es kann natürlich sein, dass der Timer0 zuschlägt und mir das ganze 
versaut. Es müsste dann ja eigentlich reichen, wenn ich vor den 
InitArray() ein cli() einfüge. Werde ich heute Abend mal testen.

Danke für den Hinweis.

Gruß
Frank

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, das sei() kommt ja später. Der Timer wird wohl das Int-Flag 
setzen, aber ohne das "I"-Bit in SREG wird keine ISR angesprungen.

MW

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Frank Link (Firma Der Platinenshop) (franklink)

>Es kann natürlich sein, dass der Timer0 zuschlägt und mir das ganze
>versaut. Es müsste dann ja eigentlich reichen, wenn ich vor den
>InitArray() ein cli() einfüge. Werde ich heute Abend mal testen.

Was soll ein Interrupt bei einem LESEZUGRIFF versauen? Kritisch ist nur 
der SCHREIBZUGRIFF, der darf nicht unterbrochen werden, sonst springt er 
nicht an.

MFG
Falk

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur so eine Idee, wenn das lesen in einer Unterfunktion nicht klappt:
wie ist der Stack initialisiert(zu klein?).

MW

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Michael,
an den Stack glaube ich nicht, da in dieser Routine nur von 
eeprom-Arrays in ram-Arrays verschoben wird. Aber schau mal in die 
Sourcen. In der Datei Button.c findest Du den Übeltäter. Wobei der 
Hinweis erlaubt ist, dass der dort abgebildete Sourcecode nur ein 
Stadium aller Versuche darstellt. Ich habe bereits alle Varianten die 
ich im Internet gefunden habe für eeprom_read_block getestet.

Wie ich oben schon geschrieben habe, in der Simulation (debugger) 
funktionierts.

Gruß
Frank

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe den Fehler gefunden!!! :-)

AVRprog ist Schuld!

Ich habe den folgenden Code erzeugt:
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <stdlib.h>

#define F_CPU   3686400
#define XTAL    3.686400e6

// UART
#define  BAUD  19200
#define bauddivider (uint)(XTAL / BAUD / 16 - 0.5)
#define uchar unsigned char
#define uint unsigned int


uint8_t eeArrKey1[]      EEMEM = { 0x11, 0x01 };    
uint8_t eeArrKey2[]      EEMEM = { 0x11, 0x02 };    
uint8_t eeArrKey3[]      EEMEM = { 0x11, 0x03 };    
uint8_t eeArrKey4[]      EEMEM = { 0x11, 0x04 };    
uint8_t eeArrKey5[]      EEMEM = { 0x11, 0x05 };    

uint8_t eeArrKeyChUp[]    EEMEM = { 0x11, 0x20 };    
uint8_t eeArrKeyChDown[]   EEMEM = { 0x11, 0x21 };    

uint8_t eeArrKeyVolUp[]   EEMEM = { 0x10, 0x10 };    
uint8_t eeArrKeyVolDown[]   EEMEM = { 0x10, 0x11 };    

uint8_t eeArrKeyOnOff[]   EEMEM = { 0x11, 0x12 };    

volatile uint8_t rArrKey1[]      = { 0x11, 0x3F };  
volatile uint8_t rArrKey2[]      = { 0x0C, 0x3F };  
volatile uint8_t rArrKey3[]      = { 0x17, 0x3F };  
volatile uint8_t rArrKey4[]      = { 0x12, 0x3F };  
volatile uint8_t rArrKey5[]      = { 0x05, 0x3F };  

volatile uint8_t rArrKeyChUp[]    = { 0x11, 0x20 };  
volatile uint8_t rArrKeyChDown[]   = { 0x11, 0x21 };  

volatile uint8_t rArrKeyVolUp[]   = { 0x11, 0x10 };  
volatile uint8_t rArrKeyVolDown[]   = { 0x11, 0x11 };  

volatile uint8_t rArrKeyOnOff[]   = { 0x11, 0x0C };  

void initArrays( void )
{
  eeprom_read_block( (void*)&rArrKey1, (const void*)&eeArrKey1, 2 );
  eeprom_read_block( (void*)&rArrKey2, (const void*)&eeArrKey2, 2 );
  eeprom_read_block( (void*)&rArrKey3, (const void*)&eeArrKey3, 2 );
  eeprom_read_block( (void*)&rArrKey4, (const void*)&eeArrKey4, 2 );
  eeprom_read_block( (void*)&rArrKey5, (const void*)&eeArrKey5, 2 );

  eeprom_read_block( (void*)&rArrKeyChUp, (const void*)&eeArrKeyChUp, 2 );
  eeprom_read_block( (void*)&rArrKeyChDown, (const void*)&eeArrKeyChDown, 2 );

  eeprom_read_block( (void*)&rArrKeyVolUp, (const void*)&eeArrKeyVolUp, 2 );
  eeprom_read_block( (void*)&rArrKeyVolDown, (const void*)&eeArrKeyVolDown, 2 );

  eeprom_read_block( (void*)&rArrKeyOnOff, (const void*)&eeArrKeyOnOff, 2 );
}


uint8_t readKey1Eprom( void )
{
  return eeprom_read_byte( &eeArrKey1[0] );
}

uint8_t readKey1Ram( void )
{
  return rArrKey1[0];
}

void putchar( char c )
{
  while( (UCSRA & 1<<UDRE) == 0 );
  UDR = c;
}


void puts( char *s )
{
  while( *s )
    putchar( *s++ );
}


int main( void )
{
  uint8_t channel;

  char s[30];                
      
    UBRRL = bauddivider;             // Baudrate
    UBRRH = bauddivider >> 8;
    UCSRA = 0;                       
    UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;     // 8 Bit
    UCSRB = 1<<RXEN^1<<TXEN;           // enable RX, TX

  puts( "hallo" );
  
  channel = readKey1Eprom();
  itoa( channel, s, 10 );
  puts( "4e_init-" );
  puts( s );
  puts( "-4e_init " );

  channel = readKey1Ram();
  itoa( channel, s, 10 );
  puts( "4r_init-" );
  puts( s );
  puts( "-4r_init " );


  initArrays();              

  channel = readKey1Eprom();
  itoa( channel, s, 10 );
  puts( "ae_init-" );
  puts( s );
  puts( "-ae_init " );

  channel = readKey1Ram();
  itoa( channel, s, 10 );
  puts( "ar_init-" );
  puts( s );
  puts( "-ar_init " );

  for (;;){}
}


Schreibe ich hex und eep-Datei mit AVRprog funktioniert es nicht.

Schreibe ich das hex-File mit AVRprog und das eep-File mit AVROspII 
funktionierts.

Mit AVROspII funktioniert beides!

Wenn jemand eine Möglichkeit kennt dieses Tool ins Studio einzubinden, 
bitte posten.

Wenn jemand eine Idee hat, welche Einstellung bei AVRprog falsch ist, 
bitte posten.

Ich bedanke mich bei allen die versucht haben mir zu helfen.

Gruß
Frank

Autor: koriander (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
hi frank,
das problem liegt m.e. darin dass du in c nach return keinen 
funktionsaufruf schreiben kannst. also hol dir den wert aus 
eeprom_read_byte in eine variable und gib sie dann mit return zurück.

  tmp = eeprom_read_byte (...);
  return tmp;

das sollte gehen
:)

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
koriander schrieb:
> das problem liegt m.e. darin dass du in c nach return keinen
> funktionsaufruf schreiben kannst.

7 Jahre zu spät, und dann auch noch Unsinn.
return func();
Das ist zulässig und absolut gar kein Problem.

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.