Forum: Mikrocontroller und Digitale Elektronik PIC 18F; Problem beim Schreiben in EEPROM


von Ludwig (Gast)


Lesenswert?

Hallo,
Viellecht kann mir jemand helfen, warum ich nicht ins interne EEPROM von 
meinem PIC 18F6620 schreiben kann. Ich hab zum schreiben und auslesen 
jeweils eine Routine geschrieben, wie im Datenblatt beschrieben.
Die Lese-Routine funktioniert, die Schreib-Routine leider nicht.
An was kann das liegen?

unsigned char LeseEEData(unsigned char Adresse)
{
unsigned char ReadData;
  EEADRH=0;
  EEADR=Adresse;
  EEPGD=0;  //Lesen von EEPRom-Data und nicht Flash-Speicher
  CFGS=0;
  RD=1;      // Das Lesen der EEProm-Zelle triggern
  ReadData=EEDATA;          //Übernahme der gelesenen Speicherzelle
  return ReadData;
  }

void SchreibeEEData(unsigned char Adresse, unsigned char WriteData)
{
  EEADRH=0;
  EEADR=Adresse;    // Die Zieladresse eintragen
  EEDATA=WriteData;           //Byte eintragen
  EEPGD=0;    //Schreiben auf EEPRom-Data und nicht Flash-Speicher
  CFGS=0;
  WREN=1;       //Schreiben der EEProm-Zelle erlauben  GIE=0;
  EECON2=0x55;
  EECON2=0xAA;
  WR=1;      // Das Schreiben starten
         while (WR)    //warten bis der Schreibvorgang
  {
  }
         GIE=1;
  WREN=0;    // Schreiben verbieten
}

von holger (Gast)


Lesenswert?

Sieht eigentlich gut aus.

>  WREN=1;       //Schreiben der EEProm-Zelle erlauben  GIE=0;

Dein GIE=0 sollte vermutlich in die nächste Zeile?

  WREN=1;       //Schreiben der EEProm-Zelle erlauben
  GIE=0;


>  EECON2=0x55;
>  EECON2=0xAA;

Die Stelle mit EECON2 ist sehr kritisch.
Schau doch mal was dein Compiler im Assemblerlisting daraus macht.

Ich nehm da lieber Inline Assembler.
Für C18 von Microchip:

_asm
  MOVLW  0x55
  MOVWF  EECON2,0
  MOVLW  0xAA
  MOVWF  EECON2,0
        BSF EECON1, WR
_endasm

von holger (Gast)


Lesenswert?

Hast du das EEPROM evtl. im Configurationword
schreibgeschützt?

von skorpionx (Gast)


Lesenswert?

void eeprom_write(unsigned char AdressInEEprom, unsigned char data_byte)
{
  unsigned char InterruptZw;

  InterruptZw = INTCONbits.GIE;

   EEADR = AdressInEEprom;         // Adresse(ZeleNr im EEProm)  #1
   EEDATA = data_byte;       // Memory Value to write  #2
    EECON1bits.EEPGD = 0;     // Point to DATA memory    #3
    EECON1bits.CFGS  = 0;     // Access EEPROM    #4
    EECON1bits.WREN = 1;       // WRITE Enable       #5
  INTCONbits.GIE  = 0;    //disable interrupts    #6
  EECON2 = 0x55;      // WRITE step       #7
  EECON2 = 0xaa;      // WRITE step      #8
  EECON1bits.WR = 1;         // Start EEPROM_writing   #9
  INTCONbits.GIE  = InterruptZw ;  //re-enable interrupts    #10
  while (!PIR2bits.EEIF)     // WRITE step       #11
        ;
   PIR2bits.EEIF = 0;        // WRITE step       #12

   /* clear the interrupt flag            */
      INTCONbits.INT0IF = 0;
        EECON1bits.WR = 0;    //Write Enable löschen    #13
}


unsigned char eeprom_read(unsigned char AdressInEEprom)
{
    while (EECON1bits.WR);        // Wait if READ/WRITE/.....
    EEADR = AdressInEEprom;        // Select EEPROM Cell
    EECON1bits.EEPGD = 0;         // Select EEPROM Memory
    EECON1bits.CFGS = 0;        // Select Memory - not Config_Word
    EECON1bits.RD = 1;            // Start Reading
    return EEDATA;           // Return Cell_Value
}

von Ludwig (Gast)


Lesenswert?

Danke für eure Tipps.
Funktioniert aber leider immer noch nicht.
Das ist der das zugehörige Disassambly Listing.


