I2C (Inter-Integrated Circuit)

group group_hal_i2c

High level interface for interacting with the I2C resource.

The I2C protocol is a synchronous serial interface protocol. This driver supports both master and slave mode of operation. The communication frequency and address (for slave operation) can be configured.

Features

  • Master or slave functionality

  • Configurable slave address

  • Configurable data rates

  • Configurable interrupt and callback assignment from I2C events - cyhal_i2c_event_t

Quick Start

Initialize an I2C instance using the cyhal_i2c_init and provide sda (I2C data) and scl (I2C clock) pins.

By default, this initializes the resource as an I2C master.

Configure the behavior (master/slave) and the interface (bus frequency, slave address) using the

cyhal_i2c_configure function.

See

Snippet 1: I2C Initialization and Configuration for example initialization as master or slave.

note

The clock parameter (const cyhal_clock_divider_t *clk) is optional and can be set to NULL to generate and use an available clock resource with a default frequency (CYHAL_I2C_MASTER_DEFAULT_FREQ).

Code Snippets

Snippet 1: I2C Initialization and Configuration

This snippet initializes an I2C resource as master or slave and assigns the sda and scl pins.

Initializing as I2C master

    // Declare variables
    cy_rslt_t   rslt;
    cyhal_i2c_t i2c_master_obj;

    // Define frequency
    uint32_t I2C_MASTER_FREQUENCY = 100000u;

    // Define the I2C master configuration structure
    cyhal_i2c_cfg_t i2c_master_config =
    {
        CYHAL_I2C_MODE_MASTER,
        0, // address is not used for master mode
        I2C_MASTER_FREQUENCY
    };

    // Initialize I2C master, set the SDA and SCL pins and assign a new clock
    rslt = cyhal_i2c_init(&i2c_master_obj, CYBSP_I2C_SDA, CYBSP_I2C_SCL, NULL);

    // Configure the I2C resource to be master
    rslt = cyhal_i2c_configure(&i2c_master_obj, &i2c_master_config);
Initializing as I2C slave
    // Declare variables
    cy_rslt_t   rslt;
    cyhal_i2c_t i2c_slave_obj;

    // Define address
    uint16_t I2C_SLAVE_ADDRESS = 0x08u;
    // Define frequency
    uint32_t I2C_SLAVE_FREQUENCY = 100000u;

    // Define the slave configuration structure
    cyhal_i2c_cfg_t i2c_slave_config =
        { CYHAL_I2C_MODE_SLAVE, I2C_SLAVE_ADDRESS, I2C_SLAVE_FREQUENCY };

    // Initialize I2C slave, set the SDA and SCL pins and assign a new clock
    rslt = cyhal_i2c_init(&i2c_slave_obj, CYBSP_I2C_SDA, CYBSP_I2C_SCL, NULL);

    // Configure the I2C resource to be slave
    rslt = cyhal_i2c_configure(&i2c_slave_obj, &i2c_slave_config);

Snippet 2: Handling events

This snippet shows how to enable and handle I2C events using cyhal_i2c_enable_event and cyhal_i2c_register_callback.

The

callback parameter of cyhal_i2c_register_callback is used to pass the callback handler that will be invoked when an event occurs.

The

event parameter of cyhal_i2c_enable_event is used to pass the bitmasks of events ( cyhal_i2c_event_t) to be enabled.


void handle_i2c_events(void* callback_arg, cyhal_i2c_event_t event)
{
    // To remove unused variable warning
    (void)callback_arg;

    // Check write complete event
    if (0UL != (CYHAL_I2C_SLAVE_WR_CMPLT_EVENT & event))
    {
        // Perform the required functions
    }
    // Check read complete event
    if (0UL != (CYHAL_I2C_SLAVE_RD_CMPLT_EVENT & event))
    {
        // Perform the required functions
    }
    // Check for errors
    if (0UL == (CYHAL_I2C_SLAVE_ERR_EVENT & event))
    {
        // Perform the required function
    }
}


