Skriva/Läsa EEPROM för en PIC16F690

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Magnus_K »

Jag har tänkt att skriva och läsa ett par byte till det inbyggda EEPROM:et som finns i PIC16F690(datablad)

Hittills har jag bara gjort en sammanställning på allt som behöver ställas rätt men det är en sak jag inte blir klok på:
I urklippet från databladet så skriver dom på ett ställe "The write will not initiate if the specific sequence is not followed exactly (write 55h to EECON2, write AAh to EECON2, then set WR bit) for each byte."

Hur gör man då med det här om jag två bytes som ska skrivas? Väntar jag till WR-biten nollas, alt EEIF-flaggan sätts och sen skriver jag ny adress + data samt det där jag citerade?

Vore hemskt tacksam om någon har lust att hjälpa mig lite på traven med "flödet" när man skriver mer är en byte till EEPROM.

Kod: Markera allt

// SAVE EEPROM DATA:
           // EECON1.WREN = 1                - ENABLE WRITES TO EEPROM
           // WRITE ADDRESS TO EEADR
           // WRITE DATA TO EEDAT
           // DISABLE INTERRUPTS             - TO NOT DISTURB THE WRITE SEQ
           // WRITE 55h TO EECON2  \
           // WRITE AAh TO EECON2   |->      - DO THIS FOR EACH BYTE
           // SET WR_BIT           /
           // EECON1.WREN = 0;               - DISABLE WRITES TO EEPROM
           // EEIF = 0                       - CLEAR WRITE FLAG
write_to_eeprom.JPG
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
SeniorLemuren
Inlägg: 8426
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av SeniorLemuren »

Använder du inte mikroC? Där finns en färdig lib för läsning och skrivning.
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Icecap »

Liksom det gör med XC8...

Men ja, är det fler bytes som ska skrivas skriver man ett åt gången, räknar adress osv. Jag använder den funktion väldigt mycket oavsett om det är PIC/FFMC-16LX/RX210/whatever µC jag använder, en av basfunktionerna är att kunde skriva/läsa ett block till/från EEPROM. Det använder jag sedan till att spara/ladda inställninger eller data ifrån.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Magnus_K »

Jo precis, brukar använda dom färdiga biblioteken men den här gången till jag vara säker på att det inte är med en massa extra lull-lull i funktionen.

Det vore också nyttigt att kunna skriva och läsa till det interna minnet utan en färdig funktion.

Kan jag skriva ny adress och data medans den första datan skrivs eller måste jag vänta på flagga innan jag rör dom registren?
Tänkte om det kanske fungerar som lite andra funktioner att det flyttar över till en buffer eller så.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av sodjan »

En skrivning i taget. Du får vänta på WR=0 efter varje skrivning.
Eller att WR=0 före varje skrivning, så hinner du kanske med
lite annat mellan skrivningarna.

> ...utan en färdig funktion.

Du kan ju skriva en egen "färdig funktion".
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Magnus_K »

Perfekt, tack!

Är det här ett vettigt sätt att splitta en två-bytes-variabel till två enskilda en-bytes-variablar? (Kära nån vilken konstig mening men ni förstår nog)

Kod: Markera allt

     unsigned char byteONE = 0;
     unsigned char byteTWO = 0;
     unsigned int DATA = 0;
     
     DATA = analogCounter;               // Max value of analogCounter = 720
     DATA >> 8;
     byteONE |= DATA;

     DATA = analogCounter;
     DATA &= 0xFF;
     byteTWO |= DATA;
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Icecap »

Nej, det är inte ett vettigt sätt.

unsigned char *Ptr;

Ptr = (unsigned char*)&analogCounter;

Nu är *Ptr lika med första byten, *(Ptr + 1) lika med andra byten osv. Detta är orsaken till att jag alltid gör en funktion där jag kan spara valfritt antal bytes.

Lite pseudokod:

Kod: Markera allt

void EEPROM_Save_Block(unsigned char* Source, unsigned short Address, unsigned short Bytes)
  {
  while(Bytes)
    {
    while(Not_Possible_To_Write_to_EEPROM); // Wait for it!
    Write_Byte_To_EEPROM(*Source, Address);
    Source++; // Point on next byte to save
    Address++; // Increment address
    Bytes--; // Decrement count
    }
  }
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av lillahuset »

Lyssna på Icecap. Han har helt rätt.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Magnus_K »

Jo jag lyssnar på Icecap, men ibland blir det lite mycket att ta in och har inte ork att sätta mig in i något nytt, som tex pointers i det här fallet.
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Icecap »

Vad menar du "sätta dig in i"?
unsigned char byteONE;
unsigned char byteTWO;
unsigned int DATA;
// Det finns ingen anledning att initiera dessa värden då de jo ändå ska skakas fram.

byteONE = (unsigned char*)&DATA;
byteTWO = (unsigned char*)(&DATA + 1);

Eller bättre om det bara är två bytes:

Kod: Markera allt

union
  {
  unsigned int DATA;
  unsigned char Bytes[2];
  } Value;
Value.DATA = någonting;
Value.Bytes[0] // = Första byte
Value.Bytes[1] // = Andra byte

EDIT: Lite klipp från mitt PIC-lib:

Kod: Markera allt

