3.4 I2C Client Driver

3.4.1 Introduction

The MPLAB® Code Configurator (MCC) Melody Inter-Integrated Circuit (I2C) Client Driver generates a portable API to support a generic I2C host interface, and also two important MCC Melody Component concepts: configuration- and firmware-portability.

The I2C Client Driver requires a Peripheral Library (PLIB) dependency that is closely associated to an I2C hardware peripheral. On PIC® MCUs, this typically takes the form of a either an I2C or a MSSP (Master Synchronous Serial Port) hardware peripheral.

The I2C bus is a multi-host serial data communication busDevices communicate in a host/client environment where the host devices initiate the communication. A client device is controlled through addressing.

3.4.2 Required Header Files

For Client mode, include the following files in your application to use the I2C abstract driver:
#include <stdbool.h>
#include <stdint.h>
#include "mcc_generated_files/i2c_client/i2c_client_interface.h"

3.4.3 How to Use the I2C Client Driver

The I2C Client Driver can be used in polled or interrupt modes. Click the links to view the code snippets associated with each:

I2C Client Driver Use-Case examples:

Both the following examples will illustrate how to use the microcontroller as an I2C device in Client mode. In both cases you can see how to use the callbackRegister and the i2c_client_transfer_events to handle the I2C communication.
  • I2C Client Polling Example: This example assumes that the MCU is configured as a Client and responds to the Host commands to write or read data via the Client_Application switch case that executes the appropriate action based on the events that occur.
  • I2C Client Interrupt Example: This example assumes that the MCU is configured as a Client and responds to the Host commands to write or read data via the Client_Application switch case that executes the appropriate action based on the events that occur.

3.4.4 I2C Client Driver Documentation

3.4.4.1 Module Documentation

3.4.4.1.1 I2C_CLIENT_DRIVER

Module description
Modules
I2C_CLIENT_INTERFACE

This file contains other data types for I2C module.

Module description

This file contains other data types for I2C module.

Version: I2C Driver Version 2.1.0
I2C_CLIENT_TYPES

This file contains other data types for I2C module.

Module description

This file contains other data types for I2C module.

Version: I2C Driver Version 2.1.0
Enumerations
Enumeration Type Documentation
i2c_client_ack_status_t

enum i2c_client_ack_status_t

I2C Ack/Nack status enumeration.

I2C_CLIENT_ACK_STATUS_RECEIVED_ACK

I2C Host is send ACK to client

I2C_CLIENT_ACK_STATUS_RECEIVED_NACK

I2C Host is send NACK to client

i2c_client_error_t

enum i2c_client_error_t

I2C client error type indicator.

I2C_CLIENT_ERROR_NONE

I2C error none

I2C_CLIENT_ERROR_BUS_COLLISION

I2C Bus collision occurred

I2C_CLIENT_ERROR_WRITE_COLLISION

I2C Write collision occurred

I2C_CLIENT_ERROR_RECEIVE_OVERFLOW

I2C Receive overflow occurred

I2C_CLIENT_ERROR_TRANSMIT_UNDERFLOW

I2C Trasmit underflow occurred

I2C_CLIENT_ERROR_READ_UNDERFLOW

I2C Receive underflow occurred

i2c_client_transfer_dir_t

enum i2c_client_transfer_dir_t

I2C_CLIENT_TRANSFER_DIR Enumeration.

I2C_CLIENT_TRANSFER_DIR_WRITE

I2C Host is writing to client

I2C_CLIENT_TRANSFER_DIR_READ

I2C Host is reading from client

i2c_client_transfer_event_t

enum i2c_client_transfer_event_t

I2C notification event type.

I2C_CLIENT_TRANSFER_EVENT_NONE

I2C Bus Idle state

I2C_CLIENT_TRANSFER_EVENT_ADDR_MATCH

Address match event

I2C_CLIENT_TRANSFER_EVENT_RX_READY

Data sent by I2C Host is available

I2C_CLIENT_TRANSFER_EVENT_TX_READY

I2C client can respond to data read request from I2C Host

I2C_CLIENT_TRANSFER_EVENT_STOP_BIT_RECEIVED

