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 }
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
Hast du das EEPROM evtl. im Configurationword schreibgeschützt?
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 }
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
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.
Was heißt das konkret für mich als Leihe? Hab das schon mal versucht, bekam es leider nicht hin.
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"
>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.
Mein Beispiel läuft mit SDCC und auch mit MCC18 von Microchip.
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)
>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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.