2.3 I2C Client Driver

2.3.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 AVR® MCUs, this is typically a Two Wire Interface (TWI) peripheral.

The 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/data through addressing.

2.3.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"

2.3.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 with each of them:

I2C Client Driver Use-Case 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.
  • 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.
  • 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.

2.3.4 Module Documentation

2.3.4.1 TWI_CLIENT_DRIVER

2.3.4.1.1 Module description

Modules
TWI_CLIENT_INTERFACE

This header file provides APIs for the TWI1 driver.

Module description

This header file provides APIs for the TWI1 driver.

Version: TWI1 Driver Version 1.0.1
TWI_CLIENT_TYPES

This header file provides APIs for the TWI1 driver.

Module description

This header file provides APIs for the TWI1 driver.

Version: TWI1 Driver Version 2.0.1
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_ERROR

I2C Bus Error occurred

I2C_CLIENT_ERROR_COLLISION

I2C Collision 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

2.3.4.2 I2C_client_example

2.3.4.2.1 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

2.3.4.2.2 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"


2.3.4.2.3 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;
}

2.3.4.2.4 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;
}

2.3.5 Class Documentation

2.3.5.1 I2C_CLIENT_INTERFACE Struct Reference

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

source/

i2c_client_interface.h

2.3.5.2 i2c_client_interface_t Struct Reference

Structure containing the function pointers of I2C driver.

2.3.5.2.1 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

2.3.6 File Documentation

2.3.6.1 source/i2c_client_interface.h File Reference

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

2.3.6.1.2 Detailed Description

TWI1 Generated Driver API Header File

2.3.6.2 source/i2c_client_types.h File Reference

2.3.6.2.1 Enumerations

2.3.6.2.2 Detailed Description

TWI1 Generated Driver API Header File