Difference between revisions of "EMAC I²C Programming"
| (13 intermediate revisions by 4 users not shown) | |||
| Line 1: | Line 1: | ||
| − | {{todo| | + | {{todo|SEOKWREV; (12.4.13-15:35->MD+);(12.26.13-14:05->MW+);(12.26.13-14:50->MG+);(03.04.14-16:25->BS-);(03.26.14-16:55->BS+);(04.14.14-14:55->BS+)|Michael Welling|project=oe 4,oe 5,mw,md,mg,bs,SEOKWREV}} |
| + | |||
| + | {{#seo: | ||
| + | |title=EMAC I²C Programming | ||
| + | |titlemode=append | ||
| + | |keywords=I²C Programming,i2c-dev Interface | ||
| + | |description=Programming I²C device. | ||
| + | }} | ||
=== Background Information === | === Background Information === | ||
| − | I²C is a low-speed two wire serial interface used to connect to a variety of sensor and I/O devices. | + | I²C is a low-speed (400 kHz max.) two wire serial interface used to connect to a variety of sensor and I/O devices. The interface uses two bi-directional open-drain I/Os, SDA and SCL, to communicate to devices based on an address encoded within the data transmission. SDA is a data signal which sends and receives serially transmitted data. SCL is a clock signal which is used to determine when to latch data from the SDA line. |
| − | The interface uses bi-directional open-drain I/Os, SDA and SCL, to communicate to devices based on an address encoded | ||
For more information about the protocol see the following page: | For more information about the protocol see the following page: | ||
| − | http://en.wikipedia.org/wiki/ | + | http://en.wikipedia.org/wiki/I²C |
| + | |||
| + | This page specifically covers the usage of the Linux I²C i2c-dev driver. | ||
| + | |||
| + | For more information about the Linux I²C subsystem: | ||
| + | https://i2c.wiki.kernel.org/index.php/Main_Page | ||
| + | |||
| + | === Accessing the i2c-dev Interface === | ||
| + | When the i2c-dev driver is properly loaded it exposes a device interface for each available I²C interface. Each interface will have an associated character device node at <code>/dev/i2c-X</code>, where X is replaced by a number representing the interface. This device node allows the user to access the I²C interface directly from a C program. | ||
| + | |||
| + | To open an I²C device node from a C program, use the standard <code>open</code> command as follows: | ||
| + | <syntaxhighlight lang="c"> | ||
| + | int fd; | ||
| + | ⋮ | ||
| + | fd = open("/dev/i2c-0", O_RDWR); | ||
| + | |||
| + | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | Once the device is open, the <code>I2C_SLAVE ioctl</code> command is used to set the address of the slave I²C device: | ||
| + | |||
| + | <syntaxhighlight lang="c"> | ||
| + | #include "i2c-dev.h" | ||
| + | ⋮ | ||
| + | int ret; | ||
| + | int addr = 0x0e; | ||
| + | ⋮ | ||
| + | ret = ioctl(fd, I2C_SLAVE, addr); | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | |||
| + | After the device address is set, the device can be accessed with the standard <code>read</code> and <code>write</code> commands: | ||
| + | <syntaxhighlight lang="c"> | ||
| + | int data = 0xaa; | ||
| + | ⋮ | ||
| + | ret = write(fd, &data, 1); | ||
| + | ⋮ | ||
| + | ret = read(fd, &data, 1); | ||
| + | </syntaxhighlight> | ||
| + | Below is a functional code listing that puts all of the commands together, showing the required include files and error checking. For a more complete example refer to the [[Example_i2c_test | I²C demo]] in the EMAC SDK. | ||
| + | ==== Simple C Code Example ==== | ||
| + | |||
| + | <syntaxhighlight lang="c"> | ||
| + | #include <stdio.h> | ||
| + | #include <stdlib.h> | ||
| + | #include <unistd.h> | ||
| + | #include <sys/ioctl.h> | ||
| + | #include <sys/types.h> | ||
| + | #include <sys/stat.h> | ||
| + | #include "i2c-dev.h" | ||
| + | |||
| + | int main(int argc, char * argv[]) | ||
| + | { | ||
| + | int fd; | ||
| + | int ret; | ||
| + | int addr = 0x0e; | ||
| + | int data = 0xaa; | ||
| + | |||
| + | fd = open("/dev/i2c-0", O_RDWR); | ||
| + | |||
| + | if(fd < 0) { | ||
| + | fprintf(stderr, "Cannot open i2c device\n"); | ||
| + | exit(-1); | ||
| + | } | ||
| + | |||
| + | ret = ioctl(fd, I2C_SLAVE, addr); | ||
| + | |||
| + | if(ret < 0) { | ||
| + | fprintf(stderr, "Cannot set slave address\n"); | ||
| + | exit(-1); | ||
| + | } | ||
| + | |||
| + | ret = write(fd, &data, 1); | ||
| + | |||
| + | if(ret != 1) | ||
| + | fprintf(stderr, "Cannot write i2c device\n"); | ||
| + | |||
| + | ret = read(fd, &data, 1); | ||
| + | |||
| + | if(ret != 1) | ||
| + | fprintf(stderr, "Cannot read i2c device\n"); | ||
| + | else | ||
| + | printf("Byte read from i2c was %x\n", data); | ||
| + | |||
| + | exit(0); | ||
| + | } | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | {{imbox | type=notice | text=The i2c-dev.h header is taken from the lm-sensor project and defines the i2c character device interface. This file is included in the i2c test demo included in the EMAC SDK.}} | ||
Latest revision as of 14:55, 14 April 2014
Background Information
I²C is a low-speed (400 kHz max.) two wire serial interface used to connect to a variety of sensor and I/O devices. The interface uses two bi-directional open-drain I/Os, SDA and SCL, to communicate to devices based on an address encoded within the data transmission. SDA is a data signal which sends and receives serially transmitted data. SCL is a clock signal which is used to determine when to latch data from the SDA line.
For more information about the protocol see the following page: http://en.wikipedia.org/wiki/I²C
This page specifically covers the usage of the Linux I²C i2c-dev driver.
For more information about the Linux I²C subsystem: https://i2c.wiki.kernel.org/index.php/Main_Page
Accessing the i2c-dev Interface
When the i2c-dev driver is properly loaded it exposes a device interface for each available I²C interface. Each interface will have an associated character device node at /dev/i2c-X, where X is replaced by a number representing the interface. This device node allows the user to access the I²C interface directly from a C program.
To open an I²C device node from a C program, use the standard open command as follows:
int fd;
⋮
fd = open("/dev/i2c-0", O_RDWR);
Once the device is open, the I2C_SLAVE ioctl command is used to set the address of the slave I²C device:
#include "i2c-dev.h"
⋮
int ret;
int addr = 0x0e;
⋮
ret = ioctl(fd, I2C_SLAVE, addr);
After the device address is set, the device can be accessed with the standard read and write commands:
int data = 0xaa;
⋮
ret = write(fd, &data, 1);
⋮
ret = read(fd, &data, 1);
Below is a functional code listing that puts all of the commands together, showing the required include files and error checking. For a more complete example refer to the I²C demo in the EMAC SDK.
Simple C Code Example
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "i2c-dev.h"
int main(int argc, char * argv[])
{
int fd;
int ret;
int addr = 0x0e;
int data = 0xaa;
fd = open("/dev/i2c-0", O_RDWR);
if(fd < 0) {
fprintf(stderr, "Cannot open i2c device\n");
exit(-1);
}
ret = ioctl(fd, I2C_SLAVE, addr);
if(ret < 0) {
fprintf(stderr, "Cannot set slave address\n");
exit(-1);
}
ret = write(fd, &data, 1);
if(ret != 1)
fprintf(stderr, "Cannot write i2c device\n");
ret = read(fd, &data, 1);
if(ret != 1)
fprintf(stderr, "Cannot read i2c device\n");
else
printf("Byte read from i2c was %x\n", data);
exit(0);
}
|
|
The i2c-dev.h header is taken from the lm-sensor project and defines the i2c character device interface. This file is included in the i2c test demo included in the EMAC SDK. |