背景:linux应用层访问i2c出错,原因分析,i2c结构体数据错误,没有给i2c结构体分配内存,设备器件地址不对。
首先确定设备挂接在哪一条总线上,通过i2c-tool。
i2cdetect -l
或者
i2cdetect -y -r 3
i2c写函数:
unsigned char base_i2c_write(unsigned char device_addr, unsigned char *buff, int ByteNo)
{
int fd, ret;
const char *i2c_dev = "/dev/i2c-3";
fd = open(i2c_dev, O_RDWR);
struct i2c_rdwr_ioctl_data data;
struct i2c_msg msgs_str[1];
data.msgs = msgs_str;
unsigned char sendbuf[255] = {0};
printf("device_addr : %x\n",device_addr);
fflush(stdout);
//device_addr <<= 1;
//printf("device_addr : %x\n",device_addr);
fflush(stdout);
data.nmsgs = 1;
data.msgs[0].len = ByteNo;
data.msgs[0].addr = device_addr;
data.msgs[0].flags = 0;
data.msgs[0].buf = sendbuf;
memset(sendbuf, 0, 255);
memcpy( sendbuf, buff, ByteNo);
ioctl(fd,I2C_RDWR,(unsigned long)&data);
printf("Write begin-> write data all :");
fflush(stdout);
for(int i=0; i<ByteNo; i++){
printf(" 0x%02x",i,(data.msgs[0]).buf[i]);
fflush(stdout);
}
printf("\n");
fflush(stdout);
if (ret < 0){
printf("write error!!!\n");
fflush(stdout);
}
close(fd);
}
i2c读函数:
unsigned char base_i2c_read(unsigned char device_addr, unsigned char *buff, int ByteNo)
{
int fd, ret;
struct i2c_rdwr_ioctl_data i2c_data;
const char *i2c_dev = "/dev/i2c-3";
fd = open(i2c_dev, O_RDWR);
if (fd<0)
{
printf("not have /dev/i2c-0 t\r\n");
fflush(stdout);
return -1;
}
i2c_data.nmsgs = 1;
i2c_data.msgs = (struct i2c_msg *)malloc(i2c_data.nmsgs *sizeof(struct i2c_msg));
if (i2c_data.msgs == NULL)
{
printf("malloc error");
fflush(stdout);
close(fd);
return -1;
}
ioctl(fd, I2C_TIMEOUT, 1);
ioctl(fd, I2C_RETRIES, 2);
i2c_data.msgs[0].len = ByteNo;
i2c_data.msgs[0].addr = device_addr;
i2c_data.msgs[0].flags = 1; // 0: write 1:read
i2c_data.msgs[0].buf = buff;
ret = ioctl(fd, I2C_RDWR, (unsigned long)&i2c_data);
if (ret < 0)
{
printf("read data %x error\r\n", device_addr);
close(fd);
free(i2c_data.msgs);
return 1;
}
free(i2c_data.msgs);
close(fd);
int i;
printf(" Begin print read data \n");
for (i = 0; i < ByteNo; i++)
{
printf(" 0x%02x",buff[i]);
}
printf("\n");
return 0;
}
注意事项:
- 从设备地址是芯片的真实地址,不是左移加上读写位那个虚地址。
- msg结构体必须分配空间,否则会出错。
- 读函数没有寄存器地址,如果需要先写寄存器再读,i2c_data.nmsgs 设为 2,msg[0]填充写的结果,msg[1]填写读的结构。
另外:
如果需要动态传设备参数,修改fd的获得方式即可。
int fd;
struct i2c_rdwr_ioctl_data i2c_data;
QString busName = QString("/dev/i2c-%1").arg(i2c_bus);
fd = open(busName.toLatin1(), O_RDWR);
if(fd < 0){
printf("Don`t open the device...");
}