Article Index

The I2C Functions

There are two initialization functions

int bcm2835_i2c_begin (void)

void bcm2835_i2c_end (void)

The begin function changes pins 3 and 5 to ALT0 which gets things ready for I2C data transfer. The end function restores them to default GPIO inputs. 

You also have to set the speed of the bus if you don't want to accept the default 100KHz. 

There are two functions to set the clock:

void bcm2835_i2c_setClockDivider(uint16_t divider)

void bcm2835_i2c_set_baudrate(uint32_t baudrate)

There are a set of constants to set the clock to common frequencies. 

BCM2835_I2C_CLOCK_DIVIDER_2500  10us = 100 kHz

BCM2835_I2C_CLOCK_DIVIDER_626  2.504us = 399.3610 kHz

BCM2835_I2C_CLOCK_DIVIDER_150  60ns = 1.666 MHz (default at reset)

BCM2835_I2C_CLOCK_DIVIDER_148  59ns = 1.689 MHz

Note the frequencies quoted all assume a standard 250MHz clock rate.

The baud rate function is used to mimic the action of the Linux driver's setting. The library doesn't use the Linux driver this is purely for convenience of transferring software. The baud rate is simply the clock speed in Hz.

There is also a function to set the slave devices address for subsequent read/write operations. 

void bcm2835_i2c_setSlaveAddress(uint8_t addr)

Simply specify the slaves' address as specified in its data sheet.

Don't worry about any of the low-level descriptions of the way the least significant bit is used to determine if a read or a write is in operation - this is often reported in datasheets as one address for write and one for read. You also need to keep in mind that the 7-bit address is sent as the high order bits in the byte. 

For example, a device might report an address of 0x40 on its data sheet. On the bus this would translate to a write address of 0x80 for write and a read address of 0x81 i.e. to write device 0x40 you use 0x80 and to write to it you use 0x81.

However when you specify the devices address you simply use 0x40 and allow the library to convert it as required.

Write

There are two write functions the most basic is:

uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)

This performs a simple write of the buffer to the previously selected slave.  

What happens when you use one of these is that first an address frame is transmitted. The address frame is a byte containing the address of the device you specified. Notice that the 7-bit address has to be shifted into the top most bits and the first bit has to be zeroed. So to when you  write to a device with an address of 0x40 you would see 0x80 on a logic analyzer i.e.   0x40<<1.

After the address frame as many data frames are sent as you specified in buf and len.

Notice that a multibyte write involves sending a single address frame which means there is a difference between trying to send a block of data one byte at a time, which repeats the address frame and sending it in one go. 

If you know about the I2C protocol then it is worth saying that the functions deal with the start sequence, the address frame, it checks the NAK/ACK bit from the slave, sends the data bits, checks the NAK/ACK bit from the slave and sends the stop sequence.

That is in normal use the write transaction sending n bytes is:

START|ADDR|ACK|DATA0|ACK|
       DATA1|ACK|
        ....
          DATAn|ACK|STOP 

Notice that it is the slave that sends the ACK bit and if the data is not received correctly it can send NACK instead. Also notice that the Pi only sends a single STOP bit when the entire transaction is complete.

A multibyte transfer is quite different from sending n single bytes one at a time.

 START| ADDR |ACK|DATA0|ACK|STOP
  START| ADDR |ACK|DATA1|ACK|STOP
   ...
   START| ADDR |ACK|DATAn|ACK|STOP

Notice that there are now multiple ADDR frames sent as well as multiple START and STOP bits.

What this means in practice is that you have to look at a device's data sheet and send however many bytes it needs as a single operation - you cannot send the same number of bytes broken into chunks. 

Write To A Register

A very standard interaction between master and slave is writing data to a register.  This isn't anything special and as far as the I2C bus is concerned you are simply writing raw data but data sheets and users tend to think in terms of reading and writing internal storage locations i.e. registers in the device. 

In fact many devices have lots of internal storage, indeed some I2C devices are nothing but internal storage, e.g.. I2C EPROMs.

In this case a standard transaction to write to a register is:

  1. send address frame
  2. send  a data frame with the command to select the register
  3. send a data frame containing the byte or word to be written to the register. 

So for example you might use:

char buf[]={registerAddress,data};
bcm2835_i2c_write(buf,2);

Notice the command that has to be sent depends on the device and you have to look it up in its datasheet. Also notice that there is a single START and STOP bit at the beginning and end of the transaction.

Read

There are two read functions and this simplest follows the logic of what the write function does:

uint8_t bcm2835_i2c_read (char *buf, uint32_t len)
This sends an address frame and then reads as many bytes from the slave as specified. As in the case of write  the address supplied is shifted up one bit and the lower order bit set to one to indicate a read operation.  So if the current slave is at address 0x40 the read sends a read address of 0x81. 
 
The read transaction is:
 
START|ADDR|ACK|DATA0|ACK|
       DATA1|ACK|
         ...
        DATAn|NACK|STOP

The master sends the address frame and the slave sends the ACK after the address to acknowledge that it has been received and it is ready to send data. Then the slave sends bytes one at a time and the master sends ACK in response to each byte. Finally master sends a NACK to indicate that the last byte has been read and then a STOP bit.  That is the master controls how many bytes are transferred.

As in the case of the write functions a block transfer of n bytes is different from transferring n bytes one at a time.