linux i2c应用程序模块

前言

I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。本文主要介绍在linux系统通过i2c设备通过应用软件发送和接收i2c消息。

一、设备打开

linux下一切皆文件,I2C设备也是一个文件,I2C_DEV为系统I2C设备/dev/i2c-1,设备打开操作如下所示:

fd = open(I2C_DEV, O_RDWR);

二、数据读写

数据写入用的不是write函数,数据读取也不是用read函数,而是统一用ioctl,用法如下:

  ioctl的第一个参数传入已经打开的I2C设备的文件描述符,第二个参数传入I2C_RDWR,表示进行数据读写,第三个参数传入一个struct i2c_rdwr_ioctl_data类型的指针,struct i2c_rdwr_ioctl_data类型定义在linux/i2c-dev.h中,其结构定义如下:

struct i2c_rdwr_ioctl_data {
    struct i2c_msg __user *msgs;    /* pointers to i2c_msgs */
    __u32 nmsgs;            /* number of i2c_msgs */
};

一个该结构表示一次传输,一次传输可以包含若干个消息,nmsgs用于指定消息数量。一般来说一次写数据包含一个消息,一次读数据包含2个消息,因此写数据时nmsgs的值为1,msgs指向一个消息,读数据时nmsgs为2,msgs指向一个包含2个消息的数组。

  struct i2c_msg结构定义如下:

struct i2c_msg {
    __u16 addr;    /* slave address            */
    __u16 flags;
#define I2C_M_TEN        0x0010    /* this is a ten bit chip address */
#define I2C_M_RD        0x0001    /* read data, from slave to master */
#define I2C_M_NOSTART        0x4000    /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR    0x2000    /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK    0x1000    /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK        0x0800    /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN        0x0400    /* length will be first received byte */
    __u16 len;        /* msg length                */
    __u8 *buf;        /* pointer to msg data            */
};

1.I2C写数据

int i2c_write(int fd, unsigned char dev_addr, unsigned char reg_addr, unsigned char * data_buf, int len)
{
	int ret = 0;
	unsigned char msg_buf[9];
	struct i2c_rdwr_ioctl_data data;
	struct i2c_msg messages;

	msg_buf[0] = reg_addr;

	if(len < 9)
	{
		memcpy((void *) &msg_buf[1], data_buf, len);
	}
	else
	{
		printf("This function supports up to 8 bytes");
		return -1;
	}

	messages.addr = dev_addr;
	messages.flags = 0;
	messages.len = len + 1;
	messages.buf = msg_buf;
	data.msgs = &messages;
	data.nmsgs = 1;
	if(ioctl(fd, I2C_RDWR, &data) < 0)
	{
		printf("I2C_RDWR err\n");
		return -1;
	}
	
	usleep(50);
	return 0;
}

2.I2C读数据

int i2c_read(int fd, unsigned char dev_addr, unsigned char reg_addr, unsigned char *data_buf, int len)
{
	int ret = 0;
	unsigned char msg_buf[9];
	struct i2c_rdwr_ioctl_data data;
	struct i2c_msg messages[2];

	messages[0].addr = dev_addr;
	messages[0].flags = 0;
	messages[0].len = 1;
	messages[0].buf = &reg_addr;

	messages[1].addr=dev_addr;
	messages[1].flags = I2C_M_RD;
	messages[1].len = len;
	messages[1].buf = data_buf;
	data.msgs = messages;
	data.nmsgs = 2;

	if(ioctl(fd, I2C_RDWR, &data) < 0)
	{
		printf("I2C_RDWR err\n");
		return -1;
	}
	
	usleep(50);

	return 0;
}

3.SMbus传输

如果I2C适配器支持SMbus协议,那么就可以使用SMbus协议与设备进行通信。查看I2C适配器关于SMbus支持情况,可以通过ioctl的I2C_FUNCS命令查询。

使用SMbus进行数据传输,需要将数据封装到i2c_smbus_ioctl_data中

struct i2c_smbus_ioctl_data {
	__u8 read_write;
	__u8 command;
	__u32 size;
	union i2c_smbus_data __user *data;
};

#define I2C_SMBUS_BLOCK_MAX	32	/* As specified in SMBus standard */
union i2c_smbus_data {
	__u8 byte;
	__u16 word;
	__u8 block[I2C_SMBUS_BLOCK_MAX + 2]; 
					/* block[0] is used for length */
			       /* and one more for user-space compatibility */
};
/* i2c_smbus_xfer read or write markers */
#define I2C_SMBUS_READ	1
#define I2C_SMBUS_WRITE	0

i2c_smbus_access接口

int i2c_smbus_access(int file, char read_write, __u8 command,
                       int size, union i2c_smbus_data *data)
{
        struct i2c_smbus_ioctl_data args;
        int err;

        args.read_write = read_write;
        args.command = command;
        args.size = size;
        args.data = data;

        err = ioctl(file, I2C_SMBUS, &args);
        if (err == -1)
                err = -errno;
        return err;
}


总结

在linux下使用i2c应用程序操作i2c设备,读者不需要熟悉i2c接口时序,不用我们去定义时序,读者能够更简单的去操作i2c接口设备。i2c接口模块可以在下面链接下载:

linuxi2c应用编程库-C文档类资源-CSDN下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flypig哗啦啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值