3.2 I2C Host Driver

3.2.1 Introduction

The MPLAB® Code Configurator (MCC) Melody Inter-Integrated Circuit (I2C) Host 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 Host 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.

3.2.2 Required Header Files:

For Host 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_host/i2c_host_interface.h"

3.2.3 How to Use the I2C Host Driver

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

I2C Host Driver Use - Case examples:

The examples below illustrate how to use the microcontroller as a I2C device in Host mode. The Polling mode and the Interrupt mode are shown in two separate cases, in which the host device writes a value and the client device reads it back. The client device used in this example has 16-bit registers, therefore both Most Significant Byte (MSB) and Least Significant Byte (LSB) are being transmitted.
  • I2C Host Polling Use - Case 1: Data 0xAA is written to the client at location 0x0010 and read back, using the I2C1_Host.Write( ) and I2C1_Host.WriteRead( ) functions.
  • I2C Host Polling Use - Case 2: Data 0x55 is written to the client at location 0x0020 and read back using the I2C1_Host.Write( ) and I2C1_Host.Read( ) functions.
  • I2C Host Interrupt Use - Case 1: Data 0xAA is written to the client at location 0x0010 and read back using the I2C1_Host.Write( ) and I2C1_Host.WriteRead( ) functions.
  • I2C Host Interrupt Use - Case 2: Data 0x55 is written to the client at location 0x0020 and read back using the I2C1_Host.Write( ) and I2C1_Host.Read( ) functions.

3.2.4 Module Documentation

3.2.4.1 TWI_HOST_DRIVER

3.2.4.1.1 Module description

Modules
TWI_HOST_INTERFACE

This header file provides APIs for the TWI0 driver.

Module description

This header file provides APIs for the TWI0 driver.

Version: TWI0 Driver Version 2.0.1
Data structures
TWI0_HOST_EVENT

This header file provides APIs for the TWI0 driver.

Module description

This header file provides APIs for the TWI0 driver.

Version: TWI0 Driver Version 2.0.1
Enumerations
  • enum i2c_event_states_t { I2C_STATE_IDLE = 0, I2C_STATE_SEND_RD_ADDR, I2C_STATE_SEND_WR_ADDR, I2C_STATE_TX, I2C_STATE_RX, I2C_STATE_NACK, I2C_STATE_ERROR, I2C_STATE_STOP, I2C_STATE_RESET }

    Enumeration for I2C states.

3.2.4.2 I2C_host_example

3.2.4.2.1 I2C Host 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:
  • Host Examples Include files

  • Host Polling Example Case 1

  • Host Polling Example Case 2

  • Host Interrupt Example Case 1

  • Host Interrupt Example Case 2

3.2.4.2.2 I2C Host Examples

The examples below illustrates how to use the microcontroller as a I2C device in Host mode. The Polling mode and the Interrupt mode are shown in two separate cases, in which the host device writes a value and the client device reads it back. The client device used in this example has 16-bit registers, therefore both Most Significant Byte (MSB) and Least Significant Byte (LSB) are being transmitted.

All the host examples use include these files:

#include "mcc_generated_files/system/system.h"
#include "mcc_generated_files/i2c_host/i2c1.h"
#include "mcc_generated_files/i2c_host/i2c_host_interface.h"

3.2.4.2.3 I2C Host Polling Example Case 1

Data 0xAA is written to the client at location 0x0010 and read back, using the I2C1_Host.Write( ) and I2C1_Host.WriteRead( ) functions.

void I2C_host_example_polling_case_1(void)
{
    uint8_t clientAddr = 0x50; // 7-bit Client address
    uint8_t deviceRegAddrMsb = 0x00;    // MSB of Client location address
    uint8_t deviceRegAddrLsb = 0x10;    // LSB of Client location address

    // Desired write and read lengths
    uint8_t writeLength;
    uint8_t readLength;

    // Write and read data buffers (buffersize is set for some overhead)
    uint8_t transmitData[10] = {};
    uint8_t readData[10] = {};

    uint8_t waitCounter = 0;
  
    // Initializes Clock, Pins, Interrupts and I2C Initialize
    SYSTEM_Initialize();

    // Write to client device
    transmitData[0] = deviceRegAddrMsb;  // load MSB of Client location address
    transmitData[1] = deviceRegAddrLsb;  // load LSB of Client location address
    transmitData[2] = 0xAA;  // load data
    writeLength = 3; // 2 bytes of location address + 1 byte data

    if ( I2C1_Host.Write(clientAddr, transmitData, writeLength))
    {
        waitCounter = 100; // This value depends on the system clock, I2C clock and data length.                                                                                          
        while ( I2C1_Host.IsBusy())
        {
            I2C1_Host.Tasks();
            waitCounter--;              
        }

        if (  I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // Write operation is successful
        }
        else
        {
            // Error handling
        }
    }

    // Read from client device
    writeLength = 2; // 2 bytes of location address
    readLength = 1; // 1 byte read
    if (I2C1_Host.WriteRead(clientAddr, transmitData, writeLength, readData , readLength))
    {
        waitCounter = 100; // This value depends on the system clock, I2C clock and data length.                                                                                          
        while ( I2C1_Host.IsBusy())
        {
            I2C1_Host.Tasks();
            waitCounter--;              
        }

        if (  I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // WriteRead operation is successful
        }
        else
        {
            // Error handling
        }
    }
    
}

