Forum: Compiler & IDEs Pointer auf EEPROM als Argument für Funktion


von guest (Gast)


Lesenswert?

Hallo liebe Forumgemeinde,

da es immer mal wieder Fehler beim Lesen/Schreiben ins eeprom gab, lege 
ich jede eep-variable drei mal dort ab in einem Array.

Bisher habe ich jede read/update Operation einzeln hingeschrieben. Um 
Speicherplatz zu sparen soll nun eine Funktion das jeweils dreimalige 
updaten/lesen übernehmen.

Dabei habe ich einige Probleme. Es gibt keine Compiler Warnungen oder 
Fehler, es funktioniert aber nicht...

Kann mir jemand helfen?
Mein Code:

1
uint8_t varEEP[] EEMEM = { 60, 60, 60 };
2
3
void eep3ArrayReadByte(const uint8_t *eep, uint8_t write)
4
{
5
  buf_eeprom = eeprom_read_byte(eep);
6
  if (buf_eeprom == 0xff)//prüfen auf fehler
7
  {
8
    buf_eeprom = eeprom_read_byte(eep+1);
9
    if (buf_eeprom == 0xff)prüfen auf fehler
10
    {
11
      buf_eeprom = eeprom_read_byte(eep+2);
12
    }
13
  }
14
  write = buf_eeprom;
15
}
16
17
void eep3ArrayUpdateByte(uint8_t *eep, uint8_t reference)
18
{
19
  eeprom_update_byte(eep, reference);
20
  eeprom_update_byte(eep+1, reference);
21
  eeprom_update_byte(eep+2, reference);
22
}
23
24
eep3ArrayReadByte(varEEP, varRAM);
25
26
eep3ArrayUpdateByte(varEEP, varRam);

von Anon (Gast)


Lesenswert?

Hallo,

also wenn der von dir gepostete Code original ist, kann ich mir nicht 
vorstellen, das es keine Warnungen/Fehler vom Compiler hagelt.

Beispielsweise:

eep3ArrayReadByte(varEEP, varRAM);

eep3ArrayUpdateByte(varEEP, varRam);

Wie heißt denn die Variable? varRam oder varRAM?


Desweiteren:
void eep3ArrayReadByte(const uint8_t *eep, uint8_t write);
eep ist also ein const Pointer, dessen Wert du mehrmals änderst. Kann 
mir nicht vorstellen das dein Compiler das nicht bemängelt.

Zitat:
"Dabei habe ich einige Probleme."

Das müsstest du etwas genauer beschreiben.

von guest (Gast)


Lesenswert?

Danke für die Antwort.

Selbstverständlich ist das nicht 1:1 der Code, der compiliert wird. Es 
fehlen die #Includes und die Funktionen werden natürlich auch nur unter 
bestimmten Bedingungen aufgerufen.

Anon schrieb:
> Desweiteren:
> void eep3ArrayReadByte(const uint8_t *eep, uint8_t write);
> eep ist also ein const Pointer, dessen Wert du mehrmals änderst. Kann
> mir nicht vorstellen das dein Compiler das nicht bemängelt.

Was ich meine, ist ein konstanter Zeiger auf eine uint_8.
Genau bei den Piontern habe ich ja meine Probleme, deshalb habe ich hier 
um Hilfe gebeten. Auch ohne const funktioniert der Code nicht. Ich hatte 
es auf Grund der Definition von eeprom_read_byte() so gemacht 
<avr/eeprom.h>.

von guest (Gast)


Lesenswert?

varRam und varRAM ist ein Tippfehler, es soll die gleiche Variable sein. 
(Die auch vorher deklariert ist.)

von Anon (Gast)


Lesenswert?

Wie gesagt, beschreib mal was genau nicht geht, will sagen: werden die 
Werte nicht geschrieben, falsch geschrieben, oder falsch gelesen etc.?

