Forum: Compiler & IDEs Problem mit eeprom_read_byte


von Frank L. (franklink)


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:
1
uint8_t eeChannel EEMEM = 5;  // Grundzustand
2
uint8_t Channel;
3
4
uint8_t readValueFromEprom( void )
5
{
6
   return eeprom_read_byte(&eeChannel);
7
}
8
9
int main( void )
10
{
11
    channel = 1;
12
    // funktioniert nicht
13
    channel = readValueFromEprom();
14
15
    // funktioniert
16
    channel = eeprom_read_byte(&eeChannel)
17
}

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

von Johannes M. (johnny-m)


Lesenswert?

Channel != channel...

von Frank L. (franklink)


Lesenswert?

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

Gruß
Frank

von Jupp V. (mng)


Lesenswert?

...probiers mal mit

volatile uint8_t Channel;

von Jupp V. (mng)


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..

von Frank L. (franklink)


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

von Jupp V. (mng)


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.

von Frank L. (franklink)


Angehängte Dateien:

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

von Jupp V. (mng)


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.

von Frank L. (franklink)


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

von Michael Wilhelm (Gast)


Lesenswert?

Klopft da eventuell ein Interrupt rein?

MW

von Frank L. (franklink)


Lesenswert?

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

Hier ein Auszug:
1
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
2
der Version 1.1.
3
4
5
int main( void )
6
{
7
  uint i;  
8
  uint key;            
9
  uint device;            
10
  int toggle;            
11
  int oldtoggle;            
12
  uint ir_on;            
13
  int oldkey;                         
14
  volatile uint8_t channel;
15
      
16
  TCCR0  = 1<<CS02;  
17
  TCCR1B = 1<<CS10;    
18
  TIMSK  = 1<<TOIE0^1<<TOIE1;  
19
20
  // stoppt Timer 1
21
  stopTimer();
22
  
23
  UBRRL = bauddivider;    
24
  UBRRH = bauddivider >> 8;
25
  UCSRA = 0;                       
26
  UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;  
27
  UCSRB = 1<<RXEN^1<<TXEN;
28
  
29
  key = 0x01;               
30
  oldkey = key;    
31
  oldtoggle = -1;  
32
  ir_on = IR_INIT;              
33
  DDRD  = CHANNEL1_INIT;
34
  PORTD = CHANNEL1_INIT;
35
            
36
  // lesen aus dem EEPROM
37
  initArrays();            
38
  channel = 0;                
39
  channel = eeprom_read_byte(&eeChannel);
40
41
  if ( channel < 1 )          
42
  {              
43
    channel = 1;
44
  }
45
  if ( channel > MAX_CHANNELS )
46
  {
47
    channel = MAX_CHANNELS;
48
  }
49
  currentChannel = channel;
50
  sei();              
51
52
  /* 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

von Michael Wilhelm (Gast)


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

von Falk B. (falk)


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

von Michael Wilhelm (Gast)


Lesenswert?

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

MW

von Frank L. (franklink)


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

von Frank L. (franklink)


Lesenswert?

Ich habe den Fehler gefunden!!! :-)

AVRprog ist Schuld!

Ich habe den folgenden Code erzeugt:
1
#include <avr/io.h>
2
#include <avr/eeprom.h>
3
#include <avr/interrupt.h>
4
#include <stdlib.h>
5
6
#define F_CPU   3686400
7
#define XTAL    3.686400e6
8
9
// UART
10
#define  BAUD  19200
11
#define bauddivider (uint)(XTAL / BAUD / 16 - 0.5)
12
#define uchar unsigned char
13
#define uint unsigned int
14
15
16
uint8_t eeArrKey1[]      EEMEM = { 0x11, 0x01 };    
17
uint8_t eeArrKey2[]      EEMEM = { 0x11, 0x02 };    
18
uint8_t eeArrKey3[]      EEMEM = { 0x11, 0x03 };    
19
uint8_t eeArrKey4[]      EEMEM = { 0x11, 0x04 };    
20
uint8_t eeArrKey5[]      EEMEM = { 0x11, 0x05 };    
21
22
uint8_t eeArrKeyChUp[]    EEMEM = { 0x11, 0x20 };    
23
uint8_t eeArrKeyChDown[]   EEMEM = { 0x11, 0x21 };    
24
25
uint8_t eeArrKeyVolUp[]   EEMEM = { 0x10, 0x10 };    
26
uint8_t eeArrKeyVolDown[]   EEMEM = { 0x10, 0x11 };    
27
28
uint8_t eeArrKeyOnOff[]   EEMEM = { 0x11, 0x12 };    
29
30
volatile uint8_t rArrKey1[]      = { 0x11, 0x3F };  
31
volatile uint8_t rArrKey2[]      = { 0x0C, 0x3F };  
32
volatile uint8_t rArrKey3[]      = { 0x17, 0x3F };  
33
volatile uint8_t rArrKey4[]      = { 0x12, 0x3F };  
34
volatile uint8_t rArrKey5[]      = { 0x05, 0x3F };  
35
36
volatile uint8_t rArrKeyChUp[]    = { 0x11, 0x20 };  
37
volatile uint8_t rArrKeyChDown[]   = { 0x11, 0x21 };  
38
39
volatile uint8_t rArrKeyVolUp[]   = { 0x11, 0x10 };  
40
volatile uint8_t rArrKeyVolDown[]   = { 0x11, 0x11 };  
41
42
volatile uint8_t rArrKeyOnOff[]   = { 0x11, 0x0C };  
43
44
void initArrays( void )
45
{
46
  eeprom_read_block( (void*)&rArrKey1, (const void*)&eeArrKey1, 2 );
47
  eeprom_read_block( (void*)&rArrKey2, (const void*)&eeArrKey2, 2 );
48
  eeprom_read_block( (void*)&rArrKey3, (const void*)&eeArrKey3, 2 );
49
  eeprom_read_block( (void*)&rArrKey4, (const void*)&eeArrKey4, 2 );
50
  eeprom_read_block( (void*)&rArrKey5, (const void*)&eeArrKey5, 2 );
51
52
  eeprom_read_block( (void*)&rArrKeyChUp, (const void*)&eeArrKeyChUp, 2 );
53
  eeprom_read_block( (void*)&rArrKeyChDown, (const void*)&eeArrKeyChDown, 2 );
54
55
  eeprom_read_block( (void*)&rArrKeyVolUp, (const void*)&eeArrKeyVolUp, 2 );
56
  eeprom_read_block( (void*)&rArrKeyVolDown, (const void*)&eeArrKeyVolDown, 2 );
57
58
  eeprom_read_block( (void*)&rArrKeyOnOff, (const void*)&eeArrKeyOnOff, 2 );
59
}
60
61
62
uint8_t readKey1Eprom( void )
63
{
64
  return eeprom_read_byte( &eeArrKey1[0] );
65
}
66
67
uint8_t readKey1Ram( void )
68
{
69
  return rArrKey1[0];
70
}
71
72
void putchar( char c )
73
{
74
  while( (UCSRA & 1<<UDRE) == 0 );
75
  UDR = c;
76
}
77
78
79
void puts( char *s )
80
{
81
  while( *s )
82
    putchar( *s++ );
83
}
84
85
86
int main( void )
87
{
88
  uint8_t channel;
89
90
  char s[30];                
91
      
92
    UBRRL = bauddivider;             // Baudrate
93
    UBRRH = bauddivider >> 8;
94
    UCSRA = 0;                       
95
    UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;     // 8 Bit
96
    UCSRB = 1<<RXEN^1<<TXEN;           // enable RX, TX
97
98
  puts( "hallo" );
99
  
100
  channel = readKey1Eprom();
101
  itoa( channel, s, 10 );
102
  puts( "4e_init-" );
103
  puts( s );
104
  puts( "-4e_init " );
105
106
  channel = readKey1Ram();
107
  itoa( channel, s, 10 );
108
  puts( "4r_init-" );
109
  puts( s );
110
  puts( "-4r_init " );
111
112
113
  initArrays();              
114
115
  channel = readKey1Eprom();
116
  itoa( channel, s, 10 );
117
  puts( "ae_init-" );
118
  puts( s );
119
  puts( "-ae_init " );
120
121
  channel = readKey1Ram();
122
  itoa( channel, s, 10 );
123
  puts( "ar_init-" );
124
  puts( s );
125
  puts( "-ar_init " );
126
127
  for (;;){}
128
}

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

von koriander (Gast)


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
:)

von Stefan E. (sternst)


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.
1
return func();
Das ist zulässig und absolut gar kein Problem.

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.