转载地址:https://i-blog.csdnimg.cn/blog_migrate/5a3cc52edd8f938b8646bdcf12565f75.png
i2c通道在开发过程中使用是非常的方便的,主要是由于其简单的结构,i2c主要有SCL,SDA两条通道,一个时钟线,一个数据线,这也是i2c之所以应用如此普遍的原因。i2c的时序如下:
实现上述时序,便可以轻松通过i2c读写寄存器了,接下来看看i2c下在Linux应用层中实现读写,主要是通过O_RDWR IOTCL读写i2c设备,写函数如下:
static int iic_write(int i2c_fd, unsigned int reg_address ,unsigned int reg_val)
{
struct i2c_rdwr_ioctl_data work_queue;
int ret;
work_queue.nmsgs = 2;
work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));
if(!work_queue.msgs)
{
printf("msgs memery alloc error\n");
close(i2c_fd);
return 0;
}
if ((work_queue.msgs[0].buf = (unsigned char *)malloc(2 * sizeof(unsigned char))) == NULL)
{
printf("buf memery alloc error...\n");
close(i2c_fd);
return 0;
}
(work_queue.msgs[0]).len = 2;
(work_queue.msgs[0]).flags = 0;
(work_queue.msgs[0]).addr = slave_address;
(work_queue.msgs[0]).buf[0] = reg_address;
(work_queue.msgs[0]).buf[1] = reg_val;
work_queue.nmsgs = 1;
ioctl(i2c_fd, I2C_RDWR, (unsigned long) &work_queue);
if(ret < 0)
{
printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);
return 0;
}
free(work_queue.msgs[0].buf);
free(work_queue.msgs);
}
上述贴出的代码分析 :
i2c_rdwr_ioctl_data结构体的源码如下
/* pointers to i2c_msgs */
struct i2c_msg __user *msgs;
/* number of i2c_msgs */
__u32 nmsgs;
};
{
unsigned short addr; //slave IIC device addr
unsigned short flags; //write read flags
#define I2C_M_TEN0x0010/* this is a ten bit chip address */
#define I2C_M_RD0x0001/* read data, from slave to master */
#define I2C_M_NOSTART0x4000/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR0x2000/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK0x1000/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK0x0800/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN0x0400/* length will be first received byte */
unsigned short len; //写入或者读出数据的个数(字节)
unsigned char *buf; //写入或者读出数据的地址 buf[0]
};
i2c的读函数如下:
static int iic_read(int i2c_fd, unsigned int reg_address)
{
struct i2c_rdwr_ioctl_data work_queue;
unsigned char val;
int ret;
work_queue.nmsgs = 2;
work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs *sizeof(struct i2c_msg));
if(!work_queue.msgs)
{
printf("Memery alloc error\n");
close(i2c_fd);
return 0;
}
val =(unsigned char)reg_address;
(work_queue.msgs[0]).len = 1;
(work_queue.msgs[0]).flags = 0;
(work_queue.msgs[0]).addr = slave_address;
(work_queue.msgs[0]).buf = &val;
(work_queue.msgs[1]).len = 1;
(work_queue.msgs[1]).flags = 1;
(work_queue.msgs[1]).addr = slave_address;
(work_queue.msgs[1]).buf = &val;
ret = ioctl(i2c_fd, I2C_RDWR, (unsigned long) &work_queue);
if(ret < 0)
{
printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);
return 0;
}
free(work_queue.msgs);
return val;
}
这样就可以直接调用i2c读写函数实现对传感器寄存器的操作了。最后在说明一点,千万不要忘记给i2c_rdwr_ioctl_data结构体中的最重要最重要最重要的结构i2c_msg中的buf分配内存。