Wenn möglich, bitte immer den original code posten, da sonst eine 
Fehlersuche schwierig wird, z.B. folgende Zeile:

  buf_eeprom = eeprom_read_byte(eep);

Welchen Typ hat die Variable buf_eeprom?

Das nur mal generell. Die Funktionsdefinition von eeprom_update_byte 
sieht übrigens so aus:

void eeprom_update_byte(uint8_t * __p, uint8_t __value);

Das heißt du benutzt die Funktion falsch. Auf deutsch heißt die 
Funktionsdeklaration sinngemäß:

void eeprom_update_byte(uint8_t * zieladresse, uint8_t wert);

Ich benutze zwar kein AVR, glaube aber nicht das varEEP deine 
Zieladressen enthält.

Wie gesagt, ohne den Original Code, sind meine Tipps mit Vorsicht zu 
genießen.

von Kai S. (zigzeg)


Lesenswert?

guest schrieb:
1
void eep3ArrayReadByte(const uint8_t *eep, uint8_t write)
2
3
eep3ArrayReadByte(varEEP, varRAM);

Hier ist der Fehler ! Auf diese Art kann niemals ein Wert aus der 
Funktion eep3ArrayReadByte zurueckgegeben werden. Auch der name "write" 
ist in einer read Funktion irgendwie verwirrend.

Am besten macht man so etwas mittels Rueckgabewert:
1
uint_8 eep3ArrayReadByte(const uint8_t *eep)
2
{
3
  uint8_t buf_eeprom = eeprom_read_byte(eep);
4
  if (buf_eeprom == 0xff) //prüfen auf fehler
5
  {
6
    buf_eeprom = eeprom_read_byte(eep+1);
7
    if (buf_eeprom == 0xff) //prüfen auf fehler
8
    {
9
      buf_eeprom = eeprom_read_byte(eep+2);
10
    }
11
  }
12
  return buf_eeprom;
13
}

Noch eine Bitte: immer Original-Code posten, mit Copy+Paste, durch das 
Abtippen enstehen neue Fehler, und man weiss nicht wirklich, welche 
Fehler Tippfehler sind und welche echt !


Anon schrieb:
> eep ist also ein const Pointer, dessen Wert du mehrmals änderst.

Wo wird hier der Wert des Pointers veraendert ?
Ausserdem ist hier nicht der Pointer constant, sondern wohin gezeigt 
wird.

Anon schrieb:
> Das heißt du benutzt die Funktion falsch.

Das sieht mir OK aus. @Anon: Bist Du sicher dass Du weisst ueber was Du 
hier redest ?

von Anon (Gast)


Lesenswert?

> Wo wird hier der Wert des Pointers veraendert ?
> Ausserdem ist hier nicht der Pointer constant, sondern wohin gezeigt
> wird.

Pointer enthalten als Wert Adressen im Speicher, a.k.a. "wohin gezeigt 
wird". Sicherlich kann man Pointer dereferenzieren, aber das tut hier 
nichts zur Sache. Wenn ich ich also ein ptr++ oder ptr + 2 habe ändere 
ich den Wert, also das worauf gezeigt wird (effektiv die Adresse auf die 
gezeigt wird). Setzen sechs.


> Anon schrieb:
>> Das heißt du benutzt die Funktion falsch.
>
> Das sieht mir OK aus. @Anon: Bist Du sicher dass Du weisst ueber was Du
> hier redest ?

Allerdings. Ich gehe davon aus das du von eep3ArrayReadByte sprichst, 
ich spreche von void eeprom_update_byte(uint8_t * __p,uint8_t __value), 
zu finden unter:

http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__eeprom_1ga63aee2719099e8435e8584d4b3e51991.html

Ich sagte zwar das meine Aussage mit Vorsicht zugenießen ist, da ich 
kein AVR benutze, aber scheinbar hat atmel auch keine Ahnung wovon sie 
rede.

von Anon (Gast)