I2C stop bit received

I2C_CLIENT_TRANSFER_EVENT_ERROR

I2C Bus error occurred

3.4.4.1.2 I2C_client_example

I2C Client Basics

The Inter-Integrated Circuit (I2C) bus is a multi-host serial data communication bus. The devices communicate in a host/client environment where the host devices initiate the communication. A client device receives commands/input/data through addressing.

The use-case code snippets explain the Interface APIs Usage for the below I2C Modes:
  • Client Examples Include files

  • Client Polling Example

  • Client Interrupt Example

I2C Client Examples

The examples below illustrate how to use the microcontroller as a I2C device in Client mode. Both cases show how to use the callbackRegister and the i2c_client_transfer_events to handle the I2C communication.

All the Client examples will use these includes:

#include "mcc_generated_files/system/system.h"
#include "mcc_generated_files/i2c_client/i2c1.h"
#include "mcc_generated_files/i2c_client/i2c_client_interface.h"


I2C Client Polling Example

This example assumes that the MCU is configured as a client and responds to the host commands to write or read data via the Client_Application switch case, which selects and implements the appropriate action based on the events that occur.

#define I2C_CLIENT_LOCATION_SIZE 10

//Private functions
static bool Client_Application(i2c_client_transfer_event_t event);

// Private variable
volatile static uint8_t CLIENT_DATA[I2C_CLIENT_LOCATION_SIZE] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
};

static uint8_t clientLocation  = 0x00;
static bool isClientLocation = false;

int I2C_client_example_polling(void)
{
    SYSTEM_Initialize();
    I2C1_Client.CallbackRegister(Client_Application);
    while (1)
    {
        I2C1_Client.Tasks();
    }
}

static bool Client_Application(i2c_client_transfer_event_t event)
{
    switch (event)
    {
        case I2C_CLIENT_TRANSFER_EVENT_ADDR_MATCH: //Address Match occured
        if (I2C1_Client.TransferDirGet() == I2C_CLIENT_TRANSFER_DIR_WRITE)
        {
            isClientLocation  = true;
        }
        break;

        case I2C_CLIENT_TRANSFER_EVENT_RX_READY: //Read the data sent by I2C Host
        if (isClientLocation )
        {
            clientLocation  = I2C1_Client.ReadByte();
            isClientLocation  = false;
            break;
        }
        else
        {
            CLIENT_DATA[clientLocation ++] = I2C1_Client.ReadByte();
            if (clientLocation  >= I2C_CLIENT_LOCATION_SIZE)
            {
                clientLocation  = 0x00;
            }
        }
        break;

        case I2C_CLIENT_TRANSFER_EVENT_TX_READY: // Provide the Client data requested by the I2C Host
        I2C1_Client.WriteByte(CLIENT_DATA[clientLocation ++]);
        if (clientLocation  >= I2C_CLIENT_LOCATION_SIZE)
        {
            clientLocation  = 0x00;
        }
        break;

        case I2C_CLIENT_TRANSFER_EVENT_STOP_BIT_RECEIVED: //Stop Communication
        clientLocation  = 0x00;
        break;

        case I2C_CLIENT_TRANSFER_EVENT_ERROR: //Error Event Handler
        clientLocation  = 0x00;
        i2c_client_error_t errorState = I2C1_Client.ErrorGet();
        if(errorState == I2C_CLIENT_ERROR_BUS_COLLISION)
        {
            // Bus Collision Error Handling
        }
        else if(errorState == I2C_CLIENT_ERROR_WRITE_COLLISION)
        {
            // Write Collision Error Handling
        }
        else if (errorState == I2C_CLIENT_ERROR_RECEIVE_OVERFLOW)
        {
            // Receive Overflow Error Handling
        }
        else if (errorState == I2C_CLIENT_ERROR_TRANSMIT_UNDERFLOW)
        {
            // Transmit Underflow Error Handling
        }
        else if (errorState == I2C_CLIENT_ERROR_READ_UNDERFLOW)
        {
            // Read Underflow Error Handling
        }
        break;

        default:
        break;
    }
    return true;
}

