- LiFePO4 Speicher Test         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 12

Thema: ATMega8 und EEPROM lesen/speichern

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    23.02.2007
    Beiträge
    62

    ATMega8 und EEPROM lesen/speichern

    Anzeige

    LiFePo4 Akku selber bauen - Video
    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

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    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
    Code:
    .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
    Code:
    .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
    Code:
    	;; 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

    was geschrieben, ich hoffe es ist verständlich genug.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    23.02.2007
    Beiträge
    62
    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

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    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
    Software is like s e x: its better when its free.
    Linus Torvald

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    23.02.2007
    Beiträge
    62
    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]

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    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:
    Code:
    .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
    Code:
    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
    Software is like s e x: its better when its free.
    Linus Torvald

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    23.02.2007
    Beiträge
    62
    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.


    Code:
    .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 (ATMEGA, 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

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Wenn ich Deinen Code umsetzen will (ATMEGA, 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
    Software is like s e x: its better when its free.
    Linus Torvald

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    23.02.2007
    Beiträge
    62
    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

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Ich glaube ich hab Deinen Fehler, schau Du willst Schreiben:
    Code:
    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,
    Code:
    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
    Software is like s e x: its better when its free.
    Linus Torvald

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen