Low Level I2C Commands.c

PIC16F877 sample code that demonstrates how to access an external I2C EEPROM chip connected to a PIC. PIC16F877 is running at 20MHz and 24LC256 with RC0 as a clock pin and RC1 as a data pin. This example does not use the I2C specific interrupt features of the PIC16F877 to enable it to be used on a wider variety of PIC's. Modular approach makes it easy to follow and adapt for other designs (by Jamie Balfour).






// External Eprom Access. Jamie Balfour. Dec 2002.

// No Liability Accepted.



#include "I2C Low Level.h"

#include "PIC Register Addresses.h"





void SendStart( void )

{

    TRISC=0x80;

    SCLw(1);

    SDAw(0);

    SCLw(0);

}



unsigned char SendDeviceAddress( unsigned char dev , unsigned char readwrite )

{

    int ia,ja;

    unsigned char moment=0;

    dev = dev<<1;

    dev = dev|(readwrite&1);

    for( ia=8 ; ia>0 ; ia=ia-1 )		/* Reverse the bits and store them in moment */

    {

        moment=moment<<1;

        moment=moment|(dev&1);

        dev=dev>>1;

    }

    for( ia=0x80 ; ia>0 ; ia=ia>>1 )		/* Output these bits */

    {

        SDAw(moment);

        moment=moment>>1;

        SCLw(1);

        SCLw(0);

    }

    return CheckForAck();

}



unsigned char CheckForAck(void)

{

    unsigned char theresult;

    TRISC=0x82;

    SCLw(1);

    theresult=SDAr();

    SCLw(0);

    SDAw(1);				/* Set the output before it becomes active to eliminate spike */

    TRISC=0x80;

    return theresult;

}



void SendData( unsigned char info )

{

    unsigned char temp=0;

    int ib;

    for( ib=8 ; ib>0 ; ib=ib-1 )		/* Reverse the bits and store them in temp */

    {

        temp=temp<<1;

        temp=temp|(info&1);

        info=info>>1;

    }

    for( ib=0x80 ; ib>0 ; ib=ib>>1 )		/* Output these bits */

    {

        SDAw(temp);

        temp=temp>>1;

        SCLw(1);

        SCLw(0);

    }

    CheckForAck();

}



void Restart( void )			/* This function must be entered with SDA High */

{

    SCLw(1);

    SDAw(0);

    SCLw(0);

}



unsigned char GetData( void )

{

    unsigned char input=0;

    int id;

    TRISC=0x82;

    for( id=8 ; id>0 ; id=id-1 )

    {

        input=input<<1;

        SCLw(1);

        input=input|SDAr();

        SCLw(0);

    }

    SDAw(1);				/* Set the output prior to enable to eliminate spike and make compatible with Restart */

    TRISC=0x80;

    return input;

}



void SendStop( void )

{

    SCLw(0);

    SDAw(0);

    SCLw(1);

    SDAw(1);				/* Should leave with both lines high to indicate finish */

}





void SDAw( unsigned char level )	/* Write to the Data line */

{

    level = level<<1;			/* Shift left one bit cos data line is RC1 */

    level = level&0x2;			/* Blank all unnecessary bits */

    PORTC=(PORTC&(~0x2))|level;		/* Send the output */

}



void SCLw( unsigned char level )	/* Write to clock line */

{

    level=level&0x1;			/* Blank all unnecessary bits */

    PORTC=(PORTC&(~0x1))|level;		/* Send the output */

}



unsigned char SDAr( void )

{

    return (PORTC&0x2)>>1;

}




Copyright© 2002 Pavel Baranov.