I2C Client Interrupt Example

This example assumes that the MCU is configured as a client and responds to the host commands to write or read data via the Client_Application switch case, which selects and implements the appropriate action based on the events that occur.


#define I2C_CLIENT_LOCATION_SIZE 10

//Private functions
static bool Client_Application(i2c_client_transfer_event_t event);

// Private variable
volatile static uint8_t CLIENT_DATA[I2C_CLIENT_LOCATION_SIZE] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
};

static uint8_t clientLocation  = 0x00;
static bool isClientLocation  = false;

int I2C_client_example_interrupt(void)
{
    SYSTEM_Initialize();
    INTERRUPT_GlobalInterruptEnable();
    I2C1_Client.CallbackRegister(Client_Application);
    while (1)
    {
    }
}

static bool Client_Application(i2c_client_transfer_event_t event)
{
    switch (event)
    {
        case I2C_CLIENT_TRANSFER_EVENT_ADDR_MATCH:  //Address Match Event
        if (I2C1_Client.TransferDirGet() == I2C_CLIENT_TRANSFER_DIR_WRITE)
        {
            isClientLocation  = true;
        }
        break;

        case I2C_CLIENT_TRANSFER_EVENT_RX_READY: //Read the data sent by I2C Host
        if (isClientLocation )
        {
            clientLocation  = I2C1_Client.ReadByte();
            isClientLocation  = false;
            break;
        }
        else
        {
            CLIENT_DATA[clientLocation ++] = I2C1_Client.ReadByte();
            if (clientLocation  >= I2C_CLIENT_LOCATION_SIZE)
            {
                clientLocation  = 0x00;
            }
        }
        break;

        case I2C_CLIENT_TRANSFER_EVENT_TX_READY: //Provide the Client data requested by the I2C Host
        I2C1_Client.WriteByte(CLIENT_DATA[clientLocation ++]);
        if (clientLocation  >= I2C_CLIENT_LOCATION_SIZE)
        {
            clientLocation  = 0x00;
        }
        break;

        case I2C_CLIENT_TRANSFER_EVENT_STOP_BIT_RECEIVED: //Stop Communication
        clientLocation  = 0x00;
        break;

        case I2C_CLIENT_TRANSFER_EVENT_ERROR: //Error Event Handler
        clientLocation  = 0x00;
        i2c_client_error_t errorState = I2C1_Client.ErrorGet();
        if(errorState == I2C_CLIENT_ERROR_BUS_COLLISION)
        {
            // Bus Collision Error Handling
        }
        else if(errorState == I2C_CLIENT_ERROR_WRITE_COLLISION)
        {
            // Write Collision Error Handling
        }
        else if (errorState == I2C_CLIENT_ERROR_RECEIVE_OVERFLOW)
        {
            // Receive Overflow Error Handling
        }
        else if (errorState == I2C_CLIENT_ERROR_TRANSMIT_UNDERFLOW)
        {
            // Transmit Underflow Error Handling
        }
        else if (errorState == I2C_CLIENT_ERROR_READ_UNDERFLOW)
        {
            // Read Underflow Error Handling
        }
        break;

        default:
        break;
    }
    return true;
}

3.4.4.2 Class Documentation

3.4.4.2.1 I2C_CLIENT_INTERFACE Struct Reference

The documentation for this struct was generated from the following file:

source/

i2c_client_interface.h

3.4.4.2.2 i2c_client_interface_t Struct Reference

Structure containing the function pointers of I2C driver.

Detailed Description

Structure containing the function pointers of I2C driver.

Section: Included FilesSection: Data Type Definitions

#include <i2c_client_interface.h>

The documentation for this struct was generated from the following file:

source/

i2c_client_interface.h

3.4.4.3 File Documentation

3.4.4.3.1 source/i2c_client_interface.h File Reference

#include <stdbool.h>
#include <stdint.h>
#include "i2c_client_types.h"
Detailed Description

I2C Generated Driver Interface Header File

3.4.4.3.2 source/i2c_client_types.h File Reference

Enumerations
Detailed Description

I2C Generated Driver Types Header File