mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik EEPROM schreiben zum 100ersten


Autor: Benjamin Böck (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Tut mir leid das ich schon wieder mit diesem EEPROM Problemen komme. Ich
sitze nun aber schon seit zwei Tage vor diesem Poblem, habe das Forum
dursucht und die Atmel-Unterlagen gelesen, komme aber einfach nicht
weiter!

Mein Problem ist das das mein Schreibzugriff nur sehr willkürlich
erfolgt.
Kann es vieleicht an der Taktung liegen ich habe einen Mega8 mit
externen 4 Mhz und den anderen mit den internen 1 Mhz betrieben. Auf
dem 4 Mhz bekomme ich meistens gar keine Werte ins EEROM geschrieben.

Wenn ich Daten mit Yaap ins EEPROM schreibe gibt es keine Probleme
weder mit lesen noch mit schreiben. Wenn ich allerdings mit meinem
Testprogramm schreiben will, schreibt er nur ein 00 an die erste
Adresse (EEARH=0,EEARL=0) die anderen Bytes sind weiterhinn auf 0xFF.
Auf der AVR-Simulation läuft alles bestens!!
An meiner Versorgungsspannung dürfte es auch nicht liegne 5V Stabiel
bis auf eine Restwelligkeit von 20 mV.

Ich habe mein Testprogramm  mal angehängt vieleicht findet ihr meinen
Fehler.

 MFG Ben

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was ist mit dem stack?

Autor: Benjamin Böck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was meinst du mit dem Stack?

Ich bin erst seit einer Woche am ASM Programmieren und daher weiß ich
nicht ob es das ist was du meinst.

Also wenn ich den Stackpointer im AVR-Simulator beobachte (SPH-SPL)
dann läuft nichts raus er springt sauber auf einen Wert (SPH 0x07, SPL
0xFE) wenn er in die Sub springt und stellt in sauber wieder auf 0x00
beim Rücksprung.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und wo steht in deinem Programm das Laden des SP? Ich sehe nichts.

Autor: Benjamin Böck (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Habe den Stackpointer nun initialisiert wie im Tut beschreiben.
Aber vieleicht bin ich auch auf dem Falschen Weg????
Hänge mein Prog noch mal an...

Vielen Dank für deine Mühe...

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SPH fehlt noch :-)

Autor: Benjamin Böck (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ups habe den Stackpointer nur für eine Adresse gestetzt noch mal...

Juchei es funktioniert!!!!!
Vielen Dank da wäre ich niemals darauf gekommen. Aber vieleicht kannst
du mir noch mal erklären wozu ich den Pointer initialisieren muß oder
warum das Problem bestand. SO daß ich nicht unwissend sterben muß ;-)

Aber ertsmal vielen vielen Dank für die schnelle Hilfe !!!!!

Autor: Benjamin Böck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gehe ich richtig in der Anahme das mein vorheriger Pointer in ein
Bereich gezeit hat den es beim Mega8 nicht gibt und er desshalb die
Rücksrungadresse nicht gefunden hat?
d.h. ich muß beim Prog- beginn immer meinen Stackpointer auf die
Oberste Ram- Adrsse setzen das er im richtigen Bereich arbeitet?? oder
liege ich damit falsch?

Autor: Dave (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich will ja crazy horse seinen Schützling nicht wegnehmen ;)

Stack Pointer ist wie er schon heißt nen Stapel-Zeiger und sobald du
einen (R)CALL machst (auch Interrupts) dann brauchste diesen Menschen.
Bei einem CALL wird die aktuelle Programm-Adresse, wo die Maschine
steht- auf den Stack geschmissen, der Stack Pointer springt automatisch
bei jedem draufgelegtem Byte eine Adresse tiefer und bei einem
abgeholten einen wieder hoch.

Initialisiert wird er mit der letzten RAM-Adresse (also ramend) und
wenn du dann deine Programmadresse ablegst (2 Bytes) dann liegt das
eine Byte auf ramend und das zweite auf ramend-1.

Beim RET(I) nimmt der Prozessor die Bytes, die unter dem Pointer und
eins höher liegen, auf und nimmt sie wieder in den Adresszähler des µC
(wo er sich gerade befindet) und springt somit an den Ort des CALLs
zurück.

Falls du den Stackpointer nicht initialisiert hast hat er anfangs die
Adresse 0x000 und da kann man nicht viel mit machen, er kann keine
Adrese beim CALL drauflegen und so nimmt er beim zurückspringen immer
die Adresse 0x000 raus, also den Anfang deines Programms.


Dave

Autor: Benjamin Böck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mensch da habe ich das Tut gelesen mir aber keine Gedanken über die
initialisierung gemacht!
Tut mir leid das ich euch wegen sowas belästigen mußte, ihr habt mir
aber sehr geholfen.

Also dickes Lob an euch!!

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach, da hab ich ein grosses Herz :-)

