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.