2.54 Inter-Integrated Circuit - I2C

The I2C PLIB can be configured in master or slave mode.

I2C master mode The I2C peripheral library supports the following I2C transfers:

Master Write: The master writes a block of data to the slave Master Read: The master reads a block of data from the slave Master Write/Read: The master writes and then reads back a block of data from slave.

Additionally, a forced write API allows writes even if the address or data is NACKed by the slave.

The block of data is transferred in a non-blocking manner using a peripheral interrupt. Application can either use a callback or IsBusy API to check for completion of data transfer.

I2C slave mode

I2C slave PLIB works with peripheral interrupt enabled. Application must register a callback, to get notified of the I2C events such as address match, transmitter ready, receiver ready etc.

I2C Master mode

// Following code demonstrates I2C write operation using polling method

#define APP_SLAVE_ADDR 0x0057
#define NUM_BYTES      10

uint8_t myWriteData [NUM_BYTES] = {'1', '0', ' ', 'B', 'Y', 'T', 'E', 'S', '!', '!',};

int main(void)
{
	/* Initialize all modules */
    SYS_Initialize ( NULL );
	
    /* Write data to the I2C Slave */
    I2C1_Write(APP_SLAVE_ADDR, &myWriteData[0], NUM_BYTES);

    /* Poll and wait for the transfer to complete */
    while(I2C1_IsBusy());

    /* Check if any error occurred */
    if(I2C1_ErrorGet() == I2C_ERROR_NONE)
    {
        //Transfer is completed successfully
    }
    else
    {
        //Error occurred during transfer.
    }
	...
}
// Following code demonstrates I2C write operation using callback method

#define APP_SLAVE_ADDR 0x0057
#define NUM_BYTES      10

uint8_t myWriteData [NUM_BYTES] = {'1', '0', ' ', 'B', 'Y', 'T', 'E', 'S', '!', '!',};

void I2C1_Callback(uintptr_t context)
{
    if(I2C1_ErrorGet() == I2C_ERROR_NONE)
    {
        //Transfer is completed successfully
    }
    else
    {
        //Error occurred during transfer.
    }
}

int main(void)
{
	/* Initialize all modules */
    SYS_Initialize ( NULL );
	
    /* Register Callback function */
    I2C1_CallbackRegister(I2C1_Callback, (uintptr_t)NULL);

    /* Submit Write Request */
    I2C1_Write(APP_SLAVE_ADDR, &myWriteData[0], NUM_BYTES);
	
	...
}

I2C Slave mode

This example uses the I2C peripheral library in slave mode and emulates an EEPROM of 512 bytes. There are two pages each of size 256 bytes. I2C slave expects two bytes of memory address from the I2C master and the memory address can range from 0x00 to 0x1FF.

#define EEPROM_PAGE_SIZE_BYTES                  256
#define EEPROM_PAGE_SIZE_MASK                   0xFF
#define EEPROM_SIZE_BYTES                       512

// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

typedef struct
{
    /* currentAddrPtr - to allow for sequential read (from the current address) */
    uint16_t                    currentAddrPtr;
    /* addrIndex - used to copy 2 bytes of EEPROM memory address */
    uint8_t                     addrIndex;        
}EEPROM_DATA;

EEPROM_DATA         eepromData;

uint8_t EEPROM_EmulationBuffer[EEPROM_SIZE_BYTES] =
{
    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
    0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
    0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
    0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
    0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
    0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
    0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
    0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
    0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
    0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
    0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
    0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
    0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,

    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
    0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
    0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
    0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
    0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
    0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
    0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
    0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
    0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
    0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
    0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
    0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
    0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
};

bool APP_I2C_SLAVE_Callback ( I2C_SLAVE_TRANSFER_EVENT event, uintptr_t contextHandle )
{
    bool isSuccess = true;

    switch(event)
    {
        case I2C_SLAVE_TRANSFER_EVENT_ADDR_MATCH:
            
            /* Reset the index. MSB address is sent first followed by LSB. */
            eepromData.addrIndex = 2;
            
            break;

        case I2C_SLAVE_TRANSFER_EVENT_RX_READY:
            /* Read the data sent by I2C Master */
            if (eepromData.addrIndex > 0)
            {
                ((uint8_t*)&eepromData.currentAddrPtr)[--eepromData.addrIndex] = I2C1_ReadByte();
            }
            else
            {
                EEPROM_EmulationBuffer[eepromData.currentAddrPtr++] = I2C1_ReadByte();
                
                /* If exceeding the page boundary, rollover to the start of the page */
                if ((eepromData.currentAddrPtr % EEPROM_PAGE_SIZE_BYTES) == 0)
                {
                    eepromData.currentAddrPtr -= EEPROM_PAGE_SIZE_BYTES;
                }                                                              
            }
            break;

        case I2C_SLAVE_TRANSFER_EVENT_TX_READY:
            
            /* Provide the EEPROM data requested by the I2C Master */
            I2C1_WriteByte(EEPROM_EmulationBuffer[eepromData.currentAddrPtr++]);
            if (eepromData.currentAddrPtr >= EEPROM_SIZE_BYTES)
            {
                eepromData.currentAddrPtr = 0;
            }
            break;
        
        default:
            break;
    }

    return isSuccess;
}

int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );

    I2C1_CallbackRegister(APP_I2C_SLAVE_Callback, 0);

    while ( true )
    {
        
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

Library Interface

I2C peripheral library provides the following interfaces:

Functions

NameDescriptionMaster modeSlave mode
I2Cx_InitializeInitializes the instance of the I2C peripheral in either master or slave modeYesYes
I2Cx_ReadReads data from the slaveYesNo
I2Cx_WriteWrites data to the slaveYesNo
I2Cx_WriteReadWrite and Read data from SlaveYesNo
I2Cx_WriteForcedForced write data to the slaveYesNo
I2Cx_IsBusyReturns the Peripheral busy statusYesYes
I2Cx_ErrorGetReturns the I2C error that occurred on the busYesYes
I2Cx_TransferSetupDynamic setup of I2C PeripheralYesNo
I2Cx_CallbackRegisterSets the pointer to the function (and it's context) to be called when the given I2C's transfer events occurYesYes
I2Cx_ReadByteRead the received I2C byteNoYes
I2Cx_WriteByteWrite a data byte to I2C masterNoYes
I2Cx_TransferDirGetReturns the I2C transfer directionNoYes
I2Cx_LastByteAckStatusGetReturns the ACK status of the last byte written to the I2C masterNoYes
I2Cx_BusScan FunctionScans and reports the target devices found on the busYesNo

Data types and constants

NameTypeDescriptionMaster modeSlave mode
I2C_ERROREnumDefines the possible errors that the I2C peripheral can generate in I2C master modeYesNo
I2C_TRANSFER_SETUPStructI2C transfer setup data structureYesNo
I2C_CALLBACKTypedefDefines the data type and function signature for the I2C peripheral callback function in I2C master modeYesNo
I2C_SLAVE_TRANSFER_DIREnumDefines the enum for I2C data transfer directionNoYes
I2C_SLAVE_ACK_STATUSEnumDefines the enum for the I2C acknowledgementNoYes
I2C_SLAVE_TRANSFER_EVENTEnumDefines the enum for the I2C slave transfer eventNoYes
I2C_SLAVE_ERROREnumDefines errors associated with I2C in slave modeNoYes
I2C_SLAVE_CALLBACKTypedefDefines the data type and function signature for the I2C Slave callback functionNoYes
Note: Not all APIs maybe implemented. See the specific device family section for available APIs.