137:               void SchreibeEEData(unsigned char HAdresse, unsigned 
char LAdresse, unsigned char WriteData)
138:               {
139:                 EEADRH=HAdresse;
  D71E    C410     MOVFF 0x410, 0xfaa
  D720    FFAA     NOP
140:                 EEADR=LAdresse;    // Die Zieladresse eintragen
  D722    C411     MOVFF 0x411, 0xfa9
  D724    FFA9     NOP
141:                 EEDATA=WriteData;  // Das zu schreibende Byte 
eintragen
  D726    C412     MOVFF 0x412, 0xfa8
  D728    FFA8     NOP
142:                 EEPGD=0;      // EEPDG-Bit löschen => Schreiben auf 
EEPRom-Data und nicht Flash-Speicher
  D72A    9EA6     BCF 0xfa6, 0x7, ACCESS
143:                 CFGS=0;
  D72C    9CA6     BCF 0xfa6, 0x6, ACCESS
144:                 WREN=1;        // Das Schreiben der EEProm-Zelle 
erlauben (WREN setzen)
  D72E    84A6     BSF 0xfa6, 0x2, ACCESS
145:                 GIE=0;
  D730    9EF2     BCF 0xff2, 0x7, ACCESS
146:                 EECON2=0x55;    // Laut PIC-Handbuch : diese 
Konstante reinschreiben
  D732    0104     MOVLB 0x4
  D734    6F13     MOVWF 0x13, BANKED
  D736    0E55     MOVLW 0x55
  D738    6EA7     MOVWF 0xfa7, ACCESS
  D73A    0104     MOVLB 0x4
  D73C    5113     MOVF 0x13, W, BANKED
147:                 EECON2=0xAA;    // Laut PIC-Handbuch : diese 
Konstante reinschreiben
  D73E    0104     MOVLB 0x4
  D740    6F13     MOVWF 0x13, BANKED
  D742    0EAA     MOVLW 0xaa
  D744    6EA7     MOVWF 0xfa7, ACCESS
  D746    0104     MOVLB 0x4
  D748    5113     MOVF 0x13, W, BANKED
148:                 WR=1;        // Das Schreiben der EEProm-Zelle 
triggern (WR setzen)
  D74A    82A6     BSF 0xfa6, 0x1, ACCESS
149:
150:                 while (WR)      // Solange warten, bis der 
Schreibvorgang abgeschlossen ist (Das WR-Flag wird gelöscht)
  D74C    D000     BRA 0xd74e
  D74E    B2A6     BTFSC 0xfa6, 0x1, ACCESS
  D750    D001     BRA 0xd754
  D752    D001     BRA 0xd756
  D754    D7FC     BRA 0xd74e
151:                 {
152:                 }
153:                 WREN=0;        // Das Schreiben der EEProm-Zelle 
verbieten (WREN löschen)
  D756    94A6     BCF 0xfa6, 0x2, ACCESS
154:                 GIE=1;
  D758    8EF2     BSF 0xff2, 0x7, ACCESS
155:               }
  D75A    0012     RETURN 0

von holger (Gast)


Lesenswert?

Da sieht man doch sehr schön, wie dir der Compiler
die eigentlich notwendige kurze Sequenz durch
Banking Befehle versaut. Da wirst du um Inline Assembler
wohl nicht herumkommen.

von Ludwig (Gast)


Lesenswert?

Was heißt das konkret für mich als Leihe?
Hab das schon mal versucht, bekam es leider nicht hin.

von Ludwig (Gast)


Lesenswert?

Wenn ich folgenden ASM-code einfüge, bekomme ich vier Errormeldungen.
Kenn mich mit asm nicht so gut aus.
Was mache ich falsch?

158   #asm
159   MOVLW  0x55
160   MOVWF  EECON2, 0
161   MOVLW  0xAA
162   MOVWF  EECON2, 0
163   BSF EECON1,  WR
164   #endasm

Error   [876] 161. Syntaxfehler
Error   [876] 163. Syntaxfehler
Error   [800] 7588. undefiniertes Symbol "EECON1"
Error   [800] 7588. undefiniertes Symbol "WR"

von holger (Gast)


Lesenswert?

>Kenn mich mit asm nicht so gut aus.

Ich auch nicht ;)

>Was mache ich falsch?

Keine Ahnung. Welcher Compiler ist das überhaupt?
Vieleicht hat der ja schon fertige EEPROM Routinen
in seiner LIB.

von ludwig (Gast)


Lesenswert?

Das der MPLAB 8.20 von HI-TECH

von skorpionx (Gast)


Lesenswert?

Mein Beispiel läuft mit SDCC und auch mit MCC18  von Microchip.

von ludwig (Gast)


