I am trying to write the routine to store the char, int, float datas in the serial eeprom 24FC512 and read back the written values using random read method.
My problem is sometimes only the data is written properly and read back corretly.
I dont know what is the reason behind the wrong writing and reading.
But my I2C_Read, I2C_Write, I2C_Start,I2C_Stop works well with my RTC DS1307.
Idont know why the problem is coming with EEPROM?
Can anybody give me a suggestion?
"I will put my coding can anybody say is it correct or not?"
Do you honestly expect anyone to read through that mess? You've made no attempy to lay it out legibly, and there's no comments at all.
Your first step must be to lay it out logically, and comment it. This exercise alone may well lead you to spot your error!
For instructions on how to post code and preserve the layout, see: http://www.keil.com/forum/tips.asp
Don't use TABs to lay out your code; use only spaces!
I am very sorry to put a messy code like that here i do it correctly.
sbit SCLK = P1^1; sbit SDA = P1^2;
void I2C_Start(void) { SCLK = 0; SDA=HIGH; Delay(15); //This is a random delay SCLK =HIGH; Delay(15); SDA = LOW; Delay(15); SCLK = LOW; }
void I2C_Stop(void) { SCLK = 0; SCLK=LOW; Delay(15); SDA=LOW; Delay(15); SCLK=HIGH; Delay(15); SDA=HIGH; }
void I2C_Write(unsigned char j) { for(i=0;i<8;i++) { SDA = ((j & 0x80) ? 1 : 0); //bit by bit SCLK = HIGH; LongDelay(18); //exactly 5.12ms delay SCLK = LOW; j<<=1; } SDA=HIGH; Delay(15); SDA = LOW; SCLK = HIGH; Delay(15); SCLK = LOW; Delay(15); }
unsigned char I2C_Read(void) { unsigned char i,j; SDA= HIGH; i = SDA; j = 0; for(i=0;i<8;i++) { SCLK = HIGH; Delay(50); j<<=1; j |= SDA; SCLK = LOW; } Delay(15); SDA = LOW; Delay(15); SCLK = HIGH; Delay(15); SCLK = LOW; Delay(15); SDA = HIGH; Delay(15); return j; }
This routine is common for both RTC and EEPROM. But my RTC is working well & EEPROM is having problem. My EEPROM coding is, #define EEPROM_WR 0xA2 #define EEPROM_RD 0xA3 unsigned int ptr; unsigned char buf[20];
void EEPROM_Location(unsigned int x) { ptr = x; }
void EEPROM_WrByte(unsigned char x) { I2C_Start(); I2C_Write(EEPROM_WR); I2C_Write((char)(ptr>>8)); I2C_Write((char)ptr); I2C_Write(x); I2C_Stop(); ptr++; Delay(500); return; }
void EEPROM_WrInt(unsigned int x) { I2C_Start(); I2C_Write(EEPROM_WR); I2C_Write((char)(ptr>>8)); I2C_Write((char)ptr); I2C_Write((unsigned char)(x>>8)); I2C_Write((unsigned char)(x)); I2C_Stop(); ptr+=2; Delay(500); return; }
unsigned char EEPROM_RdByte(void) { unsigned char x; I2C_Start(); I2C_Write(EEPROM_WR); I2C_Write((char)(ptr>>8)); I2C_Write((char)ptr); I2C_Stop(); I2C_Start(); I2C_Write(EEPROM_RD); LongDelay(18); x = I2C_Read(); I2C_Stop(); ptr++; return(x); }
unsigned int EEPROM_RdInt(void) { unsigned int x; I2C_Start(); I2C_Write(EEPROM_WR); I2C_Write((char)(ptr>>8)); I2C_Write((char)ptr); I2C_Stop(); I2C_Start(); I2C_Write(EEPROM_RD); x = I2C_Read(); x<<=8; x+=I2C_Read(); I2C_Stop(); ptr+=2; return(x); }
In my main() program i have palced the below code,
main() { EPROM_Location(0x0000); EEPROM_WrByte(0x21); LongDelay(5); EEPROM_Location(0x0001); EEPROM_WrByte(0x68); LongDelay(5); EEPROM_Location(0x0002); EEPROM_WrInt(0x1EDF); LongDelay(5); EEPROM_Location(0x0004); EEPROM_WrInt(0x1122); LongDelay(5); while(1) { EEPROM_Location(0x0000); x1 = EEPROM_RdByte(); SBUF=' '; printf("\n\n x1 byte is %bx",x1); TI = 0; Delay(50); EEPROM_Location(0x0002); x3 = EEPROM_RdInt(); SBUF = ' '; printf("\n\n x3 int is %x",x3); TI = 0; EEPROM_Location(0x0001); x2 = EEPROM_RdByte(); SBUF = ' '; printf("\n\n x2 byte is %bx",x2); TI = 0; EEPROM_Location(0x0004); x4 = EEPROM_RdInt(); SBUF = ' '; printf("\n\n x4 int is %x",x4); TI = 0; } }
The output in the hyper terminal is something like below. x1 byte is 21
x3 int is ffff
x2 byte is 68
x4 int is ffff
x1 byte is 21
Here the LongDelay(18); is exactly 5.12ms delay.
Can anybody please guide me in this programming? I am not sure where did go wrong. Please help regarding this problem
I think your problem lies in the read function you should not send stop before sending repeat start it should look like this.
unsigned int EEPROM_RdInt(void) { unsigned int x; I2C_Start(); I2C_Write(EEPROM_WR); I2C_Write((char)(ptr>>8)); I2C_Write((char)ptr); I2C_Stop(); (delete this line) I2C_Start(); I2C_Write(EEPROM_RD); x = I2C_Read(); do something here.... .... return(x); } Hope this helps. T.L
Thank you very much.
I can read int and byte value.
Anybody have idea of how to write and read the long int and float?
Any suggestion please.
Don't bother with separate functions for byte, int, long, etc.
As far as the memory is concerned, it's all just a matter of reading and writing bytes - the memory neither knows nor cares whether a particular byte actually represents a 'char', or half an 'int', or whatever!
Just write yourself two generic functions which take arguments telling them where to start, and how many bytes to transfer. Your prototypes would look something like:
// Write data to EEPROM: // source_address - start address of the data to be written; // ee_destination - starting location in the EEPROM for writing // number_of_bytes - number of bytes to be written // Return value: code indicating success/fail? char write_ee( void * source_address, unsigned int ee_destination, unsigned char number_of_bytes ); // Read data from EEPROM: // destination_address - start address for the data read from the EEPROM; // ee_source - starting location in the EEPROM for reading; // number_of_bytes - number of bytes to be read // Return value: code indicating success/fail? char read_ee( void * destination_address, unsigned int ee_source, unsigned char number_of_bytes );
You may want to adjust the data types to suit your specific requirements. Note that void* means "a pointer to anything"; use the sizeof operator to find the numbre of bytes for a particular data type - see your 'C' textbook for further details.
I did it.