Forum: Mikrocontroller und Digitale Elektronik Tiny24 und 16Bit Zahl in EEProm speichern


von Jens G. (Gast)


Lesenswert?

Hy Leute,
ich hab bisher nur einige PIC´s Programmiert (nicht wirklich tief, nur 
ein bisschen "gespielt" und darf nun in meienr Firma einen Tiny24 
programm eines ehemaligen Mitarbeiter umstricken. Dementsprechend habe 
ich hier und da auch meine Probleme mit den Programmierunterschieden.

Ich habe nun das Problem, das ich eine Variable mit 16Bit habe 
(uint16_t) die ich im EEPROM abspeichern muss.
Wenn ich das nun richtig gesehen habe, hat das EEPROM eine Wortbreite 
von nur 8Bit (ist ja auch logisch bei einem 8biter).

Ich will nun die oberen 8Bit der Variablen z.B. in die EEPROM Adresse 
0x01 schreiben und die unteren 8Bit in die EEPROM Adresse 0x02.

Ich habe mir auch schon aus dem Datenblatt des Tiny24 die EEPROM 
schreibe/lese Routine rausgezogen und implementiert, ich habe nun aber 
das Problem, das ich nicht weis wie ich es im AVR-Studio umsetze das ich 
wie erwähnt auf die oberen bzw. unteren Bits zugreifen kann.

Kann mir jemand nen Tip geben wie ich das umsetzen kann.

P.S.: Beim PIC bin ich leider auch noch nicht in die Verlegenheit 
gekommen, dies umzusetzen, von daher weis ich leider nicht wie ich 
ansetzen soll.

von Jens G. (Gast)


Lesenswert?

EDIT:

Sorry, habe vergessen zu erwähnen, dass ich in C Programmiere. :-)

von blubb (Gast)


Lesenswert?

ob tino oder sonstwas .. ein 16 bit in 2 8bit zerlegen is überall gleich

1
eepromwert_1 = (unsigned char) sechszenbitwert ;
2
eepromwert_2 = (unsigned char) (sechszenbitwert>>8) ;


oder auch
1
union 
2
{
3
  unsigned int sechszenbitwert
4
  struct
5
   {
6
     unsigned int eepromwert1;
7
     unsigned int eepromwert2;
8
   };
9
}eep_16;

von Tobi (Gast)


Lesenswert?

Hi Jens,

es gibt in der avr-libc schon Funktionen, die das für dich erledigen!
Binde im AVR Studio den header #include <avr\eeprom.h> ein. Dann 
verwende die Funktion "eeprom_write_byte (uint8_t *addr,uint8_t value)" 
oder "eeprom_write_word (uint16_t *addr,uint16_t value)".
Zu beachten ist aber: Es dürfen beim EEPROM schreiben keine Interrupts 
auftreten! Also evtl. global Interrupt Flag löschen!

von Jens G. (Gast)


Lesenswert?

Hey,
danke für die schnelle Antworten, ich werde es gleich mal versuchen.
Kann ich über diese Art auch wieder die 16Bit Daten aus dem EEPROM 
lesen?

Das mit den Interrupts weis ich und stellt auch kein Problem dar. Das 
Schreiben auf ads EEPROM ist nur eine Art Kalibrierfunktion, die nur 
unter bestimmten Umständen aufgerufen wird, dann sind die Interrupts 
sowiso aus.
Und das lesen passiert bei einem Neustart, bevor die Interrupts 
aktiviert werden.

von Tobi (Gast)


Lesenswert?

Beim Lesen müssen die Interrupts nicht gesperrt sein.

Lesen kannst du mit
1
uint16_t eeprom_read_word (const uint16_t *addr)

Btw. das mit dem Interrupt macht man so:
1
unsigned char Sreg_Temp;
2
3
Sreg_Temp=SREG;
4
cli(); //Sperrt global ALLE Interrupts
5
eeprom_write_word(0, 70000); Schreibt an die Adresse 0 die 70000
6
SREG=Sreg_Temp; //SREG wieder restauriert, eventulle Interrupts wieder aktiv

von Tobi (Gast)


Lesenswert?

> Beim Lesen müssen die Interrupts nicht gesperrt sein.

Äh, glaub ich zumindest, müsste aber selber nochmal nachlesen...

von blubb (Gast)


Lesenswert?

naja nich unbedingt ...

hatte selbst schon den effekt wenn beim lesen die ISR zuschlägt ..
das dort mal was schief gehen kann wenn man große datenmengen liest

witzig wirds dann wenn man liest
die ISR kommt und dort soll nochmal was gelesen werden
das führt dann zu sehr kuriosen fehlern die schwer zu finden sind

von Tobi (Gast)


Lesenswert?

Dann auch beim lesen leiber die I's sperren!

von Hc Z. (mizch)


Lesenswert?

Das Sperren der Interrupts an der kritischen Stelle erledigt C schon von 
selbst.  Es ist nicht nötig, das von Hand zu machen.

von Jens G. (Gast)


Lesenswert?

Hy,
danke nochmal @ all für die schnelle und Fachmänische Hilfe.
Ich hab den schreib/lese Zugriff nun über die eeprom_write_word und 
eeprom_read_word realisiert.
Zudem habe ich jeweils vor dem lesen bzw. schreiben die I´s gesperrt und 
dann natürlich wieder frei gegeben.

von Tobi (Gast)


Lesenswert?

> Das Sperren der Interrupts an der kritischen Stelle erledigt C schon von
> selbst.  Es ist nicht nötig, das von Hand zu machen.

Das ist so nicht richtig! Warum sollte C sich um die Interrupts kümmern? 
Die Sprache "C" kennt ja keine Interrupts und ist prozessorunabhängig.

von Tobi (Gast)


Lesenswert?

Aus der eeprom.h:

\note As these functions modify IO registers, they are known to be
     non-reentrant.  If any of these functions are used from both,
     standard and interrupt context, the applications must ensure
     proper protection (e.g. by disabling interrupts before accessing
     them).

von Hc Z. (mizch)


Lesenswert?

> Warum sollte C sich um die Interrupts kümmern?

Dann schau mal nach <avr/eeprom.h>.  Du wirst einen cli finden. 
(Natürlich ist die C-Laufzeitbibliothek und nicht der C-Standard 
gemeint.  Ich denke, das versteht sich aus dem Zusammenhang von selbst 
-- es ging ja um eeprom_write_word() -- und bedarf keiner Erwähnung.)

von Hc Z. (mizch)


Lesenswert?

Tobi schrieb:
> As these functions modify IO registers, they are known to be
>      non-reentrant.

Das ist nochmal eine andere Baustelle.  Unabhängig davon müssen 
Interrupts auch bei Nicht-reentrant-Zugriff gesperrt werden, und eben 
darum kümmert sich das C Runtime selber.

Dass es darüber hinaus noch Umstände geben kann, in denen Zugriffe 
gegenseitig verriegelt sein müssen (und wo das Sperren von Interrupts 
die Lösung sein kann, aber nicht muss), versteht sich von selber; davon 
war aber nicht die Rede.

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.