Skip to content

Reading a register value from a slave on I2C bus

I2C tutorial will guide you through initializing and working with the I2C module inside your MCU using mikroSDK 2.0.
In order to follow this tutorial, you will need to have familiarized yourself with context and configuration structures, their purpose and their proper initialization.
The following example will show the correct way of using the I2C driver in mikroSDK V2.

To start, we need to include the I2C driver. In this case, we need the drv_i2c_master.h as our MCU will act as master:

#include "drv_i2c_master.h"

Next step is to declare context structure as well as configuration structure, since I2C driver requires it.
We also declare two buffers, one for write and one for read:

i2c_master_t        i2c_master;       // Context structure
i2c_master_config_t i2c_master_cfg;   // Configuration structure

uint8_t write_buffer[3];
uint8_t read_buffer [3];

Moving onto the application_init() function, in which we initialize configuration structure to its default values, set SCL and SDA pins and perform initialization of the I2C driver context:

i2c_master_configure_default(&i2c_master_cfg);  /*Initialize I2C master
configuration structure to default values */

i2c_master_cfg.scl = PB8;    // Set scl pin.
i2c_master_cfg.sda = PB9;    // Set sda pin.

i2c_master_open(&i2c_master, &i2c_master_cfg);  // Initialize the driver context
i2c_master_set_speed(&i2c_master, I2C_MASTER_SPEED_STANDARD);  // Set clock speed

It is needed to use the i2c_master_set_slave_address() function to specify the slave address, otherwise it will remain zero:

i2c_master_set_slave_address(&i2c_master, 0x50);  // Set 7-bit slave address

Let's say we wish to read two bytes from this slave device. We can easily achieve that by using the i2c_master_write_then_read() function, like so:

#define write_count 1
#define read_count  2

write_buffer[0] = 0x00;    // Registry address

i2c_master_write_then_read(&i2c_master, &write_buffer, write_count, &read_buffer, read_count);

That's it. The read_buffer will now contain the data we read from the slave device.

The entire code can be found below:

#include "drv_i2c_master.h"

#define write_count 1
#define read_count  2

i2c_master_t        i2c_master;
i2c_master_config_t i2c_master_cfg;

uint8_t write_buffer[3];
uint8_t read_buffer [3];


void application_init ( )
{
    i2c_master_configure_default(&i2c_master_cfg);

    i2c_master_cfg.scl = PB8;
    i2c_master_cfg.sda = PB9;

    i2c_master_open(&i2c_master, &i2c_master_cfg);
    i2c_master_set_speed(&i2c_master, I2C_MASTER_SPEED_STANDARD);

    i2c_master_set_slave_address(&i2c_master, 0x50);

    write_buffer[0] = 0x00;

    i2c_master_write_then_read(&i2c_master, &write_buffer, write_count, &read_buffer, read_count);
}

void application_task ( )
{
    asm nop;
}

void main ( void )
{

    application_init( );

    for ( ; ; )
    {
        application_task( );
    }    
}