Thursday, October 7, 2010

EEPROM Read Write with PIC24F & 24LC512



/*********************************************************************
Description : This article explains how to integrate EEPROM with a micro controller. It should be smooth when PLL is disabled.
But PLL has to be enabled some of the applications such as USB to meet the specified clock frequecy (48 MHz) in this case.
So, the system clock would be 32MHz(Please refer microchip's PIC24F datasheet for more details). Handling EEPROM Read & Write
functions when PLL enabled is not as straight as when disabled. Configuring the baud rate (clock cycle for EEPROM R/W) will be
bit confusing in this case. PIC24F datasheet says baud rate value can not be less than 2(Again, please refer the PIC24F datasheet
for the equation). But it works for the value 1 when PLL enabled. Though it works for the value 1, EEPROM communication breaks rarely.

This rare communication problem can be fixed by decreasing the system clock frequency somewhere to 16MHz (CPDIV=0x0004, 32MHz/2 = 16MHz).
Baud rate value calculated for this speed is equal to 4 (for 100KHz). Following circuit and code combination works perfect.

This EEPROM works for clock frequencies from 100KHz and up to 400KHz.


Hardware : Micro Controller - PIC24F series, EEPROM - 24LC512, 8MHz Crystal, Communication : I2C bus (recommended if both controller & EEPROM
on same PCB, SPI is good for longer tracks/cables)
Software : MPLAB C30 Compiler
*********************************************************************/


Schematic



 





 



 



void InitI2C2(void)
{
unsigned int config1 = 0;
unsigned int config2 = 0;

CloseI2C2();
Delay10ms(10);
ConfigIntI2C2(MI2C_INT_OFF); //Disable I2C interrupt
Delay10ms(10);

config1 = (I2C_ON | I2C_7BIT_ADD );
config2 = 4; // baud rate 100KHz
OpenI2C2(config1,config2); //configure I2C2
Delay10ms(10);
}
void EEPROMWriteByte(unsigned long int address, BYTE data)
{
// START
IdleI2C2();
StartI2C2();
while(I2C2CONbits.SEN ); //Wait till Start sequence is completed
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag

// Control Byte
MasterWriteI2C2(0xA0); //Write Slave address and set master for transmission
while(I2C2STATbits.TBF); //Wait till address is transmitted
while(!IFS3bits.MI2C2IF); //Wait for ninth clock cycle
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
while(I2C2STATbits.ACKSTAT);

// Address MSB
MasterWriteI2C2((address >> 8) & 0x00ff);
while(I2C2STATbits.TBF); //Wait till address is transmitted
while(!IFS3bits.MI2C2IF); //Wait for ninth clock cycle
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
while(I2C2STATbits.ACKSTAT);

// Address LSB
MasterWriteI2C2(address & 0x00ff);
while(I2C2STATbits.TBF); //Wait till address is transmitted
while(!IFS3bits.MI2C2IF); //Wait for ninth clock cycle
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
while(I2C2STATbits.ACKSTAT);

// data byte
MasterWriteI2C2(data);
while(I2C2STATbits.TBF); //Wait till address is transmitted
while(!IFS3bits.MI2C2IF); //Wait for ninth clock cycle
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
while(I2C2STATbits.ACKSTAT);

// STOP
StopI2C2();

// make sure write cycle is complete by polling acknowledgement from slave
do
{
// start
IdleI2C2();
StartI2C2();
while(I2C2CONbits.SEN ); //Wait till Start sequence is completed
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag

// Control Byte
MasterWriteI2C2(0xA0); //Write Slave address and set master for transmission
while(I2C2STATbits.TBF); //Wait till address is transmitted
while(!IFS3bits.MI2C2IF); //Wait for ninth clock cycle
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
}while(I2C2STATbits.ACKSTAT);
}

void EEPROMRead(unsigned long int address,int length,BYTE* pData)
{
int i;

// START
IdleI2C2();
StartI2C2();
while(I2C2CONbits.SEN ); //Wait till Start sequence is completed
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag

// Control Byte
MasterWriteI2C2(0xA0); //Write Slave address and set master for transmission
while(I2C2STATbits.TBF); //Wait till address is transmitted
while(!IFS3bits.MI2C2IF); //Wait for ninth clock cycle
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
while(I2C2STATbits.ACKSTAT);

// Address MSB
MasterWriteI2C2((address >> 8) & 0x00ff);
while(I2C2STATbits.TBF); //Wait till address is transmitted
while(!IFS3bits.MI2C2IF); //Wait for ninth clock cycle
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
while(I2C2STATbits.ACKSTAT);

// Address LSB
MasterWriteI2C2(address & 0x00ff);
while(I2C2STATbits.TBF); //Wait till address is transmitted
while(!IFS3bits.MI2C2IF); //Wait for ninth clock cycle
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
while(I2C2STATbits.ACKSTAT);

// START for reading
IdleI2C2();
RestartI2C2();
while(I2C2CONbits.SEN ); //Wait till Start sequence is completed
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag

// Control Byte
MasterWriteI2C2(0xA1); //Write Slave address and set master for transmission
while(I2C2STATbits.TBF); //Wait till address is transmitted
while(!IFS3bits.MI2C2IF); //Wait for ninth clock cycle
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
while(I2C2STATbits.ACKSTAT);

*(pData + 0) = MasterReadI2C2(); // read first byte
for(i = 1;i < length;i++) // read further bytes if requested
{
AckI2C2();
MI2C2_Clear_Intr_Status_Bit; //Clear interrupt flag
while(I2C2STATbits.ACKSTAT);
*(pData + i) = MasterReadI2C2();
}
NotAckI2C2();
StopI2C2();
}

No comments:

Post a Comment