void snippet_cyhal_i2c_slave_callback_init()
{
    // Declare variables
    cy_rslt_t   rslt;
    cyhal_i2c_t i2c_slave_obj;

    // Define the slave configuration structure
    cyhal_i2c_cfg_t i2c_slave_config = { CYHAL_I2C_MODE_SLAVE, 0x08u, 100000u };

    // Initialize I2C slave, set the SDA and SCL pins and assign a new clock
    rslt = cyhal_i2c_init(&i2c_slave_obj, CYBSP_I2C_SDA, CYBSP_I2C_SCL, NULL);
    CY_ASSERT(CY_RSLT_SUCCESS == rslt);

    // Configure the I2C resource to be slave
    rslt = cyhal_i2c_configure(&i2c_slave_obj, &i2c_slave_config);
    CY_ASSERT(CY_RSLT_SUCCESS == rslt);

    // Register I2C slave event callback
    cyhal_i2c_register_callback(&i2c_slave_obj, (cyhal_i2c_event_callback_t)handle_i2c_events,
                                NULL);

    // Enable I2C Events
    cyhal_i2c_enable_event(&i2c_slave_obj, (cyhal_i2c_event_t)   \
                           (CYHAL_I2C_SLAVE_WR_CMPLT_EVENT \
                            | CYHAL_I2C_SLAVE_RD_CMPLT_EVENT \
                            | CYHAL_I2C_SLAVE_ERR_EVENT),    \
                           3u, true);
}

Snippet 3: I2C Master Asynchronous Transfer

This snippet shows how to implement asynchronous transfers using cyhal_i2c_master_transfer_async.cyhal_i2c_abort_async is used to stop the transfer, in this case when an error occurs.

// Declare variables
cyhal_i2c_t i2c_master_obj;
uint8_t     tx_buff[3] = { 1, 2, 3 };
uint8_t     rx_buff[3];

// Defining master callback handler
void master_event_handler(void* callback_arg, cyhal_i2c_event_t event)
{
    // To remove unused variable warning
    (void)callback_arg;

    // Check write complete event
    if (0UL != (CYHAL_I2C_MASTER_WR_CMPLT_EVENT & event))
    {
        // Perform the required functions
    }
    // Check read complete event
    if (0UL != (CYHAL_I2C_MASTER_RD_CMPLT_EVENT & event))
    {
        // Perform the required functions
    }
    if (0UL != (CYHAL_I2C_MASTER_ERR_EVENT & event))
    {
        // In case of error abort transfer
        cyhal_i2c_abort_async(&i2c_master_obj);
    }
}


void snippet_cyhal_async_transfer(void)
{
    cy_rslt_t rslt;

    // Define address
    uint16_t I2C_SLAVE_ADDRESS = 0x08u;
    // Define frequency
    uint32_t I2C_MASTER_FREQUENCY = 100000u;

    // Configure I2C Master
    cyhal_i2c_cfg_t i2c_master_config = { CYHAL_I2C_MODE_MASTER, 0, I2C_MASTER_FREQUENCY };

    rslt = cyhal_i2c_init(&i2c_master_obj, CYBSP_I2C_SDA, CYBSP_I2C_SCL, NULL);
    CY_ASSERT(CY_RSLT_SUCCESS == rslt);

    rslt = cyhal_i2c_configure(&i2c_master_obj, &i2c_master_config);
    CY_ASSERT(CY_RSLT_SUCCESS == rslt);

    cyhal_i2c_register_callback(&i2c_master_obj, (cyhal_i2c_event_callback_t)master_event_handler,
                                NULL);
    cyhal_i2c_enable_event(&i2c_master_obj, (cyhal_i2c_event_t)   \
                           (CYHAL_I2C_MASTER_WR_CMPLT_EVENT \
                            | CYHAL_I2C_MASTER_RD_CMPLT_EVENT \
                            | CYHAL_I2C_MASTER_ERR_EVENT),    \
                           3u, true);

    // Initiate master write and read transfer using tx_buff and rx_buff respectively.
    cyhal_i2c_master_transfer_async(&i2c_master_obj, I2C_SLAVE_ADDRESS, tx_buff, 3, rx_buff, 3);
}

More Information

Peripheral Driver Library (PDL)

Code examples (Github)

Defines

CYHAL_I2C_MODE_SLAVE

Named define for Slave mode for use when initializing the cyhal_i2c_cfg_t structure.

