I want to send a signal to i2c device though C++ application. I have tried to use system()
function, but it take about 7-10ms to return.
so I have found this library but it doesn't allow me to send the port number.
this is the command that i want to send
i2cset -f -y 0 0x74 2 0x00
where, 2 is the port number. 0x00: is the command that I need to set in destination device.
So my question is is there any way to send a direct way to communicate with i2c device the same as i2cset
application does?
Yes, there is a way. You can read some documentation here: https://www.kernel.org/doc/Documentation/i2c/dev-interface
Basically you have to first open the I2C device for reading and writing, on Raspberry Pi (which is where I have used this) it is:
int m_busFD = open("/dev/i2c-0", O_RDWR);
Then there are two ways:
ioctl
to set the address and then read()
or write()
to read or write to the line. This can look like so:bool receiveBytes(const int addr, uint8_t *buf, const int len)
{
if (ioctl(busFD, I2C_SLAVE, addr) < 0)
return -1;
int res = read(busFD, buf, len);
return res == len;
}
i2c_msg
/i2c_rdwr_ioctl_data
struct interface with ioctl
. This looks more complicated, but allows you to do more complex operations such as a write-restart-read operation. Here is the same read as before, but using this interface:bool receiveBytes(const int addr, uint8_t *buf, const int len)
{
i2c_msg msgs[1] = {
{.addr = static_cast<uint16_t>(addr),
.flags = I2C_M_RD,
.len = static_cast<uint16_t>(len),
.buf = buf}};
i2c_rdwr_ioctl_data wrapper = {
.msgs = msgs,
.nmsgs = 1};
if (ioctl(m_busFD, I2C_RDWR, &wrapper) < 0)
return false;
return (msgs[0].len == len);
}
And here is an example of a write-restart-read:
bool sendRecBytes(
const int addr,
uint8_t *sbuf, const int slen,
uint8_t *rbuf, const int rlen)
{
i2c_msg msgs[2] = {
{.addr = static_cast<uint16_t>(addr),
.flags = {},
.len = static_cast<uint16_t>(slen),
.buf = sbuf},
{.addr = static_cast<uint16_t>(addr),
.flags = I2C_M_RD,
.len = static_cast<uint16_t>(rlen),
.buf = rbuf}};
i2c_rdwr_ioctl_data wrapper = {
.msgs = msgs,
.nmsgs = 2};
if (ioctl(m_busFD, I2C_RDWR, &wrapper) < 0)
return false;
return (msgs[0].len == slen) && (msgs[1].len == rlen);
}
Edit: Forgot to mention that this all requires:
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>