View Single Post
  Spotlight this post!  
Unread 13-01-2004, 02:14
WizardOfAz's Avatar
WizardOfAz WizardOfAz is offline
Lead Mentor
AKA: Bill Bennett
FRC #1011 (CRUSH)
Team Role: Engineer
 
Join Date: Mar 2003
Rookie Year: 2002
Location: Tucson, AZ
Posts: 101
WizardOfAz will become famous soon enough
Send a message via AIM to WizardOfAz
Re: read/write EEPROM on 18F8520

What we're using the EEPROM for is to store calibration data for steering sensors. If we do any adjustment on the wheel mechanism, the alignment of the wheel to the sensor can change, and I want a way to collect and save away the sensor angle offset from the wheel angle without requiring a programmer's help to modify the constants in the code and recompile/reload it.

I've got this code working now as far as I can tell. Here it is for anybody interested. I'm wide open to feedback if anybody finds a problem with it or wants to suggest an improvement.

readEE returns the result immediately, since there is no required delay for reading. But you can't change the ee address register while a write is in progress, so readEE returns 0 if a write is in progress. This doesn't help of course, you really need to just make sure you don't do this.

writeEE puts the byte to be written on a 16 byte queue in ram, then calls processEEQueue which starts the EE write sequence. If you then call writeEE more times without some delay, the byes get added to the queue but processEEQueue does not write them since the first one is not finished writing. You have to call processEEQueue again later, multiple times with some delay between to get them all written. It doesn't hurt to call processEEQueue too much, it returns quickly if the queue is empty. What I did it call processEEQueue every time around in the main loop.

(sorry for the lack of indentation - the cut/paste into the forum threw them away)

file eeprom.h
------------
#ifndef _eeprom_h
#define _eeprom_h
#include "ifi_picdefs.h"
unsigned char readEE(unsigned short address);
void writeEE(unsigned short address, unsigned char data);
void processEEQueue(void);
#endif

file eeprom.c
------------
#include <string.h>
#include "eeprom.h"

/************************************************** ******************************/
/* read and write eeprom */
/* basic code donated by "random dude" and obtained from chiefdelphi forums */
/* queing mechanism added by bill */
/************************************************** ******************************/
typedef struct {
unsigned writeInProgress:1;
unsigned bufferNotEmpty:1;
unsigned bufferFull:1;
unsigned :4;
unsigned bufferPtr:4;
unsigned bufferEnd:4;
unsigned char dataBuffer[16];
unsigned short addressBuffer[16];
} eeControlStruct;
static eeControlStruct eeControl = {0,0,0,0,0,0,}; // initialize control bits and pointers to false

unsigned char readEE(unsigned short address) {

// should not change EEADR/EEADRH while a write is happening
if(eeControl.writeInProgress) return 0;

// Load address into address register
EEADRH = (unsigned char)(address>>8);
EEADR = (unsigned char)(address&0xFF);

//Configuration as per manual
EECON1bits.EEPGD =0;
EECON1bits.CFGS =0;
EECON1bits.RD =1;
return EEDATA;
}

void writeEE(unsigned short address, unsigned char data)
{
if(eeControl.bufferFull) return;
eeControl.dataBuffer[eeControl.bufferEnd] = data;
eeControl.addressBuffer[eeControl.bufferEnd++] = address;
eeControl.bufferFull = (eeControl.bufferEnd==eeControl.bufferPtr);
eeControl.bufferNotEmpty = 1;
processEEQueue();
}

// call this once each main loop, or more often, to process the queue
// of bytes to be written to eeprom. Note that there is no buffer
// overrun detection. Enlarge the buffer and change the size of bufferPtr
// and bufferEnd if you need more buffer space to avoid overrun.
void processEEQueue(void) {

if(eeControl.writeInProgress && !PIR2bits.EEIF) return; // previous write not complete
PIR2bits.EEIF = 0; // reset EE write done interrupt flag
if(!eeControl.bufferNotEmpty) {
eeControl.writeInProgress = 0;
return;
}

// OK, previous write is done and something is in the buffer, write it
eeControl.writeInProgress = 1;

// Load address into address register
EEADR = (unsigned char)(eeControl.addressBuffer[eeControl.bufferPtr]&0xff);
EEADRH = (unsigned char)(eeControl.addressBuffer[eeControl.bufferPtr]>>8);
EEDATA = eeControl.dataBuffer[eeControl.bufferPtr++];
eeControl.bufferNotEmpty = (eeControl.bufferPtr != eeControl.bufferEnd);

// with a little more work, we could check for error on previous write and redo it

// write sequence as per manual
EECON1bits.EEPGD =0;
EECON1bits.CFGS =0;
EECON1bits.WREN =1;
INTCONbits.GIE = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1;
INTCONbits.GIE = 1;
EECON1bits.WREN = 0;
}