CYHAL_I2C_MODE_MASTER

Named define for Master mode for use when initializing the cyhal_i2c_cfg_t structure.

Typedefs

typedef void (*cyhal_i2c_event_callback_t)(void *callback_arg, cyhal_i2c_event_t event)

Handler for I2C events.

Enums

enum cyhal_i2c_event_t

cyhal_i2c_event_t: Enum to enable/disable/report interrupt cause flags.

Values:

enumerator CYHAL_I2C_EVENT_NONE

No event.

enumerator CYHAL_I2C_SLAVE_READ_EVENT

Indicates that the slave was addressed and the master wants to read data.

enumerator CYHAL_I2C_SLAVE_WRITE_EVENT

Indicates that the slave was addressed and the master wants to write data.

enumerator CYHAL_I2C_SLAVE_RD_IN_FIFO_EVENT

All slave data from the configured Read buffer has been loaded into the TX FIFO.

enumerator CYHAL_I2C_SLAVE_RD_BUF_EMPTY_EVENT

The master has read all data out of the configured Read buffer.

enumerator CYHAL_I2C_SLAVE_RD_CMPLT_EVENT

Indicates the master completed reading from the slave (set by the master NAK or Stop)

enumerator CYHAL_I2C_SLAVE_WR_CMPLT_EVENT

Indicates the master completed writing to the slave (set by the master Stop or Restart)

enumerator CYHAL_I2C_SLAVE_ERR_EVENT

Indicates the I2C hardware detected an error.

enumerator CYHAL_I2C_MASTER_WR_IN_FIFO_EVENT

All data specified by cyhal_i2c_master_transfer_async has been loaded into the TX FIFO.

enumerator CYHAL_I2C_MASTER_WR_CMPLT_EVENT

The master write started by cyhal_i2c_master_transfer_async is complete.

enumerator CYHAL_I2C_MASTER_RD_CMPLT_EVENT

The master read started by cyhal_i2c_master_transfer_async is complete.

enumerator CYHAL_I2C_MASTER_ERR_EVENT

Indicates the I2C hardware has detected an error.

enum cyhal_i2c_fifo_type_t

cyhal_i2c_fifo_type_t: I2C FIFO type.

Values:

enumerator CYHAL_I2C_FIFO_RX

Set RX FIFO level.

enumerator CYHAL_I2C_FIFO_TX

Set TX FIFO level.

enum cyhal_i2c_output_t

cyhal_i2c_output_t: Enum of possible output signals from an I2C.

Values:

enumerator CYHAL_I2C_OUTPUT_TRIGGER_RX_FIFO_LEVEL_REACHED

Output the RX FIFO signal which is triggered when the receive FIFO has more entries than the configured level.

enumerator CYHAL_I2C_OUTPUT_TRIGGER_TX_FIFO_LEVEL_REACHED

Output the TX FIFO signal which is triggered when the transmit FIFO has less entries than the configured level.

Functions

cy_rslt_t cyhal_i2c_init(cyhal_i2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_t *clk)

Initialize the I2C peripheral, and configures its specified pins.

By default it is configured as a Master with a bus frequency = CYHAL_I2C_MASTER_DEFAULT_FREQ. Use cyhal_i2c_configure() to change the default behavior.

NOTE: Master/Slave specific functions only work when the block is configured to be in that mode.

See

Snippet 1: I2C Initialization and Configuration

Return

The status of the init request

Parameters
  • [out] obj: Pointer to an I2C object. The caller must allocate the memory for this object but the init function will initialize its contents.

  • [in] sda: The sda pin

  • [in] scl: The scl pin

  • [in] clk: The clock to use can be shared, if not provided a new clock will be allocated

void cyhal_i2c_free(cyhal_i2c_t *obj)

Deinitialize the i2c object.

Parameters
  • [inout] obj: The i2c object

cy_rslt_t cyhal_i2c_configure(cyhal_i2c_t *obj, const cyhal_i2c_cfg_t *cfg)

Configure the I2C block.

NOTE: Master/Slave specific functions only work when the block is configured to be in that mode.

See

Snippet 1: I2C Initialization and Configuration

Return

The status of the configure request

Parameters
  • [in] obj: The I2C object

  • [in] cfg: Configuration settings to apply