3.2.4.2.4 I2C Host Polling Example Case 2

Data 0x55 is written to the client at location 0x0020 and read back using the I2C1_Host.Write( ) and I2C1_Host.Read( ) functions.

void I2C_host_example_polling_case_2(void)
{
    uint8_t clientAddr = 0x50; // 7-bit Client address
    uint8_t deviceRegAddrMsb = 0x00;    // MSB of Client location address
    uint8_t deviceRegAddrLsb = 0x20;    // LSB of Client location address

    // Desired write and read lengths
    uint8_t writeLength;
    uint8_t readLength;

    // Write and read data buffers (buffersize is set for some overhead)
    uint8_t transmitData[10] = {};
    uint8_t readData[10] = {};

    uint8_t waitCounter = 0;

    // Initializes Clock, Pins, Interrupts and I2C Initialize
    SYSTEM_Initialize();


    // Write to client device
    transmitData[0] = 0x00;  // load MSB of Client location address
    transmitData[1] = 0x20;  // load LSB of Client location address
    transmitData[2] = 0x55;  // load data
    writeLength = 3; // 2 bytes of location address + 1 byte data

    if (I2C1_Host.Write(clientAddr, transmitData, writeLength))
    {
        waitCounter = 100; // This value depends on the system clock, I2C clock and data length.                                                                                          
        while (I2C1_Host.IsBusy())
        {
            I2C1_Host.Tasks();
            waitCounter--;              
        }

        if ( I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // Write operation is successful
        }
        else
        {
            // Error handling
        }
    }

    // Write which register we wish to read from
    writeLength = 2; // 2 bytes of location address
    if (I2C1_Host.Write(clientAddr, transmitData, writeLength))
    {
        waitCounter = 100; // This value depends on the system clock, I2C clock and data length.                                                                                          
        while (I2C1_Host.IsBusy())
        {
            I2C1_Host.Tasks();
            waitCounter--;              
        }

        if ( I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // Write operation is successful
        }
        else
        {
            // Error handling
        }
    }

    // Read from client device
    readLength = 1; // 1 byte read
    if (I2C1_Host.Read(clientAddr, readData, readLength))
    {
        waitCounter = 100; // This value depends on the system clock, I2C clock and data length.                                                                                          
        while (I2C1_Host.IsBusy())
        {
            I2C1_Host.Tasks();
            waitCounter--;              
        }

        if ( I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // Read operation is successful
        }
        else
        {
            // Error handling
        }
    }
}


3.2.4.2.5 I2C Host Interrupt Example Case 1

Data 0xAA is written to the client at location 0x0010 and read back using the I2C1_Host.Write( ) and I2C1_Host.WriteRead( ) functions.

void I2C_host_example_interrupt_case_1(void)
{
    uint8_t clientAddr = 0x50; // 7-bit Client address
    uint8_t deviceRegAddrMsb = 0x00;    // MSB of Client location address
    uint8_t deviceRegAddrLsb = 0x10;    // LSB of Client location address

    // Desired write and read lengths
    uint8_t writeLength;
    uint8_t readLength;

    // Write and read data buffers (buffersize is set for some overhead)
    uint8_t transmitData[10] = {};
    uint8_t readData[10] = {};


    // Initializes Clock, Pins, Interrupts and I2C Interface
    SYSTEM_Initialize();
    INTERRUPT_GlobalInterruptEnable();

    // Write to client device
    transmitData[0] = deviceRegAddrMsb;  // load MSB of Client location address
    transmitData[1] = deviceRegAddrLsb;  // load LSB of Client location address
    transmitData[2] = 0xAA;  // load data
    writeLength = 3;  // 2 bytes of location address + 1 byte data

    if(!I2C1_Host.Write(clientAddr, transmitData, writeLength))
    {
        // I2C bus busy, retry later
    }

    // Confirm write operation completed and check for error
    if(!I2C1_Host.IsBusy())
    {
        if ( I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // Write operation is successful
        }
        else
        {
            // Error handling
        }
    }

    // Read from client device
    writeLength = 2; // 2 bytes of location address
    readLength = 1; // 1 byte read
    if(I2C1_Host.WriteRead(clientAddr, transmitData, writeLength, readData , readLength))
    {
        // I2C bus busy, retry later
    }

    // Confirm write operation completed and check for error
    if(!I2C1_Host.IsBusy())
    {
        if ( I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // WriteRead operation is successful
        }
        else
        {
            // Error handling
        }
    }
}