Lesenswert?

Nachtrag für Kay S. :

> Wo wird hier der Wert des Pointers veraendert ?
> Ausserdem ist hier nicht der Pointer constant, sondern wohin gezeigt
> wird.

Was glaubst du was das hier ist (aus dem original Post):

void eep3ArrayReadByte(const uint8_t *eep, uint8_t write)
{
  buf_eeprom = eeprom_read_byte(eep);
  if (buf_eeprom == 0xff)//prüfen auf fehler
  {

    buf_eeprom = eeprom_read_byte(eep+1);  <---- herp derp, speziell für 
dich Kay  (ja, es heisst oben tatsächlich const uint8_t *eep)

    if (buf_eeprom == 0xff)prüfen auf fehler
    {
      buf_eeprom = eeprom_read_byte(eep+2);
    }
  }
  write = buf_eeprom;
}

von Oliver S. (oliverso)


Lesenswert?

guest schrieb:
> Kann mir jemand helfen?

Anstatt an den Symptomen rumzubasteln, könntest du auch einfach das 
grundlegende Problem lösen. Stichwort "Brown out". Und schon gibt's im 
Eeprom keine Fehler beim lesen und schreiben mehr.

Bei deinem Code solltest du nochmals über die beiden Zeilen nachdenken:
1
void eep3ArrayReadByte(const uint8_t *eep, uint8_t write)
2
{
3
...
4
   write = buf_eeprom;
5
}

Oliver

von Kai S. (zigzeg)


Lesenswert?

Anon schrieb:
> Wenn ich ich also ein ptr++ oder ptr + 2 habe ändere
> ich den Wert, also das worauf gezeigt wird (effektiv die Adresse auf die
> gezeigt wird).

Du kennst den Unterschied zwischen
1
const uint8_t *ptr;
und
1
uint8_t * const ptr;
? Offenbar nicht. Oder Du trollst.

Anon schrieb:
> aber scheinbar hat atmel auch keine Ahnung wovon sie
> rede.

So muss es sein. Ich denke auch dass man der Referenz Dokumentation von 
Atmel am wenigsten trauen sollte.
[/ironie]

von guest (Gast)


Lesenswert?

Hallo,

vielen Dank für die Antworten!

Da das gesamte Programm sehr umfangreich ist, habe ich hier einen 
lauffähigen Ausschnitt erstellt.

Tatsächlich lag das Problem in der Zeile:
1
write = buf_eeprom;
Sie wurde ersetzt durch "return". Vielen Dank für den Hinweis mit dem 
"Brown out" ich werde mich mal schlau machen.

So funktioniert es nun. Vieln Dank!
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <avr/eeprom.h>
4
#include "lcd.h"
5
6
uint8_t varEEP[] EEMEM = { 60, 60, 60 };
7
uint8_t buf_eeprom;
8
uint8_t varRAM;
9
char buffer[17];
10
uint8_t eepUpdateFlag = 1;
11
12
13
uint8_t eep3ArrayReadByte(uint8_t *eep)
14
{
15
  buf_eeprom = eeprom_read_byte(eep);
16
  if (buf_eeprom == 0xff)//prüfen auf fehler
17
  {
18
    buf_eeprom = eeprom_read_byte(eep+1);
19
    if (buf_eeprom == 0xff)//prüfen auf fehler
20
    {
21
      buf_eeprom = eeprom_read_byte(eep+2);
22
    }
23
  }
24
  return buf_eeprom;
25
}
26
27
void eep3ArrayUpdateByte(uint8_t *eep, uint8_t reference)
28
{
29
  eeprom_update_byte(eep, reference);
30
  eeprom_update_byte(eep+1, reference);
31
  eeprom_update_byte(eep+2, reference);
32
}
33
34
int main(void)
35
{
36
  lcd_init();
37
  varRAM = eep3ArrayReadByte(varEEP);
38
  
39
    while(1)
40
    {
41
        if (eepUpdateFlag)
42
        {
43
      itoa(varRAM, buffer, 10);
44
      lcd_setcursor(0,1);//erste Zeile
45
      lcd_string(buffer);
46
      varRAM = 99;
47
      eep3ArrayUpdateByte(varEEP, varRAM);
48
      varRAM = eep3ArrayReadByte(varEEP);
49
      itoa(varRAM, buffer, 10);
50
      lcd_setcursor(0,2);//zweite Zeile
51
      lcd_string(buffer);
52
      eepUpdateFlag = 0;
53
        }
54
    }
55
}

