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.