Archiv verlassen und diese Seite im Standarddesign anzeigen : ATMega8 und EEPROM lesen/speichern
Hallo,
ich möchte erfasste Daten im EEPROM speichern und irgendwann wieder lesen können. Leider bin ich nicht sehr bewandert in den Dingen.
Im Netz habe ich schon mal diesen Code gefunden:
.include "m8def.inc"
.DEF rTemp = R16
.DEF rH=R18
ldi rTemp, 0xFF
out DDRD, rTemp
ldi rTemp, 4, HIGH(Daten)
out EEARH, rTemp
ldi rTemp, LOW(Daten)
out EEARL, rTemp
sbi EECR, EERE
in rTemp, EEDR
out PORTD, rTemp
loop:
rjmp loop
.eseg
Daten:
.db 0B01010101
Damit kann ich nun zwar Daten lesen, aber wie schreibe ich diese?
Auch sollten ja mehrere Werte gespeichert werden.
Weiter verstehe ich diese Zeile nicht richtig.
ldi rTemp, 4, HIGH(Daten)
Hier gebe ich die Erste Adresse im EEPROM an. Was aber, wenn ich die 3. Adresse möchte? High(Daten*6)
Ich wäre iber etwas Hilfe dankbar. Vielleicht hat ja jemand ein einfaches Beispiel für mich?
Vielen Dank im Voraus - Lothar
Hallo,
Du sollst allerdings vor dem lesen testen, ob Dein EEPROM überhaupt bereit ist
gelesen zu werden.
Ich poste Dir mal zwei Makros aus meinem aktuellen Projekt:
1. lesen
.macro READMOTORVALUE
wait4eep1:
sbic EECR,EEPE
rjmp wait4eep1
ldi tmp,LOW(radrechts)
out EEARL,tmp
sbi EECR,EERE
in tmp,EEDR
wait4eep2:
sbic EECR,EEPE
rjmp wait4eep2
ldi tmp1,LOW(radlinks)
out EEARL,tmp
sbi EECR,EERE
in tmp1,EEDR
.endmacro
2. schreiben
.macro SAVEMOTORVALUEFUNC
wait4ready1:
sbic EECR,EEPE
rjmp wait4ready1
out EECR,null
ldi tmp,LOW(radrechts)
out EEARL,tmp
in tmp,OCR0A
in tmp1,OCR0B
out EEDR,tmp
cli
sbi EECR,EEMPE
sbi EECR,EEPE
sei
wait4ready2:
sbic EECR,EEPE
rjmp wait4ready2
out EECR,null
ldi tmp,LOW(radlinks)
out EEARL,tmp
out EEDR,tmp1
cli
sbi EECR,EEMPE
sbi EECR,EEPE
sei
.endmacro
Die EEprom adressen werden so deklariert
;; EEPROM Segment
.eseg
radrechts:
.db 0x80
radlinks:
.db 0x80
Es werden zwar 2 Adressen nacheinander gelesen, das sollte aber das Prinzip zeigen.
Zu HIGH und LOW habe ich hier (http://www.izaseba.roboterbastler.de/index.php?popup=Tutorial§ion=Lektion9)
was geschrieben, ich hoffe es ist verständlich genug.
Gruß Sebastian
Hi,
danke erst Mal für Deine Antwort. Jetzt bin ich noch verwirrter als vorher.
Wenn ich mir nun diesen Code anschaue,
;; EEPROM Segment
.eseg
radrechts:
.db 0x80
radlinks:
.db 0x80
verstehe ich nicht, dass radrechts an die gleiche Position wie radlinks gespeichert wird. Wenn das die gleiche Speicheradresse im EEPROM ist, überschreiben sich die Werte da nicht?
Noch eine Frage:
Ich habe bis jetzt noch nichts mit Makros gemacht. Was ist der Vorteil? Sind Unterprogramme nicht effektiver im Speicherplatz?
Ich habe den Code nun so erweitert, und dachte, Wenn ich PortPin B0 aktiviere, liest es den EEProm und bei PB1 schreibt es den EEProm. Leider läuft der Code so nicht. Wo ist denn der Fehler??
.NOLIST
.include "m8def.inc"
.LIST
.DEF tmp = R16
.DEF tmp1 = R17
LOOP:
sbis PinB, 0
READMOTORVALUE
sbis PinB, 1
SAVEMOTORVALUE
rJmp Loop
.macro READMOTORVALUE
wait4eep1:
sbic EECR,EEPE
rjmp wait4eep1
ldi tmp,LOW(radrechts)
out EEARL,tmp
sbi EECR,EERE
in tmp,EEDR
wait4eep2:
sbic EECR,EEPE
rjmp wait4eep2
ldi tmp1,LOW(radlinks)
out EEARL,tmp
sbi EECR,EERE
in tmp1,EEDR
.endmacro
.macro SAVEMOTORVALUEFUNC
wait4ready1:
sbic EECR,EEPE
rjmp wait4ready1
out EECR,null
ldi tmp,LOW(radrechts)
out EEARL,tmp
in tmp,OCR0A
in tmp1,OCR0B
out EEDR,tmp
cli
sbi EECR,EEMPE
sbi EECR,EEPE
sei
wait4ready2:
sbic EECR,EEPE
rjmp wait4ready2
out EECR,null
ldi tmp,LOW(radlinks)
out EEARL,tmp
out EEDR,tmp1
cli
sbi EECR,EEMPE
sbi EECR,EEPE
sei
.endmacro
;; EEPROM Segment
.eseg
radrechts:
.db 0x80
radlinks:
.db 0x80
Vielleicht kann mir ja noch mal wer helfen?
Danke Lothar
Sorry, ich wollte Dich nicht verwirren :-(
verstehe ich nicht, dass radrechts an die gleiche Position wie radlinks gespeichert wird. Wenn das die gleiche Speicheradresse im EEPROM ist, überschreiben sich die Werte da nicht?
Wieso gleiche Adresse ?
es sind zwei Adressen hintereinander, 0x80 ist nicht die Adresse, sondern Wert, der in diese Speicherzelle rein soll, das wird in der *.eep Datei Abgelegt.
Warum Makro ?
Naja, da muß man entscheiden was besser ist.
Wenn die Funktion nur einmal im Programm ausgerufen wird ist makro besser, wenn 20 mal ist natürlich ein call besser, spart Speicher
Was hängt denn an PinB1 und PinB0 Taster ?
Pass mit sowas auf, mann kann sich den EEprom ziemlich schnell killen, wenn man Fehler macht.
Achso, ich wollte Dich natürlich nicht unbedingt zu Makros bewegen sondern eher zeigen, wie man was in EEprom schreibt bzw. liesst.
Gruß Sebastian
Hi,
jetzt hab ich es auch verstanden - dass 0x80 ein Wert und keine Adresse ist.
An PinB,0 und PinB, 1 liegen die Taster (STK500)
Ich wollte erreichen, dass beim Drücken
die 2 Makros
sbis PinB, 0
READMOTORVALUE
und
sbis PinB, 1
SAVEMOTORVALUE
aufgerufen werden.
Sicher rufe ich die Makros falsch auf.
E:\Assemb\S\EEPROM\Test1\Test1.asm(13): error: SAVEMOTORVALUE: Unknown instruction or macro
Was ist, wenn ich variabel 1 - 10/12 Messergebnisse vorübergehend im EEProm speichern will?
Muss ich da für alle eine Marke im EEProm definieren?
Ich dachte, ich könne das so wie im Stack ablegen und dann wieder hintereinander abrufen.
Und wieso kann ich mir damit den EEPROM zerschießen?
MfG Lothar[/quote]
Und wieso kann ich mir damit den EEPROM zerschießen?
Ein Beispiel von mir:
Ein Register sollte auf Tastendruck im EEprom geschrieben werden.
Zu wenig überlegt und es war genau anders herum, kein Tastendruck bewirkte
das schreiben...
Was passiert ?
EEprom wurde nur noch beschrieben, wie lange Dauert das schreiben ?
Irgendwas mit 1 mS, also etwa 1000 Schreibzugriffe in der Sekunde,
dumm nur wenn eeprom 100000 Schreibzugriffe hält.
Bis ich darauf gekommen bin, daß ich einen Fehler gemacht habe, war die EEprom Zelle kaputt und hat kein Inhalt mehr gehalten...
Wie gut, daß es noch weitere EEprom Zellen gab, wo ich was schreiben konnte...
Wenn Du mehrere Sachen im EEprom Speichern willst würde ich das etwa so machen:
.equ eeprompuffer = 0x00
.def null = r1
...
...
clr null
loop:
clr r16
ldi r19,1
loop1:
rcall eepromsave
inc r16
inc r19
cpi r16,20
brne loop1
loop2:
rjmp loop2
eepromsave:
sbic EECR,EEPE
rjmp eepromsave
out EECR,null
ldi r17,LOW(eeprompuffer)
add r17,r16
adc r18,null
out EEARH,r18
out EEARL,r17
out EEDR,r19
cli
sbi EECR,EEMPE
sbi EECR,EEPE
sei
ret
So in etwa ? es werden 21 EEpromzellen beschrieben
Wenn Du keine Interrupt benutzt kannst Du Dir auch cli sei sparen
Tja die Makros, sowas ist schonmal nicht gut
sbis PinB, 0
READMOTORVALUE
mit sbis überspringst Du nicht READMOTORVALUE sondern nur die erste Zeile im Makro, weil an der Stelle wo der Makroname steht, fügt der Assembler alles ein was zwischen .macro und .endmacro steht.
Gruß Sebastian
Hi,
ja, das mit dem Zerschießen des EEProms habe ich mittlerweile kapiert.
In der Zwischenzeit habe ich diesen Code geschrieben. (Wie gesagt - ich habe fast noch 0 Ahnung.
.NOLIST
.include "m8def.inc"
.LIST
.DEF rTemp = R16
.DEF rT1 = R17
.DEF rP1=R18
.DEF rP2=R19
ldi rTemp, LOW(RAMEND) ; Stackpointer initialisieren
out SPL, rTemp
ldi rTemp, HIGH(RAMEND)
out SPH, rTemp
ldi rTemp, 0xFF
out DDRD, rTemp ; Port D: Ausgang
LDI rTemp, 0B11111111
OUT PORTD, rTemp
LOOP:
sbis PinB, 0 ; Auf Tastendruck abfragen
rCall READ ; EEProm lesen
sbis PinB, 1 ; Auf Tastendruck abfragen
rCall SAVE ; EEPROM schreiben
sbis PinB, 2 ; Auf Tastendruck abfragen
rCall AddT1 ; Zufällige Zahl ermitteln
rJmp Loop
AddT1:
inc rT1 ; Zufallszahl einstellen
OUT PortD, rT1
RET
READ:
RCall EEPROMLesen
Mov rT1, rTemp
OUT PORTD, rTemp
Ret
SAVE:
MOV rTemp, rT1
rCall EEPROMSchreiben
rCall Pause
rCall Pause
RET
EEPROMLesen:
ldi rTemp, HIGH(W1) ; Adresse laden
out EEARH, rTemp
ldi rTemp, LOW(W1)
out EEARL, rTemp
sbi EECR, EERE ; Lesevorgang aktivieren
in rTemp, EEDR
rCall Pause
RET
EEPROMSchreiben:
ldi rTemp, HIGH(W1) ; High-Adresse im EEPROM laden
out EEARH, rTemp ; und ins EEARH schreiben
ldi rTemp, LOW(W1) ; Low-Adresse im EEPROM laden
out EEARL, rTemp ; und ins EEARL schreiben
sbic EECR,EEWE ; Vorherigen Schreibvorgang abwarten
rjmp EEPROMSchreiben
out EEDR,rTemp ; Daten ins EEPROM-Datenregister
sbi EECR,EEMWE ; Schreiben vorbereiten
sbi EECR,EEWE
rCall Pause
RET
Pause:
DEC rP1
brne Pause
DEC rP2
brne Pause
Ret
.eseg ; EEPROM
W1:
.db 0B10101010
Es soll folgendes passieren. Druck auf Taste PortB0 und der Inhalt des EEs soll gelesen werden. - das funktioniert.
Druck auf Taste PortB2 wird aufgrund variabler Dauer ein zufälliger Wert im Register rT1 erzeugt - das funktioniert.
Druck auf Taste PortB1 soll nun den Inhalt des Registers rT1 an rTemp übergeben und im EE speichern. Das funktioniert nicht. Im EE steht nun nichts mehr. Kontrolle Taste0
Im EE habe ich aber die .eep geladen. Kontrolle Taste0 - Wert war anfangs da.
Wenn ich Deinen Code umsetzen will (ATMEGA8), bekomme ich folgende Fehler:
E:\Assemb\S\TIMER\ATM8\Test2.asm(40): error: Undefined symbol: EEPE
E:\Assemb\S\TIMER\ATM8\Test2.asm(50): error: Undefined symbol: EEMPE
E:\Assemb\S\TIMER\ATM8\Test2.asm(51): error: Undefined symbol: EEPE
Sicher liegt es nicht am Code, sondern daran, dass ich es nicht auf den ATMega8 umsetzen kann.
Hast Du vielleicht ein funktionierendes Beispiel für den ATM8?
Das wäre super! Wie ich sehe, gehts Dir leicht von der Hand.
Ciao Lothar
Wenn ich Deinen Code umsetzen will (ATMEGA8), bekomme ich folgende Fehler
Hmm, die deppen haben die Bitnamen geändert, sorry ich arbeite zur Zeit mit Tiny24 und nicht M8...
Sonst sieht Deine Save Funktion nicht schlecht aus.
In der Read Routine sollst Du auch warten, bis EEWE Low geht, vielleicht liegt hier der Hund begraben.
Wenn Du ein Beispiel möchtest schau mal ins Dattenblatt ab Seite 22 gibt es je ein Beispiel zum Schreiben und lesen.
Gruß Sebastian
Hi,
hm, lesen tut es ja einwandfrei.
Das Beispiel ist ja fast so, wie ich es postete.
Irgendwie klappt das Schreiben einfach nicht.
Vielleicht gibt es ja jemanden, der ein fertiges Anfängerbeispiel hat?
MfG LotharK
Ich glaube ich hab Deinen Fehler, schau Du willst Schreiben:
SAVE:
MOV rTemp, rT1
rCall EEPROMSchreiben
rCall Pause
rCall Pause
RET
in rtemp liegt der zu speichernde Wert, dann machst Du ein rcall nach EEPROMSchreiben, und da knallt es weil,
EEPROMSchreiben:
ldi rTemp, HIGH(W1) ; High-Adresse im EEPROM laden
out EEARH, rTemp ; und ins EEARH schreiben
ldi rTemp, LOW(W1) ; Low-Adresse im EEPROM laden
out EEARL, rTemp ; und ins EEARL schreiben
sbic EECR,EEWE ; Vorherigen Schreibvorgang abwarten
rjmp EEPROMSchreiben
out EEDR,rTemp ; Daten ins EEPROM-Datenregister
sbi EECR,EEMWE ; Schreiben vorbereiten
sbi EECR,EEWE
rCall Pause
RET
Du die den Inhalt von rtemp 2 Mal überschreibst und gespeichert wird LOW der Adresse von W1 ;-)
Entweder nimmst Du einen anderen Register für die Wertübergabe, oder Du ließt rT1 unmitelbar vor dem Schreiben in EEDR aus.
Gruß Sebastan
Hallo Sebastian,
ich hatte es auch gerade gefunden. Danke - jetzt läuft alles dank Deiner Hilfe.
Hat mich echt einen Sonntag gekostet.
Ciao LotharK
Hallo LotharK,
Hat mich echt einen Sonntag gekostet.
Was ist schon ein Sonntag bei so einer komplexen Sache wie ein µC ;-)
Immerhin gehst Du den 'schweren' Weg über Assembler...
Gruß Sebastian
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.