von Anon (Gast)


Lesenswert?

Kai S.:

Es ging mir nicht um const, sondern darum, dass er sinngemäß ptr+2 
schrieb, nicht *ptr+2. Damit ändert er wohin der Zeiger zeigt.

Ob der Wert auf den er zeigt const ist oder der Zeiger, ist egal. Er 
inkrementiert den Zeiger.

Aber es ist schon atemberaubend wie du versuchst mir etwas zu erklären 
von dem ich gar nicht spreche.

von Markus F. (mfro)


Lesenswert?

Anon schrieb:
> Ob der Wert auf den er zeigt const ist oder der Zeiger, ist egal. Er
> inkrementiert den Zeiger.

Das solltest Du dir noch mal genau anschauen. Sowohl der Satz vor dem 
Punkt als auch der danach ist falsch.

Anon schrieb:
> Aber es ist schon atemberaubend wie du versuchst mir etwas zu erklären
> von dem ich gar nicht spreche.

Mit Verlaub, Du scheinst von etwas zu sprechen, das Du nicht verstehst.

Falsche Statements lassen sich nicht durch verstärkte Inbrunst beim 
Vortragen zu richtigen verwandeln...

von Anon (Gast)


Lesenswert?

Kai S.:

Im Original Post heißt es:

uint8_t varEEP[] EEMEM = { 60, 60, 60 };

void eep3ArrayReadByte(const uint8_t *eep, uint8_t write)
{
  buf_eeprom = eeprom_read_byte(eep);
  if (buf_eeprom == 0xff)//prüfen auf fehler
  {
    buf_eeprom = eeprom_read_byte(eep+1);
    if (buf_eeprom == 0xff)prüfen auf fehler
    {

Usw.

Ich denke wir sind uns einig das eep ein Zeiger ist.
Was also bewirkt ein eep + 1 und was ein *eep + 1.

Du hast sogar zusätzlich diesen Satz falsch verstanden:


Ob der Wert auf den er zeigt const ist oder der Zeiger, ist egal. Er
inkrementiert den Zeiger.

Damit meinte ich egal für die Diskussion. Ich weiß wirklich nicht warum 
du immer über Dinge redest um die es nicht geht.

von Oliver S. (oliverso)


Lesenswert?

Anon schrieb:
> Er
> inkrementiert den Zeiger.

Nein, tut er nicht. Inkrementieren bedeutet im allgemeinen 
Sprachverständnid, daß der Wert des Zeigers verändert würde (um eins 
erhöht). Das aber passiert dort nicht. Der Wert von eep ändert sich 
durch den Ausdruck eep+1 nicht.

Oliver

von Anon (Gast)


Lesenswert?

Paul:
Anon schrieb:
> Wenn ich ich also ein ptr++ oder ptr + 2 habe ändere
> ich den Wert,

ptr++ : richtig

ptr+2 : falsch

int x[5] = {};
int *ptr = &x[0];
ptr++;
ptr += 2;

Wohin zeigt ptr?

Oliver:
Der op hat einen const uint8_t *eep. Anschließend hat er eep+1, dann 
eep+2.  Inkrementieren heißt erhöhen,in diesem Fall die Adresse.Wenn ich 
sage Wert des Zeigers meine ich die Adresse.Etwas anderes kann eine 
Zeigervariable nicht enthalten. Ich habe das Gefühl mich undeutlich 
auszudrücken.

+1 heißt übersetzt eep plus sizeof(datentyp). Was heißt dann wohl +2?

von Anon (Gast)


Lesenswert?

Nachtrag:
+1 heißt übersetzt eep plus sizeof(datentyp). Was heißt dann wohl +2?

Soll heißen:
+1 heißt übersetzt eep plus 1 * sizeof(datentyp). Was heißt dann wohl 
+2?

Ist nicht leicht ohne richtige Tastatur.

von guest (Gast)


Lesenswert?

Lieber Anon,

der Zeiger zeigt immer auf das erste Element des Arrays. Über +1 bzw +2 
wird das nächste bzw. übernächste Element gelesen/manipuliert. Der 
Zeiger selbst jedoch nicht, also darf er auch const sein.

Vielleicht verstehst du dieses Beispiel besser:
1
const uint_8t i = 1;
2
uint_8t k;
3
4
k = i+1;//k = 2
5
//i = immernoch 1

der Zeiger wird genauso wenig manipuliert, wie "i" im Beispiel.

Entschuldigt, dass ich wegen dieses (etwas dummen Fehlers ;-) ) so eine 
Diskussion angezettelt habe... ;-)

von Oliver S. (oliverso)


Lesenswert?

Anon schrieb:

> Der op hat einen const uint8_t *eep. Anschließend hat er eep+1, dann
> eep+2.

Ja und? Wo ist das Problem? Warum sollte der Compiler da warnen?
eep wird nicht verändert. Das, worauf eep zeigt, wird auch nicht 
verändert.

Das ist etwas völlig anderes als eep++ oder eep+=2.

Oliver

von Markus F. (mfro)


Lesenswert?

Deine Sturheit ist tatsächlich bewundernswert ;)
1
buf_eeprom = eeprom_read_byte(eep+1);

