Forum: Mikrocontroller und Digitale Elektronik Daten auf EEPROM schreiben und Zeit dazu addieren


von Dan N. (noname88)


Lesenswert?

Hallo Leute,
ich muss folgende Aufgabe lösen und komme nicht mehr weiter. Vielleicht 
kann mir jemand weiterhelfen.

Aufgabenstellung:
In einer Auslieferhalle für Obst und Gemüse können sich Kunden zum 
Abtransport ihrer Ware einen Gabelstapler leihen. Dazu müssen sie sich 
mittels einer personifizierten RFID-Karte an diesem Gerät 
identifizieren. Die Karten besitzen ID-Nummern von 0 bis 511. Da das 
EEPROM ebenfalls 512 Adressen(Adresse 0 bis Adresse 511) besitzt, soll 
dort unter der Adresse der jeweiligen Kartennummer die Nutzungsdauer 
zwecks Abrechnung in Minuten aufsummiert werden. Es ist davon 
auszugehen, dass die Nutzungsdauer innerhalb eines Tages den Wert 255 
Minuten nicht überschreitet. Alle Tage wird dann der Wert ausgelesen und 
wieder auf 0 zurückgesetzt.
Erstellen Sie nun zum Speichern einer einzelnen Gabelstaplernutzung eine 
Funktion in C++ mit dem Namen addiere_Nutzungsdauer() mit folgenden 
Anforderungen:
- Die Funktion hat keinen Rückgabewert
- Der Funktion werden zwei Byte-Parameter übergeben:
    - RFID-ID (=Adresse im EEPROM)
    - Ganzzahliger Wert für die Nutzungsdauer in Minuten (1 bis 255)
- Die Nutzungsdauer soll stets zu dem Wert im EEPROM hinzugezählt 
werden.

Mein Code bisher:

void addiere_Nutzungsdauer (unsigned int EEAdresse, unsigned char 
EEDaten)
{
   //Schreiben
   while(EECR & (1<<EEWE);
   EEAR = EEAdresse;
   EEDR = EEDaten;
   EECR |= (1<<EEMWE);
   EECR |= (1<<EEWE);

   //an dieser Stelle weiß ich nicht, wie ich die Nutzungsdauer 
dazuaddieren soll?

   //Auslesen und zurücksetzen
   while(EECR & (1<<EEWE);
   EEAR = EEAdresse;
   EECR |= (1<<EERE);
   cout<< "Nutzungsdauer: "<< EEDaten;
   EECR &= ~(1<<EEAR)|(1<<EEDR);
}

Ich hoffe, dass der Code soweit stimmt, wenn nicht bitte korrigieren.
Die Lücke bitte ergänzen...vielen Dank im voraus ;-)

Gruß Daniel

von M. K. (sylaina)


Lesenswert?

Du musst erst die entsprechende Speicherstelle auslesen, dann die 
geloggte Nutzungsdauer dem ausgelesenen Wert hinzuaddieren und dann das 
Ergebnis zurück an die entsprechende Speicherstelle schreiben. Hoffe das 
hilft dir zum Anstoß.

Für die Neunmalklugen:
Und ja, sowas würde man eher weniger auf ein EEPROM speichern aber hier 
gehts ja um den Lerneffekt ;)

von Falk B. (falk)


Lesenswert?

Dan N. schrieb:

> Erstellen Sie nun zum Speichern einer einzelnen Gabelstaplernutzung eine

Klingt nach Hausaufgaben.

> Funktion in C++ mit dem Namen addiere_Nutzungsdauer() mit folgenden

WOW!!! C++. Das nenn ich mal Luxus ;-)

> Anforderungen:
> - Die Funktion hat keinen Rückgabewert
> - Der Funktion werden zwei Byte-Parameter übergeben:
>     - RFID-ID (=Adresse im EEPROM)
>     - Ganzzahliger Wert für die Nutzungsdauer in Minuten (1 bis 255)
> - Die Nutzungsdauer soll stets zu dem Wert im EEPROM hinzugezählt
> werden.

