Hallo zusammen! Ich habe folgendes Problem: und zwar möchte ich mittels EEPROM daten nach dem ausschalten wieder verwenden können, sollte ja eigentlich kein Problem sein, allerdings sind meine Daten nach den Ausschalten immer weg, schreiben und lesen funktioniert einwandfrei. Ich verwende den PIC16F688, ICD3 In-Circuit-Debugger und Hi-Tech Compiler Hier mal ein einfaches Programm, bei dem das aber auch schon nicht geht. #include <htc.h> #include <stdio.h> #include <EI7C_B.h> enum STATUS{ AN, AUS }; #define ROT RC0 #define GRUEN1 RC1 #define GRUEN2 RC5 void main(void){ OSCCON = 0x71; // 8MHz internal; OSCTUNE= 0x0F; // max. frequency CMCON0 = 0x07; // compare mode disabled ANSEL = 0b00000000; // Port A IOCA = 0x00; // all interrupts on change disabled WPUA = 0x00; // all weak pull ups disabled TRISA = 0xFF; // set all input PORTA = 0x00; // clear Input Register // Port C TRISC = 0b11011100; // RC0, RC1 output, RC2:RC5 input PORTC = 0xFF; // LEDs off //ADC ADCON0 = 0b00011101; //left justified, AN7, enable ADC ADCON1 = 0b01100000; //Fosc/64 INTCON = 0x00; //enable interrupts PIE1 = 0x00; //enable AD interrupt PIR1 = 0x00; //clear ADIF //EEPROM EECON1 = 0x00000100; WREN = 1; //WRITE EEADR = 0x0F0; if(RC3 == 1){EEDAT = 0x01;} EECON2 = 0x55; EECON2 = 0xAA; WR = 1; while(EEIF != 1); //READ RD = 1; #asm NOP NOP #endasm while(RD == 1); EE_DATA = EEDAT; if (EE_DATA == 1){ROT = AN;} //EE_DATA: zwischenspeicher zum speichern des gelesenen EEPROM wertes } Schonmal Danke für dei Hilfe
Hallo Mario, Du beruecksichtigst schon, dass die EEPROM-Daten in Bank 1 liegen? > allerdings sind meine Daten nach den Ausschalten immer > weg, Wie stellst Du das genau fest? Was sagt der Emulator....werden die Daten in den EEPROM-Bereich abgelegt? Was passiert nach Reset im Emulator, sind die EEPROM Daten dort vorhanden? Gruss Michael
Hallo Michael, hier mal ein Stück Code, mit dem es bei mir immer funktioniert: EEADR = 0; //Adresse im EEProm EEDAT = Akku.low8; //Wert, der ins EEProm soll WREN = 1; //EEProm WRite ENable EECON2 = 0x55; //unlock write EECON2 = 0xAA; //unlock write WR = 1; //write while(WR==1); //warten bis WR wieder weg ist WREN = 0; //EEProm Write disable //Korrekturwert aus EEProm lesen EEADR = 0; //EEProm Adresse 0 RD = 1; //lesen Delay1ms(1); //etwas warten Korrektur=EEDAT; //Korrekturwert auslesen hth Frank
Es kann sein, dass dein Compiler deine NOPs wegoptimiert, und du so das Timing nicht einhältst, nur so als Idee. Gruß Jens
Es wäre möglich, dass der Compiler hier eine Bankumschaltung dazwischen einfügt. EECON2 = 0x55; //unlock write EECON2 = 0xAA; //unlock write Dann funktioniert das unlock nicht mehr.
So hab ich das mal bei PIC18 gemacht: //###################################################################### ####### unsigned char WriteEEPROM(unsigned char adr, unsigned char dat) //###################################################################### ####### { EEADR=adr; EEDATA=dat; EECON1bits.EEPGD=0; //Point to Data Memory EECON1bits.CFGS=0; //Access Program Flash or Data EEPROM Nop(); //Sonst Fehler möglich ? EECON1bits.WREN=1; //Enable Writes INTCONbits.GIE=0; //Disable Ints _asm MOVLW 0x55 MOVWF EECON2,0 MOVLW 0xAA MOVWF EECON2,0 _endasm EECON1bits.WR=1; INTCONbits.GIE=1; //Enable Ints //Poll EEIF Flag um zu sehen wann EEPROM Write vorbei ist while(PIR2bits.EEIF==0); PIR2bits.EEIF=0; //Clear EEIF Flag EECON1bits.WREN=0; //Disable Writes }
Und hier noch eine für 16F873 //Schreibt ein Byte ins EEPROM //Beim 16F873 Adressen von 0 bis 127 möglich void Write_EEProm(unsigned char adr, unsigned char data) { RP1=1; RP0=0; //Bank 2 setzen EEDATA = data; // Data in data register EEADR = adr; // Write to adr RP0 = 1; // Bank 3 setzen EEPGD=0; //Daten EEprom (sicherheitshalber falls Bit 1 war) WREN = 1; // Schreiben ermöglichen GIE=0; // Disable interrupts wichtig ! MOVLW(0x55); // Writing 0x55 must be followed MOVWF(EECON2); // immediately by writing 0xAA MOVLW(0xAA); // to EECON2 MOVWF(EECON2); BSF(WR); // EECON1.WR=1 d.h. schreiben des EEPROM starten GIE = 1; // Enable interrupts while(WR); // Warten bis WR auf 0 geht WREN = 0; // Schreibschutz setzen, besser is das RP1=0; RP0=0; //Bank 0 setzen //Ein Verify fehlt hier noch ;) }
Und noch ein ganz altes Teil für 16F84 //Schreibt ein Byte ins EEPROM void Write_EEProm(unsigned char addr, unsigned char data) { WREN = 1; // Schreiben ermöglichen EEDATA = data; // Data in data register EEADR = addr; // Write to addres RP0 = 1; // Set page 1 to access EECON1, EECON2 GIE=0; // Disable interrupts MOVLW(0x55); // Writing 0x55 must be followed MOVWF(EECON2); // immediately by writing 0xAA MOVLW(0xAA); // to EECON2 MOVWF(EECON2); BSF(WR); // EECON1.WR=1 d.h. schreiben des EEPROM starten GIE = 1; // Enable interrupts EEIE=1; //Interrupt bei EEPROM Write Complete RP0 = 0; // Set page 0 //Jetzt entweder länger warten und Verify //oder EEPROM-Interrupt + SLEEP + Verify SLEEP; }
@holger: Die Frage ist, für welchen Compiler die Codes sind, es sieht nach PICC aus. Der PICC braucht im Code keine Bankanweisungen, daran kann es eigentlich nicht liegen.
@holger: siehe 1. Post, HiTech. Der HiTech Compiler bringt doch eine Write und Read Funktion f"ur das interne EEPROM mit, warum nicht die verwenden? Hat bei mir jedenfalls bis jetzt immer problemlos funktioniert... Gruss Martin
>Du beruecksichtigst schon, dass die EEPROM-Daten in Bank 1 liegen? Muss ich das gesondert festlegen? Laut Datenblatt ist der Adressbereich des EEPROMS von 0 bis FF, und mein EEADR ist ja EEADR = 0x0F0; Aus dem Datenblatt "This device has 256 bytes of data EEPROM with an address range from 0h to 0FFh." >> allerdings sind meine Daten nach den Ausschalten immer >> weg, >Wie stellst Du das genau fest? Grundsätzlich lösche ich in dem Programm das EEPROM nie, frage aber die Speicheradresse ab und schalte eine LED an. Dies müsste ja dann direkt nach einem POR auch wieder leuchten. Und wie gesagt, schreiben und lesen funktioniert, da ich meine LED aufgrund der Daten im EEPROM einschalte und sie auch leuchtet. D.h. wenn ich RC3 = 1 habe, wird geschrieben, dann gelesen und die LED geht an. ist beim nächsten Einschalten RC3 = 0, bleibt die LED aber aus, sollte aber an sein, da sich im EEPROM ja nichts geändert hat... Gruß Mario
@Martin: Wie sieht die Read/Write funktion des HiTech Compilers denn aus? Kannte die bisher noch nicht
Die funktioniert einwandfrei. Dazu muss man dem Compiler aber die CPU mitteilen und auch die entsprechende Headerdatei einbinden, ohne die funktioniert es auch nicht. Müsste <pic.h> sein.
und wie rufe ich die auf und was für parameter hat die?
Da liegt so ein komisches .pdf im Ordner des installierten Compilers... dürfte sich "manual" nennen. ;) -> #include <htc.h> void eetest(void) { unsigned char value = 1; unsigned char address = 0; // write value to EEPROM address eeprom_write(address, value); // read from EEPROM at address value = eeprom_read(address); } These functions test and wait for any concurrent writes to EEPROM to conclude before performing the required operation. The eeprom_write() function will initiate the process of writing to EEPROM and this process will not have completed by the time that eeprom_write() returns. The new data written to EEPROM will become valid approximately four milliseconds later. In the above example, the new value will not yet be ready at the time when eeprom_read() is called; however, because this function waits for any concurrent writes to complete before initiating the read, the correct value will be read. It may also be convenient to use the preprocessor symbol, _EEPROMSIZE, in conjunction with some of these access methods. This symbol defines the number of EEPROM bytes available for the selected chip.
Es gibt auch noch die Macros, EEPROM_WRITE() usw. Sinnvoll wenn man nicht einen Stack verbrauchen will/kann.
Alles klar, danke, werde mir diese komische "Manual" mal anschauen :) Bei allen hilfreichen Tipps und kommentaren, das eigentliche Problem, dass der PIC nach ausschalten die Daten auf dem EEPROM nicht speichert besteht leider immer noch.... Irgendwelche Ideen hierzu? Gruß Mario
Irgendwie kommt mir das komisch vor. Du Stellst deine ADC-Kofig ein, OSC, TRIS-Register und so weiter. Aber das erste, was du mit dem EEPROM machst, ist es zu beschreiben. Wenn du den PIC startest und RC3 ist auf low, schreibt er eine 0 ins EEPROM und danach ließt du die 0 wieder aus und die LED leutet folglich nicht. Du musst nach der Konfig erstmal den Wert lesen, wenn der 1 ist, die LED anschalten und dann leutet diese auch. Dann darfst du danach nicht aber gleich wieder die EEPROM-Adresse mit der 0 überschreiben, wenn dein RC3 auf 0 ist. Also lesen, LED ggf. setzen und dann hätte ich ein Polling gemacht. Eine Taste setzt den Wert im EEPROM und eine andere Taste löscht den Wert. Dann sollte es eigentlich funktionieren Mario schrieb: > dass der PIC nach ausschalten die Daten auf dem EEPROM nicht speichert > besteht leider immer noch Ich weiß wie du das meinst, aber korrekt ist es, dass man wärend dem Durchlauf speichert, er die Daten aber auch ohne Strom halten kann. Speichern tut er nicht, wenn er aus is, das passiert vorher. edit: Ganz abgesehen davon gehört ansich in jedes C-Programm für µCs eine Endlosschleife, meist nach der Konfiguration. Bei deinem Programm ist es im Moment so, dass, wenn deine Konfig abgeschlossen ist und du den Wert ins EEPROM schreibst und danach wieder liest, ist das Programm vorbei. ggf startet der PIC dann wieder neu, schreibt wieder die Konfig usw.. Mein Plan wäre so: main(){ //Initialisierung //EEPROM-Wert lesen, evtl LED an while(1){ //RC3 gedrückt? Wenn ja, 1 ins EEPROM speichern //RC4 gedrückt? Wenn ja, 0 ins EEPROM speichern //EEPROM lesen, LED an- bzw. ausschalten } }
Ich kenn mir ehrlich gesagt nicht so mit dem Hi-Tech-Compiler aus, aber ich dachte immer, das der halt C übersetzt. Und in C muss man doch eigentlich Variablen inklusive Datentyp definieren, oder? Woher weiß der Compiler, dass EE_DATA eine Variable ist, und welchen Typ er besitzt, also char oder int z.B. . Und woher weiß der Compiler, dass der bei "ROT = AN", die LED anschalten soll? RC0 ist ja als ROT definiert, aber woher weiß er, dass AN "1" bedeutet? Wie gesagt, vielleicht ist das da ja eine Eigenheit, aber kommt mir irgendwie komisch vor.
@Michael: Die Init stammt aus dem eigentlichen Programm, dieses hier ist nur ein EEPROM Testprogramm, daher ADC und sonstige Inits. Und mit der Schleife hast du natürlich recht, die ist wohl irgendwo untergegangen. Die EE_DATA ist in der Header als unsigned char definiert, damit man auch einzelne Bits mit einem Namen komfortabel ansprechen kann, ähnlich wie die SFR des Controllers. Und was AN ist weiß der Compiler aus dem enum STATUS{ AN, AUS }; in den ersten zeilen des Quelltextes. (Und bevor Fragen aufkommen, meine LEDs gehen an, wenn der Port = 0 ist) Ich befürchte eher, dass die Daten auf dem EEPROM aufgrund irgendwelcher Einstellungen nicht gespeichert werden/verloren gehen, nicht wegen des Quelltextes. Wenn jemand noch eine Idee hat, freue ich mich, sonst wende ich mich mal direkt an Microchip. Gruß Mario
Mario schrieb: > Ich befürchte eher, dass die Daten auf dem EEPROM aufgrund irgendwelcher > Einstellungen nicht gespeichert werden/verloren gehen, nicht wegen des > Quelltextes. Ich denke eher es liegt am Aufbau vom Programm: Michael Skropski schrieb: > Aber das erste, was du mit dem EEPROM > machst, ist es zu beschreiben. Wenn du den PIC startest und RC3 ist auf > low, schreibt er eine 0 ins EEPROM und danach ließt du die 0 wieder aus > und die LED leutet folglich nicht. > > Du musst nach der Konfig erstmal den Wert lesen, wenn der 1 ist, die LED > anschalten und dann leutet diese auch. Dann darfst du danach nicht aber > gleich wieder die EEPROM-Adresse mit der 0 überschreiben, wenn dein RC3 > auf 0 ist. > > Also lesen, LED ggf. setzen und dann hätte ich ein Polling gemacht. Eine > Taste setzt den Wert im EEPROM und eine andere Taste löscht den Wert. > Dann sollte es eigentlich funktionieren Ob dein Ausgang die LED bei 0 oder 1 anschaltet ist ja egal. Fakt ist, du schreibst die EEPROM-Zelle, bevor du sie ausliest. Das ist auch nach dem Starten des PICs so. D.h. bevor du die Chance hast, den gespeicherten Wert auszulesen, überschreibst du ihn schon wieder.
Achso, jetzt versteh ich! Is ja logisch. Aber draufgekommen wär ich net... Also das Programm geht dann natürlich auch!! Super, vielen Dank, war schon ganz kurz vorm verzweifeln!!
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.