Lesenswert?

Ich habe jetzt festgestellt, dass auch das Interruptbit nach dem 
"Schreibversuch" gar nicht gesetzt wird.
1
while (!PIR2bits.EEIF)     // WRITE step       #11
2
{}
3
PIR2bits.EEIF = 0;        // WRITE step       #12


An was kann das liegen, evtl. ein Hardware Problem?
(ich benutze PIC18F6620 mit  MPLAB ICD 2)

von holger (Gast)


Lesenswert?

>Ich habe jetzt festgestellt, dass auch das Interruptbit nach dem
>"Schreibversuch" gar nicht gesetzt wird.

while (!PIR2bits.EEIF)     // WRITE step       #11
{}
PIR2bits.EEIF = 0;        // WRITE step       #12


>An was kann das liegen, evtl. ein Hardware Problem?
>(ich benutze PIC18F6620 mit  MPLAB ICD 2)

Das liegt daran das die Befehle aus dem Datenblatt
nicht in GENAU der Reihenfolge durchgeführt werden
wie sie müssten:

  MOVLW  0x55
  MOVWF  EECON2,0
  MOVLW  0xAA
  MOVWF  EECON2,0
  BSF EECON1, WR

Da darf NICHTS dazwischen kommen. Auch keine
Breakpoints vom Debugger oder sowas.

von skorpionx (Gast)


Lesenswert?

SDCC hat das so in Assembler übersetzt:

_eeprom_write:
;  .line  751; can.c  void eeprom_write(unsigned char AdressInEEprom, 
unsigned char data_byte)
  MOVFF  FSR2L, POSTDEC1
  MOVFF  FSR1L, FSR2L
  MOVFF  r0x00, POSTDEC1
  MOVFF  r0x01, POSTDEC1
  MOVFF  r0x02, POSTDEC1
  MOVLW  0x02
  MOVFF  PLUSW2, r0x00
  MOVLW  0x03
  MOVFF  PLUSW2, r0x01
;  .line  755; can.c  InterruptZw = INTCONbits.GIE;
  CLRF  r0x02
  BTFSC  _INTCONbits, 7
  INCF  r0x02, F
;  .line  763; can.c  EEADR = AdressInEEprom;         // Adresse(ZeleNr 
im EEProm)  #1
  MOVFF  r0x00, _EEADR
;  .line  764; can.c  EEDATA = data_byte;       // Memory Value to write 
#2
  MOVFF  r0x01, _EEDATA
;  .line  765; can.c  EECON1bits.EEPGD = 0;     // Point to DATA memory 
#3
  BCF  _EECON1bits, 7
;  .line  766; can.c  EECON1bits.CFGS  = 0;     // Access EEPROM    #4
  BCF  _EECON1bits, 6
;  .line  767; can.c  EECON1bits.WREN = 1;       // WRITE Enable 
#5
  BSF  _EECON1bits, 2
;  .line  768; can.c  INTCONbits.GIE  = 0;    //disable interrupts    #6
  BCF  _INTCONbits, 7
;  .line  769; can.c  EECON2 = 0x55;      // WRITE step       #7
  MOVLW  0x55
  MOVWF  _EECON2
;  .line  770; can.c  EECON2 = 0xaa;      // WRITE step      #8
  MOVLW  0xaa
  MOVWF  _EECON2
;  .line  771; can.c  EECON1bits.WR = 1;         // Start EEPROM_writing 
#9
  BSF  _EECON1bits, 1
;  .line  772; can.c  INTCONbits.GIE  = InterruptZw ;  //re-enable 
interrupts    #10
  MOVF  r0x02, W
  ANDLW  0x01
  RRNCF  WREG, W
  MOVWF  PRODH
  MOVF  _INTCONbits, W
  ANDLW  0x7f
  IORWF  PRODH, W
  MOVWF  _INTCONbits
_00285_DS_:
;  .line  773; can.c  while (!PIR2bits.EEIF)     // WRITE step       #11
  BTFSS  _PIR2bits, 4
  BRA  00285_DS
;  .line  775; can.c  PIR2bits.EEIF = 0;        // WRITE step       #12
  BCF  _PIR2bits, 4
;  .line  778; can.c  INTCONbits.INT0IF = 0;
  BCF  _INTCONbits, 1
;  .line  779; can.c  EECON1bits.WR = 0;    //Write Enable löschen 
#13
  BCF  _EECON1bits, 1
  MOVFF  PREINC1, r0x02
  MOVFF  PREINC1, r0x01
  MOVFF  PREINC1, r0x00
  MOVFF  PREINC1, FSR2L
  RETURN

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.