Getting to know the Raspberry Pi I2C bus

GPIO and the I2C Driver

To use the I2C bus, you need to load the I2C driver, which requires the WiringPi library [5] (Listing 1). You might already be familiar with the library from other projects. Before downloading, you should update the system and install the Git client (git clone). The output from gpio -v or gpio readall (Figure 2) will let you know whether the library has been installed successfully.

Listing 1

Installing WiringPi

$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install git-core
$ git clone git://git.drogon.net/wiringPi
$ cd wiringPi
Figure 2: Checking the WiringPi library installation with gpio readall.

Now you have access to the GPIO, although the system and the I2C bus are not yet able to understand one other. For this you need the i2c-tools from the packet sources; then, you should incorporate the standard user, pi, for the system in the user group i2c.

A single logout and login will activate the group membership. On activation, you should load the I2C driver using the gpio command:

$ sudo apt-get install i2c-tools$ sudo adduser pi i2c
$ gpio load i2c

The i2cdetect command will now display which devices are hanging on the bus and the address for each of them.

The test setup communicates with the controller via the address 0x20 (Listing 2). The upper 4 bits of the I/O component are in contact with the LEDs, whereas the low nibble (4 bits or one-half byte) is connected to the switches.

Listing 2

i2cdetect

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

All of the PCF8574 pins are set HIGH by default, so you should not be surprised when all of the LEDs light up. You can turn all of the LEDs off at once with the first command in Listing 3.

Listing 3

Turning LEDs Off and On

$ i2cset -y 1 0x20 0x00
$ i2cset -y 1 0x20 0x10
$ i2cset -y 1 0x20 0x20
$ i2cset -y 1 0x20 0x40
$ i2cset -y 1 0x20 0x80

The following lines then turn the LEDs on one at a time. Initially, you should set the corresponding pins HIGH to read out the switches. The PCF8574 is largely responsible for having to do things this way, a topic to be discussed in more detail in a future article.

To get started at this stage, you should therefore set the pin with i2cset and read out the condition of the switches with i2cget, using watch to echo the output to the console:

$ i2cset -y 1 0x20 0x0f
$ watch 'i2cget -y 1 0x20'

Now you are familiar with one possible way to access the I2C bus. The commands used at the command line can be called from all programming languages. As a result, even more complex I2C applications do not present obstacles. However, many developers start getting enthusiastic only when they are able to use an API for their favorite language.

I2C with C

To avoid going beyond the scope of this article at this point, I will stick to addressing just the C and Java APIs. Microcontroller enthusiasts often use C because of its thin layer of abstraction. Java is exactly the opposite. The Java programmer doesn't want to know anything at all about the hardware that executes a program. Therefore, I will begin with C.

In C, access to an I2C device is related to accessing a file. First you should get a file handle with:

wiringPiI2CSetup(<address>)

Here, <address> is the value output from i2cdetect. Table 3 lists the most important C function calls.

Table 3

Basic Functions in C

Function

Purpose

int wiringPiI2CRead(int handle)

Simple read

int wiringPiI2CWrite(int handle, int data)

Simple write

int wiringPiI2CReadReg8(int fd, int reg)

Read 8-bit values from a register

int wiringPiI2CWriteReg8(int fd, int reg, int data)

Write 8-bit values to a register

int wiringPiI2CReadReg16(int fd, int reg)

Read 16-bit values from a register

int wiringPiI2CWriteReg16(int fd, int reg, int data)

Write 16-bit values to a register

Other libraries, which I will look at more closely in future articles, build on these functions for more complex program components. By way of concluding this introduction to C, Listing 4 makes the LEDs in the test setup light up one after the other. When compiling, you need to make sure you incorporate the WiringPi library:

Listing 4

Light LEDs in C

01 #include <wiringPiI2C.h>
02
03 int main(void) {
04   int handle = wiringPiI2CSetup(0x20) ;
05   wiringPiI2CWrite(handle, 0x10);
06   delay(5000);
07   wiringPiI2CWrite(handle, 0x20);
08   delay(5000);
09   wiringPiI2CWrite(handle, 0x40);
10   delay(5000);
11   wiringPiI2CWrite(handle, 0x80);
12   delay(5000);
13   wiringPiI2CWrite(handle, 0x00);
14   return 0;
15 }
$ cc i2c_test.c -lwiringPi
$ ./a.out

Buy this article as PDF

Express-Checkout as PDF

Pages: 6

Price $2.95
(incl. VAT)

Buy Raspberry Pi Geek

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content