I²C Library

The I²C full master I²C module is available with a number of the PIC32 MCU models. The mikroC PRO for PIC32 provides a library which supports the master I²C mode.


  Important :

Library Routines

Generic Routines

I2Cx_Init

Prototype

void I2Cx_Init(unsigned long scl);

Description

This function configures and initializes the desired I²C module with default settings.

This function enables the I²C module by setting the I2CEN bit. The rest of the bits in I²C control register remains unchanged. Default initialization (after reset) of I²C module is :

  • Continue operation in IDLE mode.
  • 7-bit slave address.
  • Slew rate control enabled for High Speed mode (400 kHz).
  • General call address disabled.
  • SCL clock stretching disabled.

As per the I²C standard, SCL clock may be 100 kHz or 400 kHz. However, the user can specify any clock rate up to 1 MHz.

Parameters
  • scl: requested serial clock rate.
Returns

Nothing.

Requires

MCU with the I²C module.

Example
// Initialize the I2C1 module with clock_rate of 100000
I2C1_Init(100000);
Notes
  • Refer to the MCU's datasheet for correct values of the scl in respect with Fosc.
  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 5.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2Cx_Init_Advanced

Prototype

void I2Cx_Init_Advanced(unsigned long Fclk_Khz, unsigned long scl);

Description

This function configures and initializes the desired I²C module using Peripheral Bus Clock and default initialization settings.

As per the I²C standard, SCL clock may be 100 kHz or 400 kHz. However, the user can specify any clock rate up to 1 MHz.

Parameters
  • Fclk_Khz: Peripheral Bus Clock frequency in kHz.
  • scl: requested serial clock rate.
Returns

Nothing.

Requires

MCU with the I²C module.

Example
I2C1_Init_Advanced(50000, 100000);
Notes
  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 5.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2Cx_Start

Prototype

unsigned I2Cx_Start();

Description

Determines if the I²C bus is free and issues START signal.

Parameters

None.

Returns
  • 0 if I²C bus was successfully started.
  • 0xFFFF if I²C bus was not successfully started.
Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Example
// Issue START signal
I2C1_Start();
Notes
  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 5.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2Cx_Restart

Prototype

unsigned I2Cx_Restart();

Description

Issues repeated START signal.

Parameters

None.

Returns
  • 0 if I²C bus was successfully restarted.
  • 0xFFFF if I²C bus was not successfully restarted.
Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Example
// Issue RESTART signal
I2C1_Restart();
Notes
  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 5.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2Cx_Is_Idle

Prototype

unsigned I2Cx_Is_Idle();

Description

Waits for the I²C bus to become free. This is a blocking function.

Parameters

None.

Returns
  • 0 if I²C bus is free.
  • 1 if I²C bus is not free.
Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Example
unsigned char data_;
...
if (!I2C1_Is_Idle)
  I2C1_Write(data_);
...
Notes
  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 5.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2Cx_Read

Prototype

unsigned char I2Cx_Read(unsigned ack);

Description

Reads a byte from the I²C bus.

Parameters
  • ack: acknowledge signal parameter. If this parameter is _I2C_ACK, acknowledge signal will be sent after reading, if its value is _I2C_NACK, not acknowledge signal will be sent after reading.
Returns

Received data.

Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Also, START signal needs to be issued in order to use this function. See I2Cx_Start.

Example
unsigned char take;
...
// Read data and send the not_acknowledge signal
take = I2C1_Read(_I2C_NACK);
Notes
  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 5.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2Cx_Write

Prototype

unsigned I2Cx_Write(unsigned char data_);

Description

Sends data byte via the I²C bus.

Parameters
  • data_: data to be sent
Returns

  • 0 if there were no errors.
  • 1 if write collision was detected on the I²C bus.

Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Also, START signal needs to be issued in order to use this function. See I2Cx_Start.

Example
unsigned char data_;
unsigned error;
...
error = I2C1_Write(data_);
error = I2C1_Write(0xA3);
Notes
  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 5.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2Cx_Stop

Prototype

void I2Cx_Stop();

Description

Issues STOP signal.

Parameters

None.

Returns

Nothing.

Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Example
// Issue STOP signal
I2C1_Stop();
Notes
  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 5.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2Cx_SetTimeoutCallback

Prototype

void I2Cx_SetTimeoutCallback(unsigned long timeout, void (*I2C_timeout)(char));

Description

This function checks for a I²C timeout condition in a user defined time period, after which it jumps to a callback function if this condition is met.
Different I²C operations can cause a timeout (read, write, start and repeated start) so user may test which one caused it, as in the example below.