cy_rslt_t cyhal_i2c_master_write(cyhal_i2c_t *obj, uint16_t dev_addr, const uint8_t *data, uint16_t size, uint32_t timeout, bool send_stop)

I2C master blocking write.

This will write size bytes of data from the buffer pointed to by data. It will not return until either all of the data has been written, or the timeout has elapsed.

Return

The status of the master_write request

Parameters
  • [in] obj: The I2C object

  • [in] dev_addr: device address (7-bit)

  • [in] data: I2C send data

  • [in] size: I2C send data size

  • [in] timeout: timeout in millisecond, set this value to 0 if you want to wait forever

  • [in] send_stop: whether the stop should be send, used to support repeat start conditions

cy_rslt_t cyhal_i2c_master_read(cyhal_i2c_t *obj, uint16_t dev_addr, uint8_t *data, uint16_t size, uint32_t timeout, bool send_stop)

I2C master blocking read.

This will read size bytes of data into the buffer pointed to by data. It will not return until either all of the data has been read, or the timeout has elapsed.

Return

The status of the master_read request

Parameters
  • [in] obj: The I2C object

  • [in] dev_addr: device address (7-bit)

  • [out] data: I2C receive data

  • [in] size: I2C receive data size

  • [in] timeout: timeout in millisecond, set this value to 0 if you want to wait forever

  • [in] send_stop: whether the stop should be send, used to support repeat start conditions

cy_rslt_t cyhal_i2c_slave_config_write_buffer(cyhal_i2c_t *obj, const uint8_t *data, uint16_t size)

The function configures the write buffer on an I2C Slave.

This is the buffer to which the master writes data to. The user needs to setup a new buffer every time (i.e. call cyhal_i2c_slave_config_write_buffer and cyhal_i2c_slave_config_read_buffer every time the buffer has been used up)

See related code example:

PSoC 6 MCU: I2C Master

Return

The status of the slave_config_write_buffer request

Parameters
  • [in] obj: The I2C object

  • [in] data: I2C slave send data

  • [in] size: I2C slave send data size

cy_rslt_t cyhal_i2c_slave_config_read_buffer(cyhal_i2c_t *obj, uint8_t *data, uint16_t size)

The function configures the read buffer on an I2C Slave.

This is the buffer from which the master reads data from. The user needs to setup a new buffer every time (i.e. call cyhal_i2c_slave_config_write_buffer and cyhal_i2c_slave_config_read_buffer every time the buffer has been used up)

See related code example:

PSoC 6 MCU: I2C Master

Return

The status of the slave_config_read_buffer request

Parameters
  • [in] obj: The I2C object

  • [out] data: I2C slave receive data

  • [in] size: I2C slave receive data size

cy_rslt_t cyhal_i2c_master_mem_write(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, const uint8_t *data, uint16_t size, uint32_t timeout)

Perform an I2C write using a block of data stored at the specified memory location.

Return

The status of the write request

Parameters
  • [in] obj: The I2C object

  • [in] address: device address (7-bit)

  • [in] mem_addr: mem address to store the written data

  • [in] mem_addr_size: number of bytes in the mem address

  • [in] data: I2C master send data

  • [in] size: I2C master send data size

  • [in] timeout: timeout in millisecond, set this value to 0 if you want to wait forever

cy_rslt_t cyhal_i2c_master_mem_read(cyhal_i2c_t *obj, uint16_t address, uint16_t mem_addr, uint16_t mem_addr_size, uint8_t *data, uint16_t size, uint32_t timeout)

Perform an I2C read using a block of data stored at the specified memory location.

Return

The status of the read request

Parameters
  • [in] obj: The I2C object

  • [in] address: device address (7-bit)

  • [in] mem_addr: mem address to store the written data

  • [in] mem_addr_size: number of bytes in the mem address

  • [out] data: I2C master send data

  • [in] size: I2C master send data size

  • [in] timeout: timeout in millisecond, set this value to 0 if you want to wait forever

cy_rslt_t cyhal_i2c_master_transfer_async(cyhal_i2c_t *obj, uint16_t address, const void *tx, size_t tx_size, void *rx, size_t rx_size)