Bleibt noch zu ergänzen, das der SP nicht zwingend auf RAMEND beim
Programmstart zeigen muss, auch wenn das meist die sinnvollste Variante
ist. Genausogut könnte der Stack mitten im RAM oder auch RAMStart+x
sein, wobei für x die max. benötigte Stacktiefe steht. Der SP ist
gnadenlos. Wenn man ihn zwingt, benutzt er auch den I/O und
Registerbereich, ebenso stellt es für ihn kein Problem dar, globale
Variablen zu überschreiben, es gibt keinerlei
Speicherschutzmechanismen,  da muss der Programmierer aufpassen.
Die Reset-Einstellung 0x0000 ist aber auf jeden Fall unbrauchbar.
Legt die Variablen steigend im RAM an und den Stack von oben nach
unten, hat man den grösstmöglichen Stackspeicher. Und deswegen wird es
auch fast immer so gemacht.

Autor: Benjamin Böck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na das klärt so einiges auch warum bei meinem anderen Programmen der
Rücksrung nicht immer geklappt hat. Für ein Hochsprachen verwöhnten
Mensch ist es halt doch ein bisschen Umgewöhnung wenn er sich um alles
selber kümmern muß ;-) Aber es ist trotzdem ein Traum mal an der Basis
die Grundlagen zu lernen und Anwendungen in Echtzeit zu realisieren
freu freu freu...

Autor: dave (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur um noch mehr streng geheime Daten aus dem Datenblatt zu erzählen
(LOL):

Falls du Interrupts aufrufst, so musst du oft die SREG und nen
Arbeitsregister speichern. Dafür ist der Stack auch schön geeignet, und
zwar mit den Befehlehn PUSH und POP.

PUSH r16 legt das Byte in r16 auf den aktuellen Stack-Platz und
erniedrigt den Zeiger
POP r16 erhöht den Zeiger und nimmt das Byte, das adressiert ist, in
r16.
Beide Befehle kosten (wie alle RAM-Zugriffe) 2 Takte.

Damit, wie crazy horse es beschrieben hat, der liebe Stack dir nicht
alles nieder macht im RAM, muss auf ein (R)CALL immer ein RET(I)
folgen, sonst gibt es unregelmäßigkeiten.
Falls du nach nem CALL KEIN RET machen willst, sondern nen (R)JMP, so
bietet es sich an, einfach mal schnell die 2 gePUSHten Adressen
runterzuholen:

POP register
POP register
RJMP label
und du hascht keine Probleme damit ;)

Das mit dem Echtzeit geht doch auch in Basich g, je nachdem wie
schnell deine Echtzeit ist lol.


dave

Autor: Benjamin Böck (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin gerade dabei miene Fernsteuerung (Ir) an den Mega8 anzubinden.
Dachte dabei an eine einfach Lösung Anwendungen zu steuern. Soll
ähnlich wie Lirc- Winlirc funktionieren und später auch biderektionell
mit dem Pc. So kann ich 1. Daten Austauschen und gleichzeitig auch noch
andere Geräte die mit IR funktionieren ansteueren (Steroanlage usw.).
Dank eurer Hilfe komme ich nun auch gut vorann. Muß jetzt nur noch das
Zeitsignal in ein Binäres umwandeln und schon kann man die Ergebnisse
zuordnen- weiterverwenden.

Das schlimmste mit dem Stack ist ja das ich das alles schon gelesen
habe und dachte auch es verstanden zu haben, aber an die Anfangsadresse
hatte ich in meinem Eifer nicht gedacht...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hat mich auch gewundert. Der AVR ist ja einer der jüngsten 8-Bitter,
warum man da nicht die Erfahrungen anderer einfließen lassen hat. Selbst
beim uralten 8051 wird der Stack auf einen gültigen Bereich gesetzt.

Und das SREG läßt sich ja nicht mal pushen, einige andere MCs sichern
das SREG automatisch bei Interrupts, d.h. das RETI holt dann 3 Bytes
vom Stack.

Da der AVR ja keine Interruptprioritäten hat, ist es am einfachsten,
ein Register nur für die Sicherung des SREG abzustellen, dann braucht
man nur ein "IN" und "OUT" zum Sichern im Interrupt.
R2 ist da zu empfehlen (R0, R1 werden für LPM, MUL benötigt).


Generell ist es sinnvoll, einige Register für Interrupts abzustellen,
dann kann man sich PUSH und POP oft ganz sparen. Z.B. reserviere ich
den X-Pointer für Interrupts, da für das Hauptprogramm 2 Pointer (Y,Z)
völlig ausreichend sind.


Peter

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.