I am using imx6qsabresd board.
I want to develop user space application to access on board i2c based mma8451q 3-Axis Orientation/Motion Detection Sensor.
I am using eclipse for development.
Below is my code for that.
#include <stdlib.h>
#include <stdio.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#define SLAVE_ADDRESS 0x1D
// I2C Linux device handle
int g_i2cFile;
// open the Linux device
void i2cOpen()
{
g_i2cFile = open("/dev/i2c-0", O_RDWR);
if (g_i2cFile < 0) {
perror("i2cOpen");
puts("I2C Open Failed");
exit(1);
}
else
puts("I2C Open Success");
}
// close the Linux device
void i2cClose()
{
close(g_i2cFile);
}
// set the I2C slave address for all subsequent I2C device transfers
void i2cSetAddress(int address)
{
if (ioctl(g_i2cFile, I2C_SLAVE, address) < 0) {
perror("i2cSetAddress");
puts("I2C Set Address Failed");
exit(1);
}
else
puts("I2C Set Address Success");
}
int main(void) {
unsigned char res,i;
puts("MMA8451Q Accelerometer Test Program"); /* prints Hello World */
i2cOpen();
i2cSetAddress(SLAVE_ADDRESS);
res = i2c_smbus_read_byte_data(g_i2cFile, 0x0D);
printf("Result= %d\n\r\n\r", res);
i2cClose();
return 0;
}
First function i2c_smbus_read_byte_data() cannot be found by eclipse.
So i searched around and found solution. I run "sudo apt-get install libi2c-dev" and replace i2c_dev.h in "/opt/poky/1.8/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/include/linux" from newly created i2c_dev.h in "/usr/include/linux".
Now i can successfully compile the code.
So is this a right step?
And the output of the code is
MMA8451Q Accelerometer Test Program
I2C Open Success
I2C Set Address Success
Result= 255
It should be 0x1A (Device ID).
I am getting 255 result fro all the address.
So whats wrong in this code?
Solved! Go to Solution.
bool I2C::read(unsigned char addr, unsigned char reg,
unsigned short &val, bool msb) const
{
i2c_rdwr_ioctl_data data;
i2c_msg msgs[2];
__u8 buf[sizeof(__u8) * 2] = {reg, 0};
if (-1 == _fd)
return false;
msgs[0].addr = static_cast<__u16>(addr);
msgs[0].buf = buf;
msgs[0].flags = 0;
msgs[0].len = static_cast<__u16>(sizeof(unsigned char));
msgs[1].addr = static_cast<__u8>(addr);
msgs[1].flags = I2C_M_RD;
msgs[1].len = static_cast<__u16>(sizeof(unsigned short));
msgs[1].buf = buf;
data.msgs = msgs;
data.nmsgs = 2;
if (-1 == ioctl(_fd, I2C_RDWR, &data))
return false;
val = (buf[msb ? 1 : 0] << 8) | buf[msb ? 0 : 1];
return true;
}
bool I2C::read(unsigned char addr, unsigned char reg,
unsigned short &val, bool msb) const
{
i2c_rdwr_ioctl_data data;
i2c_msg msgs[2];
__u8 buf[sizeof(__u8) * 2] = {reg, 0};
if (-1 == _fd)
return false;
msgs[0].addr = static_cast<__u16>(addr);
msgs[0].buf = buf;
msgs[0].flags = 0;
msgs[0].len = static_cast<__u16>(sizeof(unsigned char));
msgs[1].addr = static_cast<__u8>(addr);
msgs[1].flags = I2C_M_RD;
msgs[1].len = static_cast<__u16>(sizeof(unsigned short));
msgs[1].buf = buf;
data.msgs = msgs;
data.nmsgs = 2;
if (-1 == ioctl(_fd, I2C_RDWR, &data))
return false;
val = (buf[msb ? 1 : 0] << 8) | buf[msb ? 0 : 1];
return true;
}
Thanks for the Reply.
I am not getting the 0 for all register read.
Below is my program. I modified to clear eclipse compilation error.
void I2C_read(unsigned char addr, unsigned char reg, unsigned char msb)
{
__u16 val;
struct i2c_rdwr_ioctl_data data;
struct i2c_msg msgs[2];
__u8 buf[sizeof(__u8) * 2] = {reg, 0};
msgs[0].addr = (__u16)(addr);
msgs[0].buf = buf;
msgs[0].flags = 0;
msgs[0].len = (__u16)(sizeof(unsigned char));
msgs[1].addr = (__u8)(addr);
msgs[1].flags = I2C_M_RD;
msgs[1].len = (__u16)(sizeof(unsigned short));
msgs[1].buf = buf;
data.msgs = msgs;
data.nmsgs = 2;
if (-1 == ioctl(g_i2cFile, I2C_RDWR, &data))
{
}
val = (buf[msb ? 1 : 0] << 8) | buf[msb ? 0 : 1];
printf("Result = %d\n\r", val);
}
I2C_read(0x0D,0x00,0);
the result:
MMA8451Q Accelerometer Test Program
I2C Open Success
I2C Set Address Success
Result= 0
I got 0 for all address.
Also tried for I2C_read(0x0D,0x00,1); but thje result is 0.
Whats wrong in my code?
Sensor Datasheet
http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8451Q.pdf
Refer Page19 i am reading register 0x0D.
Why you use address 0xD if datasheet describe 0x1C and 0x1D?
I think you can use register 0xD (WHO_AM_I) for check programm, it should return 0x1A.
Ya. That's my mistake.
I figured it out.
The device address is 0x1C. And if i try to open it will give message "device or resource busy".
This device driver is added as build in in kernel. So i unable to remove it. So i can't able to open i2c.
So i modify kernel configuration. And Add other i2c based MAG3110 (Digital Compass) as module.
I tried for adding MMA8451Q as module but bitbake giving me error.
And after restart i remove the module. And Run Program with correct device id.
And i am getting the Right Result.
Thanks.
But now i want to use MAC3110 kernel driver API in my application code.
Actually i am new to linux field.
So can you guide me how to so that?