void Save_To_EEPROM(unsigned char* Source, unsigned char Address, unsigned char Bytes)
  {
  while(Bytes)
    {
    PIR2.EEIF    = false;       // Clear the flag, just in case, one never know
    FSR0         = (int)&Saved; // Point on correct memory position
    EEADR       = Address; 
    EEDATA       = *Source;     // Data to save
    EECON1.EEPGD = false;     // Point on EEPROM data
    EECON1.WREN  = true;      // Enable writes
    INTCON.GIE   = false;     // Kill interrupts!
    EECON2       = 0x55;      // Required sequence
    EECON2       = 0xAA;      // Required sequence
    EECON1.WR    = true;      // Activate the write
    INTCON.GIE   = true;      // Allow interrupts!
    while(!PIR2.EEIF);        // Wait for it to do the write
    PIR2.EEIF    = false;     // Clear the flag
    Address++;
    Source++;
    Bytes--;
    }
  }


void Read_From_EEPROM(unsigned char* Destination, unsigned char Address, unsigned char Bytes)
  {
  while(Bytes)
    {
    EEADR = Address;
    EECON1.EEPGD = false;  // Point on EEPROM data
    EECON1.RD    = true;   // Do the read
    *Destination     = EEDATA; // Read data
    Destination++;                // Next position please
    Address++;
    Bytes--;    
    }
  }
Sådär, serverat på ett silverfat. Kan möjligen behövas justeras en aning beroende på vilken PIC men det är grunden i vilket fall som helst.

Vill du spara DATA gör du: Save_To_EEPROM(&Data, 0, sizeof(DATA));
Vill du läsa den sparade DATA gör du: Read_From_EEPROM(&Data, 0, sizeof(DATA));
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Magnus_K »

Nu är jag tillbaka här och kanske inte helt oväntat så stöter jag på patrull även här...
Efter lite felsökning så har jag kommit fram till att en byte skrivs (eller läses) aldrig.

Om timeCounter är 850 decimalt, dvs 0000 0011 0101 0010 och jag gör nedan skrivning och sedan läsning så är timecounter 82 decimalt och 0000 0000 0101 0010 binärt.

Är det någon som ser vart skriv/läs-felet ligger?

Kod: Markera allt

void writeEEPROM(void){

     unsigned short byteONE = 0;
     unsigned short byteTWO = 0;
     unsigned int SAVE_DATA = 0;

     SAVE_DATA = timeCounter;                 // Change back to analogCounter. Max value of analogCounter = 720
     SAVE_DATA >> 8;
     byteONE |= SAVE_DATA;
     
     SAVE_DATA = timeCounter;
     SAVE_DATA &= 0xFF;
     byteTWO |= SAVE_DATA;
     
     EEADR = 0x00;                          // WRITE ADDRESS TO EEADR
     EEDAT = byteONE;                       // WRITE DATA TO EEDAT
     EECON1.WREN = 1;                       // ENABLE WRITES TO EEPROM
     INTCON.GIE = 0;                        // DISABLE INTERRUPTS DURING INIT SEQ
     EECON2 = 0x55;                         // WRITE 55h TO EECON2   |
     EECON2 = 0xAA;                         // WRITE AAh TO EECON2   |-> - DO THIS FOR EACH BYTE
     EECON1.WR = 1;                         // SET WR_BIT            |
     INTCON.GIE = 1;                        // RE-ENABLE INTERRUPTS
     while(EECON1.WR){}                     // WAIT FOR WRITE TO COMPLETE
     EEADR = 0x01;                          // WRITE ADDRESS TO EEADR
     EEDAT = byteTWO;                       // WRITE DATA TO EEDAT
     INTCON.GIE = 0;                        // DISABLE INTERRUPTS DURING INIT SEQ
     EECON2 = 0x55;                         // WRITE 55h TO EECON2   |
     EECON2 = 0xAA;                         // WRITE AAh TO EECON2   |-> - DO THIS FOR EACH BYTE
     EECON1.WR = 1;                         // SET WR_BIT            |
     INTCON.GIE = 1;                        // RE-ENABLE INTERRUPTS
     while(EECON1.WR){}                     // WAIT FOR WRITE TO COMPLETE
     EECON1.WREN = 0;                       // DISABLE WRITES TO EEPROM
     PIR2.EEIF = 0;                         // CLEAR WRITE FLAG

}

void readEEPROM(void){
     
     EEADR = 0x00;                          // WRITE ADDRESS TO EEADR
     EECON1.EEPGD = 0;
     EECON1.RD = 1;                         // EEDAT NOW HOLDS THE BYTE
     timeCounter = EEDAT;
     timeCounter << 8;
     EEADR = 0x01;                          // WRITE ADDRESS TO EEADR
     EECON1.EEPGD = 0;
     EECON1.RD = 1;                         // EEDAT NOW HOLDS THE BYTE
     timeCounter |= EEDAT;

}
janno
Inlägg: 434
Blev medlem: 11 oktober 2009, 07:34:45
Ort: Västerås

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av janno »

Jag skulle gissa på rad 8. Var tänkte du att resultatet från shiftningen hamnar?

/J
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Magnus_K »

Hmm, det jag tänkt är att om 0000 0011 0101 0010 skiftas ner 8 ggr så är det nya värdet på SAVE_DATA 0000 0000 0000 0011, men där kanske jag har fel alltså?
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av Icecap »

Med den rutin jag gav dig (välfungerande och testat) skulle du skriva:
Save_To_EEPROM(&TimeCounter, 0, sizeof(TimeCounter));
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Skriva/Läsa EEPROM för en PIC16F690

Inlägg av sodjan »

> SAVE_DATA >> 8;

Ska det inte vara

> SAVE_DATA = SAVE_DATA >> 8;

??
Skriv svar