Initiate a non-blocking I2C master asynchronous transfer.

Supports simultaneous write and read operation.

This will transfer rx_size bytes into the buffer pointed to by rx, while simultaneously transfering tx_size bytes of data from the buffer pointed to by tx, both in the background. When the requested quantity of data has been received, the CYHAL_I2C_MASTER_RD_CMPLT_EVENT will be raised. When the requested quantity of data has been transmitted, the CYHAL_I2C_MASTER_WR_CMPLT_EVENT will be raised. See cyhal_i2c_register_callback and cyhal_i2c_enable_event. If either of tx_size or rx_size is ‘0’, the respective write or read operation is not performed. See Snippet 3: I2C Master Asynchronous Transfer

Return

The status of the master_transfer_async request

Parameters
  • [in] obj: The I2C object

  • [in] address: device address (7-bit)

  • [in] tx: The transmit buffer

  • [in] tx_size: The number of bytes to transmit. Use ‘0’ if write operation is not required.

  • [out] rx: The receive buffer

  • [in] rx_size: The number of bytes to receive. Use ‘0’ if read operation is not required.

cy_rslt_t cyhal_i2c_abort_async(cyhal_i2c_t *obj)

Abort asynchronous transfer.

This function aborts the ongoing transfer by generating a stop condition.

See

Snippet 3: I2C Master Asynchronous Transfer

Return

The status of the abort_async request

Parameters
  • [in] obj: The I2C object

void cyhal_i2c_register_callback(cyhal_i2c_t *obj, cyhal_i2c_event_callback_t callback, void *callback_arg)

Register an I2C event callback handler

This function will be called when one of the events enabled by cyhal_i2c_enable_event occurs.

See Snippet 2: Handling events

Parameters
  • [in] obj: The I2C object

  • [in] callback: The callback handler which will be invoked when an event triggers

  • [in] callback_arg: Generic argument that will be provided to the callback when called

void cyhal_i2c_enable_event(cyhal_i2c_t *obj, cyhal_i2c_event_t event, uint8_t intr_priority, bool enable)

Configure and Enable or Disable I2C Interrupt.

When an enabled event occurs, the function specified by cyhal_i2c_register_callback will be called.

See Snippet 2: Handling events

Parameters
  • [in] obj: The I2C object

  • [in] event: The I2C event type

  • [in] intr_priority: The priority for NVIC interrupt events

  • [in] enable: True to turn on interrupts, False to turn off

cy_rslt_t cyhal_i2c_set_fifo_level(cyhal_i2c_t *obj, cyhal_i2c_fifo_type_t type, uint16_t level)

Sets a threshold level for a FIFO that will generate an interrupt and a trigger output.

The RX FIFO interrupt and trigger will be activated when the receive FIFO has more entries than the threshold. The TX FIFO interrupt and trigger will be activated when the transmit FIFO has less entries than the threshold.

Return

The status of the level set

Parameters
  • [in] obj: The I2C object

  • [in] type: FIFO type to set level for

  • [in] level: Level threshold to set

cy_rslt_t cyhal_i2c_enable_output(cyhal_i2c_t *obj, cyhal_i2c_output_t output, cyhal_source_t *source)

Enables the specified output signal from an I2C.

Return

The status of the output enable

Parameters
  • [in] obj: The I2C object

  • [in] output: Which output signal to enable

  • [out] source: Pointer to user-allocated source signal object which will be initialized by enable_output. source should be passed to (dis)connect_digital functions to (dis)connect the associated endpoints.

cy_rslt_t cyhal_i2c_disable_output(cyhal_i2c_t *obj, cyhal_i2c_output_t output)

Disables the specified output signal from an I2C.

Return

The status of the output disable

Parameters
  • [in] obj: The I2C object

  • [in] output: Which output signal to disable

struct cyhal_i2c_cfg_t
#include <cyhal_i2c.h>

Initial I2C configuration.

Public Members

bool is_slave

Operates as a slave when set to (true), else as a master (false)

uint16_t address

Address of this slave resource (7-bit), should be set to 0 for master.

uint32_t frequencyhal_hz

Frequency that the I2C bus runs at (I2C data rate in bits per second)

Refer to the device datasheet for the supported I2C data rates.