Trivial

> void addiere_Nutzungsdauer (unsigned int EEAdresse, unsigned char
> EEDaten)

Warum nennst du deine Parameter nicht entsprechend. Daß die Daten im 
EEPROM landen, hat damit nix zu tun.

> {
>    //Schreiben
>    while(EECR & (1<<EEWE);
>    EEAR = EEAdresse;
>    EEDR = EEDaten;
>    EECR |= (1<<EEMWE);
>    EECR |= (1<<EEWE);
>
>    //an dieser Stelle weiß ich nicht, wie ich die Nutzungsdauer
> dazuaddieren soll?

Im Ernst? Vor allem, warum schreibst du ZUERST auf en EEPROM?

>
>    //Auslesen und zurücksetzen
>    while(EECR & (1<<EEWE);
>    EEAR = EEAdresse;
>    EECR |= (1<<EERE);
>    cout<< "Nutzungsdauer: "<< EEDaten;
>    EECR &= ~(1<<EEAR)|(1<<EEDR);
> }

> Ich hoffe, dass der Code soweit stimmt, wenn nicht bitte korrigieren.

Die Hoffnung stirbt zuletzt. Uuuup, schon ist sie tot!

> Die Lücke bitte ergänzen...

Nö.

Beitrag "Einheitlicher Umgang mit faulen Schülern etc.?"

von Dan N. (noname88)


Lesenswert?

M. K. schrieb:
> Du musst erst die entsprechende Speicherstelle auslesen, dann die
> geloggte Nutzungsdauer dem ausgelesenen Wert hinzuaddieren und dann das
> Ergebnis zurück an die entsprechende Speicherstelle schreiben. Hoffe das
> hilft dir zum Anstoß.

Danke für den Anstoß...ich versuche es mal:

void addiere_Nutzungsdauer (unsigned int ID, unsigned char Dauer)
{
   //Schreiben
   while(EECR & (1<<EEWE);
   EEAR = ID;
   EEDR = Dauer;
   EECR |= (1<<EEMWE);
   EECR |= (1<<EEWE);

   //Auslesen
   while(EECR & (1<<EEWE);
   EEDR = Dauer;
   EECR |= (1<<EERE);

   //Addieren
   Dauer = Dauer + ???;
//Was soll ich hier dazuaddieren? Ich hab ja keine Variable mit der 
eingelesenen Nutzdauer? Hast du vielleicht wieder einen Anstoß für mich?

//Schreiben
   while(EECR & (1<<EEWE);
   EEDR = Dauer;
   EECR |= (1<<EEMWE);
   EECR |= (1<<EEWE);
   cout<< "Nutzungsdauer: "<< Dauer;
   EECR &= ~(1<<EEAR)|(1<<EEDR);
}

@Falk B.:
Ich erwarte nicht, dass jemand für mich die komplette Lösung 
hinschreibt. Ich bin froh wenn jemand hilft und ich von selbst drauf 
komme, schließlich will ich dazu lernen. Ich schreibe bald eine Prüfung 
in Mikrocontollertechnik. Du hast recht...evtl hab ich mich falsch 
ausgedrückt, aber auf solche Kommentare kann ich trotzdem verzichten. 
Danke trotzdem für deine Mühe.

: Bearbeitet durch User
von Wolfgang R. (Firma: www.wolfgangrobel.de) (mikemcbike)


Lesenswert?

Da wirst Du wohl innerhalb deiner Routine eine lokale Variable 
definieren müssen, diese mit dem alten EEPROM-Wert befüllen, die 
Nutzungsdauer dazu addieren und das ganze wieder im EEPROM abspeichern 
müssen.

von Karl M. (Gast)


Lesenswert?

Hallo Dan,

ich würde ja die avr libc Funktionalität in <avr/eeprom.h> nutzen:

https://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

Andere falls eine paar Methoden (Funktionen) in einer eigenen Klasse 
anlegen und dann diese nutzen.

von Dan N. (noname88)


Lesenswert?

Wolfgang R. schrieb:
> Da wirst Du wohl innerhalb deiner Routine eine lokale Variable
> definieren müssen, diese mit dem alten EEPROM-Wert befüllen, die
> Nutzungsdauer dazu addieren und das ganze wieder im EEPROM abspeichern
> müssen.

ja so in etwa hätte ich mir das auch gedacht, aber laut aufgabe soll ich 
ja nur die "Funktion" schreiben. Verstehe ich das richtig, wenn ich 
innerhalb meiner "Funktion" per cin-Befehl einen wert für die 
nutzungsdauer einlese?
Ich dachte nämlich, dass ich dies im "int main"-Bereich tun müsste und 
den wert dann als übergabeparameter an die funktion übergeben muss.
Aber da ich ja nur dir funktion schreiben soll, stehe ich irgendwie am 
schlauch...

von Wolfgang R. (Firma: www.wolfgangrobel.de) (mikemcbike)


Lesenswert?

Die lokale Variable in der Funktion interessiert das Main Programm 
überhaupt nicht, du kannst ja prinzipiell auch eine Funktion nach dem 
Motto "schreibe EEPROM(gelesenes EEPROM + Nutzungsdauer) erstellen, da 
taucht die lokale Variable nicht explizit auf...

Du kannst in deiner Funktion immer lokale Variablen für die nötigen 
Daten anlegen...

von Dan N. (noname88)


Lesenswert?

Noch ein Versuch:

void addiere_Nutzungsdauer (unsigned int ID, unsigned char Dauer)
{
   int x;

   //Schreiben
   while(EECR & (1<<EEWE);
   EEAR = ID;
   EEDR = x;
   EECR |= (1<<EEMWE);
   EECR |= (1<<EEWE);

   //Auslesen
   while(EECR & (1<<EEWE);
   EEDR = x;
   EECR |= (1<<EERE);

   //Addieren
   x = x + Dauer;

   //Schreiben
   while(EECR & (1<<EEWE);
   EEDR = x;
   EECR |= (1<<EEMWE);
   EECR |= (1<<EEWE);
   cout<< "Nutzungsdauer: "<< x;
   EECR &= ~(1<<EEAR)|(1<<EEDR);
}

Was sagt ihr dazu? könnte das sol klappen?

von Wolfgang R. (Firma: www.wolfgangrobel.de) (mikemcbike)


Lesenswert?

EEDR = x; sollte wohl andersrum beim Lesen...

und ein Ganzzahlwert sollte hier wohl eher uint sein.

: Bearbeitet durch User
von Dan N. (noname88)


Lesenswert?

Wolfgang R. schrieb:
> Die lokale Variable in der Funktion interessiert das Main Programm
> überhaupt nicht, du kannst ja prinzipiell auch eine Funktion nach dem
> Motto "schreibe EEPROM(gelesenes EEPROM + Nutzungsdauer) erstellen, da
> taucht die lokale Variable nicht explizit auf...
>
> Du kannst in deiner Funktion immer lokale Variablen für die nötigen
> Daten anlegen...

Ach ja stimmt...ich hatte einen Denkfehler! Sorry. Ich hab erst 
angefangen zu programmieren.

von Peter D. (peda)


Lesenswert?

Dan N. schrieb:
> cout<< "Nutzungsdauer: "<< x;

Ausgaben würde ich nicht in Unterfunktionen machen. Gib nur den Wert 
zurück und mach die Ausgaben im Main.

Dan N. schrieb:
> EECR &= ~(1<<EEAR)|(1<<EEDR);

Was soll das machen und wozu?

Eine gute Idee wäre es, auch endlich mal den AVR-Typ zu nennen.

von Einer K. (Gast)


Angehängte Dateien:

Lesenswert?

Dan N. schrieb:
> Mein Code bisher:
> ........
> Ich hoffe, dass der Code soweit stimmt, wenn nicht bitte korrigieren.
> Die Lücke bitte ergänzen...vielen Dank im voraus ;-)

Warum nutzt du nicht die vorgefertigten EEPROM Routinen der AVR-Libc?


Und falls das gar ein Arduino sein sollte, dann geht das noch viel 
einfacher.
Im Anhang mal ein Testprogrämmchen aus meiner Wühlkiste

von Dan N. (noname88)


Lesenswert?

Wolfgang R. schrieb:
> EEDR = x; sollte wohl andersrum beim Lesen...

wie meinst du das?


>
> und ein Ganzzahlwert sollte hier wohl eher uint sein.

Ok. also ändere ich char auf int

von Einer K. (Gast)


Angehängte Dateien:

Lesenswert?

Arduino Fanboy D. schrieb:
> Im Anhang mal ein Testprogrämmchen aus meiner Wühlkiste
Sorry, da war/ist ein Fehler drin!

Hier jetzt eine korrigierte Version.

von Wolfgang R. (Firma: www.wolfgangrobel.de) (mikemcbike)


Lesenswert?

Du musst schon ein wenig selber denken...

die Verwendung von char, int uint (unsigned int) etc. ist Dir 
überlassen, du musst die Datentypen kennen, um zu verstehen, was damit 
alles passieren kann. Char ist o.k bei zahlen bis 255.

Wenn ich ein Datenregister in eine Variable auslese, dann muss ich 
schreiben

variable = Register;

Wenn ich ein Register aus einer Variable befülle, dann schreibe ich

Register = variable;

Also:

Ziel = Quelle;

von Dan N. (noname88)


Lesenswert?

Peter D. schrieb:
> Dan N. schrieb:
>> cout<< "Nutzungsdauer: "<< x;
>
> Ausgaben würde ich nicht in Unterfunktionen machen. Gib nur den Wert
> zurück und mach die Ausgaben im Main.

In der Aufgabe steht, dass die Funktion keinen Rückgabewert haben soll. 
Kann man dann trotzdem mit "return" etwas zurückgeben? Wenn ja, wie geht 
das dann?

>
> Dan N. schrieb:
>> EECR &= ~(1<<EEAR)|(1<<EEDR);
>
> Was soll das machen und wozu?

Dieser Befehl setzt die beiden Bits wieder auf Null, so wie es gefordert 
wird.
>
> Eine gute Idee wäre es, auch endlich mal den AVR-Typ zu nennen.

Atmega 16

von Falk B. (falk)


Lesenswert?

Dan N. schrieb:
> Noch ein Versuch:
>
> void addiere_Nutzungsdauer (unsigned int ID, unsigned char Dauer)
> {

Willst du uns eigentlich veralbern? Warum um alles in der Welt willst du 
den EPRROM zuerst beschreiben? Hat du mal versucht, den logischen Ablauf 
normal ohne Programmiersprache zu beschreiben? Dir ist doch nicht mal 
der Ablauf klar!

von Wolfgang R. (Firma: www.wolfgangrobel.de) (mikemcbike)


Lesenswert?

Dan N. schrieb:
> Kann man dann trotzdem mit "return" etwas zurückgeben? Wenn ja, wie geht
> das dann?

Mit return... ;-)

int myfunction(a, b)
{
  int c = a+b;
  return(c);
}

von Dan N. (noname88)


Lesenswert?

Wolfgang R. schrieb:

> Wenn ich ein Register aus einer Variable befülle, dann schreibe ich
>
> Register = variable;
>
> Also:
>
> Ziel = Quelle;

Ach so...jetzt verstehe ich es langsam. Danke das hat schon mal geholfen

von Karl M. (Gast)


Lesenswert?

Was Peter meint, ist

Das Register EECR besitzt keine Bits mit Namen: EEAR und EEDR !

Dan N. schrieb:
>>
>> Dan N. schrieb:
>>> EECR &= ~(1<<EEAR)|(1<<EEDR);
>>
>> Was soll das machen und wozu?
>
> Dieser Befehl setzt die beiden Bits wieder auf Null, so wie es gefordert
> wird.
>>
>> Eine gute Idee wäre es, auch endlich mal den AVR-Typ zu nennen.
>
> Atmega 16

von Dan N. (noname88)


Lesenswert?

Wolfgang R. schrieb:
> Dan N. schrieb:
>> Kann man dann trotzdem mit "return" etwas zurückgeben? Wenn ja, wie geht
>> das dann?
>
> Mit return... ;-)
>
> int myfunction(a, b)
> {
>   int c = a+b;
>   return(c);
> }

ok, aber geht das denn, wenn oben in der Funktion "void" steht?

von Karl M. (Gast)


Lesenswert?

Dan N. schrieb:
> Wolfgang R. schrieb:
>> Dan N. schrieb:
>>> Kann man dann trotzdem mit "return" etwas zurückgeben? Wenn ja, wie geht
>>> das dann?
>>
>> Mit return... ;-)
>>
>> int myfunction(a, b)
>> {
>>   int c = a+b;
>>   return(c);
>> }
>
> ok, aber geht das denn, wenn oben in der Funktion "void" steht?

Ups, jetzt wirst Du höre, C lernen zu müssen!

Void heist soviel wie nichts. Also Keine Daten.

Aber man kann es ja mal versuchen und sich die Compilermeldungen 
ansehen.

von Wolfgang R. (Firma: www.wolfgangrobel.de) (mikemcbike)


Lesenswert?

Dan N. schrieb:
> ok, aber geht das denn, wenn oben in der Funktion "void" steht?

Natürlich nicht. eine void-Funktion erwartet keinen Rückgabewert, 
deswegen ist sie ja auch vom Typ void.

Deswegen habe ich die Funktion ja auch vom Typ int deklariert in meinem 
Beispiel!

von Wolfgang R. (Firma: www.wolfgangrobel.de) (mikemcbike)


Lesenswert?

Dir fehlen die einfachsten Grundlagen von C! Kauf Dir ein Buch für 
Anfänger oder schau Dir im Internet entsprechende Beispiele gut an!

Hier hast Du auf jeden Fall genug Antworten auf Deine Frage bekommen, 
der Rest sollte Selbststudium sein, sonst ist der Lerneffekt fast null.

von Peter D. (peda)


Lesenswert?

Dan N. schrieb:
> Dieser Befehl setzt die beiden Bits wieder auf Null, so wie es gefordert
> wird.

In welchem AVR-Typ sind EEAR und EEDR Bits?

Im Datenblatt wird nichst gefordert (siehe auch Beispielcode).

von Dan N. (noname88)


Lesenswert?

void addiere_Nutzungsdauer (unsigned int ID, unsigned char Dauer)
{
   int x;

   x = Dauer;

   //Schreiben
   while(EECR & (1<<EEWE);
   EEAR = ID;
   EEDR = x;
   EECR |= (1<<EEMWE);
   EECR |= (1<<EEWE);

   //Auslesen
   while(EECR & (1<<EEWE);
   x = EEDR;   //hab es umgedreht,aber in meine Unterlagen stehts 
andersrum
   EECR |= (1<<EERE);

   //Addieren
   x = x + Dauer;

   //Schreiben
   while(EECR & (1<<EEWE);
   EEDR = x;
   EECR |= (1<<EEMWE);
   EECR |= (1<<EEWE);
   return x;
   EEAR = 0x00;
   EEDR = 0x00;
}

von Falk B. (falk)


Lesenswert?

Dan N. schrieb:
> Wolfgang R. schrieb:
>
>> Wenn ich ein Register aus einer Variable befülle, dann schreibe ich
>>
>> Register = variable;
>>
>> Also:
>>
>> Ziel = Quelle;
>
> Ach so...jetzt verstehe ich es langsam. Danke das hat schon mal geholfen

Ich auch. Du hast NULL Plan von Programmierung und C und kopierst 
hirnlos irgendwelchen Scheiß zusammen. Tolles Konzept. Wirst bestimmt 
bald Bachelor.

von Dan N. (noname88)


Lesenswert?

> Ups, jetzt wirst Du höre, C lernen zu müssen!
>
> Void heist soviel wie nichts. Also Keine Daten.
>
> Aber man kann es ja mal versuchen und sich die Compilermeldungen
> ansehen.

Das weiß ich selbst, dass VOID "nichts" heißt, deswegen frag ich ja, 
weil Wofgang geschrieben hat, dass ich mit "return" zurückgeben 
soll...aber meiner meinung nach geht das nicht

von Peter D. (peda)


Lesenswert?

Dan N. schrieb:
> In der Aufgabe steht, dass die Funktion keinen Rückgabewert haben soll.

Es ist guter Programmierstil, wenn man Funktion und Anzeige voneinander 
trennt. Denn das wird schnell ein Chaos, wenn jede Funktion wild auf das 
Display schreibt.


Dan N. schrieb:
> Kann man dann trotzdem mit "return" etwas zurückgeben? Wenn ja, wie geht
> das dann?

Steht in jedem C-Tutorial.

von Dan N. (noname88)


Lesenswert?

Peter D. schrieb:
> Dan N. schrieb:
>> Dieser Befehl setzt die beiden Bits wieder auf Null, so wie es gefordert
>> wird.
>
> In welchem AVR-Typ sind EEAR und EEDR Bits?
>
> Im Datenblatt wird nichst gefordert (siehe auch Beispielcode).

Sorry, da hab ich mich vertan...

von Dan N. (noname88)


Lesenswert?

Wolfgang R. schrieb:
> Dan N. schrieb:
>> ok, aber geht das denn, wenn oben in der Funktion "void" steht?
>
> Natürlich nicht. eine void-Funktion erwartet keinen Rückgabewert,
> deswegen ist sie ja auch vom Typ void.
>
> Deswegen habe ich die Funktion ja auch vom Typ int deklariert in meinem
> Beispiel!

Ja das verstehe ich ja, aber das darf ich in meinem Fall laut Angabe 
nicht, deswegen verwirrt mich das und bekomme von gewissen Personen 
unschöne Kommentare wenn ich nachfrage :-)

von Dan N. (noname88)


Lesenswert?

Peter D. schrieb:
> Dan N. schrieb:
>> In der Aufgabe steht, dass die Funktion keinen Rückgabewert haben soll.
>
> Es ist guter Programmierstil, wenn man Funktion und Anzeige voneinander
> trennt. Denn das wird schnell ein Chaos, wenn jede Funktion wild auf das
> Display schreibt.
>
>
> Dan N. schrieb:
>> Kann man dann trotzdem mit "return" etwas zurückgeben? Wenn ja, wie geht
>> das dann?
>
> Steht in jedem C-Tutorial.

Nochmal für alle: ich persönlich würde es auch nicht so schreiben, aber 
laut Angabe darf die Funktion keinen Rückgabewert haben!

von Dan N. (noname88)


Lesenswert?

Danke an Alle :-)

Irgendwie werde ich schon dahinter kommen...

von Theor (Gast)


Lesenswert?

Ich denke man hat sich hier von Deiner Verwendung von cout in Deinem 
ersten Code, den Du gezeigt hat, auf einen unnötigen Weg führen lassen.

Es ist schon richtig, dass es stilistisch nicht gut ist, eine evtl. 
Ausgabe in so einer Art von Funktion zu machen. Aber der Schwerpunkt lag 
ohnehin, soweit ich die Aufgabe verstehe, darin aus dem EEPROM zu lesen 
und darein zu schreiben. Falls also eine Ausgabe erfolgt, so ist das 
nicht schön, aber nicht geradewegs falsch.
In der Aufgabe selbst, steht nichts von Ausgabe; also brauchst Du das 
auch nicht implementieren.

Ausserdem wird in der Aufgabe ausdrücklich gesagt, dass die Funktion 
keinen Rückgabewert haben soll. Wie auch immer also auch die Ausgabe 
machst oder ob überhaupt; mit dem Rückgabewert (wie man es normalerweise 
schön machen würde) darfst Du es gar nicht machen.

von Dan N. (noname88)


Lesenswert?

Da hast du vollkommen recht!

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.