Skip to content

Inter-Integrated Circuit (I2C/IIC)


1. Introduction

  • I2C is a bidirectional, two-wire, synchronous serial bus consisting of SDA (serial data) and SCL (serial clock). Both SDA and SCL pins are open-drain. I2C is commonly used for communication between one or more masters and one or more slaves. Each device on the bus has a unique address, and at any given time only one master may initiate a transaction to access a slave device.
  • CI13XX supports one I2C controller. The data frame typically consists of Start, Address, Acknowledge, Data, and Stop. It supports Standard mode at 100 kbit/s and Fast mode at 400 kbit/s.

2. Features

  • SDA: Serial Data line, bidirectional I/O.
  • SCL: Serial Clock line, provided by the master.
  • Supports master and slave modes configurable via API iic_polling_init.
  • Master: Initiates bus transfers and generates the clock.
  • Slave: Any addressed device with a unique address.
  • Start condition: While SCL is high, SDA transitions from high to low to indicate the start of a transfer.
  • Address: Supports 7-bit addressing, with 7-bit address and 1-bit R/W.
  • Acknowledge: ACK indicates successful reception; NACK indicates failure or end of transfer.
  • Data: Transferred by byte, MSB first, LSB last.
  • Stop condition: While SCL is high, SDA transitions from low to high to indicate the end of a transfer.
  • Bus speed configurable via iic_polling_init: Standard (100 kbit/s) and Fast (400 kbit/s).

3. I2C Timing

3.1 I2C Bus Physical Topology

  • The I2C bus can connect multiple devices, typically one or more masters and one or more slaves. Each device has a unique address, and at any given time only one master may initiate an access to a slave device.

I2C Diagram

3.2 Timing Diagrams

  • (1) Continuous write timing:

I2C Timing

  • (2) Write-then-read timing:

I2C Timing

  • (3) Continuous read timing:

I2C Timing


  • The master starts communication by generating a Start condition: pulling SDA low while SCL is high, then sending 8 SCL pulses to transfer one byte containing a 7-bit address and 1-bit R/W. If a slave address matches, it responds with ACK. Master and slave determine send/receive roles via the R/W bit and end the transfer based on ACK/NACK. During data transfer, SDA changes only when SCL is low. To end communication, the master issues a Stop condition by pulling SDA high while SCL is high.

4. API List

Function Name Description
iic_polling_init Initialize in master or slave mode (polling)
iic_master_polling_send Master polling send
iic_master_polling_recv Master polling receive
iic_master_multi_transmission Master multi-message transfer
iic_slave_polling_send Slave polling send
iic_slave_polling_recv Slave polling receive
iic_interrupt_init Initialize in master or slave mode (interrupt)
iic_master_interrupt_send Master interrupt send
iic_master_interrupt_recv Master interrupt receive
iic_slave_interrupt_send Slave interrupt send
iic_slave_interrupt_recv Slave interrupt receive
i2c_master_only_send Single message: send only
i2c_master_send_recv Two messages: write then read
i2c_master_only_recv Single message: read only


5. Example

The following demonstrates I2C initialization and read/write:

#include "ci130x_iic.h"          /* Contains I2C interface definitions */
#include "ci130x_system.h"       /* Contains I2C registers and base addresses */


/* Without R/W bit: I2C device address << 1; with R/W bit becomes 0x40/0x41 */
#define IIC_TEST_SLAVE_ADDR  0x20


void i2c_master_test()
{
    /* Customizable I/O pin initialization */
    pad_config_for_i2c();


    /* Initialize master mode: bus IIC0, 100 kHz; own address 0 = master mode, valid value = slave mode; timeout */
    iic_polling_init(IIC0,100,0,LONG_TIME_OUT);


    /* Write 5 bytes to I2C device at address 0x20 */
    char send_buf[5] = {0x01,0x02,0x03,0x04,0x05} ;
    uint8_t last_ack_flag = 0;
    iic_master_polling_send(IIC0,IIC_TEST_SLAVE_ADDR,send_buf,5,&last_ack_flag); 


    /* Read 5 bytes from I2C device at address 0x20 */
    char recv_buf [5] = {0} ;
    iic_master_polling_recv(IIC0,IIC_TEST_SLAVE_ADDR,recv_buf,5);

}

The following configures I2C pins (PB7/PC0) as open-drain outputs:

#include "ci130x_dpmu.h"


void iic_pad_init()
{
    dpmu_set_io_reuse(PB7,THIRD_FUNCTION);              // Set pin function to I2C
    dpmu_set_io_reuse(PC0,THIRD_FUNCTION);              // Set pin function to I2C
    dpmu_set_io_open_drain(PB7,ENABLE);                 // Enable open-drain, supports external 5V pull-up
    dpmu_set_io_open_drain(PC0,ENABLE);                 // Enable open-drain, supports external 5V pull-up
    dpmu_set_io_pull(PB7,DPMU_IO_PULL_DISABLE);         // Disable pull-up
    dpmu_set_io_pull(PC0,DPMU_IO_PULL_DISABLE);         // Disable pull-up
    dpmu_set_io_direction(PC0,DPMU_IO_DIRECTION_OUTPUT);// Configure SCL as output

}

6. API Reference