mikrocontroller.net

Forum: Compiler & IDEs AVR: Problem mit eeprom_read_byte()


Autor: Eugen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe das folgende Problem: Ich will beim Initialisieren bereits im 
EEPROM abgelegten Daten nacheinander in ein Array einlesen, um sie im 
weiteren Programmverlauf zu verwenden, habe aber ein Problem mit der 
Adresse der einzulesenden Bytes. Der Code dazu sieht folgendermaßen aus:


void init(void)                /* Initialisiert den Mikrocontroller*/
{
uint8_t lettercnt, letrow;
uint16_t eepr_addr=0;

select_char=0;

strcpy(showstring,"LFB[XQ");


sei();                    // Interrupts an
TIMSK=1;
TCCR0=5;

DDRA=255;                  // Input
DDRB=255;
DDRC=0;
DDRD=255;

Clkport=0;                // Output
Dataport=255;


PORTB=255;
PORTC=255;               



// Aus EEPROM Bitmuster für Buchstaben auslesen



for (lettercnt=0;lettercnt<40;lettercnt++)
  {
    eepr_addr=lettercnt*8;
  
    for(letrow=0;letrow<8;letrow++)
      {
        while (!eeprom_is_ready())
        {
        
        }
        
        letter[lettercnt][letrow]=eeprom_read_byte(eepr_addr);
        eepr_addr++;
    }
  }



}





Der Compiler bringt eine Warnung, und wenn ich das Programm auf dem 
Mikorcontroller übertrage, bleibt er beim Initialisieren hängen. Ich 
weiß, dass eeprom_read_byte() eine Adresse als Parameter benötigt, 
dennoch müsste es so auch ohne Typecast funktionieren. Ich habe schon 
alles abgesucht und es scheint alles richtig zu sein. Vielleicht habe 
ich etwas übersehen? Für Eure Hilfe wäre ich sehr dankbar!

Es handelt sich um den ATMEGA16 Controller

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für den ATmega16 wird in der avr-libc ein Workarount für einen bekannten 
Silicon-Bug nicht implementiert, möglicherweise ist's das? (der µC löst 
eine IRQ aus, was zu einem RESET führt, wenn die entsprechende ISR nicht 
implementiert ist)

Beitrag "Re: Riesige Änderungen zwischen WinAVR 030913 und der aktuellen Version?"

BTW: wie wär's mit eeprom_read_block?

Autor: Der Neugierige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was für eine Warnung denn?

Warnungen zur Compilerzeit, werden zu Fehlern in der Laufzeit.
Alte Regel.

Autor: Eugen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Warnung lautet:

warning: passing argument 1 of 'eeprom_read_byte' makes pointer from 
integer without a cast

Habe es bereits probiert mit eeprom_read_block(). Die dazugehörige Zeile 
müsste dann so heißen, oder?

eeprom_read_block((void*)&letter[lettercnt][letrow], (const void*)eepr_addr, 1);

Das Ergebnis ist aber das Gleiche, der Mikrocontroller kommt über das 
Auslesen nicht hinaus.

Eine andere interessante Sache, die ich festgestellt habe: Das Programm 
läuft wenn ich mit Optimierungsstufen "s" oder "3" kompiliere. Ich 
brauche es aber ohne Optimierung, da mir ansonsten die eingebauten 
Warteschleifen wegopitmiert werden. Die sind aber notwendig, da der 
Mikrocontroller einen Flachbildschirm ansteuern muss, der da nicht 
mitziehen würde.

Autor: Eugen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P.S.: Mit Optimierungsstufe 2 läuft es auch, aber nicht mit den Stufen 1 
und 0

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann sind deine Warteschleifen Schrott...

Entweder nimm "util/delay.h" oder nimm Timer!!

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich
>brauche es aber ohne Optimierung, da mir ansonsten die eingebauten
>Warteschleifen wegopitmiert werden. Die sind aber notwendig, da der
>Mikrocontroller einen Flachbildschirm ansteuern muss, der da nicht
>mitziehen würde.

Das ist kein Argument für delay! Dafür gibt es Timer.

PS: Damit Warteschleifen nicht wegoptimiert werden, must du die 
Zählvariable volatile deklarieren.


Mal ne Frage:
>warning: passing argument 1 of 'eeprom_read_byte' makes pointer from
>integer without a cast

Die Fehlermeldung bekomme ich immer, wenn ich eine Variable übergebe, wo 
eigentlich die Adresse derselben Variable hin soll.

Da du hier aber den Inhalt der Variablen als Adresse haben willst, 
könnte das evtl der Grund sein warum das nicht geht.
Der Compiler könnte (durch die Warnung angezeigt) da die (SRAM)Adresse 
der Variablen eepr_addr übergeben. Somit wird mit einer SRAM-Adresse 
im EEPROM gesucht.

