I2C

SANKI Easy Install


~# apt-get update
~# apt-get install i2c-tools
-# apt-get install python-smbus

-# sudo nano /etc/modules 
i2c-dev 
i2c-bcm2708


Reboot before test


Test 
    sudo python
    import smbus

or

    sudo i2cdetect -y 0



Detail tutorials : https://learn.sparkfun.com/tutorials/i2c


Setting up the Raspberry PI i2c ports


The i2c Ports on the raspberry pi are not enabled by default. Follow these steps to enable the i2c port. These instructions are for the official Raspbian distro.


First you will need to to edit the config file that disables the i2c port by default. This setting is stored in /etc/modprobe.d/raspi-blacklist.conf. we will use nano to edit this but you could use any editor you are comfortable with.


$sudo nano /etc/modprobe.d/raspi-blacklist.conf


Once this file is open find this line blacklist i2c-bcm2708 and comment it out by adding a # to the front of it.


#blacklist i2c-bcm2708


You can now save this file with Ctrl+O and pressing enter and exit nano with Ctrl+X. Once you are back at the command prompt reboot your raspberry pi.


$sudo reboot


Once the reboot has finished you need to make the ports active by running this command:


$sudo modprobe i2c-dev


 Now you should be able to see the i2c ports listed in your /dev/ directory


$ls /dev/i2c*


You should see /dev/i2c-0 and /dev/i2c-1 listed. To be able to use these ports you need to give yourself permission to access them.


$sudo chmod o+rw /dev/i2c*


Now your i2c ports will be ready for you to use. You will have to run the modprobe and chmod commands every time you login to activate the ports and apply the permissions. If you wish to automate this process so the commands are run every time you log in then you can edit /etc/rc.local and add the commands in. 

I2C Tools

Using i2c-tools

The faster way to do the first experiments with this board is by installing and using the i2c-tools.

i2c-tools is a package contains a heterogeneous set of I2C tools for Linux such as:

  • a bus probing tool
  • a chip dumper
  • a register-level access helpers
  • an EEPROM decoding scripts
  • ...and more

To install i2c-tools on the FOX Board just type:

~# apt-get update
~# apt-get install i2c-tools
-# apt-get install python-smbus

-# sudo nano /etc/modules 
i2c-dev 
i2c-bcm2708

Using i2cdetect

i2cdetect is an userspace program to scan an I2C bus for devices. It outputs a table with the list of detected devices on the specified bus.

Example of use:

~# i2cdetect -y 0
     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: -- -- -- -- -- -- -- --                                                     

In this case a device has been detected on address 20 hex.

Using i2cset and i2cset

i2cget is a small helper program to set registers visible through the I2C bus.

The follow simple command writes the byte value 255 to the I2C device at address 20 hex on the i2c bus 0 (/dev/i2c-0).

~# i2cset -y 0 0x20 255

If for example you are using a DAISY-22 module with a PCF8574 I2C I/O expander this command will set all the GPIO lines to 1.

i2cget i2cget is a small helper program to read registers visible through the I2C bus.

The follow simple command read a byte from an I2C device at address 20 hex on the i2c bus 0 (/dev/i2c-0).

~# i2cget -y 0 0x20
0x01

Python code example

python-smbus is a Python module allows SMBus access through the I2C /dev interface on Linux hosts. The host kernel must have I2C support, I2C device interface support, and a bus adapter driver.

Write a register

The following example sends a sequence of values from 0 to 255 to the PCF8574 I2C I/O expander at address 0x20.

  • write.py
    import smbus
    import time
     
    bus = smbus.SMBus(0)
     
    for a in range(0,256):
    	bus.write_byte(0x20,a)
    	time.sleep(0.1)

Run it by typing:

~# python write.py

Read a register

The following read the GPIO status of a PCF8574 I2C I/O expander at address 0x20. Note that we have to write 1 on the input line we want to read.

  • read.py
    import smbus
     
    I2C_ADDRESS = 0x20 
     
    bus = smbus.SMBus(0)
     
    #Set all ports in input mode
    bus.write_byte(I2C_ADDRESS,0xFF)
    
    #Read all the unput lines
    value=bus.read_byte(I2C_ADDRESS)
    print "%02X" % value

Run it by typing:

~# python read.py

C code example

Write a register

