#include "I2C.h"
void SetUpI2C ( unsigned char serialPortMode, unsigned char slewRate )
{
#if defined ( _PIC16F887_H_ ) || defined ( _PIC16F886_H_ )
PORTCbits . RC3 = 1; // Set SCL and SDA pins as inputs.
PORTCbits . RC4 = 1;
#endif
SSPSTAT &= 0x3F; // Power on state.
SSPCON = 0x00; // POR value.
SSPCON2 = 0x00;
SSPCONbits . SSPM = serialPortMode;
SSPSTATbits . SMP = slewRate;
#if FREQ_8MHz
SSPADD = 19; // I2C-freq = FOSC/(4 * (SSPADD + 1))
#endif // 100kHz Baud clock(19) @8MHz.
SSPCONbits . SSPEN = 0x01; // Synchronous Serial Port.
IdleI2C ( ); // Puts the bus on idle state.
}
/* Idle or trasmition is in progres */
void WaitI2C ( void )
{
while ( ( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );
}
void StartI2C ( void )
{
// WaitI2C ( ); // Wait untill buffer is free.
SSPCON2bits . SEN = 1; // Start Condition Enabled.
while ( SSPCON2bits . SEN ); // waits till the start
} // sequence is terminated.
void RestartI2C ( void )
{
WaitI2C ( ); // Wait untill buffer is free.
SSPCON2bits . RSEN = 1; // Repeated Start Condition.
while ( SSPCON2bits . RSEN ); // waits till the restart
} // sequence is terminated.
void StopI2C ( void )
{
WaitI2C ( ); // Wait untill buffer is free.
SSPCON2bits . PEN = 1; // Stop Condition Enable.
while ( SSPCON2bits . PEN ); // Waits till the stop
// sequence is terminated.
IdleI2C ( ); // Puts the bus on idle state.
}
// sends one byte
void WriteI2C ( unsigned char data )
{
WaitI2C ( ); // Wait untill buffer is free.
SSPBUF = data; // Passing the data to Synchronous Serial Port Transmit Register.
while ( SSPCON2bits . ACKSTAT == 1 ); // Wait until slave acknowledge.
}
void I2CAddressCommand ( unsigned char address, unsigned char mode )
{
unsigned char temp;
// temp = address << 1;//Passing the address and shift one place to a variable.
// temp += mode; // Adding the write/read on the 8th bit.
temp = address + mode;
WaitI2C ( ); // Wait untill buffer is free.
SSPBUF = temp; // Passing the address + command to Transmit Register.
while ( SSPCON2bits . ACKSTAT == 1 );
}
// Read data from slave
// ack should be 1 if there is going to be more data read
// ack should be 0 if this is the last byte of data read
unsigned char ReadI2C ( unsigned char ack )
{
unsigned char I2CReadData;
WaitI2C ( ); // Wait untill buffer is free.
SSPCON2bits . RCEN = 1; // Receive enable.
WaitI2C ( ); // Wait untill receive complete.
I2CReadData = SSPBUF; // Passing data from Reciver Buffer to variable.
WaitI2C ( ); // Wait untill receive complete.
if ( ack )
ACKDT = 0; // Acknowledge.
else
ACKDT = 1; // Not Acknowledge.
ACKEN = 1; // Initiate Acknowledge sequence on SDA and SCL pins.
return ( I2CReadData ); // Return data fron Slave.
}
/* OR-ing R_W bit with SEN, RSEN, PEN, RCEN, or ACKEN will indicate if the MSSP is in Idle mode.
*/
void IdleI2C ( void )
{
while ( ( SSPCON2 & 0x1F ) | ( SSPSTATbits . R_W ) )
continue;
}