immortal13
New Member
Hello!
I need help with I2C Master.
I want to write/read bytes to/from 24LC64 EEPROM. Frequency of I2C module is 100 kHz, pull-up resistors are 4k7 Ohm.
Oscillator frequency Fosc = 48 MHz.
The code is taken from MPLAB C18 files, but I send 2 bytes with address instead of 1 byte as in MPLAB C18's program.
And function EEByteWrite returns a write collision error.
EERandomRead function returns a value 0xFF.
Few times ago, I tryed to leave 1-byte sending to EEPROM. EERandomRead function returned 0xFF value, EEByteWrite didn't return any errors, but I didn't know, if it worked.
Thanks in advance,
Vyacheslav.
I need help with I2C Master.
I want to write/read bytes to/from 24LC64 EEPROM. Frequency of I2C module is 100 kHz, pull-up resistors are 4k7 Ohm.
Oscillator frequency Fosc = 48 MHz.
The code is taken from MPLAB C18 files, but I send 2 bytes with address instead of 1 byte as in MPLAB C18's program.
And function EEByteWrite returns a write collision error.
EERandomRead function returns a value 0xFF.
Few times ago, I tryed to leave 1-byte sending to EEPROM. EERandomRead function returned 0xFF value, EEByteWrite didn't return any errors, but I didn't know, if it worked.
Code:
#define MASTER 0b1000
#define SLEW_OFF 0
#define SSPENB 0b00100000
void OpenI2C1( unsigned char sync_mode, unsigned char slew )
{
SSPSTAT &= 0x3F; // power on state
SSPCON1 = 0x00; // power on state
SSPCON2 = 0x00; // power on state
SSPCON1 |= sync_mode; // select serial mode
SSPSTAT |= slew; // slew rate on/off
SSPADD = 0x77;
TRISBbits.TRISB4 = 1;
TRISBbits.TRISB6 = 1;
SSPCON1 |= SSPENB; // enable synchronous serial port
}
void AckI2C1(void)
{
SSPCON2bits.ACKDT = 0; // set acknowledge bit state for ACK
SSPCON2bits.ACKEN = 1; // initiate bus acknowledge sequence
}
void CloseI2C1( void )
{
TRISBbits.TRISB4 = 0;
TRISBbits.TRISB6 = 0;
SSPCON1 = 0; // disable synchronous serial port
}
unsigned char DataRdyI2C1( void )
{
if ( SSPSTATbits.BF ) // test if buffer full bit is set
return ( +1 ); // data in SSPBUF register
else
return ( 0 ); // no data in SSPBUF register
}
unsigned char ReadI2C1( void )
{
if( ((SSPCON1&0x0F)==0x08) || ((SSPCON1&0x0F)==0x0B) ) //master mode only
SSPCON2bits.RCEN = 1; // enable master for 1 byte reception
while ( !SSPSTATbits.BF ); // wait until byte received
return ( SSPBUF ); // return with read byte
}
void IdleI2C1( void )
{
while ( ( SSPCON2 & 0x1F ) || ( SSPSTATbits.R_W ) )
continue;
}
void NotAckI2C1( void )
{
SSPCON2bits.ACKDT = 1; // set acknowledge bit for not ACK
SSPCON2bits.ACKEN = 1; // initiate bus acknowledge sequence
}
void RestartI2C1( void )
{
SSPCON2bits.RSEN = 1; // initiate bus restart condition
}
void StopI2C1( void )
{
SSPCON2bits.PEN = 1; // initiate bus stop condition
}
void StartI2C1( void )
{
SSPCON2bits.SEN = 1; // initiate bus start condition
}
unsigned char WriteI2C( unsigned char data_out )
{
SSPBUF = data_out; // write single byte to SSPBUF
if ( SSPCON1bits.WCOL ) // test if write collision occurred
return ( -1 ); // if WCOL bit is set return negative #
else
{
if( ((SSPCON1&0x0F)!=0x08) && ((SSPCON1&0x0F)!=0x0B) ) //Slave mode only
{
SSPCON1bits.CKP = 1; // release clock line
while ( !PIR1bits.SSPIF ); // wait until ninth clock pulse received
if ( ( !SSPSTATbits.R_W ) && ( !SSPSTATbits.BF ) )// if R/W=0 and BF=0, NOT ACK was received
{
return ( -2 ); //return NACK
}
else
{
return ( 0 ); //return ACK
}
}
else if( ((SSPCON1&0x0F)==0x08) || ((SSPCON1&0x0F)==0x0B) ) //master mode only
{
while( SSPSTATbits.BF ); // wait until write cycle is complete
IdleI2C1(); // ensure module is idle
if ( SSPCON2bits.ACKSTAT ) // test for ACK condition received
return ( -2 ); // return NACK
else return ( 0 ); //return ACK
}
}
}
unsigned char EEByteWrite( unsigned char control, unsigned char address_high, unsigned char address_low, unsigned char data )
{
int i;
IdleI2C1(); // ensure module is idle
StartI2C1(); // initiate START condition
while ( SSPCON2bits.SEN ); // wait until start condition is over
if ( PIR2bits.BCLIF ) // test for bus collision
{
return ( -1 ); // return with Bus Collision error
}
else // start condition successful
{
if ( WriteI2C( control ) ) // write byte - R/W bit should be 0
{
StopI2C1();
return ( -3 ); // set error for write collision
}
IdleI2C1(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition received
{
if ( WriteI2C( address_high ) ) // address_high for EEPROM
{
StopI2C1();
return ( -3 ); // set error for write collision
}
IdleI2C1(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition received
{
if ( WriteI2C( address_low ) ) // address_low for EEPROM
{
StopI2C1();
return ( -3 ); // set error for write collision
}
IdleI2C1(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition received
{
IdleI2C1();
if ( WriteI2C ( data ) ) //data byte for EEPROM
{
StopI2C1();
//LATC = 3;
return ( -3 ); //set error for write collision
}
// i = WriteI2C (data);
// LATC = i;
}
else
{
StopI2C1();
return ( -2 ); //return with Not Ack error condition
}
}
else
{
StopI2C1();
return ( -2 ); // return with Not Ack error condition
}
}
else
{
StopI2C1();
return ( -2 ); // return with Not Ack error condition
}
}
IdleI2C1(); // ensure module is idle
StopI2C1(); // send STOP condition
while ( SSPCON2bits.PEN ); // wait until stop condition is over
if ( PIR2bits.BCLIF ) // test for bus collision
{
return ( -1 ); // return with Bus Collision error
}
return ( 0 ); // return with no error
}
unsigned int EERandomRead( unsigned char control, unsigned char address_high, unsigned char address_low )
{
IdleI2C1(); // ensure module is idle
StartI2C1(); // initiate START condition
while ( SSPCON2bits.SEN ); // wait until start condition is over
if ( PIR2bits.BCLIF ) // test for bus collision
{
return ( -1 ); // return with Bus Collision error
}
else
{
if ( WriteI2C( control ) ) // write 1 byte
{
StopI2C1();
return ( -3 ); // return with write collision error
}
//IdleI2C1(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition, if received
{
if ( WriteI2C( address_high ) ) // write word address for EEPROM
{
StopI2C1();
return ( -3 ); // set error for write collision
}
IdleI2C1(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition received
{
if ( WriteI2C( address_low ) ) // data byte for EEPROM
{
StopI2C1();
return ( -3 ); // set error for write collision
}
//IdleI2C1(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition, if received
{
RestartI2C1(); // generate I2C bus restart condition
while ( SSPCON2bits.RSEN );// wait until re-start condition is over
if ( PIR2bits.BCLIF ) // test for bus collision
{
return ( -1 ); // return with Bus Collision error
}
if ( WriteI2C( control+1 ) )// write 1 byte - R/W bit should be 1
{
StopI2C1();
return ( -3 ); // return with write collision error
}
//IdleI2C1(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT )// test for ACK condition, if received
{
SSPCON2bits.RCEN = 1; // enable master for 1 byte reception
while ( SSPCON2bits.RCEN ); // check that receive sequence is over
NotAckI2C1(); // send ACK condition
while ( SSPCON2bits.ACKEN ); // wait until ACK sequence is over
StopI2C1(); // send STOP condition
while ( SSPCON2bits.PEN ); // wait until stop condition is over
if ( PIR2bits.BCLIF ) // test for bus collision
{
return ( -1 ); // return with Bus Collision error
}
}
else
{
StopI2C1();
return ( -2 ); // return with Not Ack error
}
}
else
{
StopI2C1();
return ( -2 ); // return with Not Ack error
}
}
else
{
StopI2C1();
return ( -2 ); // return with Not Ack error
}
}
else
{
StopI2C1();
return ( -2 ); // return with Not Ack error
}
}
//
// return 3;
return ( (unsigned int) SSPBUF ); // return with data
}
void main(void)
{
int i;
TRISC = 0;
LATC = 0;
while(1)
{
OpenI2C1(MASTER, SLEW_OFF);
i = EEByteWrite( 0b10100000, 0x01, 0x10, 0x03);
LATC = i;
i = EERandomRead(0b10100000, 0x01, 0x10);
//LATC = i;
CloseI2C1();
}
}
Thanks in advance,
Vyacheslav.
Last edited: