I2C Functions

From openPicus Wiki
Jump to: navigation, search


What you are going to learn

This tutorial shows how to add and manage I2C communication on Flyport. OpenPicus framework offers some functions to easily manage the I2C communication, using Flyport as a Master. In this way it’s possible to communicate with I2C slave devices and read/write their register. It’ possible to attach more than one device on the bus, since I2C uses addressing. The only issue is to check that any device connected on the bus must have a different address.

FlyportPRO warning

This tutorial is made for Flyport modules but works on FlyportPRO as well. Flyport PRO provides two different I2C busses. To use the I2C2 port just change APIs name, and mind that an onboard EEPROM is already available on PRO modules!

Initiating an I2C session

Before using any of the I2C functions, a bus initialization is needed, using the function I2CInit(), and specifying the speed required for the communication, LOW_SPEED (100KHz) or HIGH_SPEED (400KHz).

//   Initialization for high speed devices
//   OR initialization for low speed devices

Accessing the registers of a slave device

The fastest way to communicate with a I2C device, it's using the ready-to-go functions offered by the OpenPicus Framework to read/write its registers. Using the following functions, you don't need to know the details of the I2C communications, you are just requested to pass the device and the register(s) addresses and the commands will exchange the data with the slave device. The functions follows the standard way to read/write registers on I2C bus, if you experience some problem, always refer to the datasheet of your device to check if some particular operation is required to communicate.
Note on device addressing: in the following functions, with "device address" is intended the 7-bit I2C address of the device. You can find the default address and how to change it in the datasheet of each I2C device. The address will be correctly shifted and added with the read/write bit by the read/write functions.

Reading a single register

To read a single register from a specific device, it's possible to use the function I2CReadReg(). The sintax is the following:

char I2CReadReg(BYTE DeviceAddr, BYTE RegisterAddr, unsigned int Delay);

To perform the reading, the function first writes the address of the device and of the register on the bus, and then performs the reading. The last parameter is the delay (expressed in 10us) between the write and read operations performed. This delay is needed by some I2C device, generally the value to use is reported in the datasheet.
Example: reading of the register 0x10 from the device with address 0x20, the value of the register is put inside the variable myReg:

char myReg;
myReg = I2CReadReg(0x20, 0x10, 100)

Reading multiple registers

When 16 bit (or more) values must be read from a sensor, it's needed to perform a multiple reading of registers. The I2CReadMulti() function can perform a multiple reading of contiguous register of a device, just giving the starting one and the number to register to read.

BOOL I2CReadMulti(BYTE DeviceAddr, BYTE RegisterAddr, BYTE destination[], unsigned int numbReg, unsigned int Delay);

The function reads from the device specified in DeviceAddr a number NumbReg of registers, starting from the register RegisterAddr. The result is put inside the BYTE array destination. The operation returns TRUE in case of success, FALSE if some problem was found. Important: the size of the destination array must be equal or major than the number of register read.

Example: reading of three registers from the device with address 0x20, starting from the register 0x10.

BOOL report;
BYTE myDest[3];
report = I2CReadMulti(0x20, 0x10, myDest, 3, 100);
if (report)
    UARTWrite(1, "SUCCEDED");
    UARTWrite(1, "NOT SUCCEDED");

Writing a single register

Using the function I2CWriteReg() it's possible to read a single register from a specific I2C:

void I2CWriteReg(BYTE DeviceAddr, BYTE RegisterAddr, BYTE valueToWrite);

On the contrary of the read function, in this case a delay is not needed, since the function only performs writing operation on slave device. The function is a void, so it doesn't return anything.

Example: writing on the device 0x20, the register 0x10 is written with the value 0x01:

I2CWriteReg(0x20, 0x10, 0x01);

Writing multiple registers

Writing more than one register can be very useful to speed up writing operations in EEPROM or flash memory, when a long array of data must be saved in the non-volatile memory. The function I2CWriteMulti() fits the purpose. The syntax is the following:

void I2CWriteMulti(BYTE DeviceAddr, BYTE RegisterAddr,  BYTE dataSource[], unsigned int numbReg);

The function writes on device with address specified by DeviceAddr, starting from the register RegisterAddr, a number numReg of bytes taken from the array dataSource[]. The register address is automatically incremented, check on the datasheet of your device if multiple writing is supported (almost every I2C supports it, but some device doesn't).

Example: writing a three BYTE long array on a device with 0x20 address, starting from address register 0x10, so on device will be written the registers 0x10, 0x11, 0x12:

BOOL report;
BYTE myArray[3] = { 0x0A, 0x0B, 0x0C};
report = I2CWriteMulti(0x20, 0x10, myArray, 3);

At the end ofthe opertion, the value of the registers 0x10, 0x11 and 0x12 will be set to (respectively) 0x0A, 0x0B and 0x0C.

Basic I2C function

The I2C basic functions give the user the possibility to send/read single bytes and send start/stop/restart messages and can be combined to create your own communication procedure on I2C. As the previous set of functions, they need the I2CInit function to be called, to initialize correctly the bus communication.

Sending a start/Restart/stop messages

There are three different functions to send these management messages on the bus:

  • BOOL I2CStart() - send a start message on the bus;
  • BOOL I2CRestart() sends a restart message on the bus;
  • BOOL I2CStop() - sends a stop message on the bus

All the three function return a BOOL. If the operation is completed correctly within the timeout of 0.5sec, the functions return TRUE, otherwise FALSE.

Reading/writing a single byte

To read or write a single a byte, the functions are the following:

  • BYTE I2CRead(BYTE ack) - reads one byte from the bus, the value is returned as BYTE. The parameter ack can be 0 (ACK) or 1 (NACK).
  • BOOL I2CWrite(BYTE dataByte) - writes the single byte dataByte on the bus. The return value can be 1 (ACK) or 0 (NACK).
Personal tools