对于写I2C寄存器,我们需要做的就是给 i2c_master_send 函数传入两个字节的数据即可,
i2c_master_send 接口的三个参数:client 为此次与主机通信的从机,buf 为发送的数据指针,count 为发送数据的字节数。
示例如下:
static int xxxx_i2c_write( struct i2c_client* client,uint8_t reg,uint8_t data)
{
unsigned char buffer[2];
buffer[0] = reg;
buffer[1] = data;
if( 2!= i2c_master_send(client,buffer,2) ) {
printk( KERN_ERR " xxxx_i2c_write fail! \n" );
return -1;
}
return 0;
}
读时序需要做的操作是,先向I2C总线上写入需要读的寄存器地址,然后读I2C总线上的值。
i2c_master_recv 接口的三个参数:client 为此次与主机通信的从机,buf 为接收的数据指针,count 为接收数据的字节数。
示例如下:
static int xxxx_i2c_read( struct i2c_client* client,uint8_t reg,uint8_t *data)
{
// write reg addr
if( 1!= i2c_master_send(client,®,1) ) {
printk( KERN_ERR " xxxx_i2c_read fail! \n" );
return -1;
}
// wait
msleep(10);
// read
if( 1!= i2c_master_recv(client,data,1) ) {
printk( KERN_ERR " xxxx_i2c_read fail! \n" );
return -1;
}
return 0;
}
i2c_transfer的参数:其中 adap 为此次主机与从机通信的适配器;msgs 为通信的数据包,这里可以是单个或多个数据包;num 用于指定数据包的个数,
如果大于1则表明将进行不止一次的通信。通信一次就需要寻址一次,如果需要多次通信就需要多次寻址。
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
有的情况下我们要读一个寄存器的值,就需要先向从机发送一个寄存器地址然后再接收数据,这样如果想自己封装一个接口就需要将 num 设置为2。
接口的返回值如果失败则为负数,如果成功则返回传输的数据包个数。
比如读一个寄存器的接口可以按照如下方式封装:
static int read_reg(struct i2c_client *client, unsigned char reg, unsigned char *data)
{
int ret;
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = ®, // 寄存器地址
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = 1,
.buf = data, // 寄存器的值
},
};
ret = i2c_transfer(client->adapter, msgs, 2); // 这里 num = 2,通信成功 ret = 2
if (ret < 0)
tp_err("%s error: %d\n", __func__, ret);
return ret;
}
另一种接口封装:
static unsigned char read_reg(struct i2c_client *client, unsigned char reg)
{
unsigned char buf;
i2c_master_send(client, ®, 1); // 发送寄存器地址
i2c_master_recv(client, &buf, 1); // 接收寄存器的值
return buf;
}