3.2.4.2.6 I2C Host Interrupt Example Case 2

Data 0x55 is written to the client at location 0x0020 and read back using the I2C1_Host.Write( ) and I2C1_Host.Read( ) functions.

void I2C_host_example_interrupt_case_2(void)
  {
    uint8_t clientAddr = 0x50; // 7-bit Client address
    uint8_t deviceRegAddrMsb = 0x00;    // MSB of Client location address
    uint8_t deviceRegAddrLsb = 0x20;    // LSB of Client location address

    // Desired write and read lengths
    uint8_t writeLength;
    uint8_t readLength;

    // Write and read data buffers (buffersize is set for some overhead)
    uint8_t transmitData[10] = {};
    uint8_t readData[10] = {};


    // Initializes Clock, Pins, Interrupts and I2C Interface
    SYSTEM_Initialize();
    INTERRUPT_GlobalInterruptEnable();

    // Write to client device
    transmitData[0] = deviceRegAddrMsb;  // load MSB of Client location address
    transmitData[1] = deviceRegAddrLsb;  // load LSB of Client location address
    transmitData[2] = 0x55;  // load data
    writeLength = 2 + 1; // 2 bytes of location address + 1 byte data
    if(!I2C1_Host.Write(clientAddr, transmitData, writeLength))
    {
        // I2C bus busy, retry later
    }

    // Confirm write operation completed and check for error
    if(!I2C1_Host.IsBusy())
    {
        if ( I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // Write operation is successful
        }
        else
        {
            // Error handling
        }
    }

    // Write which register we wish to read from
    writeLength = 2; // 2 bytes of location address
    if(!I2C1_Host.Write(clientAddr, transmitData, writeLength))
    {
        // I2C bus busy, retry later
    }

    // Confirm write operation completed and check for error
    if(!I2C1_Host.IsBusy())
    {
        if ( I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // Write operation is successful
        }
        else
        {
            // Error handling
        }
    }

    // Read from client device
    readLength = 1; // 1 byte read
    if(!I2C1_Host.Read(clientAddr, readData, readLength)))
    {
        // I2C bus busy, retry later
    }

    // Confirm write operation completed and check for error
    if(!I2C1_Host.IsBusy())
    {
        if ( I2C1_Host.ErrorGet() == I2C_ERROR_NONE)
        {
            // Read operation is successful
        }
        else
        {
            // Error handling
        }
    }
}

3.2.5 Class Documentation

3.2.5.1 i2c_event_status_t Struct Reference

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

source/

i2c_host_event_types.h

3.2.5.1.1 Public Attributes

  • bool busy

  • uint16_t address

  • uint8_t * writePtr

  • size_t writeLength

  • uint8_t * readPtr

  • size_t readLength

  • bool switchToRead

  • i2c_host_error_t errorState

  • i2c_event_states_t state

3.2.5.2 i2c_host_interface_t Struct Reference

Structure containing the function pointers of I2C driver.

3.2.5.2.1 Detailed Description

Structure containing the function pointers of I2C driver.

Section: Included Files

#include <i2c_host_interface.h>

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

source/

i2c_host_interface.h

Public Attributes
  • void(* Initialize )(void)

  • void(* Deinitialize )(void)

  • bool(* Write )(uint16_t address, uint8_t *data, size_t dataLength)

  • bool(* Read )(uint16_t address, uint8_t *data, size_t dataLength)

  • bool(* WriteRead )(uint16_t address, uint8_t *writeData, size_t writeLength, uint8_t *readData, size_t readLength)

  • bool(* TransferSetup )(struct I2C_TRANSFER_SETUP *setup, uint32_t srcClkFreq)

  • i2c_host_error_t(* ErrorGet )(void)

  • bool(* IsBusy )(void)

  • void(* CallbackRegister )(void(*callback)(void))

  • void(* Tasks )(void)

3.2.6 File Documentation

3.2.6.1 source/i2c_host_event_types.h File Reference

#include "i2c_host_types.h"

3.2.6.1.2 Enumerations

  • enum i2c_event_states_t { I2C_STATE_IDLE = 0, I2C_STATE_SEND_RD_ADDR, I2C_STATE_SEND_WR_ADDR, I2C_STATE_TX, I2C_STATE_RX, I2C_STATE_NACK, I2C_STATE_ERROR, I2C_STATE_STOP, I2C_STATE_RESET }

    Enumeration for I2C states.

3.2.6.1.3 Detailed Description

TWI0 Generated Driver API Header File

3.2.6.2 source/i2c_host_interface.h File Reference

#include <stdbool.h>
#include <stdint.h>
#include <xc.h>
#include "i2c_host_types.h"

3.2.6.2.1 Data structures

3.2.6.2.2 Detailed Description

TWI0 Generated Driver API Header File