The following example sends a sequence of values from 0 to 255 to the PCF8574 I2C I/O expander at address 0x20 in C language.

  • write.c
    #include <stdio.h>
    #include <fcntl.h>
    #include <linux/i2c-dev.h>
    #include <errno.h>
    
    #define I2C_ADDR 0x20
     
    int main (void) {
    	int value;
    	int fd;
    
    	fd = open("/dev/i2c-0", O_RDWR);
    
    	if (fd < 0) {
    		printf("Error opening file: %s\n", strerror(errno));
    		return 1;
    	}
    
    	if (ioctl(fd, I2C_SLAVE, I2C_ADDR) < 0) {
    		printf("ioctl error: %s\n", strerror(errno));
    		return 1;
    	}
    
    	for (value=0; value<=255; value++) {
    		if (write(fd, &value, 1) != 1) {
    			printf("Error writing file: %s\n", strerror(errno));
    		}
    		usleep(100000);
    	}
    	return 0;
    }
    

Compile it by typing:

~# gcc write.c -o write

Then launch it:

~# ./write

Read a register

The following example get the state of the GPIO line from a PCF8574 I2C I/O expander at address 0x20.

  • read.c
    #include <stdio.h>
    #include <fcntl.h>
    #include <linux/i2c-dev.h>
    #include <errno.h>
    
    #define I2C_ADDR 0x20
     
    int main (void) {
    	char buffer[1];
    	int fd;
    
    	fd = open("/dev/i2c-0", O_RDWR);
    
    	if (fd < 0) {
    		printf("Error opening file: %s\n", strerror(errno));
    		return 1;
    	}
    
    	if (ioctl(fd, I2C_SLAVE, I2C_ADDR) < 0) {
    		printf("ioctl error: %s\n", strerror(errno));
    		return 1;
    	}
    
    	buffer[0]=0xFF;
    	write(fd, buffer, 1);
    	
    	read(fd, buffer, 1);
    	printf("0x%02X\n", buffer[0]);
    	return 0;
    }

Compile it by typing:

~# gcc read.c -o read

Then launch it:

~# ./read


Using the I2C Interface

Enabling The I2C Port

The I2C port needs to be enabled in Rasbian before it can be used. See here.

Checking For Connected Devices

At the command prompt type one of these depending on whether you are using the I2C0 or I2C1 port:


sudo i2cdetect -y 0
//or
sudo i2cdetect -y 1

The 7 bit I2C address of all found devices will be shown (ignoring the R/W bit, so I2C address 0000 0110 is displayed as hex 03).

 

SMBus (System Management Bus) Functions

SMBus (System Management Bus) is a subset from the I2C protocol
When writing a driver for an I2C device try to use the SMBus commands if possible (if the device uses only that subset of the I2C protocol) as it makes it possible to use the device driver on both SMBus adapters and I2C adapters.

Note address is the 7 bit address excluding the read / write bit (it will be shifted left 1 bit whne added to the read/write bit)


long write_quick(int addr)

Send only the read / write bit


long read_byte(int addr)

Read a single byte from a device, without specifying a device register.


long write_byte(int addr,char val)

Send a single byte to a device


long read_byte_data(int addr,char cmd)

Read Byte Data transaction.


long write_byte_data(int addr,char cmd,char val)

Write Byte Data transaction.


long read_word_data(int addr,char cmd)

Read Word Data transaction.


long write_word_data(int addr,char cmd,int val)

Write Word Data transaction.


long process_call(int addr,char cmd,int val)

Process Call transaction.


long[] read_block_data(int addr,char cmd)

Read Block Data transaction.     


write_block_data(int addr,char cmd,long vals[])

Write up to 32 bytes to a device.  This fucntion adds an initial byte indicating the length of the vals array before the valls array.  Use write_i2c_block_data instead!


long[] block_process_call(int addr,char cmd,long vals[])

Block Process Call transaction.     

I2C Access Functions


long[] read_i2c_block_data(int addr,char cmd)

Block Read transaction.


write_i2c_block_data(int addr,char cmd,long vals[])

Block Write transaction.

Code Example


#!/usr/bin/python

import smbus

bus = smbus.SMBus(1)    # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)

DEVICE_ADDRESS = 0x15      #7 bit address (will be left shifted to add the read write bit)
DEVICE_REG_MODE1 = 0x00
DEVICE_REG_LEDOUT0 = 0x1d

#Write a single register
bus.write_byte_data(DEVICE_ADDRESS, DEVICE_REG_MODE1, 0x80)

#Write an array of registers
ledout_values = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
bus.write_i2c_block_data(DEVICE_ADDRESS, DEVICE_REG_LEDOUT0, ledout_values)
MORE Example

Reference

OK