Parameters
  • timeout: Represents a number of while loops in which the I²C timeout condition is checked.
  • I2C_timeout: pointer to the callback function. Callback function must be written according to this function prototype :
    void I2C1_TimeoutCallback(char errorCode) {
    
    }	
    
Returns

Nothing.

Requires

I²C must be configured before using this function. See I2Cx_Init or I2Cx_Init_Advanced.

Example
// define callback function
void I2C1_TimeoutCallback(char errorCode) {

   if (errorCode == _I2C_TIMEOUT_RD) {
     // do something if timeout is caused during read
   }

   if (errorCode == _I2C_TIMEOUT_WR) {
     // do something if timeout is caused during write
   }

   if (errorCode == _I2C_TIMEOUT_STOP) {
     // do something if timeout is caused during stop
   }

   if (errorCode == _I2C_TIMEOUT_START) {
     // do something if timeout is caused during start
   }

   if (errorCode == _I2C_TIMEOUT_REPEATED_START) {
     // do something if timeout is caused during start
   }

   if (errorCode == _I2C_TIMEOUT_INIT) {
     // do something if timeout is caused during initialization
   }

   if (errorCode == _I2C_TIMEOUT_INIT_ADVANCED) {
     // do something if timeout is caused during advanced initialization
   }
   
}	

// initialize I2C module
I2C1_Init(100000);

// set timeout period and callback function
I2C1_SetTimeoutCallback(1000, I2C1_TimeoutCallback);
Notes
  • I²C library routines require you to specify the module you want to use. To select the desired I²C module, simply change the letter x in the routine prototype for a number from 1 to 5.
  • Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2C_Set_Active

Prototype

void I2C_Set_Active(unsigned (*start_ptr)(), unsigned (*restart_ptr)(), unsigned char (*read_ptr)(unsigned), unsigned (*write_ptr)(unsigned char), void (*stop_ptr)(), unsigned (*is_idle_ptr)());

Description

Sets the active I²C module which will be used by the I²C routines.

Parameters
Returns

Nothing.

Requires

Used I²C module must be initialized before using this function. See the I2Cx_Init and I2Cx_Init_Advanced routines.

Example
I2C_Set_Active(&I2C1_Start, &I2C1_Restart, &I2C1_Read, &I2C1_Write, &I2C1_Stop, &I2C1_Is_Idle); // Sets the I2C1 module active
Notes

Number of I²C modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

I2C_Start

Prototype

unsigned I2C_Start();

Description

Determines if the I²C bus is free and issues START signal.

This is a generic routine which uses the active I²C module previously activated by the I2C_Set_Active routine.

Parameters

None.

Returns
  • 0 if I²C bus was successfully started.
  • 0xFFFF if I²C bus was not successfully started.
Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Example
I2C_Set_Active(&I2C1_Start, &I2C1_Restart, &I2C1_Read, &I2C1_Write, &I2C1_Stop, &I2C1_Is_Idle); // Sets the I2C1 module active
// Issue START signal
I2C1_Start();
Notes

None.

I2C_Restart

Prototype

unsigned I2C_Restart();

Description

Issues repeated START signal.

This is a generic routine which uses the active I²C module previously activated by the I2C_Set_Active routine.

Parameters

None.

Returns
  • 0 if I²C bus was successfully restarted.
  • 0xFFFF if I²C bus was not successfully restarted.
Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Example
I2C_Set_Active(&I2C1_Start, &I2C1_Restart, &I2C1_Read, &I2C1_Write, &I2C1_Stop, &I2C1_Is_Idle); // Sets the I2C1 module active
...
// Issue RESTART signal
I2C_Restart();
Notes

None.

I2C_Is_Idle

Prototype

unsigned I2C_Is_Idle();

Description

Waits for the I²C bus to become free. This is a blocking function.

This is a generic routine which uses the active I²C module previously activated by the I2C_Set_Active routine.

Parameters

None.

Returns
  • 0 if I²C bus is free.
  • 1 if I²C bus is not free.
Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Example
unsigned char data_;
...
I2C_Set_Active(&I2C1_Start, &I2C1_Restart, &I2C1_Read, &I2C1_Write, &I2C1_Stop, &I2C1_Is_Idle); // Sets the I2C1 module active
if !(I2C_Is_Idle)
  I2C_Write(data_);
...
Notes

None.

I2C_Read

Prototype

unsigned char I2C_Read(unsigned ack);