Hier wird kein Pointer verändert, eep hat nach dem Funktionsaufruf immer 
noch denselben Wert. Das wär' nicht mal ein Fehler, wenn eep uint8_t * 
const deklariert wäre (was nicht der Fall ist).

von Anon (Gast)


Lesenswert?

Oliver S. schrieb:
> Anon schrieb:
>
>> Der op hat einen const uint8_t *eep. Anschließend hat er eep+1, dann
>> eep+2.
>
> Ja und? Wo ist das Problem? Warum sollte der Compiler da warnen?
> eep wird nicht verändert. Das, worauf eep zeigt, wird auch nicht
> verändert.
>
> Das ist etwas völlig anderes als eep++ oder eep+=2.
>
> Oliver

Genau.Deswegen fragte ich ja auch immer "wohin zeigt den ptr + 2".

Markus F.:
"Deine Sturheit ist tatsächlich bewundernswert ;)".

Danke, und auch das hab ich schon gesagt, ich denke ich drücke mich 
unverständlich aus (siehe zwei Zeilen weiter oben). Vielleicht klappt es 
jetzt:
Der Adresswert = Adresse die die Variable ptr enthält ändert sich.

von Anon (Gast)


Lesenswert?

Und noch ein Nachtrag.

Wenn ich sage Pointer inkrementieren meine ich "zeige bitte nicht mehr 
auf das erste Element, sondern auf das zweite, dritte...".

von Oliver S. (oliverso)


Lesenswert?

Anon schrieb:
> jetzt:
> Der Adresswert = Adresse die die Variable ptr enthält ändert sich.

Also, entweder reden wir jetzt völlig aneinander vorbei, oder du 
schreibst völligen Stuß. Ich tippe ja auf letzteres, aber vielleicht 
schreibst du ja doch noch mal etwas ausführlicher. Was genau du 
eigentlich sagen möchtest.

Oliver

von Anon (Gast)


Lesenswert?