Mach das mal richtig, so wie es gedacht ist:
uint8_t  VarImEE[40][8]  EEMEM;
uint8_t  letter[40][8];
...
eeprom_read_block( letter, VarImEE, sizeof(VarImEE)  );

(Ich bin mir jetzt bei der genauen Syntax nicht sicher)

Autor: Eugen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Warteschleifen sehen folgendermaßen aus:
for (warten=0; warten<deltatime; warten++){}

Ich kann es zwar anders probieren mit den Warteschleifen, aber das tut 
ja nichts zur Sache. Fakt ist, dass ein Befehl, der funktionieren 
sollte, einfach nicht funktioniert, obwohl die Syntax richtig zu sein 
scheint.

Autor: Eugen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also einfach nur "long volatile warten"? Damit funktioniert es nicht

>Die Fehlermeldung bekomme ich immer, wenn ich eine Variable übergebe, wo 
>eigentlich die Adresse derselben Variable hin soll.

Eben, bei mir ist es nicht so, dass ich die Adresse der Variable 
"eepr_addr" haben will, da diese Adresse sich irgendwo im RAM befindet 
und in meiner Ausleseschleife der Wert von "eepr_addr" zwar erhöht wird, 
aber die Adresse bleibt ja gleich. Demnach würde so in das ganze Array 
die gleiche Bitfolge eingeschrieben werden, falls ich "&eepr_adr" 
verwenden würde. So würde es zwar der Compiler ohne wenn und aber 
schlucken, aber es müsste ohne "&" richitg funktionieren. Ich versuche 
es aber gliech mal mit
uint8_t  VarImEE[40][8]  EEMEM;
uint8_t  letter[40][8];
...
eeprom_read_block( letter, VarImEE, sizeof(VarImEE)  );

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Also einfach nur "long volatile warten"? Damit funktioniert es nicht
volatile long warten


>Eben, bei mir ist es nicht so, dass ich die Adresse der Variable
>"eepr_addr" haben will, da diese Adresse sich irgendwo im RAM befindet
>und in meiner Ausleseschleife der Wert von "eepr_addr" zwar erhöht wird,
>aber die Adresse bleibt ja gleich.

Wenn die (zu lesende EEPROM) Adresse immer gleich bleibt, könnte das ja 
die ursache sein.

Vielleicht solltest du es doch mit einem Cast (des Wertes auf Adresse) 
probieren:
letter[lettercnt][letrow] = eeprom_read_byte( (uint8_t*)eepr_addr );

Autor: Eugen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Matthias

Die Adresse würde nur dann gleich bleiben, wenn ich ein "&" davor 
verwende. Deshlab wäre ohne schon richtig. Den von Dir vorgeschlagenen 
Typecast habe ich bereits vor dem Post ausprobiert. Bringt aber nichts.

Habe Deinen Vorschlag mit

uint8_t  VarImEE[40][8]  EEMEM;
uint8_t  letter[40][8];
...
eeprom_read_block( letter, VarImEE, sizeof(VarImEE)  );

nun ausprobiert.

Auch damit ist es so, dass es ohne Optimierung nicht funktioniert. Ganz 
nebenbei gefragt: es müsste ja egal sein, ob sich das Array 
"VarImEE[40][8]" im EEMEM befindet oder nicht? Denn die einzige 
Verwendung davon ist nur die Abfrage der Arraygröße mit 
"sizeof(VarImEE)". Da ich weiß, dass ich ab der Adresse 0 auslesen will, 
klappt es bei mir auch in der Form:

eeprom_read_block(&letter, 0, sizeof(VarImEE));

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die Adresse würde nur dann gleich bleiben, wenn ich ein "&" davor
>verwende. Deshlab wäre ohne schon richtig.

Nein eben nicht. Deine oben gepostete Warnung sagt doch aus, dass der 
Compiler ein Pointer draus gemacht hat. Also macht er von allein ein & 
davor!


>es müsste ja egal sein, ob sich das Array...
Sollte so sein.

Autor: Eugen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe es jetzt hinbekommen. Es handelt sich bei dem Problem ganz 
offensichtlich um einen Bug des Compilers. Ein Kollege hatte 
glücklicherweise eine ältere Version von WinAVR mit der GCC Ver. 3.4.5. 
Mit dieser Version hat er auch seinerzeit sein Programm compiliert, 
welches gelaufen ist und auf dem ich meins aufgebaut habe. Nachdem ich 
mir die alte Compiler-Version draufgespielt habe, hat es auf ein Mal 
funktioniert, auch mit dem von mir anfangs geposteten Code. Wobei ich 
mich dann für die von Matthias vorgeschlagene Methode mit 
eeprom_read_block() entschieden habe, da dann auch der Compiler 
zufrieden ist und ohne Warnung wegen der Parameterübergabe auskommt.

Schon ärgerlich das Ganze, dnen ich habe drei Tage lang nichts Anderes 
gemacht als diese eine Zeile angestarrt und alles Mögliche ausprobiert, 
ohne Aussicht auf Erfolg.

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.