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 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
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.
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.
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!!