Description

Reads a byte from the I²C bus.

This is a generic routine which uses the active I²C module previously activated by the I2C_Set_Active routine.

Parameters
  • ack: acknowledge signal parameter. If this parameter is _I2C_ACK, acknowledge signal will be sent after reading, if its value is _I2C_NACK, not acknowledge signal will be sent after reading.
Returns

Received data.

Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Also, START signal needs to be issued in order to use this function. See I2Cx_Start.

Example
unsigned char take;
...
I2C_Set_Active(&I2C1_Start, &I2C1_Restart, &I2C1_Read, &I2C1_Write, &I2C1_Stop, &I2C1_Is_Idle); // Sets the I2C1 module active

// Read data and send the not_acknowledge signal
take = I2C_Read(_I2C_NACK);
Notes

None.

I2C_Write

Prototype

unsigned I2C_Write(unsigned char data_);

Description

Sends data byte via the I²C bus.

This is a generic routine which uses the active I²C module previously activated by the I2C_Set_Active routine.

Parameters
  • data_: data to be sent
Returns

  • 0 if there were no errors.
  • 1 if write collision was detected on the I²C bus.

Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Also, START signal needs to be issued in order to use this function. See I2Cx_Start.

Example
unsigned char data_;
unsigned error;
...

I2C_Set_Active(&I2C1_Start, &I2C1_Restart, &I2C1_Read, &I2C1_Write, &I2C1_Stop, &I2C1_Is_Idle); // Sets the I2C1 module active

error = I2C_Write(data_);
error = I2C_Write(0xA3);
Notes

None.

I2C_Stop

Prototype

void I2C_Stop();

Description

Issues STOP signal.

This is a generic routine which uses the active I²C module previously activated by the I2C_Set_Active routine.

Parameters

None.

Returns

Nothing.

Requires

MCU with at least one I²C module.

Used I²C module must be initialized before using this function. See I2Cx_Init routine.

Example
I2C_Set_Active(&I2C1_Start, &I2C1_Restart, &I2C1_Read, &I2C1_Write, &I2C1_Stop, &I2C1_Is_Idle); // Sets the I2C1 module active
// Issue STOP signal
I2C_Stop();
Notes

None.

Library Example

This code demonstrates working with the I²C library. Program sends data to EEPROM (data is written at the address 2). After that, program reads data from the same EEPROM address and displays it on PORTB for visual check. See the figure below how to interface the 24C02 to PIC32.

Copy Code To ClipboardCopy Code To Clipboard
void EEPROM_24C02_Init() {
  I2C2_Init(100000);
}

//--------------- Writes data to 24C02 EEPROM - signle location
void EEPROM_24C02_WrSingle(unsigned short wAddr, unsigned short wData) {
  I2C2_Start();              // issue I2C start signal
  I2C2_Write(0xA0);          // send byte via I2C  (command to 24cO2)
  I2C2_Write(wAddr);         // send byte (address of EEPROM location)
  I2C2_Write(wData);         // send data (data to be written)
  I2C2_Stop();
}

//--------------- Reads data from 24C02 EEPROM - single location (random)
unsigned short EEPROM_24C02_RdSingle(unsigned short rAddr) {
  unsigned short reslt;

  I2C2_Start();              // issue I2C start signal
  I2C2_Write(0xA0);          // send byte via I2C  (device address + W)
  I2C2_Write(rAddr);         // send byte (data address)
  I2C2_Restart();            // issue I2C signal repeated start
  I2C2_Write(0xA1);          // send byte (device address + R)
  reslt = I2C2_Read(1);      // Read the data (NO acknowledge)
  I2C2_Stop();
  return reslt;
}

unsigned short i;
char b;
void main(){
  CHECON = 0x30;
  AD1PCFG = 0xFFFFFFFF;
  
  LATB = 0;                   // Set PORTB value to zero
  TRISB = 0;                  // Configure PORTB as output
  TRISD = 0;                  // Configure PORTB as output
  LATD = 0;                   // Set PORTD value to zero
  
  EEPROM_24C02_Init();        // performs I2C initialization
  b = 0x00;
  for(i = 0x00; i<0x80; i++) {
    EEPROM_24C02_WrSingle(i,b);
    b++;
    delay_ms(5);
  }
  for(i = 0x00; i < 0x80; i++){
    LATD = i;
    LATB = EEPROM_24C02_RdSingle(i);
    delay_ms(100);
  }
}

Copyright (c) 2002-2017 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code