Oliver S. schrieb:
> Anon schrieb:
>> jetzt:
>> Der Adresswert = Adresse die die Variable ptr enthält ändert sich.
>
> Also, entweder reden wir jetzt völlig aneinander vorbei, oder du
> schreibst völligen Stuß. Ich tippe ja auf letzteres, aber vielleicht
> schreibst du ja doch noch mal etwas ausführlicher. Was genau du
> eigentlich sagen möchtest.
>
> Oliver

Ersteres, leider. Was ich meine:

Wenn eine Funktion einen Zeiger auf int als Parameter nimmt,
und ich übergebe bei Aufruf der Funktion einen Zeiger auf das erste 
Element eines int Arrays mit zeiger (fiktiver Adresswert 1) , dann 
übergebe ich bei einem Aufruf der Funktion mit zeiger+1 einen Adresswert 
von "Adresswert den ptr enthält plus 1 * sizeof (int)", also auf das 
zweite Element.

Wenn ich mich jetzt nicht verständlich ausgedrückt habe, lasst es gut 
sein, dann bin ich einfach zu dumm mich zu artikulieren.

Schönen Abend noch

von Oliver S. (oliverso)


Lesenswert?

Äh, ja, und? Natürlich ist das so.
Und das ist ja in der vom TO oben gezeigten Funktion auch so gewollt.

Was hat das jetzt mir deinen seitenlangen Diskussionen zum Thema 
"Veränderung eines const-Pointers" zu tun?

Oliver

von Markus F. (mfro)


Lesenswert?

Anon schrieb:
> Wenn eine Funktion einen Zeiger auf int als Parameter nimmt,
> und ich übergebe bei Aufruf der Funktion einen Zeiger auf das erste
> Element eines int Arrays mit zeiger (fiktiver Adresswert 1) , dann
> übergebe ich bei einem Aufruf der Funktion mit zeiger+1 einen Adresswert
> von "Adresswert den ptr enthält plus 1 * sizeof (int)", also auf das
> zweite Element.

Stimmt.

Und der Parameter darf dann trotzdem const sein.

Schließlich änderst Du ihn nicht, sondern übergibst eine lokale, 
temporäre Kopie davon um eins erhöht. Daran gibt's nix zu meckern.

von Anon (Gast)


Lesenswert?

Ok, jetzt aber echt mein letzter Post ;-), dann seid ihr erlöst.

Ich zitier mich mal selbst:
"Es ging mir nicht um const, sondern darum, dass er sinngemäß ptr+2
schrieb (...)". Das findet sich gaaaaanz am Anfang.


Der Rest war, wie schon 234234345647676 mal gesagt, schlecht 
formuliert.Scheinbar hab ich damit meine Probleme.

Nix für ungut. Gute Nacht.

von Oliver S. (oliverso)


Lesenswert?

Anon schrieb:
> "Es ging mir nicht um const, sondern darum, dass er sinngemäß ptr+2
> schrieb (...)". Das findet sich gaaaaanz am Anfang.


Er hätte sinngemäß auch 3+2 schreiben können. Das ist ein Ausdruck, der 
den Wert 5 ergibt. Die 3 bleibt dabei das, was sie ist: Eine Konstante 
mit dem Wert 3.

Wir reden nicht aneinander vorbei. Nach so vielen Beiträgen von dir, die 
allesamt falsch sind, ist sicher, daß dir die absoluten Basics der 
Programmiersprache fehlen.

Oliver

von Markus F. (mfro)


Lesenswert?

Anon schrieb:
> schlecht formuliert.Scheinbar hab ich damit meine Probleme.

Nachdem man das Maul zu voll genommen hat zurückzurudern, ohne sich 
dabei lächerlich zu machen, ist - wie man ja gerade wieder mal in der 
Zeitung lesen kann - eine hohe Kunst, die nicht jedem gelingt.

Du bist nicht zufällig Bayer oder gar in der CSU?

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.