An I2C (Inter-Integrated Circuit) is a two-wire, bidirectional serial bus that provides a simple, efficient method of data exchange that minimizes the interconnection between devices. This bus is suitable for applications requiring occasional communication over a short distance between many devices. The flexible I2C standard allows you to connect additional devices to the bus for expansion and system development.
The ConnectCore platforms have several I2C interfaces. You can find more information in Hardware reference manuals and I2C.
Digi adds an API to Linux to manage these I2C devices as master. To use this API, include the following header file:
#include <libdigiapix/i2c.h>
You can configure them and communicate with connected devices over the I2C bus.
Request an I2C
You can request an I2C with one of the following functions:
Function | Description |
---|---|
|
Requests an I2C by its bus number. It returns a pointer to |
|
Requests an I2C by its alias name. The I2C alias mapping must be defined in the It returns a pointer to |
The requested I2C must be freed once it is not needed anymore. See Free an I2C. |
Both functions may fail and return NULL
for the following reasons:
-
If the provided bus number or the bus number associated with the given alias cannot be exported.
-
If the API encountered problems allocating memory to initialize the I2C. Your system may have run out of resources.
/* Request an I2C using its alias */
i2c_t *i2c1 = ldx_i2c_request_by_alias("DEFAULT_I2C");
/* Request an I2C using bus number */
i2c_t *i2c2 = ldx_i2c_request(2);
printf("The I2C-%d was requested\n", i2c1->bus);
printf("The I2C-%d was requested\n", i2c2->bus);
Establish I2C aliases
To help you identify the I2Cs of your design, you can assign aliases to your I2C Linux IDs.
Map the assigned bus number to a name in the /etc/libdigiapix.conf
file:
-
Add a section called [I2C], if one does not already exist.
-
Below the section name, add the list of mapped I2Cs following the format:
<alias> = <i2c_bus>
Where:
-
<alias>
is the human-readable name for the I2C. -
<i2c_bus>
is the I2C bus.
-
[I2C]
# I2C-1 on I2C board connector.
DEFAULT_I2C_BUS = 0
For example, using the configuration above, you can request an I2C with the API using DEFAULT_I2C_BUS
alias.
See Request an I2C.
You can get the bus associated to an alias using these functions:
int ldx_i2c_get_bus(const char * const i2c_alias);
For information on including libdigiapix.conf in your Digi Embedded Yocto images, see Define interface aliases.
|
List available I2C buses
You can determine the list of available I2C buses on the target device with the ldx_i2c_list_available_buses()
API function:
int ldx_i2c_list_available_buses(uint8_t **buses);
The function returns the number of available buses for the I2C interface, or -1 if there is an error.
uint8_t *buses = NULL;
int i, bus_number = 0;
bus_number = ldx_i2c_list_available_buses(&buses);
if (bus_number > 0) {
printf("The target has %d I2C available buses:\n", bus_number);
for (i = 0; i < bus_number; i++)
printf(" - I2C-%d\n", buses[i]);
} else {
printf("The target does not have any I2C bus available\n");
}
free(buses);
Free an I2C
You must free a requested I2C when it is no longer required.
To do so, set the ldx_i2c_free()
function.
int ldx_i2c_free(i2c_t *i2c);
i2c_t *i2c = ...;
/* [...] */
ldx_i2c_free(i2c);
Configure I2C communication
You can configure the I2C behavior to either terminate a communication on time out or to retry accessing an I2C device on acknowledge error. To specify the timeout where the I2C waits for a response from the I2C device, use the following function:
Function | Description |
---|---|
|
Sets the I2C transfer timeout in tenths of milliseconds. It returns |
The timeout parameter defines the I2C timeout in units of 10ms. If you would like to set timeout to 50 ms, set timeout to 5.
int timeout = 5; /* 50ms */
i2c_t *i2c = ldx_i2c_request(1);
ldx_i2c_set_timeout(i2c, timeout);
/* [...] */
ldx_i2c_free(i2c);
The retry parameter defines the I2C attempts when acknowledge fails in an I2C communication.
Function | Description |
---|---|
|
Sets the I2C bus poll retries. It returns |
int retry = 3;
i2c_t *i2c = ldx_i2c_request(1);
ldx_i2c_set_retries(i2c, retry);
/* [...] */
ldx_i2c_free(i2c);
Communicate with I2C slaves
The API allows three types of communication with other I2C slave devices.
Write data to I2C slave devices
You can send data to other I2C slave devices using the ldx_i2c_write()
function:
Function | Description |
---|---|
|
Sends data to I2C slave devices.
It returns |
#define DATA_SIZE 8
int i = 0;
uint8_t tx_buffer[DATA_SIZE] = {0};
uint8_t i2c_address = 0x55;
i2c_t *i2c = ...;
/* Fill the buffer with random data */
for (i = 0; i < DATA_SIZE; i++) {
tx_buffer[i] = rand() % 255;
}
printf("Writing %d bytes to I2C-%d slave %x...\n", DATA_SIZE, i2c->bus, i2c_address);
ldx_i2c_write(i2c, i2c_address, tx_buffer, DATA_SIZE);
Read data from I2C slave devices
You can receive data from other I2C slave devices using the ldx_i2c_read()
function.
One of the most common things to do with an I2C interface is read one or more bytes from a specific device slave address.
Function | Description |
---|---|
|
Receives data from I2C slave devices.
It returns |
#define DATA_SIZE 8
int i = 0;
uint8_t rx_buffer[DATA_SIZE] = {0};
uint8_t i2c_address = 0x55;
i2c_t *i2c = ...;
printf("Reading %d bytes from I2C-%d slave %x...\n", DATA_SIZE, i2c->bus, i2c_address);
ldx_i2c_read(i2c, i2c_address, rx_buffer, DATA_SIZE);
for (i = 0; i < DATA_SIZE; i++) {
printf("rx_data[%d] = 0x%02x\n", i, rx_buffer[i]);
}
Transfer data to I2C slave devices
You can write and read data simultaneously to and from I2C slave devices in one operation using the ldx_i2c_transfer()
function:
Function | Description |
---|---|
|
Transfers data with I2C slave devices.
It returns |
#define DATA_SIZE 8
int i = 0;
uint8_t tx_buffer[] = {0x23};/* I2C slave specific command or register */
uint8_t rx_buffer[DATA_SIZE] = {0};
uint8_t i2c_address = 0x55;
i2c_t *i2c = ...;
ldx_i2c_transfer(i2c, i2c_address, tx_buffer, 1, rx_buffer, DATA_SIZE);
printf("Read %d bytes from the I2C-%d slave %x...\n", DATA_SIZE, i2c->bus, i2c_address);
for (i = 0; i < DATA_SIZE; i++) {
printf("rx_data[%d] = 0x%02x\n", i, rx_buffer[i]);
}
I2C example
In this example, I2C writes the page of an external EEPROM memory with random data and then reads the data back to validate it.
You can import the example in Eclipse using the Digi Embedded Yocto plugin. For more information, see Create a new DEY sample project. This example is included in Digi Embedded Yocto. Go to GitHub to see the application source code.